diff options
413 files changed, 5483 insertions, 2526 deletions
diff --git a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java index e6c94d896e50..6383ed873e59 100644 --- a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java +++ b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java @@ -1107,7 +1107,7 @@ public class DeviceIdleController extends SystemService private long mDefaultInactiveTimeout = (30 * 60 * 1000L) / (!COMPRESS_TIME ? 1 : 10); private static final long DEFAULT_INACTIVE_TIMEOUT_SMALL_BATTERY = - (15 * 60 * 1000L) / (!COMPRESS_TIME ? 1 : 10); + (60 * 1000L) / (!COMPRESS_TIME ? 1 : 10); private long mDefaultSensingTimeout = !COMPRESS_TIME ? 4 * 60 * 1000L : 60 * 1000L; private long mDefaultLocatingTimeout = @@ -1120,7 +1120,7 @@ public class DeviceIdleController extends SystemService private long mDefaultIdleAfterInactiveTimeout = (30 * 60 * 1000L) / (!COMPRESS_TIME ? 1 : 10); private static final long DEFAULT_IDLE_AFTER_INACTIVE_TIMEOUT_SMALL_BATTERY = - (15 * 60 * 1000L) / (!COMPRESS_TIME ? 1 : 10); + (60 * 1000L) / (!COMPRESS_TIME ? 1 : 10); private long mDefaultIdlePendingTimeout = !COMPRESS_TIME ? 5 * 60 * 1000L : 30 * 1000L; private long mDefaultMaxIdlePendingTimeout = diff --git a/core/api/current.txt b/core/api/current.txt index 09abe2b0cd09..5b339fa9494d 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -10601,6 +10601,7 @@ package android.content { field public static final String RESTRICTIONS_SERVICE = "restrictions"; field public static final String ROLE_SERVICE = "role"; field public static final String SEARCH_SERVICE = "search"; + field @FlaggedApi("android.os.security_state_service") public static final String SECURITY_STATE_SERVICE = "security_state"; field public static final String SENSOR_SERVICE = "sensor"; field public static final String SHORTCUT_SERVICE = "shortcut"; field public static final String STATUS_BAR_SERVICE = "statusbar"; @@ -10613,6 +10614,7 @@ package android.content { field public static final String TELEPHONY_SUBSCRIPTION_SERVICE = "telephony_subscription_service"; field public static final String TEXT_CLASSIFICATION_SERVICE = "textclassification"; field public static final String TEXT_SERVICES_MANAGER_SERVICE = "textservices"; + field @FlaggedApi("android.media.tv.flags.enable_ad_service_fw") public static final String TV_AD_SERVICE = "tv_ad"; field public static final String TV_INPUT_SERVICE = "tv_input"; field public static final String TV_INTERACTIVE_APP_SERVICE = "tv_interactive_app"; field public static final String UI_MODE_SERVICE = "uimode"; @@ -11101,6 +11103,7 @@ package android.content { field public static final String ACTION_UID_REMOVED = "android.intent.action.UID_REMOVED"; field @Deprecated public static final String ACTION_UMS_CONNECTED = "android.intent.action.UMS_CONNECTED"; field @Deprecated public static final String ACTION_UMS_DISCONNECTED = "android.intent.action.UMS_DISCONNECTED"; + field @FlaggedApi("android.content.pm.archiving") public static final String ACTION_UNARCHIVE_PACKAGE = "android.intent.action.UNARCHIVE_PACKAGE"; field @Deprecated public static final String ACTION_UNINSTALL_PACKAGE = "android.intent.action.UNINSTALL_PACKAGE"; field public static final String ACTION_USER_BACKGROUND = "android.intent.action.USER_BACKGROUND"; field public static final String ACTION_USER_FOREGROUND = "android.intent.action.USER_FOREGROUND"; @@ -12366,6 +12369,7 @@ package android.content.pm { public class PackageInfo implements android.os.Parcelable { ctor public PackageInfo(); method public int describeContents(); + method @FlaggedApi("android.content.pm.archiving") public long getArchiveTimeMillis(); method public long getLongVersionCode(); method public void setLongVersionCode(long); method public void writeToParcel(android.os.Parcel, int); @@ -12422,6 +12426,9 @@ package android.content.pm { method @NonNull public android.content.pm.PackageInstaller.Session openSession(int) throws java.io.IOException; method public void registerSessionCallback(@NonNull android.content.pm.PackageInstaller.SessionCallback); method public void registerSessionCallback(@NonNull android.content.pm.PackageInstaller.SessionCallback, @NonNull android.os.Handler); + method @FlaggedApi("android.content.pm.archiving") @RequiresPermission(anyOf={android.Manifest.permission.INSTALL_PACKAGES, android.Manifest.permission.REQUEST_INSTALL_PACKAGES}) public void reportUnarchivalStatus(int, int, long, @Nullable android.app.PendingIntent) throws android.content.pm.PackageManager.NameNotFoundException; + method @FlaggedApi("android.content.pm.archiving") @RequiresPermission(anyOf={android.Manifest.permission.DELETE_PACKAGES, android.Manifest.permission.REQUEST_DELETE_PACKAGES}) public void requestArchive(@NonNull String, @NonNull android.content.IntentSender) throws android.content.pm.PackageManager.NameNotFoundException; + method @FlaggedApi("android.content.pm.archiving") @RequiresPermission(anyOf={android.Manifest.permission.INSTALL_PACKAGES, android.Manifest.permission.REQUEST_INSTALL_PACKAGES}) public void requestUnarchive(@NonNull String, @NonNull android.content.IntentSender) throws java.io.IOException, android.content.pm.PackageManager.NameNotFoundException; method @RequiresPermission(anyOf={android.Manifest.permission.DELETE_PACKAGES, android.Manifest.permission.REQUEST_DELETE_PACKAGES}) public void uninstall(@NonNull String, @NonNull android.content.IntentSender); method @RequiresPermission(anyOf={android.Manifest.permission.DELETE_PACKAGES, android.Manifest.permission.REQUEST_DELETE_PACKAGES}) public void uninstall(@NonNull android.content.pm.VersionedPackage, @NonNull android.content.IntentSender); method @RequiresPermission(anyOf={android.Manifest.permission.DELETE_PACKAGES, android.Manifest.permission.REQUEST_DELETE_PACKAGES}) public void uninstall(@NonNull android.content.pm.VersionedPackage, int, @NonNull android.content.IntentSender); @@ -12443,6 +12450,10 @@ package android.content.pm { field public static final String EXTRA_STATUS = "android.content.pm.extra.STATUS"; field public static final String EXTRA_STATUS_MESSAGE = "android.content.pm.extra.STATUS_MESSAGE"; field public static final String EXTRA_STORAGE_PATH = "android.content.pm.extra.STORAGE_PATH"; + field @FlaggedApi("android.content.pm.archiving") public static final String EXTRA_UNARCHIVE_ALL_USERS = "android.content.pm.extra.UNARCHIVE_ALL_USERS"; + field @FlaggedApi("android.content.pm.archiving") public static final String EXTRA_UNARCHIVE_ID = "android.content.pm.extra.UNARCHIVE_ID"; + field @FlaggedApi("android.content.pm.archiving") public static final String EXTRA_UNARCHIVE_PACKAGE_NAME = "android.content.pm.extra.UNARCHIVE_PACKAGE_NAME"; + field @FlaggedApi("android.content.pm.archiving") public static final String EXTRA_UNARCHIVE_STATUS = "android.content.pm.extra.UNARCHIVE_STATUS"; field public static final int PACKAGE_SOURCE_DOWNLOADED_FILE = 4; // 0x4 field public static final int PACKAGE_SOURCE_LOCAL_FILE = 3; // 0x3 field public static final int PACKAGE_SOURCE_OTHER = 1; // 0x1 @@ -12458,6 +12469,13 @@ package android.content.pm { field public static final int STATUS_FAILURE_TIMEOUT = 8; // 0x8 field public static final int STATUS_PENDING_USER_ACTION = -1; // 0xffffffff field public static final int STATUS_SUCCESS = 0; // 0x0 + field @FlaggedApi("android.content.pm.archiving") public static final int UNARCHIVAL_ERROR_INSTALLER_DISABLED = 4; // 0x4 + field @FlaggedApi("android.content.pm.archiving") public static final int UNARCHIVAL_ERROR_INSTALLER_UNINSTALLED = 5; // 0x5 + field @FlaggedApi("android.content.pm.archiving") public static final int UNARCHIVAL_ERROR_INSUFFICIENT_STORAGE = 2; // 0x2 + field @FlaggedApi("android.content.pm.archiving") public static final int UNARCHIVAL_ERROR_NO_CONNECTIVITY = 3; // 0x3 + field @FlaggedApi("android.content.pm.archiving") public static final int UNARCHIVAL_ERROR_USER_ACTION_NEEDED = 1; // 0x1 + field @FlaggedApi("android.content.pm.archiving") public static final int UNARCHIVAL_GENERIC_ERROR = 100; // 0x64 + field @FlaggedApi("android.content.pm.archiving") public static final int UNARCHIVAL_OK = 0; // 0x0 } public static final class PackageInstaller.InstallConstraints implements android.os.Parcelable { @@ -12621,6 +12639,7 @@ package android.content.pm { method @RequiresPermission(android.Manifest.permission.ENFORCE_UPDATE_OWNERSHIP) public void setRequestUpdateOwnership(boolean); method public void setRequireUserAction(int); method public void setSize(long); + method @FlaggedApi("android.content.pm.archiving") public void setUnarchiveId(int); method public void setWhitelistedRestrictedPermissions(@Nullable java.util.Set<java.lang.String>); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.content.pm.PackageInstaller.SessionParams> CREATOR; @@ -12650,6 +12669,7 @@ package android.content.pm { method public void writeToParcel(android.os.Parcel, int); field public int banner; field public int icon; + field @FlaggedApi("android.content.pm.archiving") public boolean isArchived; field public int labelRes; field public int logo; field public android.os.Bundle metaData; @@ -12772,6 +12792,7 @@ package android.content.pm { method public boolean hasSigningCertificate(int, @NonNull byte[], int); method public abstract boolean hasSystemFeature(@NonNull String); method public abstract boolean hasSystemFeature(@NonNull String, int); + method @FlaggedApi("android.content.pm.archiving") public boolean isAppArchivable(@NonNull String) throws android.content.pm.PackageManager.NameNotFoundException; method @RequiresPermission(value="android.permission.WHITELIST_AUTO_REVOKE_PERMISSIONS", conditional=true) public boolean isAutoRevokeWhitelisted(@NonNull String); method public boolean isAutoRevokeWhitelisted(); method public boolean isDefaultApplicationIcon(@NonNull android.graphics.drawable.Drawable); @@ -13013,6 +13034,7 @@ package android.content.pm { field public static final int INSTALL_SCENARIO_FAST = 1; // 0x1 field public static final int MATCH_ALL = 131072; // 0x20000 field public static final int MATCH_APEX = 1073741824; // 0x40000000 + field @FlaggedApi("android.content.pm.archiving") public static final long MATCH_ARCHIVED_PACKAGES = 4294967296L; // 0x100000000L field public static final int MATCH_DEFAULT_ONLY = 65536; // 0x10000 field public static final int MATCH_DIRECT_BOOT_AUTO = 268435456; // 0x10000000 field public static final int MATCH_DIRECT_BOOT_AWARE = 524288; // 0x80000 @@ -22034,6 +22056,19 @@ package android.media { method public void onJetUserIdUpdate(android.media.JetPlayer, int, int); } + @FlaggedApi("android.media.audio.loudness_configurator_api") public class LoudnessCodecConfigurator { + method @FlaggedApi("android.media.audio.loudness_configurator_api") public void addMediaCodec(@NonNull android.media.MediaCodec); + method @FlaggedApi("android.media.audio.loudness_configurator_api") @NonNull public static android.media.LoudnessCodecConfigurator create(); + method @FlaggedApi("android.media.audio.loudness_configurator_api") @NonNull public static android.media.LoudnessCodecConfigurator create(@NonNull java.util.concurrent.Executor, @NonNull android.media.LoudnessCodecConfigurator.OnLoudnessCodecUpdateListener); + method @FlaggedApi("android.media.audio.loudness_configurator_api") @NonNull public android.os.Bundle getLoudnessCodecParams(@NonNull android.media.AudioTrack, @NonNull android.media.MediaCodec); + method @FlaggedApi("android.media.audio.loudness_configurator_api") public void removeMediaCodec(@NonNull android.media.MediaCodec); + method @FlaggedApi("android.media.audio.loudness_configurator_api") public void setAudioTrack(@Nullable android.media.AudioTrack); + } + + @FlaggedApi("android.media.audio.loudness_configurator_api") public static interface LoudnessCodecConfigurator.OnLoudnessCodecUpdateListener { + method @FlaggedApi("android.media.audio.loudness_configurator_api") @NonNull public default android.os.Bundle onLoudnessCodecUpdate(@NonNull android.media.MediaCodec, @NonNull android.os.Bundle); + } + public class MediaActionSound { ctor public MediaActionSound(); method public void load(int); @@ -27302,6 +27337,13 @@ package android.media.tv { } +package android.media.tv.ad { + + @FlaggedApi("android.media.tv.flags.enable_ad_service_fw") public class TvAdManager { + } + +} + package android.media.tv.interactive { public final class AppLinkInfo implements android.os.Parcelable { @@ -33379,6 +33421,13 @@ package android.os { field @NonNull public static final android.os.Parcelable.Creator<android.os.ResultReceiver> CREATOR; } + @FlaggedApi("android.os.security_state_service") public class SecurityStateManager { + method @FlaggedApi("android.os.security_state_service") @NonNull public android.os.Bundle getGlobalSecurityState(); + field public static final String KEY_KERNEL_VERSION = "kernel_version"; + field public static final String KEY_SYSTEM_SPL = "system_spl"; + field public static final String KEY_VENDOR_SPL = "vendor_spl"; + } + public final class SharedMemory implements java.io.Closeable android.os.Parcelable { method public void close(); method @NonNull public static android.os.SharedMemory create(@Nullable String, int) throws android.system.ErrnoException; @@ -36773,7 +36822,7 @@ package android.provider { field public static final String ACTION_CAST_SETTINGS = "android.settings.CAST_SETTINGS"; field public static final String ACTION_CHANNEL_NOTIFICATION_SETTINGS = "android.settings.CHANNEL_NOTIFICATION_SETTINGS"; field public static final String ACTION_CONDITION_PROVIDER_SETTINGS = "android.settings.ACTION_CONDITION_PROVIDER_SETTINGS"; - field public static final String ACTION_CREDENTIAL_PROVIDER = "android.settings.CREDENTIAL_PROVIDER"; + field @FlaggedApi("android.credentials.flags.new_settings_intents") public static final String ACTION_CREDENTIAL_PROVIDER = "android.settings.CREDENTIAL_PROVIDER"; field public static final String ACTION_DATA_ROAMING_SETTINGS = "android.settings.DATA_ROAMING_SETTINGS"; field public static final String ACTION_DATA_USAGE_SETTINGS = "android.settings.DATA_USAGE_SETTINGS"; field public static final String ACTION_DATE_SETTINGS = "android.settings.DATE_SETTINGS"; diff --git a/core/api/removed.txt b/core/api/removed.txt index 285dcc6a3ed9..b7714f118766 100644 --- a/core/api/removed.txt +++ b/core/api/removed.txt @@ -30,36 +30,6 @@ package android.app { } -package android.app.slice { - - public final class Slice implements android.os.Parcelable { - field @Deprecated public static final String EXTRA_SLIDER_VALUE = "android.app.slice.extra.SLIDER_VALUE"; - field @Deprecated public static final String SUBTYPE_SLIDER = "slider"; - } - - public static class Slice.Builder { - ctor @Deprecated public Slice.Builder(@NonNull android.net.Uri); - method @Deprecated public android.app.slice.Slice.Builder addTimestamp(long, @Nullable String, java.util.List<java.lang.String>); - method @Deprecated public android.app.slice.Slice.Builder setSpec(android.app.slice.SliceSpec); - } - - public final class SliceItem implements android.os.Parcelable { - method @Deprecated public long getTimestamp(); - field @Deprecated public static final String FORMAT_TIMESTAMP = "long"; - } - - public class SliceManager { - method @Deprecated @Nullable public android.app.slice.Slice bindSlice(@NonNull android.net.Uri, @NonNull java.util.List<android.app.slice.SliceSpec>); - method @Deprecated @Nullable public android.app.slice.Slice bindSlice(@NonNull android.content.Intent, @NonNull java.util.List<android.app.slice.SliceSpec>); - method @Deprecated public void pinSlice(@NonNull android.net.Uri, @NonNull java.util.List<android.app.slice.SliceSpec>); - } - - public abstract class SliceProvider extends android.content.ContentProvider { - method @Deprecated public android.app.slice.Slice onBindSlice(android.net.Uri, java.util.List<android.app.slice.SliceSpec>); - } - -} - package android.app.usage { public class StorageStatsManager { diff --git a/core/api/system-current.txt b/core/api/system-current.txt index fc23f9bc43ff..0497c6087ccd 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -3614,7 +3614,6 @@ package android.content { field public static final String ACTION_SHOW_SUSPENDED_APP_DETAILS = "android.intent.action.SHOW_SUSPENDED_APP_DETAILS"; field @Deprecated public static final String ACTION_SIM_STATE_CHANGED = "android.intent.action.SIM_STATE_CHANGED"; field public static final String ACTION_SPLIT_CONFIGURATION_CHANGED = "android.intent.action.SPLIT_CONFIGURATION_CHANGED"; - field @FlaggedApi("android.content.pm.archiving") public static final String ACTION_UNARCHIVE_PACKAGE = "android.intent.action.UNARCHIVE_PACKAGE"; field public static final String ACTION_UPGRADE_SETUP = "android.intent.action.UPGRADE_SETUP"; field public static final String ACTION_USER_ADDED = "android.intent.action.USER_ADDED"; field public static final String ACTION_USER_REMOVED = "android.intent.action.USER_REMOVED"; @@ -3862,16 +3861,9 @@ package android.content.pm { field @RequiresPermission(android.Manifest.permission.ACCESS_SHORTCUTS) public static final int FLAG_GET_PERSONS_DATA = 2048; // 0x800 } - public class PackageInfo implements android.os.Parcelable { - method @FlaggedApi("android.content.pm.archiving") public long getArchiveTimeMillis(); - } - public class PackageInstaller { method @NonNull public android.content.pm.PackageInstaller.InstallInfo readInstallInfo(@NonNull java.io.File, int) throws android.content.pm.PackageInstaller.PackageParsingException; method @FlaggedApi("android.content.pm.read_install_info") @NonNull public android.content.pm.PackageInstaller.InstallInfo readInstallInfo(@NonNull android.os.ParcelFileDescriptor, @Nullable String, int) throws android.content.pm.PackageInstaller.PackageParsingException; - method @FlaggedApi("android.content.pm.archiving") @RequiresPermission(anyOf={android.Manifest.permission.INSTALL_PACKAGES, android.Manifest.permission.REQUEST_INSTALL_PACKAGES}) public void reportUnarchivalStatus(int, int, long, @Nullable android.app.PendingIntent) throws android.content.pm.PackageManager.NameNotFoundException; - method @FlaggedApi("android.content.pm.archiving") @RequiresPermission(anyOf={android.Manifest.permission.DELETE_PACKAGES, android.Manifest.permission.REQUEST_DELETE_PACKAGES}) public void requestArchive(@NonNull String, @NonNull android.content.IntentSender) throws android.content.pm.PackageManager.NameNotFoundException; - method @FlaggedApi("android.content.pm.archiving") @RequiresPermission(anyOf={android.Manifest.permission.INSTALL_PACKAGES, android.Manifest.permission.REQUEST_INSTALL_PACKAGES}) public void requestUnarchive(@NonNull String, @NonNull android.content.IntentSender) throws java.io.IOException, android.content.pm.PackageManager.NameNotFoundException; method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void setPermissionsResult(int, boolean); field public static final String ACTION_CONFIRM_INSTALL = "android.content.pm.action.CONFIRM_INSTALL"; field public static final String ACTION_CONFIRM_PRE_APPROVAL = "android.content.pm.action.CONFIRM_PRE_APPROVAL"; @@ -3882,23 +3874,12 @@ package android.content.pm { field public static final String EXTRA_DATA_LOADER_TYPE = "android.content.pm.extra.DATA_LOADER_TYPE"; field public static final String EXTRA_LEGACY_STATUS = "android.content.pm.extra.LEGACY_STATUS"; field @Deprecated public static final String EXTRA_RESOLVED_BASE_PATH = "android.content.pm.extra.RESOLVED_BASE_PATH"; - field @FlaggedApi("android.content.pm.archiving") public static final String EXTRA_UNARCHIVE_ALL_USERS = "android.content.pm.extra.UNARCHIVE_ALL_USERS"; - field @FlaggedApi("android.content.pm.archiving") public static final String EXTRA_UNARCHIVE_ID = "android.content.pm.extra.UNARCHIVE_ID"; - field @FlaggedApi("android.content.pm.archiving") public static final String EXTRA_UNARCHIVE_PACKAGE_NAME = "android.content.pm.extra.UNARCHIVE_PACKAGE_NAME"; - field @FlaggedApi("android.content.pm.archiving") public static final String EXTRA_UNARCHIVE_STATUS = "android.content.pm.extra.UNARCHIVE_STATUS"; field public static final int LOCATION_DATA_APP = 0; // 0x0 field public static final int LOCATION_MEDIA_DATA = 2; // 0x2 field public static final int LOCATION_MEDIA_OBB = 1; // 0x1 field public static final int REASON_CONFIRM_PACKAGE_CHANGE = 0; // 0x0 field public static final int REASON_OWNERSHIP_CHANGED = 1; // 0x1 field public static final int REASON_REMIND_OWNERSHIP = 2; // 0x2 - field @FlaggedApi("android.content.pm.archiving") public static final int UNARCHIVAL_ERROR_INSTALLER_DISABLED = 4; // 0x4 - field @FlaggedApi("android.content.pm.archiving") public static final int UNARCHIVAL_ERROR_INSTALLER_UNINSTALLED = 5; // 0x5 - field @FlaggedApi("android.content.pm.archiving") public static final int UNARCHIVAL_ERROR_INSUFFICIENT_STORAGE = 2; // 0x2 - field @FlaggedApi("android.content.pm.archiving") public static final int UNARCHIVAL_ERROR_NO_CONNECTIVITY = 3; // 0x3 - field @FlaggedApi("android.content.pm.archiving") public static final int UNARCHIVAL_ERROR_USER_ACTION_NEEDED = 1; // 0x1 - field @FlaggedApi("android.content.pm.archiving") public static final int UNARCHIVAL_GENERIC_ERROR = 100; // 0x64 - field @FlaggedApi("android.content.pm.archiving") public static final int UNARCHIVAL_OK = 0; // 0x0 } public static class PackageInstaller.InstallInfo { @@ -3948,14 +3929,12 @@ package android.content.pm { method public void setRequestDowngrade(boolean); method @FlaggedApi("android.content.pm.rollback_lifetime") @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) public void setRollbackLifetimeMillis(long); method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void setStaged(); - method @FlaggedApi("android.content.pm.archiving") public void setUnarchiveId(int); } public class PackageItemInfo { method public static void forceSafeLabels(); method @Deprecated @NonNull public CharSequence loadSafeLabel(@NonNull android.content.pm.PackageManager); method @NonNull public CharSequence loadSafeLabel(@NonNull android.content.pm.PackageManager, @FloatRange(from=0) float, int); - field @FlaggedApi("android.content.pm.archiving") public boolean isArchived; } public abstract class PackageManager { @@ -3987,7 +3966,6 @@ package android.content.pm { method @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS) public abstract void grantRuntimePermission(@NonNull String, @NonNull String, @NonNull android.os.UserHandle); method @Deprecated public abstract int installExistingPackage(@NonNull String) throws android.content.pm.PackageManager.NameNotFoundException; method @Deprecated public abstract int installExistingPackage(@NonNull String, int) throws android.content.pm.PackageManager.NameNotFoundException; - method @FlaggedApi("android.content.pm.archiving") public boolean isAppArchivable(@NonNull String) throws android.content.pm.PackageManager.NameNotFoundException; method @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceiversAsUser(@NonNull android.content.Intent, int, android.os.UserHandle); method @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceiversAsUser(@NonNull android.content.Intent, @NonNull android.content.pm.PackageManager.ResolveInfoFlags, @NonNull android.os.UserHandle); method @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public java.util.List<android.content.pm.ResolveInfo> queryIntentActivitiesAsUser(@NonNull android.content.Intent, int, @NonNull android.os.UserHandle); @@ -4105,7 +4083,6 @@ package android.content.pm { field @Deprecated public static final int INTENT_FILTER_VERIFICATION_SUCCESS = 1; // 0x1 field @Deprecated public static final int MASK_PERMISSION_FLAGS = 255; // 0xff field public static final int MATCH_ANY_USER = 4194304; // 0x400000 - field @FlaggedApi("android.content.pm.archiving") public static final long MATCH_ARCHIVED_PACKAGES = 4294967296L; // 0x100000000L field public static final int MATCH_CLONE_PROFILE = 536870912; // 0x20000000 field public static final int MATCH_FACTORY_ONLY = 2097152; // 0x200000 field public static final int MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS = 536870912; // 0x20000000 @@ -12214,6 +12191,7 @@ package android.service.notification { method public boolean hasExpanded(); method public boolean hasInteracted(); method public boolean hasSeen(); + method @FlaggedApi("android.app.lifetime_extension_refactor") public boolean hasSmartReplied(); method public boolean hasSnoozed(); method public boolean hasViewedSettings(); method public void setDirectReplied(); @@ -12221,6 +12199,7 @@ package android.service.notification { method public void setDismissalSurface(int); method public void setExpanded(); method public void setSeen(); + method @FlaggedApi("android.app.lifetime_extension_refactor") public void setSmartReplied(); method public void setSnoozed(); method public void setViewedSettings(); method public void writeToParcel(android.os.Parcel, int); diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 337e3f1195be..8c5773a05764 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -745,6 +745,16 @@ public class Notification implements Parcelable @TestApi public static final int FLAG_USER_INITIATED_JOB = 0x00008000; + /** + * Bit to be bitwise-ored into the {@link #flags} field that should be + * set if this notification has been lifetime extended due to a direct reply. + * + * This flag is for internal use only; applications cannot set this flag directly. + * @hide + */ + @FlaggedApi(Flags.FLAG_LIFETIME_EXTENSION_REFACTOR) + public static final int FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY = 0x00010000; + private static final List<Class<? extends Style>> PLATFORM_STYLE_CLASSES = Arrays.asList( BigTextStyle.class, BigPictureStyle.class, InboxStyle.class, MediaStyle.class, DecoratedCustomViewStyle.class, DecoratedMediaCustomViewStyle.class, diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index 79a5879b5cc0..9cf732abb86a 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -137,6 +137,8 @@ import android.media.projection.MediaProjectionManager; import android.media.soundtrigger.SoundTriggerManager; import android.media.tv.ITvInputManager; import android.media.tv.TvInputManager; +import android.media.tv.ad.ITvAdManager; +import android.media.tv.ad.TvAdManager; import android.media.tv.interactive.ITvInteractiveAppManager; import android.media.tv.interactive.TvInteractiveAppManager; import android.media.tv.tunerresourcemanager.ITunerResourceManager; @@ -174,6 +176,7 @@ import android.os.IHardwarePropertiesManager; import android.os.IPowerManager; import android.os.IPowerStatsService; import android.os.IRecoverySystem; +import android.os.ISecurityStateManager; import android.os.ISystemUpdateManager; import android.os.IThermalService; import android.os.IUserManager; @@ -182,6 +185,7 @@ import android.os.PerformanceHintManager; import android.os.PermissionEnforcer; import android.os.PowerManager; import android.os.RecoverySystem; +import android.os.SecurityStateManager; import android.os.ServiceManager; import android.os.ServiceManager.ServiceNotFoundException; import android.os.StatsFrameworkInitializer; @@ -628,6 +632,17 @@ public final class SystemServiceRegistry { ctx.mMainThread.getHandler()); }}); + registerService(Context.SECURITY_STATE_SERVICE, SecurityStateManager.class, + new CachedServiceFetcher<SecurityStateManager>() { + @Override + public SecurityStateManager createService(ContextImpl ctx) + throws ServiceNotFoundException { + IBinder b = ServiceManager.getServiceOrThrow( + Context.SECURITY_STATE_SERVICE); + ISecurityStateManager service = ISecurityStateManager.Stub.asInterface(b); + return new SecurityStateManager(service); + }}); + registerService(Context.SENSOR_SERVICE, SensorManager.class, new CachedServiceFetcher<SensorManager>() { @Override @@ -960,6 +975,18 @@ public final class SystemServiceRegistry { return new TvInteractiveAppManager(service, ctx.getUserId()); }}); + registerService(Context.TV_AD_SERVICE, TvAdManager.class, + new CachedServiceFetcher<TvAdManager>() { + @Override + public TvAdManager createService(ContextImpl ctx) + throws ServiceNotFoundException { + IBinder iBinder = + ServiceManager.getServiceOrThrow(Context.TV_AD_SERVICE); + ITvAdManager service = + ITvAdManager.Stub.asInterface(iBinder); + return new TvAdManager(service, ctx.getUserId()); + }}); + registerService(Context.TV_INPUT_SERVICE, TvInputManager.class, new CachedServiceFetcher<TvInputManager>() { @Override diff --git a/core/java/android/app/slice/Slice.java b/core/java/android/app/slice/Slice.java index 823fdd26db1e..475ee7a1ce3d 100644 --- a/core/java/android/app/slice/Slice.java +++ b/core/java/android/app/slice/Slice.java @@ -195,13 +195,6 @@ public final class Slice implements Parcelable { */ public static final String EXTRA_TOGGLE_STATE = "android.app.slice.extra.TOGGLE_STATE"; /** - * Key to retrieve an extra added to an intent when the value of a slider is changed. - * @deprecated remove once support lib is update to use EXTRA_RANGE_VALUE instead - * @removed - */ - @Deprecated - public static final String EXTRA_SLIDER_VALUE = "android.app.slice.extra.SLIDER_VALUE"; - /** * Key to retrieve an extra added to an intent when the value of an input range is changed. */ public static final String EXTRA_RANGE_VALUE = "android.app.slice.extra.RANGE_VALUE"; @@ -223,13 +216,6 @@ public final class Slice implements Parcelable { */ public static final String SUBTYPE_COLOR = "color"; /** - * Subtype to tag an item as representing a slider. - * @deprecated remove once support lib is update to use SUBTYPE_RANGE instead - * @removed - */ - @Deprecated - public static final String SUBTYPE_SLIDER = "slider"; - /** * Subtype to tag an item as representing a range. * Expected to be on an item of format {@link SliceItem#FORMAT_SLICE} containing * a {@link #SUBTYPE_VALUE} and possibly a {@link #SUBTYPE_MAX}. @@ -361,15 +347,6 @@ public final class Slice implements Parcelable { private SliceSpec mSpec; /** - * @deprecated TO BE REMOVED - * @removed - */ - @Deprecated - public Builder(@NonNull Uri uri) { - mUri = uri; - } - - /** * Create a builder which will construct a {@link Slice} for the given Uri. * @param uri Uri to tag for this slice. * @param spec the spec for this slice. @@ -413,15 +390,6 @@ public final class Slice implements Parcelable { } /** - * @deprecated TO BE REMOVED - * @removed - */ - public Builder setSpec(SliceSpec spec) { - mSpec = spec; - return this; - } - - /** * Add a sub-slice to the slice being constructed * @param subType Optional template-specific type information * @see SliceItem#getSubType() @@ -498,16 +466,6 @@ public final class Slice implements Parcelable { } /** - * @deprecated TO BE REMOVED. - * @removed - */ - @Deprecated - public Slice.Builder addTimestamp(long time, @Nullable @SliceSubtype String subType, - @SliceHint List<String> hints) { - return addLong(time, subType, hints); - } - - /** * Add a long to the slice being constructed * @param subType Optional template-specific type information * @see SliceItem#getSubType() diff --git a/core/java/android/app/slice/SliceItem.java b/core/java/android/app/slice/SliceItem.java index ed32a1b7be2c..2d6f4a6fd227 100644 --- a/core/java/android/app/slice/SliceItem.java +++ b/core/java/android/app/slice/SliceItem.java @@ -102,12 +102,6 @@ public final class SliceItem implements Parcelable { */ public static final String FORMAT_LONG = "long"; /** - * @deprecated TO BE REMOVED - * @removed - */ - @Deprecated - public static final String FORMAT_TIMESTAMP = FORMAT_LONG; - /** * A {@link SliceItem} that contains a {@link RemoteInput}. */ public static final String FORMAT_REMOTE_INPUT = "input"; @@ -257,15 +251,6 @@ public final class SliceItem implements Parcelable { } /** - * @deprecated replaced by {@link #getLong()} - * @removed - */ - @Deprecated - public long getTimestamp() { - return (Long) mObj; - } - - /** * @param hint The hint to check for * @return true if this item contains the given hint */ @@ -348,7 +333,7 @@ public final class SliceItem implements Parcelable { case FORMAT_INT: dest.writeInt((Integer) obj); break; - case FORMAT_TIMESTAMP: + case FORMAT_LONG: dest.writeLong((Long) obj); break; } @@ -368,7 +353,7 @@ public final class SliceItem implements Parcelable { Slice.CREATOR.createFromParcel(in)); case FORMAT_INT: return in.readInt(); - case FORMAT_TIMESTAMP: + case FORMAT_LONG: return in.readLong(); case FORMAT_REMOTE_INPUT: return RemoteInput.CREATOR.createFromParcel(in); diff --git a/core/java/android/app/slice/SliceManager.java b/core/java/android/app/slice/SliceManager.java index 1e4934ebb6f5..2e179d063b76 100644 --- a/core/java/android/app/slice/SliceManager.java +++ b/core/java/android/app/slice/SliceManager.java @@ -141,15 +141,6 @@ public class SliceManager { } /** - * @deprecated TO BE REMOVED - * @removed - */ - @Deprecated - public void pinSlice(@NonNull Uri uri, @NonNull List<SliceSpec> specs) { - pinSlice(uri, new ArraySet<>(specs)); - } - - /** * Remove a pin for a slice. * <p> * If the slice has no other pins/callbacks then the slice will be unpinned. @@ -273,15 +264,6 @@ public class SliceManager { } /** - * @deprecated TO BE REMOVED - * @removed - */ - @Deprecated - public @Nullable Slice bindSlice(@NonNull Uri uri, @NonNull List<SliceSpec> supportedSpecs) { - return bindSlice(uri, new ArraySet<>(supportedSpecs)); - } - - /** * Turns a slice intent into a slice uri. Expects an explicit intent. * <p> * This goes through a several stage resolution process to determine if any slice @@ -412,17 +394,6 @@ public class SliceManager { } /** - * @deprecated TO BE REMOVED. - * @removed - */ - @Deprecated - @Nullable - public Slice bindSlice(@NonNull Intent intent, - @NonNull List<SliceSpec> supportedSpecs) { - return bindSlice(intent, new ArraySet<>(supportedSpecs)); - } - - /** * Determine whether a particular process and user ID has been granted * permission to access a specific slice URI. * diff --git a/core/java/android/app/slice/SliceProvider.java b/core/java/android/app/slice/SliceProvider.java index 63835cb5446b..42c3aa6aa0ea 100644 --- a/core/java/android/app/slice/SliceProvider.java +++ b/core/java/android/app/slice/SliceProvider.java @@ -209,15 +209,6 @@ public abstract class SliceProvider extends ContentProvider { * @see Slice#HINT_PARTIAL */ public Slice onBindSlice(Uri sliceUri, Set<SliceSpec> supportedSpecs) { - return onBindSlice(sliceUri, new ArrayList<>(supportedSpecs)); - } - - /** - * @deprecated TO BE REMOVED - * @removed - */ - @Deprecated - public Slice onBindSlice(Uri sliceUri, List<SliceSpec> supportedSpecs) { return null; } @@ -479,7 +470,7 @@ public abstract class SliceProvider extends ContentProvider { } finally { Handler.getMain().removeCallbacks(mAnr); } - Slice.Builder parent = new Slice.Builder(sliceUri); + Slice.Builder parent = new Slice.Builder(sliceUri, null); Slice.Builder childAction = new Slice.Builder(parent) .addIcon(Icon.createWithResource(context, com.android.internal.R.drawable.ic_permission), null, @@ -492,7 +483,8 @@ public abstract class SliceProvider extends ContentProvider { .getTheme().resolveAttribute(android.R.attr.colorAccent, tv, true); int deviceDefaultAccent = tv.data; - parent.addSubSlice(new Slice.Builder(sliceUri.buildUpon().appendPath("permission").build()) + Uri subSliceUri = sliceUri.buildUpon().appendPath("permission").build(); + Slice.Builder subSlice = new Slice.Builder(subSliceUri, null) .addIcon(Icon.createWithResource(context, com.android.internal.R.drawable.ic_arrow_forward), null, Collections.emptyList()) @@ -500,8 +492,8 @@ public abstract class SliceProvider extends ContentProvider { Collections.emptyList()) .addInt(deviceDefaultAccent, SUBTYPE_COLOR, Collections.emptyList()) - .addSubSlice(childAction.build(), null) - .build(), null); + .addSubSlice(childAction.build(), null); + parent.addSubSlice(subSlice.build(), null); return parent.addHints(Arrays.asList(Slice.HINT_PERMISSION_REQUEST)).build(); } diff --git a/core/java/android/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java index 0ae00cd7d133..9eb73b32a2a7 100644 --- a/core/java/android/app/usage/UsageEvents.java +++ b/core/java/android/app/usage/UsageEvents.java @@ -837,6 +837,7 @@ public final class UsageEvents implements Parcelable { if (mEventCount != mEventsToWrite.size()) { Log.w(TAG, "Partial usage event list received: " + mEventCount + " != " + mEventsToWrite.size()); + mEventCount = mEventsToWrite.size(); } } diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java index 51a7f1ce8c5f..6e451479c5a4 100644 --- a/core/java/android/appwidget/AppWidgetManager.java +++ b/core/java/android/appwidget/AppWidgetManager.java @@ -558,7 +558,7 @@ public class AppWidgetManager { } }).toArray(ComponentName[]::new)); } catch (Exception e) { - Log.e(TAG, "Nofity service of inheritance info", e); + Log.e(TAG, "Notify service of inheritance info", e); } }); } diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 1c6c7b5baa58..b75c64dcc3c1 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -72,6 +72,7 @@ import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Environment; +import android.os.Flags; import android.os.Handler; import android.os.HandlerExecutor; import android.os.IBinder; @@ -4214,6 +4215,7 @@ public abstract class Context { DEVICE_LOCK_SERVICE, VIRTUALIZATION_SERVICE, GRAMMATICAL_INFLECTION_SERVICE, + SECURITY_STATE_SERVICE, }) @Retention(RetentionPolicy.SOURCE) @@ -5818,6 +5820,17 @@ public abstract class Context { /** * Use with {@link #getSystemService(String)} to retrieve a + * {@link android.media.tv.ad.TvAdManager} for interacting with TV client-side advertisement + * services on the device. + * + * @see #getSystemService(String) + * @see android.media.tv.ad.TvAdManager + */ + @FlaggedApi(android.media.tv.flags.Flags.FLAG_ENABLE_AD_SERVICE_FW) + public static final String TV_AD_SERVICE = "tv_ad"; + + /** + * Use with {@link #getSystemService(String)} to retrieve a * {@link android.media.tv.TunerResourceManager} for interacting with TV * tuner resources on the device. * @@ -6478,6 +6491,16 @@ public abstract class Context { public static final String SHARED_CONNECTIVITY_SERVICE = "shared_connectivity"; /** + * Use with {@link #getSystemService(String)} to retrieve a + * {@link android.os.SecurityStateManager} for accessing the security state manager service. + * + * @see #getSystemService(String) + * @see android.os.SecurityStateManager + */ + @FlaggedApi(Flags.FLAG_SECURITY_STATE_SERVICE) + public static final String SECURITY_STATE_SERVICE = "security_state"; + + /** * Determine whether the given permission is allowed for a particular * process and user ID running in the system. * diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index c7a86fbe0171..38bcfa220af4 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -5353,11 +5353,11 @@ public class Intent implements Parcelable, Cloneable { * Broadcast Action: Sent to the responsible installer of an archived package when unarchival * is requested. * - * @see android.content.pm.PackageInstaller#requestUnarchive(String) - * @hide + * @see android.content.pm.PackageInstaller#requestUnarchive */ - @SystemApi @FlaggedApi(android.content.pm.Flags.FLAG_ARCHIVING) + @BroadcastBehavior(explicitOnly = true) + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_UNARCHIVE_PACKAGE = "android.intent.action.UNARCHIVE_PACKAGE"; // --------------------------------------------------------------------- diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java index 1cfdb8b37fcd..5736a6d8cb4a 100644 --- a/core/java/android/content/pm/PackageInfo.java +++ b/core/java/android/content/pm/PackageInfo.java @@ -20,7 +20,6 @@ import android.annotation.CurrentTimeMillisLong; import android.annotation.FlaggedApi; import android.annotation.NonNull; import android.annotation.Nullable; -import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; import android.os.Build; import android.os.Parcel; @@ -522,9 +521,7 @@ public class PackageInfo implements Parcelable { /** * Returns the time at which the app was archived for the user. Units are as * per {@link System#currentTimeMillis()}. - * @hide */ - @SystemApi @FlaggedApi(Flags.FLAG_ARCHIVING) public @CurrentTimeMillisLong long getArchiveTimeMillis() { return mArchiveTimeMillis; diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java index 6df1f600c3ef..d35c3922e9b7 100644 --- a/core/java/android/content/pm/PackageInstaller.java +++ b/core/java/android/content/pm/PackageInstaller.java @@ -354,10 +354,7 @@ public class PackageInstaller { /** * Extra field for the package name of a package that is requested to be unarchived. Sent as * part of the {@link android.content.Intent#ACTION_UNARCHIVE_PACKAGE} intent. - * - * @hide */ - @SystemApi @FlaggedApi(Flags.FLAG_ARCHIVING) public static final String EXTRA_UNARCHIVE_PACKAGE_NAME = "android.content.pm.extra.UNARCHIVE_PACKAGE_NAME"; @@ -366,22 +363,16 @@ public class PackageInstaller { * Extra field for the unarchive ID. Sent as * part of the {@link android.content.Intent#ACTION_UNARCHIVE_PACKAGE} intent. * - * @see Session#setUnarchiveId(int) - * - * @hide + * @see SessionParams#setUnarchiveId */ - @SystemApi @FlaggedApi(Flags.FLAG_ARCHIVING) public static final String EXTRA_UNARCHIVE_ID = "android.content.pm.extra.UNARCHIVE_ID"; /** * If true, the requestor of the unarchival has specified that the app should be unarchived - * for {@link android.os.UserHandle#ALL}. - * - * @hide + * for all users. */ - @SystemApi @FlaggedApi(Flags.FLAG_ARCHIVING) public static final String EXTRA_UNARCHIVE_ALL_USERS = "android.content.pm.extra.UNARCHIVE_ALL_USERS"; @@ -398,9 +389,7 @@ public class PackageInstaller { * failure dialog. * * @see #requestUnarchive - * @hide */ - @SystemApi @FlaggedApi(Flags.FLAG_ARCHIVING) public static final String EXTRA_UNARCHIVE_STATUS = "android.content.pm.extra.UNARCHIVE_STATUS"; @@ -675,10 +664,7 @@ public class PackageInstaller { * * <p> Note that this does not mean that the unarchival has completed. This status should be * sent before any longer asynchronous action (e.g. app download) is started. - * - * @hide */ - @SystemApi @FlaggedApi(Flags.FLAG_ARCHIVING) public static final int UNARCHIVAL_OK = 0; @@ -687,10 +673,7 @@ public class PackageInstaller { * * <p> An example use case for this could be that the user needs to login to allow the * download for a paid app. - * - * @hide */ - @SystemApi @FlaggedApi(Flags.FLAG_ARCHIVING) public static final int UNARCHIVAL_ERROR_USER_ACTION_NEEDED = 1; @@ -700,19 +683,13 @@ public class PackageInstaller { * <p> The installer can optionally provide a {@code userActionIntent} for a space-clearing * dialog. If no action is provided, then a generic intent * {@link android.os.storage.StorageManager#ACTION_MANAGE_STORAGE} is started instead. - * - * @hide */ - @SystemApi @FlaggedApi(Flags.FLAG_ARCHIVING) public static final int UNARCHIVAL_ERROR_INSUFFICIENT_STORAGE = 2; /** * The device is not connected to the internet - * - * @hide */ - @SystemApi @FlaggedApi(Flags.FLAG_ARCHIVING) public static final int UNARCHIVAL_ERROR_NO_CONNECTIVITY = 3; @@ -720,10 +697,7 @@ public class PackageInstaller { * The installer responsible for the unarchival is disabled. * * <p> Should only be used by the system. - * - * @hide */ - @SystemApi @FlaggedApi(Flags.FLAG_ARCHIVING) public static final int UNARCHIVAL_ERROR_INSTALLER_DISABLED = 4; @@ -731,19 +705,13 @@ public class PackageInstaller { * The installer responsible for the unarchival has been uninstalled * * <p> Should only be used by the system. - * - * @hide */ - @SystemApi @FlaggedApi(Flags.FLAG_ARCHIVING) public static final int UNARCHIVAL_ERROR_INSTALLER_UNINSTALLED = 5; /** * Generic error: The app cannot be unarchived. - * - * @hide */ - @SystemApi @FlaggedApi(Flags.FLAG_ARCHIVING) public static final int UNARCHIVAL_GENERIC_ERROR = 100; @@ -2364,12 +2332,10 @@ public class PackageInstaller { * @param statusReceiver Callback used to notify when the operation is completed. * @throws PackageManager.NameNotFoundException If {@code packageName} isn't found or not * available to the caller or isn't archived. - * @hide */ @RequiresPermission(anyOf = { Manifest.permission.DELETE_PACKAGES, Manifest.permission.REQUEST_DELETE_PACKAGES}) - @SystemApi @FlaggedApi(Flags.FLAG_ARCHIVING) public void requestArchive(@NonNull String packageName, @NonNull IntentSender statusReceiver) throws PackageManager.NameNotFoundException { @@ -2395,19 +2361,16 @@ public class PackageInstaller { * * @param statusReceiver Callback used to notify whether the installer has accepted the * unarchival request or an error has occurred. The status update will be - * sent though {@link EXTRA_UNARCHIVE_STATUS}. Only one status will be + * sent though {@link #EXTRA_UNARCHIVE_STATUS}. Only one status will be * sent. * @throws PackageManager.NameNotFoundException If {@code packageName} isn't found or not * visible to the caller or if the package has no * installer on the device anymore to unarchive it. * @throws IOException If parameters were unsatisfiable, such as lack of disk space. - * - * @hide */ @RequiresPermission(anyOf = { Manifest.permission.INSTALL_PACKAGES, Manifest.permission.REQUEST_INSTALL_PACKAGES}) - @SystemApi @FlaggedApi(Flags.FLAG_ARCHIVING) public void requestUnarchive(@NonNull String packageName, @NonNull IntentSender statusReceiver) throws IOException, PackageManager.NameNotFoundException { @@ -2435,12 +2398,10 @@ public class PackageInstaller { * @param userActionIntent Optional intent to start a follow up action required to * facilitate the unarchival flow (e.g. user needs to log in). * @throws PackageManager.NameNotFoundException if no unarchival with {@code unarchiveId} exists - * @hide */ @RequiresPermission(anyOf = { Manifest.permission.INSTALL_PACKAGES, Manifest.permission.REQUEST_INSTALL_PACKAGES}) - @SystemApi @FlaggedApi(Flags.FLAG_ARCHIVING) public void reportUnarchivalStatus(int unarchiveId, @UnarchivalStatus int status, long requiredStorageBytes, @Nullable PendingIntent userActionIntent) @@ -3454,11 +3415,8 @@ public class PackageInstaller { * <p> The ID should be retrieved from the unarchive intent and passed into the * session that's being created to unarchive the app in question. Used to link the unarchive * intent and the install session to disambiguate. - * - * @hide */ @FlaggedApi(Flags.FLAG_ARCHIVING) - @SystemApi public void setUnarchiveId(int unarchiveId) { this.unarchiveId = unarchiveId; } diff --git a/core/java/android/content/pm/PackageItemInfo.java b/core/java/android/content/pm/PackageItemInfo.java index c7091ad99199..70e6f9864eb6 100644 --- a/core/java/android/content/pm/PackageItemInfo.java +++ b/core/java/android/content/pm/PackageItemInfo.java @@ -177,12 +177,10 @@ public class PackageItemInfo { /** * Whether the package is currently in an archived state. * - * <p>Packages can be archived through {@link PackageArchiver} and do not have any APKs stored - * on the device, but do keep the data directory. - * @hide + * <p>Packages can be archived through {@link PackageInstaller#requestArchive} and do not have + * any APKs stored on the device, but do keep the data directory. + * */ - // TODO(b/278553670) Unhide and update @links before launch. - @SystemApi @FlaggedApi(Flags.FLAG_ARCHIVING) public boolean isArchived; diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 6775f9b8d84d..a22fe3f1452b 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -1263,18 +1263,14 @@ public abstract class PackageManager { /** * Flag parameter to also retrieve some information about archived packages. - * Packages can be archived through - * {@link PackageInstaller#requestArchive(String, IntentSender)} and do not have any APKs stored - * on the device, but do keep the data directory. + * Packages can be archived through {@link PackageInstaller#requestArchive} and do not have any + * APKs stored on the device, but do keep the data directory. * <p> Note: Archived apps are a subset of apps returned by {@link #MATCH_UNINSTALLED_PACKAGES}. * <p> Note: this flag may cause less information about currently installed * applications to be returned. * <p> Note: use of this flag requires the android.permission.QUERY_ALL_PACKAGES * permission to see uninstalled packages. - * @hide */ - // TODO(b/278553670) Unhide and update @links before launch. - @SystemApi @FlaggedApi(android.content.pm.Flags.FLAG_ARCHIVING) public static final long MATCH_ARCHIVED_PACKAGES = 1L << 32; @@ -8969,10 +8965,7 @@ public abstract class PackageManager { * * @throws NameNotFoundException if the given package name is not available to the caller. * @see PackageInstaller#requestArchive(String, IntentSender) - * - * @hide */ - @SystemApi @FlaggedApi(android.content.pm.Flags.FLAG_ARCHIVING) public boolean isAppArchivable(@NonNull String packageName) throws NameNotFoundException { throw new UnsupportedOperationException("isAppArchivable not implemented"); diff --git a/core/java/android/content/pm/flags.aconfig b/core/java/android/content/pm/flags.aconfig index a565f6825e7a..d21b81854584 100644 --- a/core/java/android/content/pm/flags.aconfig +++ b/core/java/android/content/pm/flags.aconfig @@ -94,3 +94,10 @@ flag { description: "Feature flag to read install related information from an APK." bug: "275658500" } + +flag { + name: "use_pia_v2" + namespace: "package_manager_service" + description: "Feature flag to enable the refactored Package Installer app with updated UI." + bug: "182205982" +} diff --git a/core/java/android/content/res/flags.aconfig b/core/java/android/content/res/flags.aconfig index 1b8eb0748737..40592a151fa7 100644 --- a/core/java/android/content/res/flags.aconfig +++ b/core/java/android/content/res/flags.aconfig @@ -15,3 +15,12 @@ flag { description: "Feature flag for passing in an AssetFileDescriptor to create an frro" bug: "304478666" } + +flag { + name: "manifest_flagging" + namespace: "resource_manager" + description: "Feature flag for flagging manifest entries" + bug: "297373084" + # This flag is read in PackageParser at boot time, and in aapt2 which is a build tool. + is_fixed_read_only: true +} diff --git a/core/java/android/hardware/SensorPrivacyManager.java b/core/java/android/hardware/SensorPrivacyManager.java index d786d9a20189..18c95bfbb297 100644 --- a/core/java/android/hardware/SensorPrivacyManager.java +++ b/core/java/android/hardware/SensorPrivacyManager.java @@ -66,6 +66,13 @@ public final class SensorPrivacyManager { + ".extra.sensor"; /** + * An extra containing the notification id that triggered the intent + * @hide + */ + public static final String EXTRA_NOTIFICATION_ID = SensorPrivacyManager.class.getName() + + ".extra.notification_id"; + + /** * An extra indicating if all sensors are affected * @hide */ diff --git a/core/java/android/os/BatteryUsageStats.java b/core/java/android/os/BatteryUsageStats.java index ed3100251040..eabe13b0c54f 100644 --- a/core/java/android/os/BatteryUsageStats.java +++ b/core/java/android/os/BatteryUsageStats.java @@ -123,6 +123,12 @@ public final class BatteryUsageStats implements Parcelable, Closeable { private static final int STATSD_PULL_ATOM_MAX_BYTES = 45000; + private static final int[] UID_USAGE_TIME_PROCESS_STATES = { + BatteryConsumer.PROCESS_STATE_FOREGROUND, + BatteryConsumer.PROCESS_STATE_BACKGROUND, + BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE + }; + private final int mDischargePercentage; private final double mBatteryCapacityMah; private final long mStatsStartTimestampMs; @@ -516,6 +522,22 @@ public final class BatteryUsageStats implements Parcelable, Closeable { proto.write( BatteryUsageStatsAtomsProto.UidBatteryConsumer.TIME_IN_BACKGROUND_MILLIS, bgMs); + for (int processState : UID_USAGE_TIME_PROCESS_STATES) { + final long timeInStateMillis = consumer.getTimeInProcessStateMs(processState); + if (timeInStateMillis <= 0) { + continue; + } + final long timeInStateToken = proto.start( + BatteryUsageStatsAtomsProto.UidBatteryConsumer.TIME_IN_STATE); + proto.write( + BatteryUsageStatsAtomsProto.UidBatteryConsumer.TimeInState.PROCESS_STATE, + processState); + proto.write( + BatteryUsageStatsAtomsProto.UidBatteryConsumer.TimeInState + .TIME_IN_STATE_MILLIS, + timeInStateMillis); + proto.end(timeInStateToken); + } proto.end(token); if (proto.getRawSize() >= maxRawSize) { diff --git a/core/java/android/os/ISecurityStateManager.aidl b/core/java/android/os/ISecurityStateManager.aidl new file mode 100644 index 000000000000..8ae624d0371d --- /dev/null +++ b/core/java/android/os/ISecurityStateManager.aidl @@ -0,0 +1,26 @@ +/* //device/java/android/android/os/ISecurityStateManager.aidl +** +** Copyright 2023, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +package android.os; + +import android.os.Bundle; +import android.os.PersistableBundle; + +/** @hide */ +interface ISecurityStateManager { + Bundle getGlobalSecurityState(); +} diff --git a/core/java/android/os/SecurityStateManager.java b/core/java/android/os/SecurityStateManager.java new file mode 100644 index 000000000000..4fa61e0ca782 --- /dev/null +++ b/core/java/android/os/SecurityStateManager.java @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.os; + +import static java.util.Objects.requireNonNull; + +import android.annotation.FlaggedApi; +import android.annotation.NonNull; +import android.annotation.SystemService; +import android.content.Context; + +/** + * SecurityStateManager provides the functionality to query the security status of the system and + * platform components. For example, this includes the system and vendor security patch level. + */ +@FlaggedApi(Flags.FLAG_SECURITY_STATE_SERVICE) +@SystemService(Context.SECURITY_STATE_SERVICE) +public class SecurityStateManager { + + /** + * The system SPL key returned as part of the {@code Bundle} from + * {@code getGlobalSecurityState}. + */ + public static final String KEY_SYSTEM_SPL = "system_spl"; + + /** + * The vendor SPL key returned as part of the {@code Bundle} from + * {@code getGlobalSecurityState}. + */ + public static final String KEY_VENDOR_SPL = "vendor_spl"; + + /** + * The kernel version key returned as part of the {@code Bundle} from + * {@code getGlobalSecurityState}. + */ + public static final String KEY_KERNEL_VERSION = "kernel_version"; + + private final ISecurityStateManager mService; + + /** + * @hide + */ + public SecurityStateManager(ISecurityStateManager service) { + mService = requireNonNull(service, "missing ISecurityStateManager"); + } + + /** + * Returns the current global security state. Each key-value pair is a mapping of a component + * of the global security state to its current version/SPL (security patch level). For example, + * the {@code KEY_SYSTEM_SPL} key will map to the SPL of the system as defined in + * {@link android.os.Build.VERSION}. The bundle will also include mappings from WebView packages + * and packages listed under config {@code config_securityStatePackages} to their respective + * versions as defined in {@link android.content.pm.PackageInfo#versionName}. + * + * @return A {@code Bundle} that contains the global security state information as + * string-to-string key-value pairs. + */ + @FlaggedApi(Flags.FLAG_SECURITY_STATE_SERVICE) + @NonNull + public Bundle getGlobalSecurityState() { + try { + return mService.getGlobalSecurityState(); + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); + } + } +} diff --git a/core/java/android/os/flags.aconfig b/core/java/android/os/flags.aconfig index a78f221fc962..c085f334457a 100644 --- a/core/java/android/os/flags.aconfig +++ b/core/java/android/os/flags.aconfig @@ -57,6 +57,13 @@ flag { } flag { + name: "security_state_service" + namespace: "dynamic_spl" + description: "Guards the Security State API." + bug: "302189431" +} + +flag { name: "battery_saver_supported_check_api" namespace: "backstage_power" description: "Guards a new API in PowerManager to check if battery saver is supported or not." diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java index 6853892348d9..78a12f75a508 100644 --- a/core/java/android/os/storage/StorageManager.java +++ b/core/java/android/os/storage/StorageManager.java @@ -1738,23 +1738,6 @@ public class StorageManager { return RoSystemProperties.CRYPTO_FILE_ENCRYPTED; } - /** {@hide} - * @deprecated Use {@link #isFileEncrypted} instead, since emulated FBE is no longer supported. - */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - @Deprecated - public static boolean isFileEncryptedNativeOnly() { - return isFileEncrypted(); - } - - /** {@hide} - * @deprecated Use {@link #isFileEncrypted} instead, since emulated FBE is no longer supported. - */ - @Deprecated - public static boolean isFileEncryptedNativeOrEmulated() { - return isFileEncrypted(); - } - /** {@hide} */ public static boolean hasAdoptable() { switch (SystemProperties.get(PROP_ADOPTABLE)) { diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 8f18c5f58c7e..1a33b768a039 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -2542,6 +2542,7 @@ public final class Settings { * ComponentName)} and only use this action to start an activity if they return {@code false}. */ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + @FlaggedApi(android.credentials.flags.Flags.FLAG_NEW_SETTINGS_INTENTS) public static final String ACTION_CREDENTIAL_PROVIDER = "android.settings.CREDENTIAL_PROVIDER"; @@ -8845,6 +8846,24 @@ public final class Settings { "reduce_bright_colors_persist_across_reboots"; /** + * Setting that specifies whether Even Dimmer - a feature that allows the brightness + * slider to go below what the display can conventionally do, should be enabled. + * + * @hide + */ + public static final String EVEN_DIMMER_ACTIVATED = + "even_dimmer_activated"; + + /** + * Setting that specifies which nits level Even Dimmer should allow the screen brightness + * to go down to. + * + * @hide + */ + public static final String EVEN_DIMMER_MIN_NITS = + "even_dimmer_min_nits"; + + /** * List of the enabled print services. * * N and beyond uses {@link #DISABLED_PRINT_SERVICES}. But this might be used in an upgrade diff --git a/core/java/android/security/OWNERS b/core/java/android/security/OWNERS index 33a67aed6023..533d459e532b 100644 --- a/core/java/android/security/OWNERS +++ b/core/java/android/security/OWNERS @@ -8,4 +8,4 @@ per-file *NetworkSecurityPolicy.java = file:net/OWNERS per-file Confirmation*.java = file:/keystore/OWNERS per-file FileIntegrityManager.java = file:platform/system/security:/fsverity/OWNERS per-file IFileIntegrityService.aidl = file:platform/system/security:/fsverity/OWNERS -per-file *.aconfig = victorhsieh@google.com +per-file *.aconfig = victorhsieh@google.com,eranm@google.com diff --git a/core/java/android/service/notification/NotificationRankingUpdate.java b/core/java/android/service/notification/NotificationRankingUpdate.java index 2a4cbaf79a75..46ea158b8f90 100644 --- a/core/java/android/service/notification/NotificationRankingUpdate.java +++ b/core/java/android/service/notification/NotificationRankingUpdate.java @@ -15,7 +15,6 @@ */ package android.service.notification; -import android.annotation.Nullable; import android.annotation.SuppressLint; import android.app.Notification; import android.os.Bundle; @@ -26,6 +25,7 @@ import android.system.ErrnoException; import android.system.OsConstants; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import java.nio.ByteBuffer; @@ -75,10 +75,6 @@ public class NotificationRankingUpdate implements Parcelable { } // We only need read-only access to the shared memory region. buffer = mRankingMapFd.mapReadOnly(); - if (buffer == null) { - mRankingMap = null; - return; - } byte[] payload = new byte[buffer.remaining()]; buffer.get(payload); mapParcel.unmarshall(payload, 0, payload.length); @@ -98,7 +94,7 @@ public class NotificationRankingUpdate implements Parcelable { } finally { mapParcel.recycle(); if (buffer != null && mRankingMapFd != null) { - mRankingMapFd.unmap(buffer); + SharedMemory.unmap(buffer); mRankingMapFd.close(); } } @@ -210,6 +206,7 @@ public class NotificationRankingUpdate implements Parcelable { new NotificationListenerService.Ranking[0] ) ); + ByteBuffer buffer = null; try { // Parcels the ranking map and measures its size. @@ -217,13 +214,10 @@ public class NotificationRankingUpdate implements Parcelable { int mapSize = mapParcel.dataSize(); // Creates a new SharedMemory object with enough space to hold the ranking map. - SharedMemory mRankingMapFd = SharedMemory.create(mSharedMemoryName, mapSize); - if (mRankingMapFd == null) { - return; - } + mRankingMapFd = SharedMemory.create(mSharedMemoryName, mapSize); // Gets a read/write buffer mapping the entire shared memory region. - final ByteBuffer buffer = mRankingMapFd.mapReadWrite(); + buffer = mRankingMapFd.mapReadWrite(); // Puts the ranking map into the shared memory region buffer. buffer.put(mapParcel.marshall(), 0, mapSize); // Protects the region from being written to, by setting it to be read-only. @@ -238,6 +232,12 @@ public class NotificationRankingUpdate implements Parcelable { throw new RuntimeException(e); } finally { mapParcel.recycle(); + // To prevent memory leaks, we can close the ranking map fd here. + // Because a reference to this still exists + if (buffer != null && mRankingMapFd != null) { + SharedMemory.unmap(buffer); + mRankingMapFd.close(); + } } } else { out.writeParcelable(mRankingMap, flags); @@ -247,7 +247,7 @@ public class NotificationRankingUpdate implements Parcelable { /** * @hide */ - public static final @android.annotation.NonNull Parcelable.Creator<NotificationRankingUpdate> CREATOR + public static final @NonNull Parcelable.Creator<NotificationRankingUpdate> CREATOR = new Parcelable.Creator<NotificationRankingUpdate>() { public NotificationRankingUpdate createFromParcel(Parcel parcel) { return new NotificationRankingUpdate(parcel); diff --git a/core/java/android/service/notification/NotificationStats.java b/core/java/android/service/notification/NotificationStats.java index e5ad85cb526f..07367df7bc91 100644 --- a/core/java/android/service/notification/NotificationStats.java +++ b/core/java/android/service/notification/NotificationStats.java @@ -15,10 +15,12 @@ */ package android.service.notification; +import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; +import android.app.Flags; import android.app.RemoteInput; import android.os.Parcel; import android.os.Parcelable; @@ -36,6 +38,7 @@ public final class NotificationStats implements Parcelable { private boolean mSeen; private boolean mExpanded; private boolean mDirectReplied; + private boolean mSmartReplied; private boolean mSnoozed; private boolean mViewedSettings; private boolean mInteracted; @@ -125,6 +128,9 @@ public final class NotificationStats implements Parcelable { mSeen = in.readByte() != 0; mExpanded = in.readByte() != 0; mDirectReplied = in.readByte() != 0; + if (Flags.lifetimeExtensionRefactor()) { + mSmartReplied = in.readByte() != 0; + } mSnoozed = in.readByte() != 0; mViewedSettings = in.readByte() != 0; mInteracted = in.readByte() != 0; @@ -137,6 +143,9 @@ public final class NotificationStats implements Parcelable { dest.writeByte((byte) (mSeen ? 1 : 0)); dest.writeByte((byte) (mExpanded ? 1 : 0)); dest.writeByte((byte) (mDirectReplied ? 1 : 0)); + if (Flags.lifetimeExtensionRefactor()) { + dest.writeByte((byte) (mSmartReplied ? 1 : 0)); + } dest.writeByte((byte) (mSnoozed ? 1 : 0)); dest.writeByte((byte) (mViewedSettings ? 1 : 0)); dest.writeByte((byte) (mInteracted ? 1 : 0)); @@ -210,6 +219,23 @@ public final class NotificationStats implements Parcelable { } /** + * Returns whether the user has replied to a notification that has a smart reply at least once. + */ + @FlaggedApi(Flags.FLAG_LIFETIME_EXTENSION_REFACTOR) + public boolean hasSmartReplied() { + return mSmartReplied; + } + + /** + * Records that the user has replied to a notification that has a smart reply at least once. + */ + @FlaggedApi(Flags.FLAG_LIFETIME_EXTENSION_REFACTOR) + public void setSmartReplied() { + mSmartReplied = true; + mInteracted = true; + } + + /** * Returns whether the user has snoozed this notification at least once. */ public boolean hasSnoozed() { @@ -286,6 +312,9 @@ public final class NotificationStats implements Parcelable { if (mSeen != that.mSeen) return false; if (mExpanded != that.mExpanded) return false; if (mDirectReplied != that.mDirectReplied) return false; + if (Flags.lifetimeExtensionRefactor()) { + if (mSmartReplied != that.mSmartReplied) return false; + } if (mSnoozed != that.mSnoozed) return false; if (mViewedSettings != that.mViewedSettings) return false; if (mInteracted != that.mInteracted) return false; @@ -297,6 +326,9 @@ public final class NotificationStats implements Parcelable { int result = (mSeen ? 1 : 0); result = 31 * result + (mExpanded ? 1 : 0); result = 31 * result + (mDirectReplied ? 1 : 0); + if (Flags.lifetimeExtensionRefactor()) { + result = 31 * result + (mSmartReplied ? 1 : 0); + } result = 31 * result + (mSnoozed ? 1 : 0); result = 31 * result + (mViewedSettings ? 1 : 0); result = 31 * result + (mInteracted ? 1 : 0); @@ -311,6 +343,9 @@ public final class NotificationStats implements Parcelable { sb.append("mSeen=").append(mSeen); sb.append(", mExpanded=").append(mExpanded); sb.append(", mDirectReplied=").append(mDirectReplied); + if (Flags.lifetimeExtensionRefactor()) { + sb.append(", mSmartReplied=").append(mSmartReplied); + } sb.append(", mSnoozed=").append(mSnoozed); sb.append(", mViewedSettings=").append(mViewedSettings); sb.append(", mInteracted=").append(mInteracted); diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java index 90663c7ad38e..147c15bea076 100644 --- a/core/java/android/view/InsetsController.java +++ b/core/java/android/view/InsetsController.java @@ -216,6 +216,14 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation default CompatibilityInfo.Translator getTranslator() { return null; } + + /** + * Notifies when the state of running animation is changed. The state is either "running" or + * "idle". + * + * @param running {@code true} if there is any animation running; {@code false} otherwise. + */ + default void notifyAnimationRunningStateChanged(boolean running) {} } private static final String TAG = "InsetsController"; @@ -749,6 +757,9 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation final InsetsAnimationControlRunner runner = new InsetsResizeAnimationRunner( mFrame, state1, mToState, RESIZE_INTERPOLATOR, ANIMATION_DURATION_RESIZE, mTypes, InsetsController.this); + if (mRunningAnimations.isEmpty()) { + mHost.notifyAnimationRunningStateChanged(true); + } mRunningAnimations.add(new RunningAnimation(runner, runner.getAnimationType())); } }; @@ -1382,6 +1393,9 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation } } ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_ANIMATION_RUNNING); + if (mRunningAnimations.isEmpty()) { + mHost.notifyAnimationRunningStateChanged(true); + } mRunningAnimations.add(new RunningAnimation(runner, animationType)); if (DEBUG) Log.d(TAG, "Animation added to runner. useInsetsAnimationThread: " + useInsetsAnimationThread); @@ -1588,6 +1602,9 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation break; } } + if (mRunningAnimations.isEmpty()) { + mHost.notifyAnimationRunningStateChanged(false); + } onAnimationStateChanged(removedTypes, false /* running */); } diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index cac5387116a1..ff1e831ea9b8 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -816,6 +816,8 @@ public final class ViewRootImpl implements ViewParent, private long mFpsPrevTime = -1; private int mFpsNumFrames; + private boolean mInsetsAnimationRunning; + /** * The resolved pointer icon type requested by this window. * A null value indicates the resolved pointer icon has not yet been calculated. @@ -2179,6 +2181,10 @@ public final class ViewRootImpl implements ViewParent, } } + void notifyInsetsAnimationRunningStateChanged(boolean running) { + mInsetsAnimationRunning = running; + } + @Override public void requestLayout() { if (!mHandlingLayoutInLayoutRequest) { diff --git a/core/java/android/view/ViewRootInsetsControllerHost.java b/core/java/android/view/ViewRootInsetsControllerHost.java index a2708eead171..40730e8de849 100644 --- a/core/java/android/view/ViewRootInsetsControllerHost.java +++ b/core/java/android/view/ViewRootInsetsControllerHost.java @@ -279,6 +279,13 @@ public class ViewRootInsetsControllerHost implements InsetsController.Host { return null; } + @Override + public void notifyAnimationRunningStateChanged(boolean running) { + if (mViewRoot != null) { + mViewRoot.notifyInsetsAnimationRunningStateChanged(running); + } + } + private boolean isVisibleToUser() { return mViewRoot.getHostVisibility() == View.VISIBLE; } diff --git a/core/java/android/view/accessibility/IWindowMagnificationConnection.aidl b/core/java/android/view/accessibility/IWindowMagnificationConnection.aidl index a11c6d0ce956..a404bd6f8c97 100644 --- a/core/java/android/view/accessibility/IWindowMagnificationConnection.aidl +++ b/core/java/android/view/accessibility/IWindowMagnificationConnection.aidl @@ -54,7 +54,7 @@ oneway interface IWindowMagnificationConnection { * @param displayId the logical display id. * @param scale magnification scale. */ - void setScale(int displayId, float scale); + void setScaleForWindowMagnification(int displayId, float scale); /** * Disables window magnification on specified display with animation. diff --git a/core/java/android/window/ITaskOrganizerController.aidl b/core/java/android/window/ITaskOrganizerController.aidl index e10f7c838c74..478aeece0888 100644 --- a/core/java/android/window/ITaskOrganizerController.aidl +++ b/core/java/android/window/ITaskOrganizerController.aidl @@ -70,20 +70,4 @@ interface ITaskOrganizerController { /** Updates a state of camera compat control for stretched issues in the viewfinder. */ void updateCameraCompatControlState(in WindowContainerToken task, int state); - - /** - * Controls whether ignore orientation request logic in {@link - * com.android.server.wm.DisplayArea} is disabled at runtime and how to optionally map some - * requested orientations to others. - * - * @param isDisabled when {@code true}, the system always ignores the value of {@link - * com.android.server.wm.DisplayArea#getIgnoreOrientationRequest} and app - * requested orientation is respected. - * @param fromOrientations The orientations we want to map to the correspondent orientations - * in toOrientation. - * @param toOrientations The orientations we map to the ones in fromOrientations at the same - * index - */ - void setOrientationRequestPolicy(boolean isIgnoreOrientationRequestDisabled, - in int[] fromOrientations, in int[] toOrientations); } diff --git a/core/java/android/window/TaskFragmentOperation.java b/core/java/android/window/TaskFragmentOperation.java index 4e0f9a51c0a0..0ec9ffe6390b 100644 --- a/core/java/android/window/TaskFragmentOperation.java +++ b/core/java/android/window/TaskFragmentOperation.java @@ -108,6 +108,18 @@ public final class TaskFragmentOperation implements Parcelable { */ public static final int OP_TYPE_REORDER_TO_TOP_OF_TASK = 13; + /** + * Creates a decor surface in the parent Task of the TaskFragment. The created decor surface + * will be provided in {@link TaskFragmentTransaction#TYPE_TASK_FRAGMENT_PARENT_INFO_CHANGED} + * event callback. + */ + public static final int OP_TYPE_CREATE_TASK_FRAGMENT_DECOR_SURFACE = 14; + + /** + * Removes the decor surface in the parent Task of the TaskFragment. + */ + public static final int OP_TYPE_REMOVE_TASK_FRAGMENT_DECOR_SURFACE = 15; + @IntDef(prefix = { "OP_TYPE_" }, value = { OP_TYPE_UNKNOWN, OP_TYPE_CREATE_TASK_FRAGMENT, @@ -124,6 +136,8 @@ public final class TaskFragmentOperation implements Parcelable { OP_TYPE_SET_ISOLATED_NAVIGATION, OP_TYPE_REORDER_TO_BOTTOM_OF_TASK, OP_TYPE_REORDER_TO_TOP_OF_TASK, + OP_TYPE_CREATE_TASK_FRAGMENT_DECOR_SURFACE, + OP_TYPE_REMOVE_TASK_FRAGMENT_DECOR_SURFACE, }) @Retention(RetentionPolicy.SOURCE) public @interface OperationType {} diff --git a/core/java/android/window/TaskFragmentParentInfo.java b/core/java/android/window/TaskFragmentParentInfo.java index e6eeca4b4801..a77c23475c60 100644 --- a/core/java/android/window/TaskFragmentParentInfo.java +++ b/core/java/android/window/TaskFragmentParentInfo.java @@ -22,6 +22,9 @@ import android.app.WindowConfiguration; import android.content.res.Configuration; import android.os.Parcel; import android.os.Parcelable; +import android.view.SurfaceControl; + +import java.util.Objects; /** * The information about the parent Task of a particular TaskFragment @@ -37,12 +40,15 @@ public class TaskFragmentParentInfo implements Parcelable { private final boolean mHasDirectActivity; + @Nullable private final SurfaceControl mDecorSurface; + public TaskFragmentParentInfo(@NonNull Configuration configuration, int displayId, - boolean visible, boolean hasDirectActivity) { + boolean visible, boolean hasDirectActivity, @Nullable SurfaceControl decorSurface) { mConfiguration.setTo(configuration); mDisplayId = displayId; mVisible = visible; mHasDirectActivity = hasDirectActivity; + mDecorSurface = decorSurface; } public TaskFragmentParentInfo(@NonNull TaskFragmentParentInfo info) { @@ -50,6 +56,7 @@ public class TaskFragmentParentInfo implements Parcelable { mDisplayId = info.mDisplayId; mVisible = info.mVisible; mHasDirectActivity = info.mHasDirectActivity; + mDecorSurface = info.mDecorSurface; } /** The {@link Configuration} of the parent Task */ @@ -92,7 +99,13 @@ public class TaskFragmentParentInfo implements Parcelable { return false; } return getWindowingMode() == that.getWindowingMode() && mDisplayId == that.mDisplayId - && mVisible == that.mVisible && mHasDirectActivity == that.mHasDirectActivity; + && mVisible == that.mVisible && mHasDirectActivity == that.mHasDirectActivity + && mDecorSurface == that.mDecorSurface; + } + + @Nullable + public SurfaceControl getDecorSurface() { + return mDecorSurface; } @WindowConfiguration.WindowingMode @@ -107,6 +120,7 @@ public class TaskFragmentParentInfo implements Parcelable { + ", displayId=" + mDisplayId + ", visible=" + mVisible + ", hasDirectActivity=" + mHasDirectActivity + + ", decorSurface=" + mDecorSurface + "}"; } @@ -128,7 +142,8 @@ public class TaskFragmentParentInfo implements Parcelable { return mConfiguration.equals(that.mConfiguration) && mDisplayId == that.mDisplayId && mVisible == that.mVisible - && mHasDirectActivity == that.mHasDirectActivity; + && mHasDirectActivity == that.mHasDirectActivity + && mDecorSurface == that.mDecorSurface; } @Override @@ -137,6 +152,7 @@ public class TaskFragmentParentInfo implements Parcelable { result = 31 * result + mDisplayId; result = 31 * result + (mVisible ? 1 : 0); result = 31 * result + (mHasDirectActivity ? 1 : 0); + result = 31 * result + Objects.hashCode(mDecorSurface); return result; } @@ -146,6 +162,7 @@ public class TaskFragmentParentInfo implements Parcelable { dest.writeInt(mDisplayId); dest.writeBoolean(mVisible); dest.writeBoolean(mHasDirectActivity); + dest.writeTypedObject(mDecorSurface, flags); } private TaskFragmentParentInfo(Parcel in) { @@ -153,6 +170,7 @@ public class TaskFragmentParentInfo implements Parcelable { mDisplayId = in.readInt(); mVisible = in.readBoolean(); mHasDirectActivity = in.readBoolean(); + mDecorSurface = in.readTypedObject(SurfaceControl.CREATOR); } public static final Creator<TaskFragmentParentInfo> CREATOR = diff --git a/core/java/android/window/TaskOrganizer.java b/core/java/android/window/TaskOrganizer.java index cd1275c23ed6..6d36b579dcc2 100644 --- a/core/java/android/window/TaskOrganizer.java +++ b/core/java/android/window/TaskOrganizer.java @@ -266,31 +266,6 @@ public class TaskOrganizer extends WindowOrganizer { } /** - * Controls whether ignore orientation request logic in {@link - * com.android.server.wm.DisplayArea} is disabled at runtime and how to optionally map some - * requested orientation to others. - * - * @param isIgnoreOrientationRequestDisabled when {@code true}, the system always ignores the - * value of {@link com.android.server.wm.DisplayArea#getIgnoreOrientationRequest} - * and app requested orientation is respected. - * @param fromOrientations The orientations we want to map to the correspondent orientations - * in toOrientation. - * @param toOrientations The orientations we map to the ones in fromOrientations at the same - * index - * @hide - */ - @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) - public void setOrientationRequestPolicy(boolean isIgnoreOrientationRequestDisabled, - @Nullable int[] fromOrientations, @Nullable int[] toOrientations) { - try { - mTaskOrganizerController.setOrientationRequestPolicy(isIgnoreOrientationRequestDisabled, - fromOrientations, toOrientations); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** * Gets the executor to run callbacks on. * @hide */ diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto index 4d6ed80aa763..3887dd7a753f 100644 --- a/core/proto/android/providers/settings/secure.proto +++ b/core/proto/android/providers/settings/secure.proto @@ -268,6 +268,13 @@ message SecureSettingsProto { optional SettingProto enhanced_voice_privacy_enabled = 23 [ (android.privacy).dest = DEST_AUTOMATIC ]; + message EvenDimmer { + optional SettingProto even_dimmer_activated = 1 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto even_dimmer_min_nits = 2 [ (android.privacy).dest = DEST_AUTOMATIC ]; + } + + optional EvenDimmer even_dimmer = 98; + optional SettingProto font_weight_adjustment = 85 [ (android.privacy).dest = DEST_AUTOMATIC ]; message Gesture { @@ -712,5 +719,5 @@ message SecureSettingsProto { // Please insert fields in alphabetical order and group them into messages // if possible (to avoid reaching the method limit). - // Next tag = 98; + // Next tag = 99; } diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index bd98a8130f35..c9d4ba468cd4 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -4996,6 +4996,11 @@ <!-- Component name for the default module metadata provider on this device --> <string name="config_defaultModuleMetadataProvider" translatable="false">com.android.modulemetadata</string> + <!-- Packages that contain a security state. + {@link SecurityStateManager#getGlobalSecurityState} will read and report the state/version + of these packages. --> + <string-array name="config_securityStatePackages" translatable="false" /> + <!-- Package name for the default Health Connect app. OEMs can set this with their own health app package name to define a default app with high priority for the app to store the health data. If set the app always has priority of 1 diff --git a/core/res/res/values/config_device_idle.xml b/core/res/res/values/config_device_idle.xml index bc9ca3decec3..7a707c0a6cdc 100644 --- a/core/res/res/values/config_device_idle.xml +++ b/core/res/res/values/config_device_idle.xml @@ -28,7 +28,7 @@ <integer name="device_idle_flex_time_short_ms">60000</integer> <!-- Default for DeviceIdleController.Constants.LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT --> - <integer name="device_idle_light_after_inactive_to_ms">240000</integer> + <integer name="device_idle_light_after_inactive_to_ms">60000</integer> <!-- Default for DeviceIdleController.Constants.LIGHT_IDLE_TIMEOUT --> <integer name="device_idle_light_idle_to_ms">300000</integer> @@ -43,7 +43,7 @@ <item name="device_idle_light_idle_factor" format="float" type="integer">2.0</item> <!-- Default for DeviceIdleController.Constants.LIGHT_IDLE_INCREASE_LINEARLY --> - <bool name="device_idle_light_idle_increase_linearly">false</bool> + <bool name="device_idle_light_idle_increase_linearly">true</bool> <!-- Default for DeviceIdleController.Constants.LIGHT_IDLE_LINEAR_INCREASE_FACTOR_MS --> <integer name="device_idle_light_idle_linear_increase_factor_ms">300000</integer> @@ -52,7 +52,7 @@ <integer name="device_idle_light_idle_flex_linear_increase_factor_ms">60000</integer> <!-- Default for DeviceIdleController.Constants.LIGHT_MAX_IDLE_TIMEOUT --> - <integer name="device_idle_light_max_idle_to_ms">900000</integer> + <integer name="device_idle_light_max_idle_to_ms">1800000</integer> <!-- Default for DeviceIdleController.Constants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET --> <integer name="device_idle_light_idle_maintenance_min_budget_ms">60000</integer> @@ -67,13 +67,13 @@ <integer name="device_idle_min_deep_maintenance_time_ms">30000</integer> <!-- Default for DeviceIdleController.Constants.INACTIVE_TIMEOUT --> - <integer name="device_idle_inactive_to_ms">1800000</integer> + <integer name="device_idle_inactive_to_ms">60000</integer> <!-- Default for DeviceIdleController.Constants.SENSING_TIMEOUT --> - <integer name="device_idle_sensing_to_ms">240000</integer> + <integer name="device_idle_sensing_to_ms">30000</integer> <!-- Default for DeviceIdleController.Constants.LOCATING_TIMEOUT --> - <integer name="device_idle_locating_to_ms">30000</integer> + <integer name="device_idle_locating_to_ms">15000</integer> <!-- Default for DeviceIdleController.Constants.LOCATION_ACCURACY --> <item name="device_idle_location_accuracy" format="float" type="integer">20.0</item> @@ -85,7 +85,7 @@ <integer name="device_idle_motion_inactive_to_flex_ms">60000</integer> <!-- Default for DeviceIdleController.Constants.IDLE_AFTER_INACTIVE_TIMEOUT --> - <integer name="device_idle_idle_after_inactive_to_ms">1800000</integer> + <integer name="device_idle_idle_after_inactive_to_ms">60000</integer> <!-- Default for DeviceIdleController.Constants.IDLE_PENDING_TIMEOUT --> <integer name="device_idle_idle_pending_to_ms">300000</integer> @@ -100,7 +100,7 @@ <integer name="device_idle_quick_doze_delay_to_ms">60000</integer> <!-- Default for DeviceIdleController.Constants.IDLE_TIMEOUT --> - <integer name="device_idle_idle_to_ms">3600000</integer> + <integer name="device_idle_idle_to_ms">900000</integer> <!-- Default for DeviceIdleController.Constants.MAX_IDLE_TIMEOUT --> <integer name="device_idle_max_idle_to_ms">21600000</integer> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index d8b266a7b422..efbab309b1d4 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1275,6 +1275,7 @@ <java-symbol type="array" name="policy_exempt_apps" /> <java-symbol type="array" name="vendor_policy_exempt_apps" /> <java-symbol type="array" name="cloneable_apps" /> + <java-symbol type="array" name="config_securityStatePackages" /> <java-symbol type="drawable" name="default_wallpaper" /> <java-symbol type="drawable" name="default_lock_wallpaper" /> diff --git a/core/tests/batterystatstests/BatteryUsageStatsProtoTests/src/com/android/internal/os/BatteryUsageStatsPulledTest.java b/core/tests/batterystatstests/BatteryUsageStatsProtoTests/src/com/android/internal/os/BatteryUsageStatsPulledTest.java index aaaa3c7740c5..ac1f7d0e345f 100644 --- a/core/tests/batterystatstests/BatteryUsageStatsProtoTests/src/com/android/internal/os/BatteryUsageStatsPulledTest.java +++ b/core/tests/batterystatstests/BatteryUsageStatsProtoTests/src/com/android/internal/os/BatteryUsageStatsPulledTest.java @@ -48,6 +48,11 @@ public class BatteryUsageStatsPulledTest { private static final int UID_1 = 2000; private static final int UID_2 = 3000; private static final int UID_3 = 4000; + private static final int[] UID_USAGE_TIME_PROCESS_STATES = { + BatteryConsumer.PROCESS_STATE_FOREGROUND, + BatteryConsumer.PROCESS_STATE_BACKGROUND, + BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE + }; @Test public void testGetStatsProto() { @@ -195,6 +200,20 @@ public class BatteryUsageStatsPulledTest { assertEquals("For uid " + uid, uidConsumer.getTimeInStateMs(android.os.UidBatteryConsumer.STATE_BACKGROUND), uidConsumerProto.timeInBackgroundMillis); + for (int processState : UID_USAGE_TIME_PROCESS_STATES) { + final long timeInStateMillis = uidConsumer.getTimeInProcessStateMs(processState); + if (timeInStateMillis <= 0) { + continue; + } + assertEquals("For uid " + uid + ", process state " + processState, + timeInStateMillis, + Arrays.stream(uidConsumerProto.timeInState) + .filter(timeInState -> timeInState.processState == processState) + .findFirst() + .orElseThrow() + .timeInStateMillis); + } + if (expectNullBatteryConsumerData) { assertNull("For uid " + uid, uidConsumerProto.batteryConsumerData); } else { @@ -250,8 +269,8 @@ public class BatteryUsageStatsPulledTest { final UidBatteryConsumer.Builder uidBuilder = builder .getOrCreateUidBatteryConsumerBuilder(UID_0) .setPackageWithHighestDrain("myPackage0") - .setTimeInStateMs(UidBatteryConsumer.STATE_FOREGROUND, 1000) - .setTimeInStateMs(UidBatteryConsumer.STATE_BACKGROUND, 2000) + .setTimeInProcessStateMs(BatteryConsumer.PROCESS_STATE_FOREGROUND, 1000) + .setTimeInProcessStateMs(BatteryConsumer.PROCESS_STATE_BACKGROUND, 2000) .setConsumedPower( BatteryConsumer.POWER_COMPONENT_SCREEN, 300) .setConsumedPower( @@ -285,7 +304,7 @@ public class BatteryUsageStatsPulledTest { builder.getOrCreateUidBatteryConsumerBuilder(UID_1) .setPackageWithHighestDrain("myPackage1") - .setTimeInStateMs(android.os.UidBatteryConsumer.STATE_FOREGROUND, 1234); + .setTimeInProcessStateMs(BatteryConsumer.PROCESS_STATE_FOREGROUND, 1234); builder.getOrCreateUidBatteryConsumerBuilder(UID_2) .setConsumedPower(BatteryConsumer.POWER_COMPONENT_SCREEN, @@ -331,8 +350,10 @@ public class BatteryUsageStatsPulledTest { // significantly larger than 50 Kb for (int i = 0; i < 3000; i++) { builder.getOrCreateUidBatteryConsumerBuilder(i) - .setTimeInStateMs(android.os.UidBatteryConsumer.STATE_FOREGROUND, 1 * 60 * 1000) - .setTimeInStateMs(android.os.UidBatteryConsumer.STATE_BACKGROUND, 2 * 60 * 1000) + .setTimeInProcessStateMs( + BatteryConsumer.PROCESS_STATE_FOREGROUND, 1 * 60 * 1000) + .setTimeInProcessStateMs( + BatteryConsumer.PROCESS_STATE_BACKGROUND, 2 * 60 * 1000) .setConsumedPower(BatteryConsumer.POWER_COMPONENT_SCREEN, 30) .setConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU, 40); } @@ -340,16 +361,16 @@ public class BatteryUsageStatsPulledTest { // Add a UID with much larger battery footprint final int largeConsumerUid = 3001; builder.getOrCreateUidBatteryConsumerBuilder(largeConsumerUid) - .setTimeInStateMs(android.os.UidBatteryConsumer.STATE_FOREGROUND, 10 * 60 * 1000) - .setTimeInStateMs(android.os.UidBatteryConsumer.STATE_BACKGROUND, 20 * 60 * 1000) + .setTimeInProcessStateMs(BatteryConsumer.PROCESS_STATE_FOREGROUND, 10 * 60 * 1000) + .setTimeInProcessStateMs(BatteryConsumer.PROCESS_STATE_BACKGROUND, 20 * 60 * 1000) .setConsumedPower(BatteryConsumer.POWER_COMPONENT_SCREEN, 300) .setConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU, 400); // Add a UID with much larger usage duration final int highUsageUid = 3002; builder.getOrCreateUidBatteryConsumerBuilder(highUsageUid) - .setTimeInStateMs(android.os.UidBatteryConsumer.STATE_FOREGROUND, 60 * 60 * 1000) - .setTimeInStateMs(android.os.UidBatteryConsumer.STATE_BACKGROUND, 120 * 60 * 1000) + .setTimeInProcessStateMs(BatteryConsumer.PROCESS_STATE_FOREGROUND, 60 * 60 * 1000) + .setTimeInProcessStateMs(BatteryConsumer.PROCESS_STATE_BACKGROUND, 120 * 60 * 1000) .setConsumedPower(BatteryConsumer.POWER_COMPONENT_SCREEN, 3) .setConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU, 4); diff --git a/core/tests/coretests/src/android/service/notification/NotificationRankingUpdateTest.java b/core/tests/coretests/src/android/service/notification/NotificationRankingUpdateTest.java index 0855268411eb..1bdb006c3465 100644 --- a/core/tests/coretests/src/android/service/notification/NotificationRankingUpdateTest.java +++ b/core/tests/coretests/src/android/service/notification/NotificationRankingUpdateTest.java @@ -472,6 +472,9 @@ public class NotificationRankingUpdateTest { NotificationRankingUpdate nru = generateUpdate(getContext()); Parcel parcel = Parcel.obtain(); nru.writeToParcel(parcel, 0); + if (Flags.rankingUpdateAshmem()) { + assertTrue(nru.isFdNotNullAndClosed()); + } parcel.setDataPosition(0); NotificationRankingUpdate nru1 = NotificationRankingUpdate.CREATOR.createFromParcel(parcel); // The rankingUpdate file descriptor is only non-null in the new path. diff --git a/data/keyboards/Generic.kcm b/data/keyboards/Generic.kcm index 1048742adb70..e7e174064849 100644 --- a/data/keyboards/Generic.kcm +++ b/data/keyboards/Generic.kcm @@ -500,7 +500,7 @@ key PLUS { key ESCAPE { base: none - alt, meta: fallback HOME + alt: fallback HOME ctrl: fallback MENU } diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/OverlayPresentationTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/OverlayPresentationTest.java index 50cfd941adb3..4c2433fab2f8 100644 --- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/OverlayPresentationTest.java +++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/OverlayPresentationTest.java @@ -443,7 +443,8 @@ public class OverlayPresentationTest { assertThat(taskContainer.getTaskFragmentContainers()).containsExactly(overlayContainer); taskContainer.updateTaskFragmentParentInfo(new TaskFragmentParentInfo(Configuration.EMPTY, - DEFAULT_DISPLAY, true /* visible */, false /* hasDirectActivity */)); + DEFAULT_DISPLAY, true /* visible */, false /* hasDirectActivity */, + null /* decorSurface */)); mSplitController.updateOverlayContainer(mTransaction, overlayContainer); diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java index 02031a67e7e3..8c274a26177d 100644 --- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java +++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java @@ -1139,7 +1139,8 @@ public class SplitControllerTest { public void testOnTransactionReady_taskFragmentParentInfoChanged() { final TaskFragmentTransaction transaction = new TaskFragmentTransaction(); final TaskFragmentParentInfo parentInfo = new TaskFragmentParentInfo(Configuration.EMPTY, - DEFAULT_DISPLAY, true /* visible */, false /* hasDirectActivity */); + DEFAULT_DISPLAY, true /* visible */, false /* hasDirectActivity */, + null /* decorSurface */); transaction.addChange(new TaskFragmentTransaction.Change( TYPE_TASK_FRAGMENT_PARENT_INFO_CHANGED) .setTaskId(TASK_ID) diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskContainerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskContainerTest.java index e56c8ab686e7..7b77235f66f7 100644 --- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskContainerTest.java +++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskContainerTest.java @@ -79,14 +79,16 @@ public class TaskContainerTest { configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN); taskContainer.updateTaskFragmentParentInfo(new TaskFragmentParentInfo(configuration, - DEFAULT_DISPLAY, true /* visible */, false /* hasDirectActivity */)); + DEFAULT_DISPLAY, true /* visible */, false /* hasDirectActivity */, + null /* decorSurface */)); assertEquals(WINDOWING_MODE_MULTI_WINDOW, taskContainer.getWindowingModeForSplitTaskFragment(splitBounds)); configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM); taskContainer.updateTaskFragmentParentInfo(new TaskFragmentParentInfo(configuration, - DEFAULT_DISPLAY, true /* visible */, false /* hasDirectActivity */)); + DEFAULT_DISPLAY, true /* visible */, false /* hasDirectActivity */, + null /* decorSurface */)); assertEquals(WINDOWING_MODE_FREEFORM, taskContainer.getWindowingModeForSplitTaskFragment(splitBounds)); @@ -106,13 +108,15 @@ public class TaskContainerTest { configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN); taskContainer.updateTaskFragmentParentInfo(new TaskFragmentParentInfo(configuration, - DEFAULT_DISPLAY, true /* visible */, false /* hasDirectActivity */)); + DEFAULT_DISPLAY, true /* visible */, false /* hasDirectActivity */, + null /* decorSurface */)); assertFalse(taskContainer.isInPictureInPicture()); configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_PINNED); taskContainer.updateTaskFragmentParentInfo(new TaskFragmentParentInfo(configuration, - DEFAULT_DISPLAY, true /* visible */, false /* hasDirectActivity */)); + DEFAULT_DISPLAY, true /* visible */, false /* hasDirectActivity */, + null /* decorSurface */)); assertTrue(taskContainer.isInPictureInPicture()); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java index f5b877a70b84..a3eb429b1d7e 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java @@ -412,6 +412,23 @@ public class BubbleExpandedView extends LinearLayout { setLayoutDirection(LAYOUT_DIRECTION_LOCALE); } + + /** Updates the width of the task view if it changed. */ + void updateTaskViewContentWidth() { + if (mTaskView != null) { + int width = getContentWidth(); + if (mTaskView.getWidth() != width) { + FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(width, MATCH_PARENT); + mTaskView.setLayoutParams(lp); + } + } + } + + private int getContentWidth() { + boolean isStackOnLeft = mPositioner.isStackOnLeft(mStackView.getStackPosition()); + return mPositioner.getTaskViewContentWidth(isStackOnLeft); + } + /** * Initialize {@link BubbleController} and {@link BubbleStackView} here, this method must need * to be called after view inflate. @@ -438,7 +455,12 @@ public class BubbleExpandedView extends LinearLayout { mController.getTaskViewTransitions(), mController.getSyncTransactionQueue()); mTaskView = new TaskView(mContext, mTaskViewTaskController); mTaskView.setListener(mController.getMainExecutor(), mTaskViewListener); - mExpandedViewContainer.addView(mTaskView); + + // set a fixed width so it is not recalculated as part of a rotation. the width will be + // updated manually after the rotation. + FrameLayout.LayoutParams lp = + new FrameLayout.LayoutParams(getContentWidth(), MATCH_PARENT); + mExpandedViewContainer.addView(mTaskView, lp); bringChildToFront(mTaskView); } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java index 1efd9df3a1d9..baa52a0b5626 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java @@ -375,6 +375,13 @@ public class BubblePositioner { } } + /** Returns the width of the task view content. */ + public int getTaskViewContentWidth(boolean onLeft) { + int[] paddings = getExpandedViewContainerPadding(onLeft, /* isOverflow = */ false); + int pointerOffset = showBubblesVertically() ? getPointerSize() : 0; + return mPositionRect.width() - paddings[0] - paddings[2] - pointerOffset; + } + /** Gets the y position of the expanded view if it was top-aligned. */ public float getExpandedViewYTopAligned() { final int top = getAvailableRect().top; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java index 45c948ba0554..91a8ce726c42 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java @@ -3288,6 +3288,7 @@ public class BubbleStackView extends FrameLayout mExpandedViewContainer.setTranslationY(mPositioner.getExpandedViewY(mExpandedBubble, mPositioner.showBubblesVertically() ? p.y : p.x)); mExpandedViewContainer.setTranslationX(0f); + mExpandedBubble.getExpandedView().updateTaskViewContentWidth(); mExpandedBubble.getExpandedView().updateView( mExpandedViewContainer.getLocationOnScreen()); updatePointerPosition(false /* forIme */); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java index 271a3b26305d..79c20761abed 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java @@ -590,7 +590,7 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler { cancel("transit_sleep"); return; } - if (mKeyguardLocked) { + if (mKeyguardLocked || (info.getFlags() & TRANSIT_FLAG_KEYGUARD_LOCKED) != 0) { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION, "[%d] RecentsController.merge: keyguard is locked", mInstanceId); // We will not accept new changes if we are swiping over the keyguard. @@ -627,7 +627,8 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler { && mRecentsTask.equals(change.getContainer()); hasTaskChange = hasTaskChange || isRootTask; final boolean isLeafTask = leafTaskFilter.test(change); - if (TransitionUtil.isOpeningType(change.getMode())) { + if (TransitionUtil.isOpeningType(change.getMode()) + || TransitionUtil.isOrderOnly(change)) { if (isRecentsTask) { recentsOpening = change; } else if (isRootTask || isLeafTask) { diff --git a/libs/WindowManager/Shell/tests/flicker/pip/Android.bp b/libs/WindowManager/Shell/tests/flicker/pip/Android.bp index 386983ce6aae..b9b56c2ae950 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/Android.bp +++ b/libs/WindowManager/Shell/tests/flicker/pip/Android.bp @@ -132,5 +132,6 @@ android_test { csuite_test { name: "csuite-1p3p-pip-flickers", + test_plan_include: "csuitePlan.xml", test_config_template: "csuiteDefaultTemplate.xml", } diff --git a/libs/WindowManager/Shell/tests/flicker/pip/csuiteDefaultTemplate.xml b/libs/WindowManager/Shell/tests/flicker/pip/csuiteDefaultTemplate.xml index fafd37bba14b..f5a8655b81f0 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/csuiteDefaultTemplate.xml +++ b/libs/WindowManager/Shell/tests/flicker/pip/csuiteDefaultTemplate.xml @@ -79,8 +79,6 @@ value="appops set com.android.shell android:mock_location deny"/> </target_preparer> - <target_preparer class="com.android.csuite.core.AppCrawlTesterHostPreparer"/> - <!-- Use app crawler to log into Netflix --> <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer"> <option name="run-command" diff --git a/libs/WindowManager/Shell/tests/flicker/pip/csuitePlan.xml b/libs/WindowManager/Shell/tests/flicker/pip/csuitePlan.xml new file mode 100644 index 000000000000..a2fc6b45c2ad --- /dev/null +++ b/libs/WindowManager/Shell/tests/flicker/pip/csuitePlan.xml @@ -0,0 +1,3 @@ +<configuration description="Flicker tests C-Suite Crawler Test Plan"> + <target_preparer class="com.android.csuite.core.AppCrawlTesterHostPreparer"/> +</configuration>
\ No newline at end of file diff --git a/libs/androidfw/Android.bp b/libs/androidfw/Android.bp index 47a7f3579764..2f28363aedc7 100644 --- a/libs/androidfw/Android.bp +++ b/libs/androidfw/Android.bp @@ -63,15 +63,21 @@ cc_library { "AssetsProvider.cpp", "AttributeResolution.cpp", "BigBuffer.cpp", + "BigBufferStream.cpp", "ChunkIterator.cpp", "ConfigDescription.cpp", + "FileStream.cpp", "Idmap.cpp", "LoadedArsc.cpp", "Locale.cpp", "LocaleData.cpp", "misc.cpp", + "NinePatch.cpp", "ObbFile.cpp", "PosixUtils.cpp", + "Png.cpp", + "PngChunkFilter.cpp", + "PngCrunch.cpp", "ResourceTimer.cpp", "ResourceTypes.cpp", "ResourceUtils.cpp", @@ -84,7 +90,10 @@ cc_library { ], export_include_dirs: ["include"], export_shared_lib_headers: ["libz"], - static_libs: ["libincfs-utils"], + static_libs: [ + "libincfs-utils", + "libpng", + ], whole_static_libs: [ "libandroidfw_pathutils", "libincfs-utils", @@ -198,9 +207,11 @@ cc_test { "tests/ConfigDescription_test.cpp", "tests/ConfigLocale_test.cpp", "tests/DynamicRefTable_test.cpp", + "tests/FileStream_test.cpp", "tests/Idmap_test.cpp", "tests/LoadedArsc_test.cpp", "tests/Locale_test.cpp", + "tests/NinePatch_test.cpp", "tests/ResourceTimer_test.cpp", "tests/ResourceUtils_test.cpp", "tests/ResTable_test.cpp", diff --git a/tools/aapt2/io/BigBufferStream.cpp b/libs/androidfw/BigBufferStream.cpp index 9704caae4719..f18199cfa52b 100644 --- a/tools/aapt2/io/BigBufferStream.cpp +++ b/libs/androidfw/BigBufferStream.cpp @@ -14,10 +14,11 @@ * limitations under the License. */ -#include "io/BigBufferStream.h" +#include "androidfw/BigBufferStream.h" -namespace aapt { -namespace io { +#include <algorithm> + +namespace android { // // BigBufferInputStream @@ -76,6 +77,34 @@ size_t BigBufferInputStream::TotalSize() const { return buffer_->size(); } +bool BigBufferInputStream::ReadFullyAtOffset(void* data, size_t byte_count, off64_t offset) { + if (byte_count == 0) { + return true; + } + if (offset < 0) { + return false; + } + if (offset > std::numeric_limits<off64_t>::max() - byte_count) { + return false; + } + if (offset + byte_count > buffer_->size()) { + return false; + } + auto p = reinterpret_cast<uint8_t*>(data); + for (auto iter = buffer_->begin(); iter != buffer_->end() && byte_count > 0; ++iter) { + if (offset < iter->size) { + size_t to_read = std::min(byte_count, (size_t)(iter->size - offset)); + memcpy(p, iter->buffer.get() + offset, to_read); + byte_count -= to_read; + p += to_read; + offset = 0; + } else { + offset -= iter->size; + } + } + return byte_count == 0; +} + // // BigBufferOutputStream // @@ -97,5 +126,4 @@ bool BigBufferOutputStream::HadError() const { return false; } -} // namespace io -} // namespace aapt +} // namespace android diff --git a/tools/aapt2/io/FileStream.cpp b/libs/androidfw/FileStream.cpp index 27529bc08a16..b86c9cb729d4 100644 --- a/tools/aapt2/io/FileStream.cpp +++ b/libs/androidfw/FileStream.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "io/FileStream.h" +#include "androidfw/FileStream.h" #include <errno.h> // for errno #include <fcntl.h> // for O_RDONLY @@ -34,8 +34,7 @@ using ::android::base::SystemErrorCodeToString; using ::android::base::unique_fd; -namespace aapt { -namespace io { +namespace android { FileInputStream::FileInputStream(const std::string& path, size_t buffer_capacity) : buffer_capacity_(buffer_capacity) { @@ -108,6 +107,10 @@ std::string FileInputStream::GetError() const { return error_; } +bool FileInputStream::ReadFullyAtOffset(void* data, size_t byte_count, off64_t offset) { + return base::ReadFullyAtOffset(fd_, data, byte_count, offset); +} + FileOutputStream::FileOutputStream(const std::string& path, size_t buffer_capacity) : buffer_capacity_(buffer_capacity) { int mode = O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_BINARY; @@ -199,5 +202,4 @@ std::string FileOutputStream::GetError() const { return error_; } -} // namespace io -} // namespace aapt +} // namespace android diff --git a/tools/aapt2/compile/NinePatch.cpp b/libs/androidfw/NinePatch.cpp index 4538ecc56e4c..1fdbebfb6daa 100644 --- a/tools/aapt2/compile/NinePatch.cpp +++ b/libs/androidfw/NinePatch.cpp @@ -14,20 +14,17 @@ * limitations under the License. */ -#include "compile/Image.h" - #include <sstream> #include <string> #include <vector> +#include "androidfw/Image.h" #include "androidfw/ResourceTypes.h" #include "androidfw/StringPiece.h" -#include "util/Util.h" - using android::StringPiece; -namespace aapt { +namespace android { // Colors in the format 0xAARRGGBB (the way 9-patch expects it). constexpr static const uint32_t kColorOpaqueWhite = 0xffffffffu; @@ -90,10 +87,8 @@ class ColorValidator { // }; // template <typename ImageLine> -static bool FillRanges(const ImageLine* image_line, - const ColorValidator* color_validator, - std::vector<Range>* primary_ranges, - std::vector<Range>* secondary_ranges, +static bool FillRanges(const ImageLine* image_line, const ColorValidator* color_validator, + std::vector<Range>* primary_ranges, std::vector<Range>* secondary_ranges, std::string* out_err) { const int32_t length = image_line->GetLength(); @@ -133,11 +128,13 @@ static bool FillRanges(const ImageLine* image_line, */ class HorizontalImageLine { public: - explicit HorizontalImageLine(uint8_t** rows, int32_t xoffset, int32_t yoffset, - int32_t length) - : rows_(rows), xoffset_(xoffset), yoffset_(yoffset), length_(length) {} + explicit HorizontalImageLine(uint8_t** rows, int32_t xoffset, int32_t yoffset, int32_t length) + : rows_(rows), xoffset_(xoffset), yoffset_(yoffset), length_(length) { + } - inline int32_t GetLength() const { return length_; } + inline int32_t GetLength() const { + return length_; + } inline uint32_t GetColor(int32_t idx) const { return NinePatch::PackRGBA(rows_[yoffset_] + (idx + xoffset_) * 4); @@ -156,11 +153,13 @@ class HorizontalImageLine { */ class VerticalImageLine { public: - explicit VerticalImageLine(uint8_t** rows, int32_t xoffset, int32_t yoffset, - int32_t length) - : rows_(rows), xoffset_(xoffset), yoffset_(yoffset), length_(length) {} + explicit VerticalImageLine(uint8_t** rows, int32_t xoffset, int32_t yoffset, int32_t length) + : rows_(rows), xoffset_(xoffset), yoffset_(yoffset), length_(length) { + } - inline int32_t GetLength() const { return length_; } + inline int32_t GetLength() const { + return length_; + } inline uint32_t GetColor(int32_t idx) const { return NinePatch::PackRGBA(rows_[yoffset_ + idx] + (xoffset_ * 4)); @@ -175,20 +174,22 @@ class VerticalImageLine { class DiagonalImageLine { public: - explicit DiagonalImageLine(uint8_t** rows, int32_t xoffset, int32_t yoffset, - int32_t xstep, int32_t ystep, int32_t length) + explicit DiagonalImageLine(uint8_t** rows, int32_t xoffset, int32_t yoffset, int32_t xstep, + int32_t ystep, int32_t length) : rows_(rows), xoffset_(xoffset), yoffset_(yoffset), xstep_(xstep), ystep_(ystep), - length_(length) {} + length_(length) { + } - inline int32_t GetLength() const { return length_; } + inline int32_t GetLength() const { + return length_; + } inline uint32_t GetColor(int32_t idx) const { - return NinePatch::PackRGBA(rows_[yoffset_ + (idx * ystep_)] + - ((idx + xoffset_) * xstep_) * 4); + return NinePatch::PackRGBA(rows_[yoffset_ + (idx * ystep_)] + ((idx + xoffset_) * xstep_) * 4); } private: @@ -243,8 +244,7 @@ static bool PopulateBounds(const std::vector<Range>& padding, if (layout_bounds.size() > 2) { std::stringstream err_stream; - err_stream << "too many layout bounds sections on " << edge_name - << " border"; + err_stream << "too many layout bounds sections on " << edge_name << " border"; *out_err = err_stream.str(); return false; } @@ -258,8 +258,7 @@ static bool PopulateBounds(const std::vector<Range>& padding, // end at length. if (range.start != 0 && range.end != length) { std::stringstream err_stream; - err_stream << "layout bounds on " << edge_name - << " border must start at edge"; + err_stream << "layout bounds on " << edge_name << " border must start at edge"; *out_err = err_stream.str(); return false; } @@ -269,8 +268,7 @@ static bool PopulateBounds(const std::vector<Range>& padding, const Range& range = layout_bounds.back(); if (range.end != length) { std::stringstream err_stream; - err_stream << "layout bounds on " << edge_name - << " border must start at edge"; + err_stream << "layout bounds on " << edge_name << " border must start at edge"; *out_err = err_stream.str(); return false; } @@ -280,8 +278,7 @@ static bool PopulateBounds(const std::vector<Range>& padding, return true; } -static int32_t CalculateSegmentCount(const std::vector<Range>& stretch_regions, - int32_t length) { +static int32_t CalculateSegmentCount(const std::vector<Range>& stretch_regions, int32_t length) { if (stretch_regions.size() == 0) { return 0; } @@ -299,8 +296,7 @@ static int32_t CalculateSegmentCount(const std::vector<Range>& stretch_regions, static uint32_t GetRegionColor(uint8_t** rows, const Bounds& region) { // Sample the first pixel to compare against. - const uint32_t expected_color = - NinePatch::PackRGBA(rows[region.top] + region.left * 4); + const uint32_t expected_color = NinePatch::PackRGBA(rows[region.top] + region.left * 4); for (int32_t y = region.top; y < region.bottom; y++) { const uint8_t* row = rows[y]; for (int32_t x = region.left; x < region.right; x++) { @@ -336,10 +332,11 @@ static uint32_t GetRegionColor(uint8_t** rows, const Bounds& region) { // the indices must be offset by 1. // // width and height also include the 9-patch 1px border. -static void CalculateRegionColors( - uint8_t** rows, const std::vector<Range>& horizontal_stretch_regions, - const std::vector<Range>& vertical_stretch_regions, const int32_t width, - const int32_t height, std::vector<uint32_t>* out_colors) { +static void CalculateRegionColors(uint8_t** rows, + const std::vector<Range>& horizontal_stretch_regions, + const std::vector<Range>& vertical_stretch_regions, + const int32_t width, const int32_t height, + std::vector<uint32_t>* out_colors) { int32_t next_top = 0; Bounds bounds; auto row_iter = vertical_stretch_regions.begin(); @@ -401,8 +398,7 @@ static void CalculateRegionColors( // alpha value begins // (on both sides). template <typename ImageLine> -static void FindOutlineInsets(const ImageLine* image_line, int32_t* out_start, - int32_t* out_end) { +static void FindOutlineInsets(const ImageLine* image_line, int32_t* out_start, int32_t* out_end) { *out_start = 0; *out_end = 0; @@ -455,10 +451,8 @@ uint32_t NinePatch::PackRGBA(const uint8_t* pixel) { return (pixel[3] << 24) | (pixel[0] << 16) | (pixel[1] << 8) | pixel[2]; } -std::unique_ptr<NinePatch> NinePatch::Create(uint8_t** rows, - const int32_t width, - const int32_t height, - std::string* out_err) { +std::unique_ptr<NinePatch> NinePatch::Create(uint8_t** rows, const int32_t width, + const int32_t height, std::string* out_err) { if (width < 3 || height < 3) { *out_err = "image must be at least 3x3 (1x1 image with 1 pixel border)"; return {}; @@ -472,12 +466,11 @@ std::unique_ptr<NinePatch> NinePatch::Create(uint8_t** rows, std::unique_ptr<ColorValidator> color_validator; if (rows[0][3] == 0) { - color_validator = util::make_unique<TransparentNeutralColorValidator>(); + color_validator = std::make_unique<TransparentNeutralColorValidator>(); } else if (PackRGBA(rows[0]) == kColorOpaqueWhite) { - color_validator = util::make_unique<WhiteNeutralColorValidator>(); + color_validator = std::make_unique<WhiteNeutralColorValidator>(); } else { - *out_err = - "top-left corner pixel must be either opaque white or transparent"; + *out_err = "top-left corner pixel must be either opaque white or transparent"; return {}; } @@ -485,9 +478,8 @@ std::unique_ptr<NinePatch> NinePatch::Create(uint8_t** rows, auto nine_patch = std::unique_ptr<NinePatch>(new NinePatch()); HorizontalImageLine top_row(rows, 0, 0, width); - if (!FillRanges(&top_row, color_validator.get(), - &nine_patch->horizontal_stretch_regions, &unexpected_ranges, - out_err)) { + if (!FillRanges(&top_row, color_validator.get(), &nine_patch->horizontal_stretch_regions, + &unexpected_ranges, out_err)) { return {}; } @@ -501,9 +493,8 @@ std::unique_ptr<NinePatch> NinePatch::Create(uint8_t** rows, } VerticalImageLine left_col(rows, 0, 0, height); - if (!FillRanges(&left_col, color_validator.get(), - &nine_patch->vertical_stretch_regions, &unexpected_ranges, - out_err)) { + if (!FillRanges(&left_col, color_validator.get(), &nine_patch->vertical_stretch_regions, + &unexpected_ranges, out_err)) { return {}; } @@ -522,32 +513,28 @@ std::unique_ptr<NinePatch> NinePatch::Create(uint8_t** rows, } if (!PopulateBounds(horizontal_padding, horizontal_layout_bounds, - nine_patch->horizontal_stretch_regions, width - 2, - &nine_patch->padding.left, &nine_patch->padding.right, - &nine_patch->layout_bounds.left, + nine_patch->horizontal_stretch_regions, width - 2, &nine_patch->padding.left, + &nine_patch->padding.right, &nine_patch->layout_bounds.left, &nine_patch->layout_bounds.right, "bottom", out_err)) { return {}; } VerticalImageLine right_col(rows, width - 1, 0, height); - if (!FillRanges(&right_col, color_validator.get(), &vertical_padding, - &vertical_layout_bounds, out_err)) { + if (!FillRanges(&right_col, color_validator.get(), &vertical_padding, &vertical_layout_bounds, + out_err)) { return {}; } if (!PopulateBounds(vertical_padding, vertical_layout_bounds, - nine_patch->vertical_stretch_regions, height - 2, - &nine_patch->padding.top, &nine_patch->padding.bottom, - &nine_patch->layout_bounds.top, + nine_patch->vertical_stretch_regions, height - 2, &nine_patch->padding.top, + &nine_patch->padding.bottom, &nine_patch->layout_bounds.top, &nine_patch->layout_bounds.bottom, "right", out_err)) { return {}; } // Fill the region colors of the 9-patch. - const int32_t num_rows = - CalculateSegmentCount(nine_patch->horizontal_stretch_regions, width - 2); - const int32_t num_cols = - CalculateSegmentCount(nine_patch->vertical_stretch_regions, height - 2); + const int32_t num_rows = CalculateSegmentCount(nine_patch->horizontal_stretch_regions, width - 2); + const int32_t num_cols = CalculateSegmentCount(nine_patch->vertical_stretch_regions, height - 2); if ((int64_t)num_rows * (int64_t)num_cols > 0x7f) { *out_err = "too many regions in 9-patch"; return {}; @@ -555,40 +542,35 @@ std::unique_ptr<NinePatch> NinePatch::Create(uint8_t** rows, nine_patch->region_colors.reserve(num_rows * num_cols); CalculateRegionColors(rows, nine_patch->horizontal_stretch_regions, - nine_patch->vertical_stretch_regions, width - 2, - height - 2, &nine_patch->region_colors); + nine_patch->vertical_stretch_regions, width - 2, height - 2, + &nine_patch->region_colors); // Compute the outline based on opacity. // Find left and right extent of 9-patch content on center row. HorizontalImageLine mid_row(rows, 1, height / 2, width - 2); - FindOutlineInsets(&mid_row, &nine_patch->outline.left, - &nine_patch->outline.right); + FindOutlineInsets(&mid_row, &nine_patch->outline.left, &nine_patch->outline.right); // Find top and bottom extent of 9-patch content on center column. VerticalImageLine mid_col(rows, width / 2, 1, height - 2); - FindOutlineInsets(&mid_col, &nine_patch->outline.top, - &nine_patch->outline.bottom); + FindOutlineInsets(&mid_col, &nine_patch->outline.top, &nine_patch->outline.bottom); - const int32_t outline_width = - (width - 2) - nine_patch->outline.left - nine_patch->outline.right; + const int32_t outline_width = (width - 2) - nine_patch->outline.left - nine_patch->outline.right; const int32_t outline_height = (height - 2) - nine_patch->outline.top - nine_patch->outline.bottom; // Find the largest alpha value within the outline area. - HorizontalImageLine outline_mid_row( - rows, 1 + nine_patch->outline.left, - 1 + nine_patch->outline.top + (outline_height / 2), outline_width); - VerticalImageLine outline_mid_col( - rows, 1 + nine_patch->outline.left + (outline_width / 2), - 1 + nine_patch->outline.top, outline_height); + HorizontalImageLine outline_mid_row(rows, 1 + nine_patch->outline.left, + 1 + nine_patch->outline.top + (outline_height / 2), + outline_width); + VerticalImageLine outline_mid_col(rows, 1 + nine_patch->outline.left + (outline_width / 2), + 1 + nine_patch->outline.top, outline_height); nine_patch->outline_alpha = std::max(FindMaxAlpha(&outline_mid_row), FindMaxAlpha(&outline_mid_col)); // Assuming the image is a round rect, compute the radius by marching // diagonally from the top left corner towards the center. - DiagonalImageLine diagonal(rows, 1 + nine_patch->outline.left, - 1 + nine_patch->outline.top, 1, 1, + DiagonalImageLine diagonal(rows, 1 + nine_patch->outline.left, 1 + nine_patch->outline.top, 1, 1, std::min(outline_width, outline_height)); int32_t top_left, bottom_right; FindOutlineInsets(&diagonal, &top_left, &bottom_right); @@ -614,10 +596,9 @@ std::unique_ptr<uint8_t[]> NinePatch::SerializeBase(size_t* outLen) const { data.paddingBottom = padding.bottom; auto buffer = std::unique_ptr<uint8_t[]>(new uint8_t[data.serializedSize()]); - android::Res_png_9patch::serialize( - data, (const int32_t*)horizontal_stretch_regions.data(), - (const int32_t*)vertical_stretch_regions.data(), region_colors.data(), - buffer.get()); + android::Res_png_9patch::serialize(data, (const int32_t*)horizontal_stretch_regions.data(), + (const int32_t*)vertical_stretch_regions.data(), + region_colors.data(), buffer.get()); // Convert to file endianness. reinterpret_cast<android::Res_png_9patch*>(buffer.get())->deviceToFile(); @@ -625,8 +606,7 @@ std::unique_ptr<uint8_t[]> NinePatch::SerializeBase(size_t* outLen) const { return buffer; } -std::unique_ptr<uint8_t[]> NinePatch::SerializeLayoutBounds( - size_t* out_len) const { +std::unique_ptr<uint8_t[]> NinePatch::SerializeLayoutBounds(size_t* out_len) const { size_t chunk_len = sizeof(uint32_t) * 4; auto buffer = std::unique_ptr<uint8_t[]>(new uint8_t[chunk_len]); uint8_t* cursor = buffer.get(); @@ -647,8 +627,7 @@ std::unique_ptr<uint8_t[]> NinePatch::SerializeLayoutBounds( return buffer; } -std::unique_ptr<uint8_t[]> NinePatch::SerializeRoundedRectOutline( - size_t* out_len) const { +std::unique_ptr<uint8_t[]> NinePatch::SerializeRoundedRectOutline(size_t* out_len) const { size_t chunk_len = sizeof(uint32_t) * 6; auto buffer = std::unique_ptr<uint8_t[]>(new uint8_t[chunk_len]); uint8_t* cursor = buffer.get(); @@ -679,20 +658,25 @@ std::unique_ptr<uint8_t[]> NinePatch::SerializeRoundedRectOutline( } ::std::ostream& operator<<(::std::ostream& out, const Bounds& bounds) { - return out << "l=" << bounds.left << " t=" << bounds.top - << " r=" << bounds.right << " b=" << bounds.bottom; + return out << "l=" << bounds.left << " t=" << bounds.top << " r=" << bounds.right + << " b=" << bounds.bottom; +} + +template <typename T> +std::ostream& operator<<(std::ostream& os, const std::vector<T>& v) { + for (int i = 0; i < v.size(); ++i) { + os << v[i]; + if (i != v.size() - 1) os << " "; + } + return os; } ::std::ostream& operator<<(::std::ostream& out, const NinePatch& nine_patch) { - return out << "horizontalStretch:" - << util::Joiner(nine_patch.horizontal_stretch_regions, " ") - << " verticalStretch:" - << util::Joiner(nine_patch.vertical_stretch_regions, " ") - << " padding: " << nine_patch.padding - << ", bounds: " << nine_patch.layout_bounds - << ", outline: " << nine_patch.outline - << " rad=" << nine_patch.outline_radius + return out << "horizontalStretch:" << nine_patch.horizontal_stretch_regions + << " verticalStretch:" << nine_patch.vertical_stretch_regions + << " padding: " << nine_patch.padding << ", bounds: " << nine_patch.layout_bounds + << ", outline: " << nine_patch.outline << " rad=" << nine_patch.outline_radius << " alpha=" << nine_patch.outline_alpha; } -} // namespace aapt +} // namespace android diff --git a/tools/aapt2/compile/Png.cpp b/libs/androidfw/Png.cpp index 76db815129dd..fb45cd9b49d0 100644 --- a/tools/aapt2/compile/Png.cpp +++ b/libs/androidfw/Png.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "Png.h" +#include "androidfw/Png.h" #include <png.h> #include <zlib.h> @@ -24,13 +24,12 @@ #include <string> #include <vector> +#include "android-base/strings.h" #include "androidfw/BigBuffer.h" #include "androidfw/ResourceTypes.h" #include "androidfw/Source.h" -#include "trace/TraceBuffer.h" -#include "util/Util.h" -namespace aapt { +namespace android { constexpr bool kDebug = false; @@ -47,9 +46,8 @@ struct PngInfo { } void* serialize9Patch() { - void* serialized = android::Res_png_9patch::serialize(info9Patch, xDivs, - yDivs, colors.data()); - reinterpret_cast<android::Res_png_9patch*>(serialized)->deviceToFile(); + void* serialized = Res_png_9patch::serialize(info9Patch, xDivs, yDivs, colors.data()); + reinterpret_cast<Res_png_9patch*>(serialized)->deviceToFile(); return serialized; } @@ -58,7 +56,7 @@ struct PngInfo { std::vector<png_bytep> rows; bool is9Patch = false; - android::Res_png_9patch info9Patch; + Res_png_9patch info9Patch; int32_t* xDivs = nullptr; int32_t* yDivs = nullptr; std::vector<uint32_t> colors; @@ -79,34 +77,30 @@ struct PngInfo { uint8_t outlineAlpha; }; -static void readDataFromStream(png_structp readPtr, png_bytep data, - png_size_t length) { - std::istream* input = - reinterpret_cast<std::istream*>(png_get_io_ptr(readPtr)); +static void readDataFromStream(png_structp readPtr, png_bytep data, png_size_t length) { + std::istream* input = reinterpret_cast<std::istream*>(png_get_io_ptr(readPtr)); if (!input->read(reinterpret_cast<char*>(data), length)) { png_error(readPtr, strerror(errno)); } } -static void writeDataToStream(png_structp writePtr, png_bytep data, - png_size_t length) { - android::BigBuffer* outBuffer = reinterpret_cast<android::BigBuffer*>(png_get_io_ptr(writePtr)); +static void writeDataToStream(png_structp writePtr, png_bytep data, png_size_t length) { + BigBuffer* outBuffer = reinterpret_cast<BigBuffer*>(png_get_io_ptr(writePtr)); png_bytep buf = outBuffer->NextBlock<png_byte>(length); memcpy(buf, data, length); } -static void flushDataToStream(png_structp /*writePtr*/) {} +static void flushDataToStream(png_structp /*writePtr*/) { +} static void logWarning(png_structp readPtr, png_const_charp warningMessage) { - android::IDiagnostics* diag = - reinterpret_cast<android::IDiagnostics*>(png_get_error_ptr(readPtr)); - diag->Warn(android::DiagMessage() << warningMessage); + IDiagnostics* diag = reinterpret_cast<IDiagnostics*>(png_get_error_ptr(readPtr)); + diag->Warn(DiagMessage() << warningMessage); } -static bool readPng(android::IDiagnostics* diag, png_structp readPtr, png_infop infoPtr, - PngInfo* outInfo) { +static bool readPng(IDiagnostics* diag, png_structp readPtr, png_infop infoPtr, PngInfo* outInfo) { if (setjmp(png_jmpbuf(readPtr))) { - diag->Error(android::DiagMessage() << "failed reading png"); + diag->Error(DiagMessage() << "failed reading png"); return false; } @@ -114,8 +108,8 @@ static bool readPng(android::IDiagnostics* diag, png_structp readPtr, png_infop png_read_info(readPtr, infoPtr); int colorType, bitDepth, interlaceType, compressionType; - png_get_IHDR(readPtr, infoPtr, &outInfo->width, &outInfo->height, &bitDepth, - &colorType, &interlaceType, &compressionType, nullptr); + png_get_IHDR(readPtr, infoPtr, &outInfo->width, &outInfo->height, &bitDepth, &colorType, + &interlaceType, &compressionType, nullptr); if (colorType == PNG_COLOR_TYPE_PALETTE) { png_set_palette_to_rgb(readPtr); @@ -137,8 +131,7 @@ static bool readPng(android::IDiagnostics* diag, png_structp readPtr, png_infop png_set_add_alpha(readPtr, 0xFF, PNG_FILLER_AFTER); } - if (colorType == PNG_COLOR_TYPE_GRAY || - colorType == PNG_COLOR_TYPE_GRAY_ALPHA) { + if (colorType == PNG_COLOR_TYPE_GRAY || colorType == PNG_COLOR_TYPE_GRAY_ALPHA) { png_set_gray_to_rgb(readPtr); } @@ -156,12 +149,11 @@ static bool readPng(android::IDiagnostics* diag, png_structp readPtr, png_infop return true; } -static void checkNinePatchSerialization(android::Res_png_9patch* inPatch, - void* data) { +static void checkNinePatchSerialization(Res_png_9patch* inPatch, void* data) { size_t patchSize = inPatch->serializedSize(); void* newData = malloc(patchSize); memcpy(newData, data, patchSize); - android::Res_png_9patch* outPatch = inPatch->deserialize(newData); + Res_png_9patch* outPatch = inPatch->deserialize(newData); outPatch->fileToDevice(); // deserialization is done in place, so outPatch == newData assert(outPatch == newData); @@ -244,10 +236,9 @@ PNG_COLOR_TYPE_RGB_ALPHA) { #define MAX(a, b) ((a) > (b) ? (a) : (b)) #define ABS(a) ((a) < 0 ? -(a) : (a)) -static void analyze_image(android::IDiagnostics* diag, const PngInfo& imageInfo, - int grayscaleTolerance, png_colorp rgbPalette, png_bytep alphaPalette, - int* paletteEntries, bool* hasTransparency, int* colorType, - png_bytepp outRows) { +static void analyze_image(IDiagnostics* diag, const PngInfo& imageInfo, int grayscaleTolerance, + png_colorp rgbPalette, png_bytep alphaPalette, int* paletteEntries, + bool* hasTransparency, int* colorType, png_bytepp outRows) { int w = imageInfo.width; int h = imageInfo.height; int i, j, rr, gg, bb, aa, idx; @@ -284,8 +275,8 @@ static void analyze_image(android::IDiagnostics* diag, const PngInfo& imageInfo, maxGrayDeviation = MAX(ABS(bb - rr), maxGrayDeviation); if (maxGrayDeviation > odev) { if (kDebug) { - printf("New max dev. = %d at pixel (%d, %d) = (%d %d %d %d)\n", - maxGrayDeviation, i, j, rr, gg, bb, aa); + printf("New max dev. = %d at pixel (%d, %d) = (%d %d %d %d)\n", maxGrayDeviation, i, j, + rr, gg, bb, aa); } } @@ -293,8 +284,7 @@ static void analyze_image(android::IDiagnostics* diag, const PngInfo& imageInfo, if (isGrayscale) { if (rr != gg || rr != bb) { if (kDebug) { - printf("Found a non-gray pixel at %d, %d = (%d %d %d %d)\n", i, j, - rr, gg, bb, aa); + printf("Found a non-gray pixel at %d, %d = (%d %d %d %d)\n", i, j, rr, gg, bb, aa); } isGrayscale = false; } @@ -304,8 +294,7 @@ static void analyze_image(android::IDiagnostics* diag, const PngInfo& imageInfo, if (isOpaque) { if (aa != 0xff) { if (kDebug) { - printf("Found a non-opaque pixel at %d, %d = (%d %d %d %d)\n", i, j, - rr, gg, bb, aa); + printf("Found a non-opaque pixel at %d, %d = (%d %d %d %d)\n", i, j, rr, gg, bb, aa); } isOpaque = false; } @@ -349,10 +338,9 @@ static void analyze_image(android::IDiagnostics* diag, const PngInfo& imageInfo, printf("isGrayscale = %s\n", isGrayscale ? "true" : "false"); printf("isOpaque = %s\n", isOpaque ? "true" : "false"); printf("isPalette = %s\n", isPalette ? "true" : "false"); - printf("Size w/ palette = %d, gray+alpha = %d, rgb(a) = %d\n", paletteSize, - 2 * w * h, bpp * w * h); - printf("Max gray deviation = %d, tolerance = %d\n", maxGrayDeviation, - grayscaleTolerance); + printf("Size w/ palette = %d, gray+alpha = %d, rgb(a) = %d\n", paletteSize, 2 * w * h, + bpp * w * h); + printf("Max gray deviation = %d, tolerance = %d\n", maxGrayDeviation, grayscaleTolerance); } // Choose the best color type for the image. @@ -381,8 +369,8 @@ static void analyze_image(android::IDiagnostics* diag, const PngInfo& imageInfo, *colorType = PNG_COLOR_TYPE_PALETTE; } else { if (maxGrayDeviation <= grayscaleTolerance) { - diag->Note(android::DiagMessage() - << "forcing image to gray (max deviation = " << maxGrayDeviation << ")"); + diag->Note(DiagMessage() << "forcing image to gray (max deviation = " << maxGrayDeviation + << ")"); *colorType = isOpaque ? PNG_COLOR_TYPE_GRAY : PNG_COLOR_TYPE_GRAY_ALPHA; } else { *colorType = isOpaque ? PNG_COLOR_TYPE_RGB : PNG_COLOR_TYPE_RGB_ALPHA; @@ -404,8 +392,7 @@ static void analyze_image(android::IDiagnostics* diag, const PngInfo& imageInfo, rgbPalette[idx].blue = (png_byte)((col >> 8) & 0xff); alphaPalette[idx] = (png_byte)(col & 0xff); } - } else if (*colorType == PNG_COLOR_TYPE_GRAY || - *colorType == PNG_COLOR_TYPE_GRAY_ALPHA) { + } else if (*colorType == PNG_COLOR_TYPE_GRAY || *colorType == PNG_COLOR_TYPE_GRAY_ALPHA) { // If the image is gray or gray + alpha, compact the pixels into outRows for (j = 0; j < h; j++) { const png_byte* row = imageInfo.rows[j]; @@ -429,10 +416,10 @@ static void analyze_image(android::IDiagnostics* diag, const PngInfo& imageInfo, } } -static bool writePng(android::IDiagnostics* diag, png_structp writePtr, png_infop infoPtr, - PngInfo* info, int grayScaleTolerance) { +static bool writePng(IDiagnostics* diag, png_structp writePtr, png_infop infoPtr, PngInfo* info, + int grayScaleTolerance) { if (setjmp(png_jmpbuf(writePtr))) { - diag->Error(android::DiagMessage() << "failed to write png"); + diag->Error(DiagMessage() << "failed to write png"); return false; } @@ -444,8 +431,7 @@ static bool writePng(android::IDiagnostics* diag, png_structp writePtr, png_info unknowns[1].data = nullptr; unknowns[2].data = nullptr; - png_bytepp outRows = - (png_bytepp)malloc((int)info->height * sizeof(png_bytep)); + png_bytepp outRows = (png_bytepp)malloc((int)info->height * sizeof(png_bytep)); if (outRows == (png_bytepp)0) { printf("Can't allocate output buffer!\n"); exit(1); @@ -461,8 +447,7 @@ static bool writePng(android::IDiagnostics* diag, png_structp writePtr, png_info png_set_compression_level(writePtr, Z_BEST_COMPRESSION); if (kDebug) { - diag->Note(android::DiagMessage() - << "writing image: w = " << info->width << ", h = " << info->height); + diag->Note(DiagMessage() << "writing image: w = " << info->width << ", h = " << info->height); } png_color rgbPalette[256]; @@ -470,48 +455,45 @@ static bool writePng(android::IDiagnostics* diag, png_structp writePtr, png_info bool hasTransparency; int paletteEntries; - analyze_image(diag, *info, grayScaleTolerance, rgbPalette, alphaPalette, - &paletteEntries, &hasTransparency, &colorType, outRows); + analyze_image(diag, *info, grayScaleTolerance, rgbPalette, alphaPalette, &paletteEntries, + &hasTransparency, &colorType, outRows); // If the image is a 9-patch, we need to preserve it as a ARGB file to make // sure the pixels will not be pre-dithered/clamped until we decide they are - if (info->is9Patch && - (colorType == PNG_COLOR_TYPE_RGB || colorType == PNG_COLOR_TYPE_GRAY || - colorType == PNG_COLOR_TYPE_PALETTE)) { + if (info->is9Patch && (colorType == PNG_COLOR_TYPE_RGB || colorType == PNG_COLOR_TYPE_GRAY || + colorType == PNG_COLOR_TYPE_PALETTE)) { colorType = PNG_COLOR_TYPE_RGB_ALPHA; } if (kDebug) { switch (colorType) { case PNG_COLOR_TYPE_PALETTE: - diag->Note(android::DiagMessage() << "has " << paletteEntries << " colors" - << (hasTransparency ? " (with alpha)" : "") - << ", using PNG_COLOR_TYPE_PALLETTE"); + diag->Note(DiagMessage() << "has " << paletteEntries << " colors" + << (hasTransparency ? " (with alpha)" : "") + << ", using PNG_COLOR_TYPE_PALLETTE"); break; case PNG_COLOR_TYPE_GRAY: - diag->Note(android::DiagMessage() << "is opaque gray, using PNG_COLOR_TYPE_GRAY"); + diag->Note(DiagMessage() << "is opaque gray, using PNG_COLOR_TYPE_GRAY"); break; case PNG_COLOR_TYPE_GRAY_ALPHA: - diag->Note(android::DiagMessage() << "is gray + alpha, using PNG_COLOR_TYPE_GRAY_ALPHA"); + diag->Note(DiagMessage() << "is gray + alpha, using PNG_COLOR_TYPE_GRAY_ALPHA"); break; case PNG_COLOR_TYPE_RGB: - diag->Note(android::DiagMessage() << "is opaque RGB, using PNG_COLOR_TYPE_RGB"); + diag->Note(DiagMessage() << "is opaque RGB, using PNG_COLOR_TYPE_RGB"); break; case PNG_COLOR_TYPE_RGB_ALPHA: - diag->Note(android::DiagMessage() << "is RGB + alpha, using PNG_COLOR_TYPE_RGB_ALPHA"); + diag->Note(DiagMessage() << "is RGB + alpha, using PNG_COLOR_TYPE_RGB_ALPHA"); break; } } - png_set_IHDR(writePtr, infoPtr, info->width, info->height, 8, colorType, - PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, - PNG_FILTER_TYPE_DEFAULT); + png_set_IHDR(writePtr, infoPtr, info->width, info->height, 8, colorType, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); if (colorType == PNG_COLOR_TYPE_PALETTE) { png_set_PLTE(writePtr, infoPtr, rgbPalette, paletteEntries); if (hasTransparency) { - png_set_tRNS(writePtr, infoPtr, alphaPalette, paletteEntries, - (png_color_16p)0); + png_set_tRNS(writePtr, infoPtr, alphaPalette, paletteEntries, (png_color_16p)0); } png_set_filter(writePtr, 0, PNG_NO_FILTERS); } else { @@ -526,13 +508,12 @@ static bool writePng(android::IDiagnostics* diag, png_structp writePtr, png_info // Chunks ordered thusly because older platforms depend on the base 9 patch // data being last - png_bytep chunkNames = info->haveLayoutBounds - ? (png_bytep) "npOl\0npLb\0npTc\0" - : (png_bytep) "npOl\0npTc"; + png_bytep chunkNames = + info->haveLayoutBounds ? (png_bytep) "npOl\0npLb\0npTc\0" : (png_bytep) "npOl\0npTc"; // base 9 patch data if (kDebug) { - diag->Note(android::DiagMessage() << "adding 9-patch info.."); + diag->Note(DiagMessage() << "adding 9-patch info.."); } memcpy((char*)unknowns[pIndex].name, "npTc", 5); unknowns[pIndex].data = (png_byte*)info->serialize9Patch(); @@ -563,8 +544,7 @@ static bool writePng(android::IDiagnostics* diag, png_structp writePtr, png_info for (int i = 0; i < chunkCount; i++) { unknowns[i].location = PNG_HAVE_PLTE; } - png_set_keep_unknown_chunks(writePtr, PNG_HANDLE_CHUNK_ALWAYS, chunkNames, - chunkCount); + png_set_keep_unknown_chunks(writePtr, PNG_HANDLE_CHUNK_ALWAYS, chunkNames, chunkCount); png_set_unknown_chunks(writePtr, infoPtr, unknowns, chunkCount); #if PNG_LIBPNG_VER < 10600 @@ -579,8 +559,7 @@ static bool writePng(android::IDiagnostics* diag, png_structp writePtr, png_info png_write_info(writePtr, infoPtr); png_bytepp rows; - if (colorType == PNG_COLOR_TYPE_RGB || - colorType == PNG_COLOR_TYPE_RGB_ALPHA) { + if (colorType == PNG_COLOR_TYPE_RGB || colorType == PNG_COLOR_TYPE_RGB_ALPHA) { if (colorType == PNG_COLOR_TYPE_RGB) { png_set_filler(writePtr, 0, PNG_FILLER_AFTER); } @@ -605,14 +584,13 @@ static bool writePng(android::IDiagnostics* diag, png_structp writePtr, png_info free(unknowns[1].data); free(unknowns[2].data); - png_get_IHDR(writePtr, infoPtr, &width, &height, &bitDepth, &colorType, - &interlaceType, &compressionType, nullptr); + png_get_IHDR(writePtr, infoPtr, &width, &height, &bitDepth, &colorType, &interlaceType, + &compressionType, nullptr); if (kDebug) { - diag->Note(android::DiagMessage() - << "image written: w = " << width << ", h = " << height << ", d = " << bitDepth - << ", colors = " << colorType << ", inter = " << interlaceType - << ", comp = " << compressionType); + diag->Note(DiagMessage() << "image written: w = " << width << ", h = " << height + << ", d = " << bitDepth << ", colors = " << colorType + << ", inter = " << interlaceType << ", comp = " << compressionType); } return true; } @@ -673,9 +651,8 @@ static TickType tickType(png_bytep p, bool transparent, const char** outError) { enum class TickState { kStart, kInside1, kOutside1 }; -static bool getHorizontalTicks(png_bytep row, int width, bool transparent, - bool required, int32_t* outLeft, - int32_t* outRight, const char** outError, +static bool getHorizontalTicks(png_bytep row, int width, bool transparent, bool required, + int32_t* outLeft, int32_t* outRight, const char** outError, uint8_t* outDivs, bool multipleAllowed) { *outLeft = *outRight = -1; TickState state = TickState::kStart; @@ -683,8 +660,7 @@ static bool getHorizontalTicks(png_bytep row, int width, bool transparent, for (int i = 1; i < width - 1; i++) { if (tickType(row + i * 4, transparent, outError) == TickType::kTick) { - if (state == TickState::kStart || - (state == TickState::kOutside1 && multipleAllowed)) { + if (state == TickState::kStart || (state == TickState::kOutside1 && multipleAllowed)) { *outLeft = i - 1; *outRight = width - 2; found = true; @@ -719,18 +695,16 @@ static bool getHorizontalTicks(png_bytep row, int width, bool transparent, return true; } -static bool getVerticalTicks(png_bytepp rows, int offset, int height, - bool transparent, bool required, int32_t* outTop, - int32_t* outBottom, const char** outError, - uint8_t* outDivs, bool multipleAllowed) { +static bool getVerticalTicks(png_bytepp rows, int offset, int height, bool transparent, + bool required, int32_t* outTop, int32_t* outBottom, + const char** outError, uint8_t* outDivs, bool multipleAllowed) { *outTop = *outBottom = -1; TickState state = TickState::kStart; bool found = false; for (int i = 1; i < height - 1; i++) { if (tickType(rows[i] + offset, transparent, outError) == TickType::kTick) { - if (state == TickState::kStart || - (state == TickState::kOutside1 && multipleAllowed)) { + if (state == TickState::kStart || (state == TickState::kOutside1 && multipleAllowed)) { *outTop = i - 1; *outBottom = height - 2; found = true; @@ -765,10 +739,8 @@ static bool getVerticalTicks(png_bytepp rows, int offset, int height, return true; } -static bool getHorizontalLayoutBoundsTicks(png_bytep row, int width, - bool transparent, - bool /* required */, - int32_t* outLeft, int32_t* outRight, +static bool getHorizontalLayoutBoundsTicks(png_bytep row, int width, bool transparent, + bool /* required */, int32_t* outLeft, int32_t* outRight, const char** outError) { *outLeft = *outRight = 0; @@ -779,23 +751,20 @@ static bool getHorizontalLayoutBoundsTicks(png_bytep row, int width, while (i < width - 1) { (*outLeft)++; i++; - if (tickType(row + i * 4, transparent, outError) != - TickType::kLayoutBounds) { + if (tickType(row + i * 4, transparent, outError) != TickType::kLayoutBounds) { break; } } } // Look for right tick - if (tickType(row + (width - 2) * 4, transparent, outError) == - TickType::kLayoutBounds) { + if (tickType(row + (width - 2) * 4, transparent, outError) == TickType::kLayoutBounds) { // Ending with a layout padding tick int i = width - 2; while (i > 1) { (*outRight)++; i--; - if (tickType(row + i * 4, transparent, outError) != - TickType::kLayoutBounds) { + if (tickType(row + i * 4, transparent, outError) != TickType::kLayoutBounds) { break; } } @@ -803,38 +772,32 @@ static bool getHorizontalLayoutBoundsTicks(png_bytep row, int width, return true; } -static bool getVerticalLayoutBoundsTicks(png_bytepp rows, int offset, - int height, bool transparent, - bool /* required */, int32_t* outTop, - int32_t* outBottom, +static bool getVerticalLayoutBoundsTicks(png_bytepp rows, int offset, int height, bool transparent, + bool /* required */, int32_t* outTop, int32_t* outBottom, const char** outError) { *outTop = *outBottom = 0; // Look for top tick - if (tickType(rows[1] + offset, transparent, outError) == - TickType::kLayoutBounds) { + if (tickType(rows[1] + offset, transparent, outError) == TickType::kLayoutBounds) { // Starting with a layout padding tick int i = 1; while (i < height - 1) { (*outTop)++; i++; - if (tickType(rows[i] + offset, transparent, outError) != - TickType::kLayoutBounds) { + if (tickType(rows[i] + offset, transparent, outError) != TickType::kLayoutBounds) { break; } } } // Look for bottom tick - if (tickType(rows[height - 2] + offset, transparent, outError) == - TickType::kLayoutBounds) { + if (tickType(rows[height - 2] + offset, transparent, outError) == TickType::kLayoutBounds) { // Ending with a layout padding tick int i = height - 2; while (i > 1) { (*outBottom)++; i--; - if (tickType(rows[i] + offset, transparent, outError) != - TickType::kLayoutBounds) { + if (tickType(rows[i] + offset, transparent, outError) != TickType::kLayoutBounds) { break; } } @@ -842,13 +805,12 @@ static bool getVerticalLayoutBoundsTicks(png_bytepp rows, int offset, return true; } -static void findMaxOpacity(png_bytepp rows, int startX, int startY, int endX, - int endY, int dX, int dY, int* outInset) { +static void findMaxOpacity(png_bytepp rows, int startX, int startY, int endX, int endY, int dX, + int dY, int* outInset) { uint8_t maxOpacity = 0; int inset = 0; *outInset = 0; - for (int x = startX, y = startY; x != endX && y != endY; - x += dX, y += dY, inset++) { + for (int x = startX, y = startY; x != endX && y != endY; x += dX, y += dY, inset++) { png_byte* color = rows[y] + x * 4; uint8_t opacity = color[3]; if (opacity > maxOpacity) { @@ -868,8 +830,7 @@ static uint8_t maxAlphaOverRow(png_bytep row, int startX, int endX) { return maxAlpha; } -static uint8_t maxAlphaOverCol(png_bytepp rows, int offsetX, int startY, - int endY) { +static uint8_t maxAlphaOverCol(png_bytepp rows, int offsetX, int startY, int endY) { uint8_t maxAlpha = 0; for (int y = startY; y < endY; y++) { uint8_t alpha = (rows[y] + offsetX * 4)[3]; @@ -886,10 +847,8 @@ static void getOutline(PngInfo* image) { // find left and right extent of nine patch content on center row if (image->width > 4) { - findMaxOpacity(image->rows.data(), 1, midY, midX, -1, 1, 0, - &image->outlineInsetsLeft); - findMaxOpacity(image->rows.data(), endX, midY, midX, -1, -1, 0, - &image->outlineInsetsRight); + findMaxOpacity(image->rows.data(), 1, midY, midX, -1, 1, 0, &image->outlineInsetsLeft); + findMaxOpacity(image->rows.data(), endX, midY, midX, -1, -1, 0, &image->outlineInsetsRight); } else { image->outlineInsetsLeft = 0; image->outlineInsetsRight = 0; @@ -897,10 +856,8 @@ static void getOutline(PngInfo* image) { // find top and bottom extent of nine patch content on center column if (image->height > 4) { - findMaxOpacity(image->rows.data(), midX, 1, -1, midY, 0, 1, - &image->outlineInsetsTop); - findMaxOpacity(image->rows.data(), midX, endY, -1, midY, 0, -1, - &image->outlineInsetsBottom); + findMaxOpacity(image->rows.data(), midX, 1, -1, midY, 0, 1, &image->outlineInsetsTop); + findMaxOpacity(image->rows.data(), midX, endY, -1, midY, 0, -1, &image->outlineInsetsBottom); } else { image->outlineInsetsTop = 0; image->outlineInsetsBottom = 0; @@ -915,13 +872,13 @@ static void getOutline(PngInfo* image) { // assuming the image is a round rect, compute the radius by marching // diagonally from the top left corner towards the center - image->outlineAlpha = std::max( - maxAlphaOverRow(image->rows[innerMidY], innerStartX, innerEndX), - maxAlphaOverCol(image->rows.data(), innerMidX, innerStartY, innerStartY)); + image->outlineAlpha = + std::max(maxAlphaOverRow(image->rows[innerMidY], innerStartX, innerEndX), + maxAlphaOverCol(image->rows.data(), innerMidX, innerStartY, innerStartY)); int diagonalInset = 0; - findMaxOpacity(image->rows.data(), innerStartX, innerStartY, innerMidX, - innerMidY, 1, 1, &diagonalInset); + findMaxOpacity(image->rows.data(), innerStartX, innerStartY, innerMidX, innerMidY, 1, 1, + &diagonalInset); /* Determine source radius based upon inset: * sqrt(r^2 + r^2) = sqrt(i^2 + i^2) + r @@ -932,19 +889,17 @@ static void getOutline(PngInfo* image) { image->outlineRadius = 3.4142f * diagonalInset; if (kDebug) { - printf("outline insets %d %d %d %d, rad %f, alpha %x\n", - image->outlineInsetsLeft, image->outlineInsetsTop, - image->outlineInsetsRight, image->outlineInsetsBottom, + printf("outline insets %d %d %d %d, rad %f, alpha %x\n", image->outlineInsetsLeft, + image->outlineInsetsTop, image->outlineInsetsRight, image->outlineInsetsBottom, image->outlineRadius, image->outlineAlpha); } } -static uint32_t getColor(png_bytepp rows, int left, int top, int right, - int bottom) { +static uint32_t getColor(png_bytepp rows, int left, int top, int right, int bottom) { png_bytep color = rows[top] + left * 4; if (left > right || top > bottom) { - return android::Res_png_9patch::TRANSPARENT_COLOR; + return Res_png_9patch::TRANSPARENT_COLOR; } while (top <= bottom) { @@ -952,18 +907,17 @@ static uint32_t getColor(png_bytepp rows, int left, int top, int right, png_bytep p = rows[top] + i * 4; if (color[3] == 0) { if (p[3] != 0) { - return android::Res_png_9patch::NO_COLOR; + return Res_png_9patch::NO_COLOR; } - } else if (p[0] != color[0] || p[1] != color[1] || p[2] != color[2] || - p[3] != color[3]) { - return android::Res_png_9patch::NO_COLOR; + } else if (p[0] != color[0] || p[1] != color[1] || p[2] != color[2] || p[3] != color[3]) { + return Res_png_9patch::NO_COLOR; } } top++; } if (color[3] == 0) { - return android::Res_png_9patch::TRANSPARENT_COLOR; + return Res_png_9patch::TRANSPARENT_COLOR; } return (color[3] << 24) | (color[0] << 16) | (color[1] << 8) | color[2]; } @@ -1014,23 +968,22 @@ static bool do9Patch(PngInfo* image, std::string* outError) { } // Validate frame... - if (!transparent && - (p[0] != 0xFF || p[1] != 0xFF || p[2] != 0xFF || p[3] != 0xFF)) { + if (!transparent && (p[0] != 0xFF || p[1] != 0xFF || p[2] != 0xFF || p[3] != 0xFF)) { errorMsg = "Must have one-pixel frame that is either transparent or white"; goto getout; } // Find left and right of sizing areas... - if (!getHorizontalTicks(p, W, transparent, true, &xDivs[0], &xDivs[1], - &errorMsg, &numXDivs, true)) { + if (!getHorizontalTicks(p, W, transparent, true, &xDivs[0], &xDivs[1], &errorMsg, &numXDivs, + true)) { errorPixel = xDivs[0]; errorEdge = "top"; goto getout; } // Find top and bottom of sizing areas... - if (!getVerticalTicks(image->rows.data(), 0, H, transparent, true, &yDivs[0], - &yDivs[1], &errorMsg, &numYDivs, true)) { + if (!getVerticalTicks(image->rows.data(), 0, H, transparent, true, &yDivs[0], &yDivs[1], + &errorMsg, &numYDivs, true)) { errorPixel = yDivs[0]; errorEdge = "left"; goto getout; @@ -1041,10 +994,8 @@ static bool do9Patch(PngInfo* image, std::string* outError) { image->info9Patch.numYDivs = numYDivs; // Find left and right of padding area... - if (!getHorizontalTicks(image->rows[H - 1], W, transparent, false, - &image->info9Patch.paddingLeft, - &image->info9Patch.paddingRight, &errorMsg, nullptr, - false)) { + if (!getHorizontalTicks(image->rows[H - 1], W, transparent, false, &image->info9Patch.paddingLeft, + &image->info9Patch.paddingRight, &errorMsg, nullptr, false)) { errorPixel = image->info9Patch.paddingLeft; errorEdge = "bottom"; goto getout; @@ -1052,9 +1003,8 @@ static bool do9Patch(PngInfo* image, std::string* outError) { // Find top and bottom of padding area... if (!getVerticalTicks(image->rows.data(), (W - 1) * 4, H, transparent, false, - &image->info9Patch.paddingTop, - &image->info9Patch.paddingBottom, &errorMsg, nullptr, - false)) { + &image->info9Patch.paddingTop, &image->info9Patch.paddingBottom, &errorMsg, + nullptr, false)) { errorPixel = image->info9Patch.paddingTop; errorEdge = "right"; goto getout; @@ -1062,22 +1012,18 @@ static bool do9Patch(PngInfo* image, std::string* outError) { // Find left and right of layout padding... getHorizontalLayoutBoundsTicks(image->rows[H - 1], W, transparent, false, - &image->layoutBoundsLeft, - &image->layoutBoundsRight, &errorMsg); + &image->layoutBoundsLeft, &image->layoutBoundsRight, &errorMsg); - getVerticalLayoutBoundsTicks(image->rows.data(), (W - 1) * 4, H, transparent, - false, &image->layoutBoundsTop, - &image->layoutBoundsBottom, &errorMsg); + getVerticalLayoutBoundsTicks(image->rows.data(), (W - 1) * 4, H, transparent, false, + &image->layoutBoundsTop, &image->layoutBoundsBottom, &errorMsg); - image->haveLayoutBounds = - image->layoutBoundsLeft != 0 || image->layoutBoundsRight != 0 || - image->layoutBoundsTop != 0 || image->layoutBoundsBottom != 0; + image->haveLayoutBounds = image->layoutBoundsLeft != 0 || image->layoutBoundsRight != 0 || + image->layoutBoundsTop != 0 || image->layoutBoundsBottom != 0; if (image->haveLayoutBounds) { if (kDebug) { - printf("layoutBounds=%d %d %d %d\n", image->layoutBoundsLeft, - image->layoutBoundsTop, image->layoutBoundsRight, - image->layoutBoundsBottom); + printf("layoutBounds=%d %d %d %d\n", image->layoutBoundsLeft, image->layoutBoundsTop, + image->layoutBoundsRight, image->layoutBoundsBottom); } } @@ -1189,7 +1135,7 @@ static bool do9Patch(PngInfo* image, std::string* outError) { c = getColor(image->rows.data(), left, top, right - 1, bottom - 1); image->colors[colorIndex++] = c; if (kDebug) { - if (c != android::Res_png_9patch::NO_COLOR) { + if (c != Res_png_9patch::NO_COLOR) { hasColor = true; } } @@ -1214,8 +1160,7 @@ getout: if (errorEdge) { err << "." << std::endl; if (errorPixel >= 0) { - err << "Found at pixel #" << errorPixel << " along " << errorEdge - << " edge"; + err << "Found at pixel #" << errorPixel << " along " << errorEdge << " edge"; } else { err << "Found along " << errorEdge << " edge"; } @@ -1226,20 +1171,19 @@ getout: return true; } -bool Png::process(const android::Source& source, std::istream* input, android::BigBuffer* outBuffer, +bool Png::process(const Source& source, std::istream* input, BigBuffer* outBuffer, const PngOptions& options) { - TRACE_CALL(); png_byte signature[kPngSignatureSize]; // Read the PNG signature first. if (!input->read(reinterpret_cast<char*>(signature), kPngSignatureSize)) { - mDiag->Error(android::DiagMessage() << strerror(errno)); + mDiag->Error(DiagMessage() << strerror(errno)); return false; } // If the PNG signature doesn't match, bail early. if (png_sig_cmp(signature, 0, kPngSignatureSize) != 0) { - mDiag->Error(android::DiagMessage() << "not a valid png file"); + mDiag->Error(DiagMessage() << "not a valid png file"); return false; } @@ -1252,18 +1196,17 @@ bool Png::process(const android::Source& source, std::istream* input, android::B readPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, nullptr, nullptr); if (!readPtr) { - mDiag->Error(android::DiagMessage() << "failed to allocate read ptr"); + mDiag->Error(DiagMessage() << "failed to allocate read ptr"); goto bail; } infoPtr = png_create_info_struct(readPtr); if (!infoPtr) { - mDiag->Error(android::DiagMessage() << "failed to allocate info ptr"); + mDiag->Error(DiagMessage() << "failed to allocate info ptr"); goto bail; } - png_set_error_fn(readPtr, reinterpret_cast<png_voidp>(mDiag), nullptr, - logWarning); + png_set_error_fn(readPtr, reinterpret_cast<png_voidp>(mDiag), nullptr, logWarning); // Set the read function to read from std::istream. png_set_read_fn(readPtr, (png_voidp)input, readDataFromStream); @@ -1272,35 +1215,32 @@ bool Png::process(const android::Source& source, std::istream* input, android::B goto bail; } - if (util::EndsWith(source.path, ".9.png")) { + if (android::base::EndsWith(source.path, ".9.png")) { std::string errorMsg; if (!do9Patch(&pngInfo, &errorMsg)) { - mDiag->Error(android::DiagMessage() << errorMsg); + mDiag->Error(DiagMessage() << errorMsg); goto bail; } } - writePtr = - png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, nullptr, nullptr); + writePtr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, nullptr, nullptr); if (!writePtr) { - mDiag->Error(android::DiagMessage() << "failed to allocate write ptr"); + mDiag->Error(DiagMessage() << "failed to allocate write ptr"); goto bail; } writeInfoPtr = png_create_info_struct(writePtr); if (!writeInfoPtr) { - mDiag->Error(android::DiagMessage() << "failed to allocate write info ptr"); + mDiag->Error(DiagMessage() << "failed to allocate write info ptr"); goto bail; } png_set_error_fn(writePtr, nullptr, nullptr, logWarning); // Set the write function to write to std::ostream. - png_set_write_fn(writePtr, (png_voidp)outBuffer, writeDataToStream, - flushDataToStream); + png_set_write_fn(writePtr, (png_voidp)outBuffer, writeDataToStream, flushDataToStream); - if (!writePng(mDiag, writePtr, writeInfoPtr, &pngInfo, - options.grayscale_tolerance)) { + if (!writePng(mDiag, writePtr, writeInfoPtr, &pngInfo, options.grayscale_tolerance)) { goto bail; } @@ -1316,4 +1256,4 @@ bail: return result; } -} // namespace aapt +} // namespace android diff --git a/tools/aapt2/compile/PngChunkFilter.cpp b/libs/androidfw/PngChunkFilter.cpp index 2e55d0c82b7b..331b94803e93 100644 --- a/tools/aapt2/compile/PngChunkFilter.cpp +++ b/libs/androidfw/PngChunkFilter.cpp @@ -14,25 +14,22 @@ * limitations under the License. */ -#include "compile/Png.h" - #include "android-base/stringprintf.h" +#include "android-base/strings.h" +#include "androidfw/Png.h" +#include "androidfw/Streams.h" #include "androidfw/StringPiece.h" -#include "io/Io.h" - -using ::android::StringPiece; using ::android::base::StringPrintf; -namespace aapt { +namespace android { static constexpr const char* kPngSignature = "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a"; // Useful helper function that encodes individual bytes into a uint32 // at compile time. constexpr uint32_t u32(uint8_t a, uint8_t b, uint8_t c, uint8_t d) { - return (((uint32_t)a) << 24) | (((uint32_t)b) << 16) | (((uint32_t)c) << 8) | - ((uint32_t)d); + return (((uint32_t)a) << 24) | (((uint32_t)b) << 16) | (((uint32_t)c) << 8) | ((uint32_t)d); } // Allow list of PNG chunk types that we want to keep in the resulting PNG. @@ -71,7 +68,7 @@ static bool IsPngChunkAllowed(uint32_t type) { } PngChunkFilter::PngChunkFilter(StringPiece data) : data_(data) { - if (util::StartsWith(data_, kPngSignature)) { + if (android::base::StartsWith(data_, kPngSignature)) { window_start_ = 0; window_end_ = kPngSignatureSize; } else { @@ -176,5 +173,4 @@ bool PngChunkFilter::Rewind() { window_end_ = kPngSignatureSize; return true; } - -} // namespace aapt +} // namespace android diff --git a/tools/aapt2/compile/PngCrunch.cpp b/libs/androidfw/PngCrunch.cpp index 4ef87ba3671b..cf3c0eeff402 100644 --- a/tools/aapt2/compile/PngCrunch.cpp +++ b/libs/androidfw/PngCrunch.cpp @@ -14,8 +14,6 @@ * limitations under the License. */ -#include "compile/Png.h" - #include <png.h> #include <zlib.h> @@ -26,16 +24,16 @@ #include "android-base/errors.h" #include "android-base/logging.h" #include "android-base/macros.h" +#include "androidfw/Png.h" -#include "trace/TraceBuffer.h" - -namespace aapt { +namespace android { // Custom deleter that destroys libpng read and info structs. class PngReadStructDeleter { public: PngReadStructDeleter(png_structp read_ptr, png_infop info_ptr) - : read_ptr_(read_ptr), info_ptr_(info_ptr) {} + : read_ptr_(read_ptr), info_ptr_(info_ptr) { + } ~PngReadStructDeleter() { png_destroy_read_struct(&read_ptr_, &info_ptr_, nullptr); @@ -52,7 +50,8 @@ class PngReadStructDeleter { class PngWriteStructDeleter { public: PngWriteStructDeleter(png_structp write_ptr, png_infop info_ptr) - : write_ptr_(write_ptr), info_ptr_(info_ptr) {} + : write_ptr_(write_ptr), info_ptr_(info_ptr) { + } ~PngWriteStructDeleter() { png_destroy_write_struct(&write_ptr_, &info_ptr_); @@ -83,7 +82,7 @@ static void LogError(png_structp png_ptr, png_const_charp error_msg) { } static void ReadDataFromStream(png_structp png_ptr, png_bytep buffer, png_size_t len) { - io::InputStream* in = (io::InputStream*)png_get_io_ptr(png_ptr); + InputStream* in = (InputStream*)png_get_io_ptr(png_ptr); const void* in_buffer; size_t in_len; @@ -108,7 +107,7 @@ static void ReadDataFromStream(png_structp png_ptr, png_bytep buffer, png_size_t } static void WriteDataToStream(png_structp png_ptr, png_bytep buffer, png_size_t len) { - io::OutputStream* out = (io::OutputStream*)png_get_io_ptr(png_ptr); + OutputStream* out = (OutputStream*)png_get_io_ptr(png_ptr); void* out_buffer; size_t out_len; @@ -143,28 +142,22 @@ static void WriteDataToStream(png_structp png_ptr, png_bytep buffer, png_size_t } } -std::unique_ptr<Image> ReadPng(IAaptContext* context, const android::Source& source, - io::InputStream* in) { - TRACE_CALL(); - // Create a diagnostics that has the source information encoded. - android::SourcePathDiagnostics source_diag(source, context->GetDiagnostics()); - +std::unique_ptr<Image> ReadPng(InputStream* in, IDiagnostics* diag) { // Read the first 8 bytes of the file looking for the PNG signature. // Bail early if it does not match. const png_byte* signature; size_t buffer_size; if (!in->Next((const void**)&signature, &buffer_size)) { if (in->HadError()) { - source_diag.Error(android::DiagMessage() - << "failed to read PNG signature: " << in->GetError()); + diag->Error(android::DiagMessage() << "failed to read PNG signature: " << in->GetError()); } else { - source_diag.Error(android::DiagMessage() << "not enough data for PNG signature"); + diag->Error(android::DiagMessage() << "not enough data for PNG signature"); } return {}; } if (buffer_size < kPngSignatureSize || png_sig_cmp(signature, 0, kPngSignatureSize) != 0) { - source_diag.Error(android::DiagMessage() << "file signature does not match PNG signature"); + diag->Error(android::DiagMessage() << "file signature does not match PNG signature"); return {}; } @@ -176,14 +169,14 @@ std::unique_ptr<Image> ReadPng(IAaptContext* context, const android::Source& sou // version of libpng. png_structp read_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); if (read_ptr == nullptr) { - source_diag.Error(android::DiagMessage() << "failed to create libpng read png_struct"); + diag->Error(android::DiagMessage() << "failed to create libpng read png_struct"); return {}; } // Create and initialize the memory for image header and data. png_infop info_ptr = png_create_info_struct(read_ptr); if (info_ptr == nullptr) { - source_diag.Error(android::DiagMessage() << "failed to create libpng read png_info"); + diag->Error(android::DiagMessage() << "failed to create libpng read png_info"); png_destroy_read_struct(&read_ptr, nullptr, nullptr); return {}; } @@ -199,7 +192,7 @@ std::unique_ptr<Image> ReadPng(IAaptContext* context, const android::Source& sou } // Handle warnings ourselves via IDiagnostics. - png_set_error_fn(read_ptr, (png_voidp)&source_diag, LogError, LogWarning); + png_set_error_fn(read_ptr, (png_voidp)&diag, LogError, LogWarning); // Set up the read functions which read from our custom data sources. png_set_read_fn(read_ptr, (png_voidp)in, ReadDataFromStream); @@ -213,8 +206,8 @@ std::unique_ptr<Image> ReadPng(IAaptContext* context, const android::Source& sou // Extract image meta-data from the various chunk headers. uint32_t width, height; int bit_depth, color_type, interlace_method, compression_method, filter_method; - png_get_IHDR(read_ptr, info_ptr, &width, &height, &bit_depth, &color_type, - &interlace_method, &compression_method, &filter_method); + png_get_IHDR(read_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_method, + &compression_method, &filter_method); // When the image is read, expand it so that it is in RGBA 8888 format // so that image handling is uniform. @@ -239,8 +232,7 @@ std::unique_ptr<Image> ReadPng(IAaptContext* context, const android::Source& sou png_set_add_alpha(read_ptr, 0xFF, PNG_FILLER_AFTER); } - if (color_type == PNG_COLOR_TYPE_GRAY || - color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { + if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { png_set_gray_to_rgb(read_ptr); } @@ -256,12 +248,12 @@ std::unique_ptr<Image> ReadPng(IAaptContext* context, const android::Source& sou // something // that can always be represented by 9-patch. if (width > std::numeric_limits<int32_t>::max() || height > std::numeric_limits<int32_t>::max()) { - source_diag.Error(android::DiagMessage() - << "PNG image dimensions are too large: " << width << "x" << height); + diag->Error(android::DiagMessage() + << "PNG image dimensions are too large: " << width << "x" << height); return {}; } - std::unique_ptr<Image> output_image = util::make_unique<Image>(); + std::unique_ptr<Image> output_image = std::make_unique<Image>(); output_image->width = static_cast<int32_t>(width); output_image->height = static_cast<int32_t>(height); @@ -272,7 +264,7 @@ std::unique_ptr<Image> ReadPng(IAaptContext* context, const android::Source& sou output_image->data = std::unique_ptr<uint8_t[]>(new uint8_t[height * row_bytes]); // Create an array of rows that index into the data block. - output_image->rows = std::unique_ptr<uint8_t* []>(new uint8_t*[height]); + output_image->rows = std::unique_ptr<uint8_t*[]>(new uint8_t*[height]); for (uint32_t h = 0; h < height; h++) { output_image->rows[h] = output_image->data.get() + (h * row_bytes); } @@ -332,8 +324,7 @@ static int PickColorType(int32_t width, int32_t height, bool grayscale, // This grayscale has alpha and can fit within a palette. // See if it is worth fitting into a palette. const size_t palette_threshold = palette_chunk_size + alpha_chunk_size + - palette_data_chunk_size + - kPaletteOverheadConstant; + palette_data_chunk_size + kPaletteOverheadConstant; if (grayscale_alpha_data_chunk_size > palette_threshold) { return PNG_COLOR_TYPE_PALETTE; } @@ -343,16 +334,14 @@ static int PickColorType(int32_t width, int32_t height, bool grayscale, if (color_palette_size <= 256 && !has_nine_patch) { // This image can fit inside a palette. Let's see if it is worth it. - size_t total_size_with_palette = - palette_data_chunk_size + palette_chunk_size; + size_t total_size_with_palette = palette_data_chunk_size + palette_chunk_size; size_t total_size_without_palette = color_data_chunk_size; if (alpha_palette_size > 0) { total_size_with_palette += alpha_palette_size; total_size_without_palette = color_alpha_data_chunk_size; } - if (total_size_without_palette > - total_size_with_palette + kPaletteOverheadConstant) { + if (total_size_without_palette > total_size_with_palette + kPaletteOverheadConstant) { return PNG_COLOR_TYPE_PALETTE; } } @@ -482,26 +471,22 @@ static void WriteNinePatch(png_structp write_ptr, png_infop write_info_ptr, png_set_unknown_chunks(write_ptr, write_info_ptr, unknown_chunks, index); } -bool WritePng(IAaptContext* context, const Image* image, - const NinePatch* nine_patch, io::OutputStream* out, - const PngOptions& options) { - TRACE_CALL(); +bool WritePng(const Image* image, const NinePatch* nine_patch, OutputStream* out, + const PngOptions& options, IDiagnostics* diag, bool verbose) { // Create and initialize the write png_struct with the default error and // warning handlers. // The header version is also passed in to ensure that this was built against the same // version of libpng. png_structp write_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); if (write_ptr == nullptr) { - context->GetDiagnostics()->Error(android::DiagMessage() - << "failed to create libpng write png_struct"); + diag->Error(android::DiagMessage() << "failed to create libpng write png_struct"); return false; } // Allocate memory to store image header data. png_infop write_info_ptr = png_create_info_struct(write_ptr); if (write_info_ptr == nullptr) { - context->GetDiagnostics()->Error(android::DiagMessage() - << "failed to create libpng write png_info"); + diag->Error(android::DiagMessage() << "failed to create libpng write png_info"); png_destroy_write_struct(&write_ptr, nullptr); return false; } @@ -516,7 +501,7 @@ bool WritePng(IAaptContext* context, const Image* image, } // Handle warnings with our IDiagnostics. - png_set_error_fn(write_ptr, (png_voidp)context->GetDiagnostics(), LogError, LogWarning); + png_set_error_fn(write_ptr, (png_voidp)&diag, LogError, LogWarning); // Set up the write functions which write to our custom data sources. png_set_write_fn(write_ptr, (png_voidp)out, WriteDataToStream, nullptr); @@ -578,22 +563,21 @@ bool WritePng(IAaptContext* context, const Image* image, } } - if (context->IsVerbose()) { + if (verbose) { android::DiagMessage msg; - msg << " paletteSize=" << color_palette.size() - << " alphaPaletteSize=" << alpha_palette.size() + msg << " paletteSize=" << color_palette.size() << " alphaPaletteSize=" << alpha_palette.size() << " maxGrayDeviation=" << max_gray_deviation << " grayScale=" << (grayscale ? "true" : "false"); - context->GetDiagnostics()->Note(msg); + diag->Note(msg); } const bool convertible_to_grayscale = max_gray_deviation <= options.grayscale_tolerance; - const int new_color_type = PickColorType( - image->width, image->height, grayscale, convertible_to_grayscale, - nine_patch != nullptr, color_palette.size(), alpha_palette.size()); + const int new_color_type = + PickColorType(image->width, image->height, grayscale, convertible_to_grayscale, + nine_patch != nullptr, color_palette.size(), alpha_palette.size()); - if (context->IsVerbose()) { + if (verbose) { android::DiagMessage msg; msg << "encoding PNG "; if (nine_patch) { @@ -619,12 +603,11 @@ bool WritePng(IAaptContext* context, const Image* image, msg << "unknown type " << new_color_type; break; } - context->GetDiagnostics()->Note(msg); + diag->Note(msg); } - png_set_IHDR(write_ptr, write_info_ptr, image->width, image->height, 8, - new_color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, - PNG_FILTER_TYPE_DEFAULT); + png_set_IHDR(write_ptr, write_info_ptr, image->width, image->height, 8, new_color_type, + PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); if (new_color_type & PNG_COLOR_MASK_PALETTE) { // Assigns indices to the palette, and writes the encoded palette to the @@ -666,11 +649,9 @@ bool WritePng(IAaptContext* context, const Image* image, } png_write_row(write_ptr, out_row.get()); } - } else if (new_color_type == PNG_COLOR_TYPE_GRAY || - new_color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { + } else if (new_color_type == PNG_COLOR_TYPE_GRAY || new_color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { const size_t bpp = new_color_type == PNG_COLOR_TYPE_GRAY ? 1 : 2; - auto out_row = - std::unique_ptr<png_byte[]>(new png_byte[image->width * bpp]); + auto out_row = std::unique_ptr<png_byte[]>(new png_byte[image->width * bpp]); for (int32_t y = 0; y < image->height; y++) { png_const_bytep in_row = image->rows[y]; @@ -691,8 +672,7 @@ bool WritePng(IAaptContext* context, const Image* image, // The image is convertible to grayscale, use linear-luminance of // sRGB colorspace: // https://en.wikipedia.org/wiki/Grayscale#Colorimetric_.28luminance-preserving.29_conversion_to_grayscale - out_row[x * bpp] = - (png_byte)(rr * 0.2126f + gg * 0.7152f + bb * 0.0722f); + out_row[x * bpp] = (png_byte)(rr * 0.2126f + gg * 0.7152f + bb * 0.0722f); } if (bpp == 2) { @@ -747,4 +727,4 @@ bool WritePng(IAaptContext* context, const Image* image, return true; } -} // namespace aapt +} // namespace android diff --git a/tools/aapt2/io/BigBufferStream.h b/libs/androidfw/include/androidfw/BigBufferStream.h index 63a5e5756ed4..e55fe0d653cc 100644 --- a/tools/aapt2/io/BigBufferStream.h +++ b/libs/androidfw/include/androidfw/BigBufferStream.h @@ -14,18 +14,16 @@ * limitations under the License. */ -#ifndef AAPT_IO_BIGBUFFERSTREAM_H -#define AAPT_IO_BIGBUFFERSTREAM_H +#pragma once -#include "androidfw/BigBuffer.h" -#include "io/Io.h" +#include "BigBuffer.h" +#include "Streams.h" -namespace aapt { -namespace io { +namespace android { class BigBufferInputStream : public KnownSizeInputStream { public: - inline explicit BigBufferInputStream(const android::BigBuffer* buffer) + inline explicit BigBufferInputStream(const BigBuffer* buffer) : buffer_(buffer), iter_(buffer->begin()) { } virtual ~BigBufferInputStream() = default; @@ -44,18 +42,20 @@ class BigBufferInputStream : public KnownSizeInputStream { size_t TotalSize() const override; + bool ReadFullyAtOffset(void* data, size_t byte_count, off64_t offset) override; + private: DISALLOW_COPY_AND_ASSIGN(BigBufferInputStream); - const android::BigBuffer* buffer_; - android::BigBuffer::const_iterator iter_; + const BigBuffer* buffer_; + BigBuffer::const_iterator iter_; size_t offset_ = 0; size_t bytes_read_ = 0; }; class BigBufferOutputStream : public OutputStream { public: - inline explicit BigBufferOutputStream(android::BigBuffer* buffer) : buffer_(buffer) { + inline explicit BigBufferOutputStream(BigBuffer* buffer) : buffer_(buffer) { } virtual ~BigBufferOutputStream() = default; @@ -70,10 +70,7 @@ class BigBufferOutputStream : public OutputStream { private: DISALLOW_COPY_AND_ASSIGN(BigBufferOutputStream); - android::BigBuffer* buffer_; + BigBuffer* buffer_; }; -} // namespace io -} // namespace aapt - -#endif // AAPT_IO_BIGBUFFERSTREAM_H +} // namespace android
\ No newline at end of file diff --git a/tools/aapt2/io/FileStream.h b/libs/androidfw/include/androidfw/FileStream.h index 62d910f0b06a..fb84a91a00de 100644 --- a/tools/aapt2/io/FileStream.h +++ b/libs/androidfw/include/androidfw/FileStream.h @@ -14,19 +14,16 @@ * limitations under the License. */ -#ifndef AAPT_IO_FILESTREAM_H -#define AAPT_IO_FILESTREAM_H - -#include "io/Io.h" +#pragma once #include <memory> #include <string> +#include "Streams.h" #include "android-base/macros.h" #include "android-base/unique_fd.h" -namespace aapt { -namespace io { +namespace android { constexpr size_t kDefaultBufferCapacity = 4096u; @@ -48,6 +45,8 @@ class FileInputStream : public InputStream { std::string GetError() const override; + bool ReadFullyAtOffset(void* data, size_t byte_count, off64_t offset) override; + private: DISALLOW_COPY_AND_ASSIGN(FileInputStream); @@ -101,7 +100,4 @@ class FileOutputStream : public OutputStream { size_t total_byte_count_ = 0u; }; -} // namespace io -} // namespace aapt - -#endif // AAPT_IO_FILESTREAM_H +} // namespace android
\ No newline at end of file diff --git a/tools/aapt2/compile/Image.h b/libs/androidfw/include/androidfw/Image.h index db0b945e1f18..c18c34c25bf9 100644 --- a/tools/aapt2/compile/Image.h +++ b/libs/androidfw/include/androidfw/Image.h @@ -14,8 +14,7 @@ * limitations under the License. */ -#ifndef AAPT_COMPILE_IMAGE_H -#define AAPT_COMPILE_IMAGE_H +#pragma once #include <cstdint> #include <memory> @@ -24,7 +23,7 @@ #include "android-base/macros.h" -namespace aapt { +namespace android { /** * An in-memory image, loaded from disk, with pixels in RGBA_8888 format. @@ -37,7 +36,7 @@ class Image { * A `height` sized array of pointers, where each element points to a * `width` sized row of RGBA_8888 pixels. */ - std::unique_ptr<uint8_t* []> rows; + std::unique_ptr<uint8_t*[]> rows; /** * The width of the image in RGBA_8888 pixels. This is int32_t because of @@ -72,7 +71,8 @@ struct Range { int32_t end = 0; explicit Range() = default; - inline explicit Range(int32_t s, int32_t e) : start(s), end(e) {} + inline explicit Range(int32_t s, int32_t e) : start(s), end(e) { + } }; inline bool operator==(const Range& left, const Range& right) { @@ -93,7 +93,8 @@ struct Bounds { explicit Bounds() = default; inline explicit Bounds(int32_t l, int32_t t, int32_t r, int32_t b) - : left(l), top(t), right(r), bottom(b) {} + : left(l), top(t), right(r), bottom(b) { + } bool nonZero() const; }; @@ -103,8 +104,8 @@ inline bool Bounds::nonZero() const { } inline bool operator==(const Bounds& left, const Bounds& right) { - return left.left == right.left && left.top == right.top && - left.right == right.right && left.bottom == right.bottom; + return left.left == right.left && left.top == right.top && left.right == right.right && + left.bottom == right.bottom; } /** @@ -115,8 +116,7 @@ inline bool operator==(const Bounds& left, const Bounds& right) { class NinePatch { public: static std::unique_ptr<NinePatch> Create(uint8_t** rows, const int32_t width, - const int32_t height, - std::string* err_out); + const int32_t height, std::string* err_out); /** * Packs the RGBA_8888 data pointed to by pixel into a uint32_t @@ -204,6 +204,4 @@ class NinePatch { ::std::ostream& operator<<(::std::ostream& out, const Bounds& bounds); ::std::ostream& operator<<(::std::ostream& out, const NinePatch& nine_patch); -} // namespace aapt - -#endif /* AAPT_COMPILE_IMAGE_H */ +} // namespace android
\ No newline at end of file diff --git a/tools/aapt2/compile/Png.h b/libs/androidfw/include/androidfw/Png.h index a8b7dd18f12f..2ece43e08110 100644 --- a/tools/aapt2/compile/Png.h +++ b/libs/androidfw/include/androidfw/Png.h @@ -14,22 +14,18 @@ * limitations under the License. */ -#ifndef AAPT_PNG_H -#define AAPT_PNG_H +#pragma once -#include <iostream> #include <string> +#include "BigBuffer.h" +#include "IDiagnostics.h" +#include "Image.h" +#include "Source.h" +#include "Streams.h" #include "android-base/macros.h" -#include "androidfw/BigBuffer.h" -#include "androidfw/IDiagnostics.h" -#include "androidfw/Source.h" -#include "compile/Image.h" -#include "io/Io.h" -#include "process/IResourceTableConsumer.h" - -namespace aapt { +namespace android { // Size in bytes of the PNG signature. constexpr size_t kPngSignatureSize = 8u; @@ -42,32 +38,36 @@ struct PngOptions { */ class Png { public: - explicit Png(android::IDiagnostics* diag) : mDiag(diag) { + explicit Png(IDiagnostics* diag) : mDiag(diag) { } - bool process(const android::Source& source, std::istream* input, android::BigBuffer* outBuffer, + bool process(const Source& source, std::istream* input, BigBuffer* outBuffer, const PngOptions& options); private: DISALLOW_COPY_AND_ASSIGN(Png); - android::IDiagnostics* mDiag; + IDiagnostics* mDiag; }; /** * An InputStream that filters out unimportant PNG chunks. */ -class PngChunkFilter : public io::InputStream { +class PngChunkFilter : public InputStream { public: - explicit PngChunkFilter(android::StringPiece data); + explicit PngChunkFilter(StringPiece data); virtual ~PngChunkFilter() = default; bool Next(const void** buffer, size_t* len) override; void BackUp(size_t count) override; - bool CanRewind() const override { return true; } + bool CanRewind() const override { + return true; + } bool Rewind() override; - size_t ByteCount() const override { return window_start_; } + size_t ByteCount() const override { + return window_start_; + } bool HadError() const override { return !error_msg_.empty(); @@ -81,26 +81,20 @@ class PngChunkFilter : public io::InputStream { bool ConsumeWindow(const void** buffer, size_t* len); - android::StringPiece data_; + StringPiece data_; size_t window_start_ = 0; size_t window_end_ = 0; std::string error_msg_; }; - /** * Reads a PNG from the InputStream into memory as an RGBA Image. */ -std::unique_ptr<Image> ReadPng(IAaptContext* context, const android::Source& source, - io::InputStream* in); +std::unique_ptr<Image> ReadPng(InputStream* in, IDiagnostics* diag); /** * Writes the RGBA Image, with optional 9-patch meta-data, into the OutputStream * as a PNG. */ -bool WritePng(IAaptContext* context, const Image* image, - const NinePatch* nine_patch, io::OutputStream* out, - const PngOptions& options); - -} // namespace aapt - -#endif // AAPT_PNG_H +bool WritePng(const Image* image, const NinePatch* nine_patch, OutputStream* out, + const PngOptions& options, IDiagnostics* diag, bool verbose); +} // namespace android
\ No newline at end of file diff --git a/tools/aapt2/io/Io.h b/libs/androidfw/include/androidfw/Streams.h index e1df23a698f5..89f16205162a 100644 --- a/tools/aapt2/io/Io.h +++ b/libs/androidfw/include/androidfw/Streams.h @@ -14,13 +14,11 @@ * limitations under the License. */ -#ifndef AAPT_IO_IO_H -#define AAPT_IO_IO_H +#pragma once #include <string> -namespace aapt { -namespace io { +namespace android { // InputStream interface that mimics protobuf's ZeroCopyInputStream, // with added error handling methods to better report issues. @@ -41,21 +39,34 @@ class InputStream { virtual void BackUp(size_t count) = 0; // Returns true if this InputStream can rewind. If so, Rewind() can be called. - virtual bool CanRewind() const { return false; }; + virtual bool CanRewind() const { + return false; + }; // Rewinds the stream to the beginning so it can be read again. // Returns true if the rewind succeeded. // This does nothing if CanRewind() returns false. - virtual bool Rewind() { return false; } + virtual bool Rewind() { + return false; + } // Returns the number of bytes that have been read from the stream. virtual size_t ByteCount() const = 0; // Returns an error message if HadError() returned true. - virtual std::string GetError() const { return {}; } + virtual std::string GetError() const { + return {}; + } // Returns true if an error occurred. Errors are permanent. virtual bool HadError() const = 0; + + virtual bool ReadFullyAtOffset(void* data, size_t byte_count, off64_t offset) { + (void)data; + (void)byte_count; + (void)offset; + return false; + } }; // A sub-InputStream interface that knows the total size of its stream. @@ -87,13 +98,12 @@ class OutputStream { virtual size_t ByteCount() const = 0; // Returns an error message if HadError() returned true. - virtual std::string GetError() const { return {}; } + virtual std::string GetError() const { + return {}; + } // Returns true if an error occurred. Errors are permanent. virtual bool HadError() const = 0; }; -} // namespace io -} // namespace aapt - -#endif /* AAPT_IO_IO_H */ +} // namespace android
\ No newline at end of file diff --git a/tools/aapt2/io/FileStream_test.cpp b/libs/androidfw/tests/FileStream_test.cpp index cc9cd2808a0c..978597507a6d 100644 --- a/tools/aapt2/io/FileStream_test.cpp +++ b/libs/androidfw/tests/FileStream_test.cpp @@ -14,20 +14,21 @@ * limitations under the License. */ -#include "io/FileStream.h" +#include "androidfw/FileStream.h" +#include "androidfw/StringPiece.h" #include "android-base/file.h" #include "android-base/macros.h" -#include "test/Test.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" using ::android::StringPiece; using ::testing::Eq; using ::testing::NotNull; using ::testing::StrEq; -namespace aapt { -namespace io { +namespace android { TEST(FileInputStreamTest, NextAndBackup) { std::string input = "this is a cool string"; @@ -123,5 +124,4 @@ TEST(FileOutputStreamTest, NextAndBackup) { EXPECT_THAT(actual, StrEq(input)); } -} // namespace io -} // namespace aapt +} // namespace android diff --git a/tools/aapt2/compile/NinePatch_test.cpp b/libs/androidfw/tests/NinePatch_test.cpp index f54bb2e62842..7ee8e9ebd624 100644 --- a/tools/aapt2/compile/NinePatch_test.cpp +++ b/libs/androidfw/tests/NinePatch_test.cpp @@ -14,11 +14,11 @@ * limitations under the License. */ -#include "compile/Image.h" +#include "androidfw/Image.h" +#include "androidfw/ResourceTypes.h" +#include "gtest/gtest.h" -#include "test/Test.h" - -namespace aapt { +namespace android { // Pixels are in RGBA_8888 packing. @@ -33,16 +33,19 @@ namespace aapt { #define TRANS "\x00\x00\x00\x00" static uint8_t* k2x2[] = { - (uint8_t*)WHITE WHITE, (uint8_t*)WHITE WHITE, + (uint8_t*)WHITE WHITE, + (uint8_t*)WHITE WHITE, }; static uint8_t* kMixedNeutralColor3x3[] = { - (uint8_t*)WHITE BLACK TRANS, (uint8_t*)TRANS RED TRANS, + (uint8_t*)WHITE BLACK TRANS, + (uint8_t*)TRANS RED TRANS, (uint8_t*)WHITE WHITE WHITE, }; static uint8_t* kTransparentNeutralColor3x3[] = { - (uint8_t*)TRANS BLACK TRANS, (uint8_t*)BLACK RED BLACK, + (uint8_t*)TRANS BLACK TRANS, + (uint8_t*)BLACK RED BLACK, (uint8_t*)TRANS BLACK TRANS, }; @@ -66,55 +69,44 @@ static uint8_t* kMultipleStretch10x7[] = { }; static uint8_t* kPadding6x5[] = { - (uint8_t*)WHITE WHITE WHITE WHITE WHITE WHITE, - (uint8_t*)WHITE WHITE WHITE WHITE WHITE WHITE, - (uint8_t*)WHITE WHITE WHITE WHITE WHITE BLACK, - (uint8_t*)WHITE WHITE WHITE WHITE WHITE WHITE, + (uint8_t*)WHITE WHITE WHITE WHITE WHITE WHITE, (uint8_t*)WHITE WHITE WHITE WHITE WHITE WHITE, + (uint8_t*)WHITE WHITE WHITE WHITE WHITE BLACK, (uint8_t*)WHITE WHITE WHITE WHITE WHITE WHITE, (uint8_t*)WHITE WHITE BLACK BLACK WHITE WHITE, }; static uint8_t* kLayoutBoundsWrongEdge3x3[] = { - (uint8_t*)WHITE RED WHITE, (uint8_t*)RED WHITE WHITE, + (uint8_t*)WHITE RED WHITE, + (uint8_t*)RED WHITE WHITE, (uint8_t*)WHITE WHITE WHITE, }; static uint8_t* kLayoutBoundsNotEdgeAligned5x5[] = { - (uint8_t*)WHITE WHITE WHITE WHITE WHITE, - (uint8_t*)WHITE WHITE WHITE WHITE WHITE, - (uint8_t*)WHITE WHITE WHITE WHITE RED, - (uint8_t*)WHITE WHITE WHITE WHITE WHITE, + (uint8_t*)WHITE WHITE WHITE WHITE WHITE, (uint8_t*)WHITE WHITE WHITE WHITE WHITE, + (uint8_t*)WHITE WHITE WHITE WHITE RED, (uint8_t*)WHITE WHITE WHITE WHITE WHITE, (uint8_t*)WHITE WHITE RED WHITE WHITE, }; static uint8_t* kLayoutBounds5x5[] = { - (uint8_t*)WHITE WHITE WHITE WHITE WHITE, - (uint8_t*)WHITE WHITE WHITE WHITE RED, - (uint8_t*)WHITE WHITE WHITE WHITE WHITE, - (uint8_t*)WHITE WHITE WHITE WHITE RED, + (uint8_t*)WHITE WHITE WHITE WHITE WHITE, (uint8_t*)WHITE WHITE WHITE WHITE RED, + (uint8_t*)WHITE WHITE WHITE WHITE WHITE, (uint8_t*)WHITE WHITE WHITE WHITE RED, (uint8_t*)WHITE RED WHITE RED WHITE, }; static uint8_t* kAsymmetricLayoutBounds5x5[] = { - (uint8_t*)WHITE WHITE WHITE WHITE WHITE, - (uint8_t*)WHITE WHITE WHITE WHITE RED, - (uint8_t*)WHITE WHITE WHITE WHITE WHITE, - (uint8_t*)WHITE WHITE WHITE WHITE WHITE, + (uint8_t*)WHITE WHITE WHITE WHITE WHITE, (uint8_t*)WHITE WHITE WHITE WHITE RED, + (uint8_t*)WHITE WHITE WHITE WHITE WHITE, (uint8_t*)WHITE WHITE WHITE WHITE WHITE, (uint8_t*)WHITE RED WHITE WHITE WHITE, }; static uint8_t* kPaddingAndLayoutBounds5x5[] = { - (uint8_t*)WHITE WHITE WHITE WHITE WHITE, - (uint8_t*)WHITE WHITE WHITE WHITE RED, - (uint8_t*)WHITE WHITE WHITE WHITE BLACK, - (uint8_t*)WHITE WHITE WHITE WHITE RED, + (uint8_t*)WHITE WHITE WHITE WHITE WHITE, (uint8_t*)WHITE WHITE WHITE WHITE RED, + (uint8_t*)WHITE WHITE WHITE WHITE BLACK, (uint8_t*)WHITE WHITE WHITE WHITE RED, (uint8_t*)WHITE RED BLACK RED WHITE, }; static uint8_t* kColorfulImage5x5[] = { - (uint8_t*)WHITE BLACK WHITE BLACK WHITE, - (uint8_t*)BLACK RED BLUE GREEN WHITE, - (uint8_t*)BLACK RED GREEN GREEN WHITE, - (uint8_t*)WHITE TRANS BLUE GREEN WHITE, + (uint8_t*)WHITE BLACK WHITE BLACK WHITE, (uint8_t*)BLACK RED BLUE GREEN WHITE, + (uint8_t*)BLACK RED GREEN GREEN WHITE, (uint8_t*)WHITE TRANS BLUE GREEN WHITE, (uint8_t*)WHITE WHITE WHITE WHITE WHITE, }; @@ -145,33 +137,21 @@ static uint8_t* kOutlineTranslucent10x10[] = { }; static uint8_t* kOutlineOffsetTranslucent12x10[] = { - (uint8_t*) - WHITE WHITE WHITE BLACK BLACK BLACK BLACK BLACK BLACK BLACK BLACK WHITE, - (uint8_t*) - WHITE TRANS TRANS TRANS TRANS TRANS TRANS TRANS TRANS TRANS TRANS WHITE, - (uint8_t*) - WHITE TRANS TRANS TRANS TRANS GR_20 GR_20 GR_20 GR_20 TRANS TRANS WHITE, - (uint8_t*) - WHITE TRANS TRANS TRANS TRANS GR_50 GR_50 GR_50 GR_50 TRANS TRANS WHITE, - (uint8_t*) - WHITE TRANS TRANS TRANS GR_20 GR_50 GR_70 GR_70 GR_50 GR_20 TRANS WHITE, - (uint8_t*) - WHITE TRANS TRANS TRANS GR_20 GR_50 GR_70 GR_70 GR_50 GR_20 TRANS WHITE, - (uint8_t*) - WHITE TRANS TRANS TRANS TRANS GR_50 GR_50 GR_50 GR_50 TRANS TRANS WHITE, - (uint8_t*) - WHITE TRANS TRANS TRANS TRANS GR_20 GR_20 GR_20 GR_20 TRANS TRANS WHITE, - (uint8_t*) - WHITE TRANS TRANS TRANS TRANS TRANS TRANS TRANS TRANS TRANS TRANS WHITE, - (uint8_t*) - WHITE WHITE WHITE WHITE WHITE WHITE WHITE WHITE WHITE WHITE WHITE WHITE, + (uint8_t*)WHITE WHITE WHITE BLACK BLACK BLACK BLACK BLACK BLACK BLACK BLACK WHITE, + (uint8_t*)WHITE TRANS TRANS TRANS TRANS TRANS TRANS TRANS TRANS TRANS TRANS WHITE, + (uint8_t*)WHITE TRANS TRANS TRANS TRANS GR_20 GR_20 GR_20 GR_20 TRANS TRANS WHITE, + (uint8_t*)WHITE TRANS TRANS TRANS TRANS GR_50 GR_50 GR_50 GR_50 TRANS TRANS WHITE, + (uint8_t*)WHITE TRANS TRANS TRANS GR_20 GR_50 GR_70 GR_70 GR_50 GR_20 TRANS WHITE, + (uint8_t*)WHITE TRANS TRANS TRANS GR_20 GR_50 GR_70 GR_70 GR_50 GR_20 TRANS WHITE, + (uint8_t*)WHITE TRANS TRANS TRANS TRANS GR_50 GR_50 GR_50 GR_50 TRANS TRANS WHITE, + (uint8_t*)WHITE TRANS TRANS TRANS TRANS GR_20 GR_20 GR_20 GR_20 TRANS TRANS WHITE, + (uint8_t*)WHITE TRANS TRANS TRANS TRANS TRANS TRANS TRANS TRANS TRANS TRANS WHITE, + (uint8_t*)WHITE WHITE WHITE WHITE WHITE WHITE WHITE WHITE WHITE WHITE WHITE WHITE, }; static uint8_t* kOutlineRadius5x5[] = { - (uint8_t*)WHITE BLACK BLACK BLACK WHITE, - (uint8_t*)BLACK TRANS GREEN TRANS WHITE, - (uint8_t*)BLACK GREEN GREEN GREEN WHITE, - (uint8_t*)BLACK TRANS GREEN TRANS WHITE, + (uint8_t*)WHITE BLACK BLACK BLACK WHITE, (uint8_t*)BLACK TRANS GREEN TRANS WHITE, + (uint8_t*)BLACK GREEN GREEN GREEN WHITE, (uint8_t*)BLACK TRANS GREEN TRANS WHITE, (uint8_t*)WHITE WHITE WHITE WHITE WHITE, }; @@ -195,14 +175,12 @@ TEST(NinePatchTest, MixedNeutralColors) { TEST(NinePatchTest, TransparentNeutralColor) { std::string err; - EXPECT_NE(nullptr, - NinePatch::Create(kTransparentNeutralColor3x3, 3, 3, &err)); + EXPECT_NE(nullptr, NinePatch::Create(kTransparentNeutralColor3x3, 3, 3, &err)); } TEST(NinePatchTest, SingleStretchRegion) { std::string err; - std::unique_ptr<NinePatch> nine_patch = - NinePatch::Create(kSingleStretch7x6, 7, 6, &err); + std::unique_ptr<NinePatch> nine_patch = NinePatch::Create(kSingleStretch7x6, 7, 6, &err); ASSERT_NE(nullptr, nine_patch); ASSERT_EQ(1u, nine_patch->horizontal_stretch_regions.size()); @@ -214,8 +192,7 @@ TEST(NinePatchTest, SingleStretchRegion) { TEST(NinePatchTest, MultipleStretchRegions) { std::string err; - std::unique_ptr<NinePatch> nine_patch = - NinePatch::Create(kMultipleStretch10x7, 10, 7, &err); + std::unique_ptr<NinePatch> nine_patch = NinePatch::Create(kMultipleStretch10x7, 10, 7, &err); ASSERT_NE(nullptr, nine_patch); ASSERT_EQ(3u, nine_patch->horizontal_stretch_regions.size()); @@ -231,16 +208,14 @@ TEST(NinePatchTest, MultipleStretchRegions) { TEST(NinePatchTest, InferPaddingFromStretchRegions) { std::string err; - std::unique_ptr<NinePatch> nine_patch = - NinePatch::Create(kMultipleStretch10x7, 10, 7, &err); + std::unique_ptr<NinePatch> nine_patch = NinePatch::Create(kMultipleStretch10x7, 10, 7, &err); ASSERT_NE(nullptr, nine_patch); EXPECT_EQ(Bounds(1, 0, 1, 0), nine_patch->padding); } TEST(NinePatchTest, Padding) { std::string err; - std::unique_ptr<NinePatch> nine_patch = - NinePatch::Create(kPadding6x5, 6, 5, &err); + std::unique_ptr<NinePatch> nine_patch = NinePatch::Create(kPadding6x5, 6, 5, &err); ASSERT_NE(nullptr, nine_patch); EXPECT_EQ(Bounds(1, 1, 1, 1), nine_patch->padding); } @@ -253,15 +228,13 @@ TEST(NinePatchTest, LayoutBoundsAreOnWrongEdge) { TEST(NinePatchTest, LayoutBoundsMustTouchEdges) { std::string err; - EXPECT_EQ(nullptr, - NinePatch::Create(kLayoutBoundsNotEdgeAligned5x5, 5, 5, &err)); + EXPECT_EQ(nullptr, NinePatch::Create(kLayoutBoundsNotEdgeAligned5x5, 5, 5, &err)); EXPECT_FALSE(err.empty()); } TEST(NinePatchTest, LayoutBounds) { std::string err; - std::unique_ptr<NinePatch> nine_patch = - NinePatch::Create(kLayoutBounds5x5, 5, 5, &err); + std::unique_ptr<NinePatch> nine_patch = NinePatch::Create(kLayoutBounds5x5, 5, 5, &err); ASSERT_NE(nullptr, nine_patch); EXPECT_EQ(Bounds(1, 1, 1, 1), nine_patch->layout_bounds); @@ -272,8 +245,7 @@ TEST(NinePatchTest, LayoutBounds) { TEST(NinePatchTest, PaddingAndLayoutBounds) { std::string err; - std::unique_ptr<NinePatch> nine_patch = - NinePatch::Create(kPaddingAndLayoutBounds5x5, 5, 5, &err); + std::unique_ptr<NinePatch> nine_patch = NinePatch::Create(kPaddingAndLayoutBounds5x5, 5, 5, &err); ASSERT_NE(nullptr, nine_patch); EXPECT_EQ(Bounds(1, 1, 1, 1), nine_patch->padding); EXPECT_EQ(Bounds(1, 1, 1, 1), nine_patch->layout_bounds); @@ -281,25 +253,20 @@ TEST(NinePatchTest, PaddingAndLayoutBounds) { TEST(NinePatchTest, RegionColorsAreCorrect) { std::string err; - std::unique_ptr<NinePatch> nine_patch = - NinePatch::Create(kColorfulImage5x5, 5, 5, &err); + std::unique_ptr<NinePatch> nine_patch = NinePatch::Create(kColorfulImage5x5, 5, 5, &err); ASSERT_NE(nullptr, nine_patch); std::vector<uint32_t> expected_colors = { - NinePatch::PackRGBA((uint8_t*)RED), - (uint32_t)android::Res_png_9patch::NO_COLOR, - NinePatch::PackRGBA((uint8_t*)GREEN), - (uint32_t)android::Res_png_9patch::TRANSPARENT_COLOR, - NinePatch::PackRGBA((uint8_t*)BLUE), - NinePatch::PackRGBA((uint8_t*)GREEN), + NinePatch::PackRGBA((uint8_t*)RED), (uint32_t)android::Res_png_9patch::NO_COLOR, + NinePatch::PackRGBA((uint8_t*)GREEN), (uint32_t)android::Res_png_9patch::TRANSPARENT_COLOR, + NinePatch::PackRGBA((uint8_t*)BLUE), NinePatch::PackRGBA((uint8_t*)GREEN), }; EXPECT_EQ(expected_colors, nine_patch->region_colors); } TEST(NinePatchTest, OutlineFromOpaqueImage) { std::string err; - std::unique_ptr<NinePatch> nine_patch = - NinePatch::Create(kOutlineOpaque10x10, 10, 10, &err); + std::unique_ptr<NinePatch> nine_patch = NinePatch::Create(kOutlineOpaque10x10, 10, 10, &err); ASSERT_NE(nullptr, nine_patch); EXPECT_EQ(Bounds(2, 2, 2, 2), nine_patch->outline); EXPECT_EQ(0x000000ffu, nine_patch->outline_alpha); @@ -308,8 +275,7 @@ TEST(NinePatchTest, OutlineFromOpaqueImage) { TEST(NinePatchTest, OutlineFromTranslucentImage) { std::string err; - std::unique_ptr<NinePatch> nine_patch = - NinePatch::Create(kOutlineTranslucent10x10, 10, 10, &err); + std::unique_ptr<NinePatch> nine_patch = NinePatch::Create(kOutlineTranslucent10x10, 10, 10, &err); ASSERT_NE(nullptr, nine_patch); EXPECT_EQ(Bounds(3, 3, 3, 3), nine_patch->outline); EXPECT_EQ(0x000000b3u, nine_patch->outline_alpha); @@ -337,8 +303,7 @@ TEST(NinePatchTest, OutlineFromOffCenterImage) { TEST(NinePatchTest, OutlineRadius) { std::string err; - std::unique_ptr<NinePatch> nine_patch = - NinePatch::Create(kOutlineRadius5x5, 5, 5, &err); + std::unique_ptr<NinePatch> nine_patch = NinePatch::Create(kOutlineRadius5x5, 5, 5, &err); ASSERT_NE(nullptr, nine_patch); EXPECT_EQ(Bounds(0, 0, 0, 0), nine_patch->outline); EXPECT_EQ(3.4142f, nine_patch->outline_radius); @@ -353,8 +318,7 @@ TEST(NinePatchTest, OutlineRadius) { TEST(NinePatchTest, SerializePngEndianness) { std::string err; - std::unique_ptr<NinePatch> nine_patch = - NinePatch::Create(kStretchAndPadding5x5, 5, 5, &err); + std::unique_ptr<NinePatch> nine_patch = NinePatch::Create(kStretchAndPadding5x5, 5, 5, &err); ASSERT_NE(nullptr, nine_patch); size_t len; @@ -374,4 +338,4 @@ TEST(NinePatchTest, SerializePngEndianness) { EXPECT_TRUE(BigEndianOne(cursor + 12)); } -} // namespace aapt +} // namespace android diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl index d14775fa9ad9..5c8758a6aa73 100644 --- a/media/java/android/media/IAudioService.aidl +++ b/media/java/android/media/IAudioService.aidl @@ -739,7 +739,7 @@ interface IAudioService { oneway void stopLoudnessCodecUpdates(int piid); - oneway void addLoudnessCodecInfo(int piid, in LoudnessCodecInfo codecInfo); + oneway void addLoudnessCodecInfo(int piid, int mediaCodecHash, in LoudnessCodecInfo codecInfo); oneway void removeLoudnessCodecInfo(int piid, in LoudnessCodecInfo codecInfo); diff --git a/media/java/android/media/LoudnessCodecConfigurator.java b/media/java/android/media/LoudnessCodecConfigurator.java index 92f337244daf..de9d87c0b28c 100644 --- a/media/java/android/media/LoudnessCodecConfigurator.java +++ b/media/java/android/media/LoudnessCodecConfigurator.java @@ -30,10 +30,10 @@ import androidx.annotation.GuardedBy; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.concurrent.Executor; @@ -47,9 +47,6 @@ import java.util.concurrent.atomic.AtomicBoolean; * parameter updates are defined by the CTA-2075 standard. * <p>A new object should be instantiated for each {@link AudioTrack} with the help * of {@link #create()} or {@link #create(Executor, OnLoudnessCodecUpdateListener)}. - * - * TODO: remove hide once API is final - * @hide */ @FlaggedApi(FLAG_LOUDNESS_CONFIGURATOR_API) public class LoudnessCodecConfigurator { @@ -57,9 +54,6 @@ public class LoudnessCodecConfigurator { /** * Listener used for receiving asynchronous loudness metadata updates. - * - * TODO: remove hide once API is final - * @hide */ @FlaggedApi(FLAG_LOUDNESS_CONFIGURATOR_API) public interface OnLoudnessCodecUpdateListener { @@ -76,9 +70,6 @@ public class LoudnessCodecConfigurator { * @return a Bundle which contains the original computed codecValues * aggregated with user edits. The platform will configure the associated * MediaCodecs with the returned Bundle params. - * - * TODO: remove hide once API is final - * @hide */ @FlaggedApi(FLAG_LOUDNESS_CONFIGURATOR_API) @NonNull @@ -112,9 +103,6 @@ public class LoudnessCodecConfigurator { * Otherwise, use {@link #create(Executor, OnLoudnessCodecUpdateListener)}. * * @return the {@link LoudnessCodecConfigurator} instance - * - * TODO: remove hide once API is final - * @hide */ @FlaggedApi(FLAG_LOUDNESS_CONFIGURATOR_API) public static @NonNull LoudnessCodecConfigurator create() { @@ -133,9 +121,6 @@ public class LoudnessCodecConfigurator { * @param listener used for receiving updates * * @return the {@link LoudnessCodecConfigurator} instance - * - * TODO: remove hide once API is final - * @hide */ @FlaggedApi(FLAG_LOUDNESS_CONFIGURATOR_API) public static @NonNull LoudnessCodecConfigurator create( @@ -200,12 +185,9 @@ public class LoudnessCodecConfigurator { * method will have the effect of clearing the existing set * {@link AudioTrack} and will stop receiving asynchronous * loudness updates - * - * TODO: remove hide once API is final - * @hide */ @FlaggedApi(FLAG_LOUDNESS_CONFIGURATOR_API) - public void setAudioTrack(AudioTrack audioTrack) { + public void setAudioTrack(@Nullable AudioTrack audioTrack) { List<LoudnessCodecInfo> codecInfos; int piid = PLAYER_PIID_INVALID; int oldPiid = PLAYER_PIID_INVALID; @@ -250,10 +232,11 @@ public class LoudnessCodecConfigurator { * previously added. * * @param mediaCodec the codec to start receiving asynchronous loudness - * updates - * - * TODO: remove hide once API is final - * @hide + * updates. The codec has to be in a configured or started + * state in order to add it for loudness updates. + * @throws IllegalArgumentException if the {@code mediaCodec} was not configured, + * does not contain loudness metadata or if it + * was already added before */ @FlaggedApi(FLAG_LOUDNESS_CONFIGURATOR_API) public void addMediaCodec(@NonNull MediaCodec mediaCodec) { @@ -262,31 +245,32 @@ public class LoudnessCodecConfigurator { int piid = PLAYER_PIID_INVALID; final LoudnessCodecInfo mcInfo = getCodecInfo(mc); - if (mcInfo != null) { - synchronized (mConfiguratorLock) { - final AtomicBoolean containsCodec = new AtomicBoolean(false); - Set<MediaCodec> newSet = mMediaCodecs.computeIfPresent(mcInfo, (info, codecSet) -> { - containsCodec.set(!codecSet.add(mc)); - return codecSet; - }); - if (newSet == null) { - newSet = new HashSet<>(); - newSet.add(mc); - mMediaCodecs.put(mcInfo, newSet); - } - if (containsCodec.get()) { - Log.v(TAG, "Loudness configurator already added media codec " + mediaCodec); - return; - } - if (mAudioTrack != null) { - piid = mAudioTrack.getPlayerIId(); - } + if (mcInfo == null) { + throw new IllegalArgumentException("Could not extract codec loudness information"); + } + synchronized (mConfiguratorLock) { + final AtomicBoolean containsCodec = new AtomicBoolean(false); + Set<MediaCodec> newSet = mMediaCodecs.computeIfPresent(mcInfo, (info, codecSet) -> { + containsCodec.set(!codecSet.add(mc)); + return codecSet; + }); + if (newSet == null) { + newSet = new HashSet<>(); + newSet.add(mc); + mMediaCodecs.put(mcInfo, newSet); } - - if (piid != PLAYER_PIID_INVALID) { - mLcDispatcher.addLoudnessCodecInfo(piid, mcInfo); + if (containsCodec.get()) { + throw new IllegalArgumentException( + "Loudness configurator already added " + mediaCodec); + } + if (mAudioTrack != null) { + piid = mAudioTrack.getPlayerIId(); } } + + if (piid != PLAYER_PIID_INVALID) { + mLcDispatcher.addLoudnessCodecInfo(piid, mediaCodec.hashCode(), mcInfo); + } } /** @@ -297,37 +281,44 @@ public class LoudnessCodecConfigurator { * <p>No elements will be removed if the passed mediaCodec was not added before. * * @param mediaCodec the element to remove for receiving asynchronous updates - * - * TODO: remove hide once API is final - * @hide + * @throws IllegalArgumentException if the {@code mediaCodec} was not configured, + * does not contain loudness metadata or if it + * was not added before */ @FlaggedApi(FLAG_LOUDNESS_CONFIGURATOR_API) public void removeMediaCodec(@NonNull MediaCodec mediaCodec) { int piid = PLAYER_PIID_INVALID; LoudnessCodecInfo mcInfo; - AtomicBoolean removed = new AtomicBoolean(false); + AtomicBoolean removedMc = new AtomicBoolean(false); + AtomicBoolean removeInfo = new AtomicBoolean(false); mcInfo = getCodecInfo(Objects.requireNonNull(mediaCodec, "MediaCodec for removeMediaCodec cannot be null")); - if (mcInfo != null) { - synchronized (mConfiguratorLock) { - if (mAudioTrack != null) { - piid = mAudioTrack.getPlayerIId(); + if (mcInfo == null) { + throw new IllegalArgumentException("Could not extract codec loudness information"); + } + synchronized (mConfiguratorLock) { + if (mAudioTrack != null) { + piid = mAudioTrack.getPlayerIId(); + } + mMediaCodecs.computeIfPresent(mcInfo, (format, mcs) -> { + removedMc.set(mcs.remove(mediaCodec)); + if (mcs.isEmpty()) { + // remove the entry + removeInfo.set(true); + return null; } - mMediaCodecs.computeIfPresent(mcInfo, (format, mcs) -> { - removed.set(mcs.remove(mediaCodec)); - if (mcs.isEmpty()) { - // remove the entry - return null; - } - return mcs; - }); + return mcs; + }); + if (!removedMc.get()) { + throw new IllegalArgumentException( + "Loudness configurator does not contain " + mediaCodec); } + } - if (piid != PLAYER_PIID_INVALID && removed.get()) { - mLcDispatcher.removeLoudnessCodecInfo(piid, mcInfo); - } + if (piid != PLAYER_PIID_INVALID && removeInfo.get()) { + mLcDispatcher.removeLoudnessCodecInfo(piid, mcInfo); } } @@ -342,9 +333,6 @@ public class LoudnessCodecConfigurator { * * @return the {@link Bundle} containing the current loudness parameters. Caller is * responsible to update the {@link MediaCodec} - * - * TODO: remove hide once API is final - * @hide */ @FlaggedApi(FLAG_LOUDNESS_CONFIGURATOR_API) @NonNull @@ -375,9 +363,9 @@ public class LoudnessCodecConfigurator { } /** @hide */ - /*package*/ List<MediaCodec> getRegisteredMediaCodecList() { + /*package*/ Map<LoudnessCodecInfo, Set<MediaCodec>> getRegisteredMediaCodecs() { synchronized (mConfiguratorLock) { - return mMediaCodecs.values().stream().flatMap(Collection::stream).toList(); + return mMediaCodecs; } } @@ -397,40 +385,43 @@ public class LoudnessCodecConfigurator { return null; } - final MediaFormat inputFormat = mediaCodec.getInputFormat(); - final String mimeType = inputFormat.getString(MediaFormat.KEY_MIME); - if (MediaFormat.MIMETYPE_AUDIO_AAC.equalsIgnoreCase(mimeType)) { - // check both KEY_AAC_PROFILE and KEY_PROFILE as some codecs may only recognize one of - // these two keys - int aacProfile = -1; - int profile = -1; - try { - aacProfile = inputFormat.getInteger(MediaFormat.KEY_AAC_PROFILE); - } catch (NullPointerException e) { - // does not contain KEY_AAC_PROFILE. do nothing - } - try { - profile = inputFormat.getInteger(MediaFormat.KEY_PROFILE); - } catch (NullPointerException e) { - // does not contain KEY_PROFILE. do nothing - } - if (aacProfile == MediaCodecInfo.CodecProfileLevel.AACObjectXHE - || profile == MediaCodecInfo.CodecProfileLevel.AACObjectXHE) { - lci.metadataType = CODEC_METADATA_TYPE_MPEG_D; + try { + final MediaFormat inputFormat = mediaCodec.getInputFormat(); + final String mimeType = inputFormat.getString(MediaFormat.KEY_MIME); + if (MediaFormat.MIMETYPE_AUDIO_AAC.equalsIgnoreCase(mimeType)) { + // check both KEY_AAC_PROFILE and KEY_PROFILE as some codecs may only recognize + // one of these two keys + int aacProfile = -1; + int profile = -1; + try { + aacProfile = inputFormat.getInteger(MediaFormat.KEY_AAC_PROFILE); + } catch (NullPointerException e) { + // does not contain KEY_AAC_PROFILE. do nothing + } + try { + profile = inputFormat.getInteger(MediaFormat.KEY_PROFILE); + } catch (NullPointerException e) { + // does not contain KEY_PROFILE. do nothing + } + if (aacProfile == MediaCodecInfo.CodecProfileLevel.AACObjectXHE + || profile == MediaCodecInfo.CodecProfileLevel.AACObjectXHE) { + lci.metadataType = CODEC_METADATA_TYPE_MPEG_D; + } else { + lci.metadataType = CODEC_METADATA_TYPE_MPEG_4; + } } else { - lci.metadataType = CODEC_METADATA_TYPE_MPEG_4; + Log.w(TAG, "MediaCodec mime type not supported for loudness annotation"); + return null; } - } else { - Log.w(TAG, "MediaCodec mime type not supported for loudness annotation"); + + final MediaFormat outputFormat = mediaCodec.getOutputFormat(); + lci.isDownmixing = outputFormat.getInteger(MediaFormat.KEY_CHANNEL_COUNT) + < inputFormat.getInteger(MediaFormat.KEY_CHANNEL_COUNT); + } catch (IllegalStateException e) { + Log.e(TAG, "MediaCodec is not configured", e); return null; } - final MediaFormat outputFormat = mediaCodec.getOutputFormat(); - lci.isDownmixing = outputFormat.getInteger(MediaFormat.KEY_CHANNEL_COUNT) - < inputFormat.getInteger(MediaFormat.KEY_CHANNEL_COUNT); - - lci.mediaCodecHashCode = mediaCodec.hashCode(); - return lci; } } diff --git a/media/java/android/media/LoudnessCodecDispatcher.java b/media/java/android/media/LoudnessCodecDispatcher.java index 5237caed27d3..b546a81b0498 100644 --- a/media/java/android/media/LoudnessCodecDispatcher.java +++ b/media/java/android/media/LoudnessCodecDispatcher.java @@ -33,8 +33,10 @@ import androidx.annotation.NonNull; import java.util.HashMap; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.Map.Entry; import java.util.Objects; +import java.util.Set; import java.util.concurrent.Executor; /** @@ -71,33 +73,49 @@ public class LoudnessCodecDispatcher implements CallbackUtil.DispatcherStub { @Override public void dispatchLoudnessCodecParameterChange(int piid, PersistableBundle params) { + if (DEBUG) { + Log.d(TAG, "dispatchLoudnessCodecParameterChange for piid " + piid + + " persistable bundle: " + params); + } mLoudnessListenerMgr.callListeners(listener -> { synchronized (mLock) { mConfiguratorListener.computeIfPresent(listener, (l, lcConfig) -> { // send the appropriate bundle for the user to update if (lcConfig.getAssignedTrackPiid() == piid) { - final List<MediaCodec> mediaCodecs = - lcConfig.getRegisteredMediaCodecList(); - for (MediaCodec mediaCodec : mediaCodecs) { - final String infoKey = Integer.toString(mediaCodec.hashCode()); + final Map<LoudnessCodecInfo, Set<MediaCodec>> mediaCodecsMap = + lcConfig.getRegisteredMediaCodecs(); + for (LoudnessCodecInfo codecInfo : mediaCodecsMap.keySet()) { + final String infoKey = Integer.toString(codecInfo.hashCode()); + Bundle bundle = null; if (params.containsKey(infoKey)) { - Bundle bundle = new Bundle( - params.getPersistableBundle(infoKey)); - if (DEBUG) { - Log.d(TAG, - "Received for piid " + piid + " bundle: " + bundle); + bundle = new Bundle(params.getPersistableBundle(infoKey)); + } + + final Set<MediaCodec> mediaCodecs = mediaCodecsMap.get(codecInfo); + for (MediaCodec mediaCodec : mediaCodecs) { + final String mediaCodecKey = Integer.toString( + mediaCodec.hashCode()); + if (bundle == null && !params.containsKey(mediaCodecKey)) { + continue; + } + boolean canBreak = false; + if (bundle == null) { + // key was set by media codec hash to update single codec + bundle = new Bundle( + params.getPersistableBundle(mediaCodecKey)); + canBreak = true; } bundle = LoudnessCodecUpdatesDispatcherStub.filterLoudnessParams( - l.onLoudnessCodecUpdate(mediaCodec, bundle)); - if (DEBUG) { - Log.d(TAG, "User changed for piid " + piid - + " to filtered bundle: " + bundle); - } + l.onLoudnessCodecUpdate(mediaCodec, + bundle)); if (!bundle.isDefinitelyEmpty()) { mediaCodec.setParameters(bundle); } + if (canBreak) { + break; + } } } } @@ -221,9 +239,10 @@ public class LoudnessCodecDispatcher implements CallbackUtil.DispatcherStub { } /** @hide */ - public void addLoudnessCodecInfo(int piid, @NonNull LoudnessCodecInfo mcInfo) { + public void addLoudnessCodecInfo(int piid, int mediaCodecHash, + @NonNull LoudnessCodecInfo mcInfo) { try { - mAudioService.addLoudnessCodecInfo(piid, mcInfo); + mAudioService.addLoudnessCodecInfo(piid, mediaCodecHash, mcInfo); } catch (RemoteException e) { e.rethrowFromSystemServer(); } diff --git a/media/java/android/media/LoudnessCodecInfo.aidl b/media/java/android/media/LoudnessCodecInfo.aidl index fd695179057d..0ac5646a3047 100644 --- a/media/java/android/media/LoudnessCodecInfo.aidl +++ b/media/java/android/media/LoudnessCodecInfo.aidl @@ -23,7 +23,7 @@ package android.media; * * {@hide} */ -@JavaDerive(equals = true) +@JavaDerive(equals = true, toString = true) parcelable LoudnessCodecInfo { /** Supported codec metadata types for loudness updates. */ @Backing(type="int") @@ -37,7 +37,6 @@ parcelable LoudnessCodecInfo { CODEC_METADATA_TYPE_DTS_UHD = 6 } - int mediaCodecHashCode; CodecMetadataType metadataType; boolean isDownmixing; }
\ No newline at end of file diff --git a/media/java/android/media/tv/ad/TvAdManager.java b/media/java/android/media/tv/ad/TvAdManager.java index aa5a290346b0..2b52c4b107b6 100644 --- a/media/java/android/media/tv/ad/TvAdManager.java +++ b/media/java/android/media/tv/ad/TvAdManager.java @@ -16,6 +16,10 @@ package android.media.tv.ad; +import android.annotation.FlaggedApi; +import android.annotation.SystemService; +import android.content.Context; +import android.media.tv.flags.Flags; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; @@ -23,14 +27,17 @@ import android.util.Log; /** * Central system API to the overall client-side TV AD architecture, which arbitrates interaction * between applications and AD services. - * @hide */ +@FlaggedApi(Flags.FLAG_ENABLE_AD_SERVICE_FW) +@SystemService(Context.TV_AD_SERVICE) public class TvAdManager { + // TODO: implement more methods and unhide APIs. private static final String TAG = "TvAdManager"; private final ITvAdManager mService; private final int mUserId; + /** @hide */ public TvAdManager(ITvAdManager service, int userId) { mService = service; mUserId = userId; @@ -38,6 +45,7 @@ public class TvAdManager { /** * The Session provides the per-session functionality of AD service. + * @hide */ public static final class Session { private final IBinder mToken; diff --git a/media/java/android/media/tv/flags/media_tv.aconfig b/media/java/android/media/tv/flags/media_tv.aconfig index a73d1ff72a17..018eaf6dc32f 100644 --- a/media/java/android/media/tv/flags/media_tv.aconfig +++ b/media/java/android/media/tv/flags/media_tv.aconfig @@ -5,4 +5,11 @@ flag { namespace: "media_tv" description: "Constants for standardizing broadcast visibility types." bug: "222402395" +} + +flag { + name: "enable_ad_service_fw" + namespace: "media_tv" + description: "Enable the TV client-side AD framework." + bug: "303506816" }
\ No newline at end of file diff --git a/media/tests/LoudnessCodecApiTest/src/com/android/loudnesscodecapitest/LoudnessCodecConfiguratorTest.java b/media/tests/LoudnessCodecApiTest/src/com/android/loudnesscodecapitest/LoudnessCodecConfiguratorTest.java index 65a9799431e7..c9e36b7f10bd 100644 --- a/media/tests/LoudnessCodecApiTest/src/com/android/loudnesscodecapitest/LoudnessCodecConfiguratorTest.java +++ b/media/tests/LoudnessCodecApiTest/src/com/android/loudnesscodecapitest/LoudnessCodecConfiguratorTest.java @@ -208,7 +208,7 @@ public class LoudnessCodecConfiguratorTest { verify(mAudioService).startLoudnessCodecUpdates(eq(track.getPlayerIId()), anyList()); mLcc.addMediaCodec(createAndConfigureMediaCodec()); - verify(mAudioService).addLoudnessCodecInfo(eq(track.getPlayerIId()), any()); + verify(mAudioService).addLoudnessCodecInfo(eq(track.getPlayerIId()), anyInt(), any()); } @Test diff --git a/packages/PackageInstaller/Android.bp b/packages/PackageInstaller/Android.bp index 38bd7d5f3944..6213b34034af 100644 --- a/packages/PackageInstaller/Android.bp +++ b/packages/PackageInstaller/Android.bp @@ -49,6 +49,7 @@ android_app { "androidx.fragment_fragment", "androidx.lifecycle_lifecycle-livedata", "androidx.lifecycle_lifecycle-extensions", + "android.content.pm.flags-aconfig-java", ], lint: { @@ -75,6 +76,7 @@ android_app { "androidx.fragment_fragment", "androidx.lifecycle_lifecycle-livedata", "androidx.lifecycle_lifecycle-extensions", + "android.content.pm.flags-aconfig-java", ], aaptflags: ["--product tablet"], @@ -103,6 +105,7 @@ android_app { "androidx.fragment_fragment", "androidx.lifecycle_lifecycle-livedata", "androidx.lifecycle_lifecycle-extensions", + "android.content.pm.flags-aconfig-java", ], aaptflags: ["--product tv"], diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java b/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java index daedb1aac298..8d8254ad4058 100644 --- a/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java +++ b/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java @@ -298,7 +298,14 @@ public class InstallInstalling extends Activity { broadcastIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE); - session.commit(pendingIntent.getIntentSender()); + try { + session.commit(pendingIntent.getIntentSender()); + } catch (Exception e) { + Log.e(LOG_TAG, "Cannot install package: ", e); + launchFailure(PackageInstaller.STATUS_FAILURE, + PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null); + return; + } mCancelButton.setEnabled(false); setFinishOnTouchOutside(false); } else { diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/InstallStart.java b/packages/PackageInstaller/src/com/android/packageinstaller/InstallStart.java index e2107ebe2525..418705845065 100644 --- a/packages/PackageInstaller/src/com/android/packageinstaller/InstallStart.java +++ b/packages/PackageInstaller/src/com/android/packageinstaller/InstallStart.java @@ -16,12 +16,14 @@ package com.android.packageinstaller; +import static android.content.pm.Flags.usePiaV2; import static com.android.packageinstaller.PackageUtil.getMaxTargetSdkVersionForUid; import android.Manifest; import android.app.Activity; import android.app.DialogFragment; import android.app.admin.DevicePolicyManager; +import android.content.ComponentName; import android.content.ContentResolver; import android.content.Intent; import android.content.pm.ApplicationInfo; @@ -57,14 +59,21 @@ public class InstallStart extends Activity { private final boolean mLocalLOGV = false; - // TODO (sumedhsen): Replace with an Android Feature Flag once implemented - private static final boolean USE_PIA_V2 = false; - @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); - if (USE_PIA_V2) { + mPackageManager = getPackageManager(); + if (usePiaV2()) { + Log.i(TAG, "Using Pia V2"); + + mPackageManager.setComponentEnabledSetting(new ComponentName(this, + com.android.packageinstaller.InstallEventReceiver.class), + PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 0); + mPackageManager.setComponentEnabledSetting(new ComponentName(this, + com.android.packageinstaller.v2.model.InstallEventReceiver.class), + PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0); + Intent piaV2 = new Intent(getIntent()); piaV2.putExtra(InstallLaunch.EXTRA_CALLING_PKG_NAME, getCallingPackage()); piaV2.putExtra(InstallLaunch.EXTRA_CALLING_PKG_UID, getLaunchedFromUid()); @@ -74,7 +83,6 @@ public class InstallStart extends Activity { finish(); return; } - mPackageManager = getPackageManager(); mUserManager = getSystemService(UserManager.class); Intent intent = getIntent(); diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/UninstallerActivity.java b/packages/PackageInstaller/src/com/android/packageinstaller/UninstallerActivity.java index 34062a4cbde6..ba627e9e9202 100644 --- a/packages/PackageInstaller/src/com/android/packageinstaller/UninstallerActivity.java +++ b/packages/PackageInstaller/src/com/android/packageinstaller/UninstallerActivity.java @@ -17,8 +17,8 @@ package com.android.packageinstaller; import static android.app.AppOpsManager.MODE_ALLOWED; +import static android.content.pm.Flags.usePiaV2; import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; - import static com.android.packageinstaller.PackageUtil.getMaxTargetSdkVersionForUid; import android.Manifest; @@ -81,9 +81,6 @@ public class UninstallerActivity extends Activity { private String mPackageName; private DialogInfo mDialogInfo; - // TODO (sumedhsen): Replace with an Android Feature Flag once implemented - private static final boolean USE_PIA_V2 = false; - @Override public void onCreate(Bundle icicle) { getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); @@ -92,7 +89,18 @@ public class UninstallerActivity extends Activity { // be stale, if e.g. the app was uninstalled while the activity was destroyed. super.onCreate(null); - if (USE_PIA_V2 && !isTv()) { + if (usePiaV2() && !isTv()) { + Log.i(TAG, "Using Pia V2"); + + PackageManager pm = getPackageManager(); + pm.setComponentEnabledSetting( + new ComponentName(this, com.android.packageinstaller.UninstallEventReceiver.class), + PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 0); + pm.setComponentEnabledSetting( + new ComponentName(this, + com.android.packageinstaller.v2.model.UninstallEventReceiver.class), + PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0); + boolean returnResult = getIntent().getBooleanExtra(Intent.EXTRA_RETURN_RESULT, false); Intent piaV2 = new Intent(getIntent()); piaV2.putExtra(UninstallLaunch.EXTRA_CALLING_PKG_UID, getLaunchedFromUid()); diff --git a/packages/SettingsLib/Spa/build.gradle.kts b/packages/SettingsLib/Spa/build.gradle.kts index 80b944f5749f..60bf48c8b75e 100644 --- a/packages/SettingsLib/Spa/build.gradle.kts +++ b/packages/SettingsLib/Spa/build.gradle.kts @@ -25,11 +25,11 @@ plugins { alias(libs.plugins.kotlin.android) apply false } -val androidTop : String = File(rootDir, "../../../../..").canonicalPath +val androidTop: String = File(rootDir, "../../../../..").canonicalPath allprojects { extra["androidTop"] = androidTop - extra["jetpackComposeVersion"] = "1.6.0-alpha08" + extra["jetpackComposeVersion"] = "1.6.0-beta01" } subprojects { diff --git a/packages/SettingsLib/Spa/spa/build.gradle.kts b/packages/SettingsLib/Spa/spa/build.gradle.kts index 4335173dd706..acd90f3c4f4d 100644 --- a/packages/SettingsLib/Spa/spa/build.gradle.kts +++ b/packages/SettingsLib/Spa/spa/build.gradle.kts @@ -57,13 +57,13 @@ dependencies { api("androidx.slice:slice-builders:1.1.0-alpha02") api("androidx.slice:slice-core:1.1.0-alpha02") api("androidx.slice:slice-view:1.1.0-alpha02") - api("androidx.compose.material3:material3:1.2.0-alpha10") + api("androidx.compose.material3:material3:1.2.0-alpha11") api("androidx.compose.material:material-icons-extended:$jetpackComposeVersion") api("androidx.compose.runtime:runtime-livedata:$jetpackComposeVersion") api("androidx.compose.ui:ui-tooling-preview:$jetpackComposeVersion") api("androidx.lifecycle:lifecycle-livedata-ktx") api("androidx.lifecycle:lifecycle-runtime-compose") - api("androidx.navigation:navigation-compose:2.7.5") + api("androidx.navigation:navigation-compose:2.7.4") api("com.github.PhilJay:MPAndroidChart:v3.1.0-alpha") api("com.google.android.material:material:1.7.0-alpha03") debugApi("androidx.compose.ui:ui-tooling:$jetpackComposeVersion") diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/SettingsTheme.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/SettingsTheme.kt index 26372b6bfd32..c395558b769c 100644 --- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/SettingsTheme.kt +++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/SettingsTheme.kt @@ -17,9 +17,7 @@ package com.android.settingslib.spa.framework.theme import androidx.compose.foundation.isSystemInDarkTheme -import androidx.compose.material.ripple.LocalRippleTheme -import androidx.compose.material.ripple.RippleAlpha -import androidx.compose.material.ripple.RippleTheme +import androidx.compose.material3.LocalContentColor import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider @@ -39,7 +37,7 @@ fun SettingsTheme(content: @Composable () -> Unit) { MaterialTheme(colorScheme = colorScheme, typography = rememberSettingsTypography()) { CompositionLocalProvider( LocalColorScheme provides settingsColorScheme(isDarkTheme), - LocalRippleTheme provides SettingsRippleTheme, + LocalContentColor provides MaterialTheme.colorScheme.onSurface, ) { content() } @@ -52,19 +50,3 @@ object SettingsTheme { @ReadOnlyComposable get() = LocalColorScheme.current } - -private object SettingsRippleTheme : RippleTheme { - @Composable - override fun defaultColor() = MaterialTheme.colorScheme.onSurface - - @Composable - override fun rippleAlpha() = RippleAlpha -} - -/** Alpha levels for all content. */ -private val RippleAlpha = RippleAlpha( - pressedAlpha = 0.48f, - focusedAlpha = 0.48f, - draggedAlpha = 0.32f, - hoveredAlpha = 0.16f, -) diff --git a/packages/SettingsLib/src/com/android/settingslib/PrimarySwitchPreference.java b/packages/SettingsLib/src/com/android/settingslib/PrimarySwitchPreference.java index 0a2d9fc3372e..e41126f03c60 100644 --- a/packages/SettingsLib/src/com/android/settingslib/PrimarySwitchPreference.java +++ b/packages/SettingsLib/src/com/android/settingslib/PrimarySwitchPreference.java @@ -140,12 +140,6 @@ public class PrimarySwitchPreference extends RestrictedPreference { } } - @Override - public void setEnabled(boolean enabled) { - super.setEnabled(enabled); - setSwitchEnabled(enabled); - } - @VisibleForTesting(otherwise = VisibleForTesting.NONE) public boolean isSwitchEnabled() { return mEnableSwitch; diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java index 8b0f19d455d2..29ea25e13835 100644 --- a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java +++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java @@ -22,7 +22,6 @@ import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; import android.app.admin.DevicePolicyManager; import android.content.Context; import android.content.res.TypedArray; -import android.graphics.drawable.Drawable; import android.os.Build; import android.os.UserHandle; import android.text.TextUtils; @@ -237,15 +236,13 @@ public class RestrictedPreferenceHelper { } private void updateDisabledState() { - boolean isEnabled = !(mDisabledByAdmin || mDisabledByAppOps); if (!(mPreference instanceof RestrictedTopLevelPreference)) { - mPreference.setEnabled(isEnabled); + mPreference.setEnabled(!(mDisabledByAdmin || mDisabledByAppOps)); } - Drawable icon = mPreference.getIcon(); - if (!isEnabled && icon != null) { - Utils.convertToGrayscale(icon); - mPreference.setIcon(icon); + if (mPreference instanceof PrimarySwitchPreference) { + ((PrimarySwitchPreference) mPreference) + .setSwitchEnabled(!(mDisabledByAdmin || mDisabledByAppOps)); } } } diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java index f03263b71138..107d5f8a8ae9 100644 --- a/packages/SettingsLib/src/com/android/settingslib/Utils.java +++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java @@ -728,14 +728,4 @@ public class Utils { return false; } - /** - * Convert a drawable to grayscale drawable - */ - public static void convertToGrayscale(@NonNull Drawable drawable) { - ColorMatrix matrix = new ColorMatrix(); - matrix.setSaturation(0.0f); - - ColorMatrixColorFilter filter = new ColorMatrixColorFilter(matrix); - drawable.setColorFilter(filter); - } } diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java index 8412cbaaea36..5c09b1692453 100644 --- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java +++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java @@ -251,6 +251,8 @@ public class SecureSettings { Settings.Secure.STYLUS_HANDWRITING_ENABLED, Settings.Secure.DEFAULT_NOTE_TASK_PROFILE, Settings.Secure.CREDENTIAL_SERVICE, - Settings.Secure.CREDENTIAL_SERVICE_PRIMARY + Settings.Secure.CREDENTIAL_SERVICE_PRIMARY, + Settings.Secure.EVEN_DIMMER_ACTIVATED, + Settings.Secure.EVEN_DIMMER_MIN_NITS }; } diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java index 9197554662d3..b0169a115ec5 100644 --- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java +++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java @@ -110,6 +110,9 @@ public class SecureSettingsValidators { VALIDATORS.put(Secure.FONT_WEIGHT_ADJUSTMENT, ANY_INTEGER_VALIDATOR); VALIDATORS.put(Secure.REDUCE_BRIGHT_COLORS_LEVEL, PERCENTAGE_INTEGER_VALIDATOR); VALIDATORS.put(Secure.REDUCE_BRIGHT_COLORS_PERSIST_ACROSS_REBOOTS, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.EVEN_DIMMER_ACTIVATED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.EVEN_DIMMER_MIN_NITS, + new InclusiveFloatRangeValidator(0.0f, Float.MAX_VALUE)); VALIDATORS.put(Secure.TTS_DEFAULT_RATE, NON_NEGATIVE_INTEGER_VALIDATOR); VALIDATORS.put(Secure.TTS_DEFAULT_PITCH, NON_NEGATIVE_INTEGER_VALIDATOR); VALIDATORS.put(Secure.TTS_DEFAULT_SYNTH, PACKAGE_NAME_VALIDATOR); diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java index a509ba33bad2..a97888949446 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java @@ -2135,6 +2135,15 @@ class SettingsProtoDumpUtil { Settings.Secure.ENHANCED_VOICE_PRIVACY_ENABLED, SecureSettingsProto.ENHANCED_VOICE_PRIVACY_ENABLED); + final long evenDimmerToken = p.start(SecureSettingsProto.EVEN_DIMMER); + dumpSetting(s, p, + Settings.Secure.EVEN_DIMMER_ACTIVATED, + SecureSettingsProto.EvenDimmer.EVEN_DIMMER_ACTIVATED); + dumpSetting(s, p, + Settings.Secure.EVEN_DIMMER_MIN_NITS, + SecureSettingsProto.EvenDimmer.EVEN_DIMMER_MIN_NITS); + p.end(evenDimmerToken); + final long gestureToken = p.start(SecureSettingsProto.GESTURE); dumpSetting(s, p, Settings.Secure.AWARE_ENABLED, diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp index d78038ecee61..7cf562f48ff3 100644 --- a/packages/SystemUI/Android.bp +++ b/packages/SystemUI/Android.bp @@ -242,184 +242,10 @@ filegroup { } filegroup { - name: "SystemUI-test-fakes", - srcs: [ - /* Status bar fakes */ - "tests/src/com/android/systemui/statusbar/pipeline/airplane/data/repository/FakeAirplaneModeRepository.kt", - "tests/src/com/android/systemui/statusbar/pipeline/shared/data/repository/FakeConnectivityRepository.kt", - "tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/FakeWifiRepository.kt", - "tests/src/com/android/systemui/statusbar/pipeline/mobile/util/FakeSubscriptionManagerProxy.kt", - - /* QS fakes */ - "tests/src/com/android/systemui/qs/pipeline/domain/interactor/FakeQSTile.kt", - ], - path: "tests/src", -} - -filegroup { - name: "SystemUI-tests-robolectric-pilots", - srcs: [ - /* Keyguard converted tests */ - // data - "tests/src/com/android/systemui/bouncer/data/repository/SimBouncerRepositoryTest.kt", - "tests/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfigTest.kt", - "tests/src/com/android/systemui/keyguard/data/quickaffordance/FlashlightQuickAffordanceConfigTest.kt", - "tests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigTest.kt", - "tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLegacySettingSyncerTest.kt", - "tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLocalUserSelectionManagerTest.kt", - "tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceRemoteUserSelectionManagerTest.kt", - "tests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceConfigTest.kt", - "tests/src/com/android/systemui/keyguard/data/quickaffordance/QrCodeScannerKeyguardQuickAffordanceConfigTest.kt", - "tests/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfigTest.kt", - "tests/src/com/android/systemui/keyguard/data/quickaffordance/VideoCameraQuickAffordanceConfigTest.kt", - "tests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt", - "tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt", - "tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepositoryTest.kt", - "tests/src/com/android/systemui/keyguard/data/repository/DevicePostureRepositoryTest.kt", - "tests/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepositoryTest.kt", - "tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt", - "tests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt", - "tests/src/com/android/systemui/keyguard/data/repository/TrustRepositoryTest.kt", - // domain - "tests/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractorTest.kt", - "tests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerCallbackInteractorTest.kt", - "tests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt", - "tests/src/com/android/systemui/bouncer/domain/interactor/SimBouncerInteractorTest.kt", - "tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt", - "tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardLongPressInteractorTest.kt", - "tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt", - "tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt", - "tests/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorTest.kt", - // ui - "tests/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModelTest.kt", - "tests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelTest.kt", - "tests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModelTest.kt", - "tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelTest.kt", - "tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelTest.kt", - "tests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelTest.kt", - "tests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt", - // Keyguard helper - "tests/src/com/android/systemui/keyguard/data/quickaffordance/FakeKeyguardQuickAffordanceConfig.kt", - "tests/src/com/android/systemui/dock/DockManagerFake.java", - "tests/src/com/android/systemui/dump/LogBufferHelper.kt", - "tests/src/com/android/systemui/statusbar/phone/FakeKeyguardStateController.java", - - /* Biometric converted tests */ - "tests/src/com/android/systemui/biometrics/BiometricTestExtensions.kt", - "tests/src/com/android/systemui/biometrics/AuthControllerTest.java", - "tests/src/com/android/systemui/biometrics/BiometricDisplayListenerTest.java", - "tests/src/com/android/systemui/biometrics/FaceHelpMessageDeferralTest.kt", - "tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt", - "tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt", - "tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java", - "tests/src/com/android/systemui/biometrics/UdfpsDialogMeasureAdapterTest.java", - "tests/src/com/android/systemui/biometrics/UdfpsDisplayModeTest.java", - "tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacyControllerBaseTest.java", - "tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacyControllerTest.java", - "tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacyControllerWithCoroutinesTest.kt", - "tests/src/com/android/systemui/biometrics/UdfpsShellTest.kt", - "tests/src/com/android/systemui/biometrics/UdfpsViewTest.kt", - - /* Status bar wifi converted tests */ - "tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcherTest.kt", - "tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/DisabledWifiRepositoryTest.kt", - "tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt", - "tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorImplTest.kt", - "tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt", - "tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/FakeMobileIconsInteractor.kt", - "tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/FakeMobileIconInteractor.kt", - - /* Bouncer UI tests */ - "tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt", - "tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt", - "tests/src/com/android/keyguard/KeyguardPinBasedInputViewControllerTest.java", - "tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt", - "tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java", - "tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt", - "tests/src/com/android/keyguard/KeyguardSecurityViewFlipperControllerTest.java", - "tests/src/com/android/keyguard/KeyguardSimPinViewControllerTest.kt", - "tests/src/com/android/keyguard/KeyguardSimPukViewControllerTest.kt", - - /* Communal tests */ - "tests/src/com/android/systemui/communal/data/repository/CommunalWidgetRepositoryImplTest.kt", - "tests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt", - "tests/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprintTest.kt", - - /* Dream tests */ - "tests/src/com/android/systemui/dreams/complication/HideComplicationTouchHandlerTest.java", - "tests/src/com/android/systemui/dreams/conditions/AssistantAttentionConditionTest.java", - "tests/src/com/android/systemui/dreams/conditions/DreamConditionTest.java", - "tests/src/com/android/systemui/dreams/touch/scrim/BouncerlessScrimControllerTest.java", - "tests/src/com/android/systemui/dreams/touch/scrim/ScrimManagerTest.java", - "tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java", - "tests/src/com/android/systemui/dreams/touch/ShadeTouchHandlerTest.java", - "tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt", - "tests/src/com/android/systemui/dreams/DreamOverlayCallbackControllerTest.kt", - "tests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java", - "tests/src/com/android/systemui/dreams/DreamOverlayNotificationCountProviderTest.java", - "tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java", - "tests/src/com/android/systemui/dreams/DreamOverlayStateControllerTest.java", - "tests/src/com/android/systemui/dreams/DreamOverlayStatusBarItemsProviderTest.java", - "tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java", - - /* Smartspace tests */ - "tests/src/com/android/systemui/smartspace/BcSmartspaceConfigProviderTest.kt", - "tests/src/com/android/systemui/smartspace/DreamSmartspaceControllerTest.kt", - "tests/src/com/android/systemui/smartspace/LockscreenAndDreamTargetFilterTest.kt", - "tests/src/com/android/systemui/smartspace/LockscreenPreconditionTest.kt", - - /* Quick Settings new pipeline converted tests */ - "tests/src/com/android/systemui/qs/pipeline/data/**/*Test.kt", - "tests/src/com/android/systemui/qs/pipeline/domain/**/*Test.kt", - "tests/src/com/android/systemui/qs/pipeline/shared/TileSpecTest.kt", - "tests/src/com/android/systemui/qs/tiles/base/**/*.kt", - "tests/src/com/android/systemui/qs/tiles/viewmodel/**/*.kt", - "tests/src/com/android/systemui/qs/tiles/impl/**/*.kt", - - /* Authentication */ - "tests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt", - "tests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt", - - /* Device entry */ - "tests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryRepositoryTest.kt", - "tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorTest.kt", - - /* Bouncer scene */ - "tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt", - "tests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt", - "tests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt", - "tests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt", - "tests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt", - "tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt", - "tests/src/com/android/systemui/bouncer/ui/viewmodel/PinInputViewModelTest.kt", - - /* Lockscreen scene */ - "tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt", - - /* Shade scene */ - "tests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt", - "tests/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModelTest.kt", - - /* Quick Settings scene */ - "tests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt", - - /* Flexiglass / Scene framework tests */ - "tests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt", - "tests/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryTest.kt", - "tests/src/com/android/systemui/scene/data/repository/WindowRootViewVisibilityRepositoryTest.kt", - "tests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt", - "tests/src/com/android/systemui/scene/domain/interactor/WindowRootViewVisibilityInteractorTest.kt", - "tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt", - "tests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt", - - ], - path: "tests/src", -} - -filegroup { name: "SystemUI-tests-multivalent", srcs: [ "multivalentTests/src/**/*.kt", + "multivalentTests/src/**/*.java", ], path: "multivalentTests/src", } @@ -597,8 +423,6 @@ android_robolectric_test { "tests/robolectric/src/**/*.kt", "tests/robolectric/src/**/*.java", ":SystemUI-tests-utils", - ":SystemUI-test-fakes", - ":SystemUI-tests-robolectric-pilots", ":SystemUI-tests-multivalent", ], static_libs: [ diff --git a/packages/SystemUI/aconfig/OWNERS b/packages/SystemUI/aconfig/OWNERS index e1a7a0f84ad0..902ba907a100 100644 --- a/packages/SystemUI/aconfig/OWNERS +++ b/packages/SystemUI/aconfig/OWNERS @@ -1 +1,2 @@ per-file accessibility.aconfig = file:/core/java/android/view/accessibility/OWNERS +per-file biometrics_framework.aconfig = file:/services/core/java/com/android/server/biometrics/OWNERS diff --git a/packages/SystemUI/aconfig/biometrics_framework.aconfig b/packages/SystemUI/aconfig/biometrics_framework.aconfig new file mode 100644 index 000000000000..5fd3b485e9ed --- /dev/null +++ b/packages/SystemUI/aconfig/biometrics_framework.aconfig @@ -0,0 +1,10 @@ +package: "com.android.systemui" + +# NOTE: Keep alphabetized to help limit merge conflicts from multiple simultaneous editors. + +flag { + name: "bp_talkback" + namespace: "biometrics_framework" + description: "Adds talkback directional guidance when using UDFPS with biometric prompt" + bug: "310044658" +}
\ No newline at end of file diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PasswordBouncer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PasswordBouncer.kt index 0b1338305076..eb0688914b9d 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PasswordBouncer.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PasswordBouncer.kt @@ -16,12 +16,10 @@ package com.android.systemui.bouncer.ui.composable +import android.view.ViewTreeObserver import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.ExperimentalLayoutApi import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.imeAnimationTarget import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material3.LocalTextStyle @@ -30,46 +28,56 @@ import androidx.compose.material3.TextField import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.State import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.produceState import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberUpdatedState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.drawBehind import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester +import androidx.compose.ui.focus.onFocusChanged import androidx.compose.ui.geometry.Offset import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.platform.LocalView import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.input.PasswordVisualTransformation import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp +import androidx.core.view.WindowInsetsCompat import com.android.systemui.bouncer.ui.viewmodel.PasswordBouncerViewModel /** UI for the input part of a password-requiring version of the bouncer. */ -@OptIn(ExperimentalLayoutApi::class) @Composable internal fun PasswordBouncer( viewModel: PasswordBouncerViewModel, modifier: Modifier = Modifier, ) { val focusRequester = remember { FocusRequester() } + val isTextFieldFocusRequested by viewModel.isTextFieldFocusRequested.collectAsState() + LaunchedEffect(isTextFieldFocusRequested) { + if (isTextFieldFocusRequested) { + focusRequester.requestFocus() + } + } + val (isTextFieldFocused, onTextFieldFocusChanged) = remember { mutableStateOf(false) } + LaunchedEffect(isTextFieldFocused) { + viewModel.onTextFieldFocusChanged(isFocused = isTextFieldFocused) + } + val password: String by viewModel.password.collectAsState() val isInputEnabled: Boolean by viewModel.isInputEnabled.collectAsState() val animateFailure: Boolean by viewModel.animateFailure.collectAsState() - val density = LocalDensity.current - val isImeVisible by rememberUpdatedState(WindowInsets.imeAnimationTarget.getBottom(density) > 0) + val isImeVisible by isSoftwareKeyboardVisible() LaunchedEffect(isImeVisible) { viewModel.onImeVisibilityChanged(isImeVisible) } DisposableEffect(Unit) { viewModel.onShown() - - // When the UI comes up, request focus on the TextField to bring up the software keyboard. - focusRequester.requestFocus() - onDispose { viewModel.onHidden() } } @@ -104,16 +112,39 @@ internal fun PasswordBouncer( onDone = { viewModel.onAuthenticateKeyPressed() }, ), modifier = - Modifier.focusRequester(focusRequester).drawBehind { - drawLine( - color = color, - start = Offset(x = 0f, y = size.height - lineWidthPx), - end = Offset(size.width, y = size.height - lineWidthPx), - strokeWidth = lineWidthPx, - ) - }, + Modifier.focusRequester(focusRequester) + .onFocusChanged { onTextFieldFocusChanged(it.isFocused) } + .drawBehind { + drawLine( + color = color, + start = Offset(x = 0f, y = size.height - lineWidthPx), + end = Offset(size.width, y = size.height - lineWidthPx), + strokeWidth = lineWidthPx, + ) + }, ) Spacer(Modifier.height(100.dp)) } } + +/** Returns a [State] with `true` when the IME/keyboard is visible and `false` when it's not. */ +@Composable +fun isSoftwareKeyboardVisible(): State<Boolean> { + val view = LocalView.current + val viewTreeObserver = view.viewTreeObserver + + return produceState( + initialValue = false, + key1 = viewTreeObserver, + ) { + val listener = + ViewTreeObserver.OnGlobalLayoutListener { + value = view.rootWindowInsets?.isVisible(WindowInsetsCompat.Type.ime()) ?: false + } + + viewTreeObserver.addOnGlobalLayoutListener(listener) + + awaitDispose { viewTreeObserver.removeOnGlobalLayoutListener(listener) } + } +} diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt index 3fbcf6d77f82..3fbcf6d77f82 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt index 74c922561343..74c922561343 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinBasedInputViewControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPinBasedInputViewControllerTest.java index d41c2497b230..d41c2497b230 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinBasedInputViewControllerTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPinBasedInputViewControllerTest.java diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt index 80d45bcc23dd..80d45bcc23dd 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt index 543b2910bbda..543b2910bbda 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerTest.java index 156e06843d15..156e06843d15 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerTest.java diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityViewFlipperControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityViewFlipperControllerTest.java index 7bb6ef1c8895..7bb6ef1c8895 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityViewFlipperControllerTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityViewFlipperControllerTest.java diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSimPinViewControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSimPinViewControllerTest.kt index 94c3bde29597..94c3bde29597 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSimPinViewControllerTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSimPinViewControllerTest.kt diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSimPukViewControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSimPukViewControllerTest.kt index 7b1f302da6e8..7b1f302da6e8 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSimPukViewControllerTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSimPukViewControllerTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt index 64ddbc7828ac..64ddbc7828ac 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt index 56d3d260d196..56d3d260d196 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/AuthControllerTest.java index 602f3dc29491..602f3dc29491 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/AuthControllerTest.java diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricDisplayListenerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/BiometricDisplayListenerTest.java index 714461b715d6..714461b715d6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricDisplayListenerTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/BiometricDisplayListenerTest.java diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricTestExtensions.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/BiometricTestExtensions.kt index 15633d1baed1..15633d1baed1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricTestExtensions.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/BiometricTestExtensions.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/FaceHelpMessageDeferralTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/FaceHelpMessageDeferralTest.kt index 39f0d570cb26..39f0d570cb26 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/FaceHelpMessageDeferralTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/FaceHelpMessageDeferralTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt index a1b801cd3d3f..a1b801cd3d3f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt index f5b6f14a627c..f5b6f14a627c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsControllerTest.java index e2cab29c473c..e2cab29c473c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsControllerTest.java diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsDialogMeasureAdapterTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsDialogMeasureAdapterTest.java index cd9189bef7f1..cd9189bef7f1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsDialogMeasureAdapterTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsDialogMeasureAdapterTest.java diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsDisplayModeTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsDisplayModeTest.java index 5239966f1923..5239966f1923 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsDisplayModeTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsDisplayModeTest.java diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacyControllerBaseTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacyControllerBaseTest.java index 2ea803c6aa8f..2ea803c6aa8f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacyControllerBaseTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacyControllerBaseTest.java diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacyControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacyControllerTest.java index 98d8b054716c..98d8b054716c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacyControllerTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacyControllerTest.java diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacyControllerWithCoroutinesTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacyControllerWithCoroutinesTest.kt index 79f062536404..79f062536404 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacyControllerWithCoroutinesTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacyControllerWithCoroutinesTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsShellTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsShellTest.kt index 8b374ae54127..8b374ae54127 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsShellTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsShellTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsViewTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsViewTest.kt index 9fbe09619ff1..9fbe09619ff1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsViewTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsViewTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/data/repository/SimBouncerRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/data/repository/SimBouncerRepositoryTest.kt index b391b5a45799..b391b5a45799 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/data/repository/SimBouncerRepositoryTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/data/repository/SimBouncerRepositoryTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractorTest.kt index f0d26b6bbb78..f0d26b6bbb78 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractorTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt index 1e8073246f98..83fb17fa50e4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt @@ -319,10 +319,10 @@ class BouncerInteractorTest : SysuiTestCase() { @Test fun imeHiddenEvent_isTriggered() = testScope.runTest { - val imeHiddenEvent by collectLastValue(underTest.onImeHidden) + val imeHiddenEvent by collectLastValue(underTest.onImeHiddenByUser) runCurrent() - underTest.onImeHidden() + underTest.onImeHiddenByUser() runCurrent() assertThat(imeHiddenEvent).isNotNull() diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerCallbackInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerCallbackInteractorTest.kt index 4aea4f329858..4aea4f329858 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerCallbackInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerCallbackInteractorTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt index bdf5041f8a38..bdf5041f8a38 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/SimBouncerInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/SimBouncerInteractorTest.kt index 8c53c0e3f267..8c53c0e3f267 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/SimBouncerInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/SimBouncerInteractorTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt index 63c992bd7854..45c186dc3a77 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt @@ -23,8 +23,6 @@ import com.android.systemui.authentication.data.repository.FakeAuthenticationRep import com.android.systemui.authentication.shared.model.AuthenticationMethodModel import com.android.systemui.coroutines.collectLastValue import com.android.systemui.scene.SceneTestUtils -import com.android.systemui.scene.shared.model.SceneKey -import com.android.systemui.scene.shared.model.SceneModel import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.test.runTest @@ -76,18 +74,4 @@ class AuthMethodBouncerViewModelTest : SysuiTestCase() { underTest.onAuthenticateButtonClicked() assertThat(animateFailure).isFalse() } - - @Test - fun onImeVisibilityChanged() = - testScope.runTest { - sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "") - sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "") - val onImeHidden by collectLastValue(bouncerInteractor.onImeHidden) - - underTest.onImeVisibilityChanged(true) - assertThat(onImeHidden).isNull() - - underTest.onImeVisibilityChanged(false) - assertThat(onImeHidden).isNotNull() - } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt index 75d6a007b4aa..75d6a007b4aa 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModelTest.kt index 90e0c19b7c65..90e0c19b7c65 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModelTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt index 9b1e9585979a..937c703d6775 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt @@ -20,7 +20,9 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.authentication.shared.model.AuthenticationMethodModel +import com.android.systemui.authentication.shared.model.AuthenticationThrottlingModel import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.coroutines.collectValues import com.android.systemui.res.R import com.android.systemui.scene.SceneTestUtils import com.android.systemui.scene.shared.model.SceneKey @@ -43,7 +45,11 @@ class PasswordBouncerViewModelTest : SysuiTestCase() { private val utils = SceneTestUtils(this) private val testScope = utils.testScope - private val authenticationInteractor = utils.authenticationInteractor() + private val authenticationRepository = utils.authenticationRepository + private val authenticationInteractor = + utils.authenticationInteractor( + repository = authenticationRepository, + ) private val sceneInteractor = utils.sceneInteractor() private val bouncerInteractor = utils.bouncerInteractor( @@ -207,6 +213,101 @@ class PasswordBouncerViewModelTest : SysuiTestCase() { assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer)) } + @Test + fun onImeVisibilityChanged_false_doesNothing() = + testScope.runTest { + val events by collectValues(bouncerInteractor.onImeHiddenByUser) + assertThat(events).isEmpty() + + underTest.onImeVisibilityChanged(isVisible = false) + assertThat(events).isEmpty() + } + + @Test + fun onImeVisibilityChanged_falseAfterTrue_emitsOnImeHiddenByUserEvent() = + testScope.runTest { + val events by collectValues(bouncerInteractor.onImeHiddenByUser) + assertThat(events).isEmpty() + + underTest.onImeVisibilityChanged(isVisible = true) + assertThat(events).isEmpty() + + underTest.onImeVisibilityChanged(isVisible = false) + assertThat(events).hasSize(1) + + underTest.onImeVisibilityChanged(isVisible = true) + assertThat(events).hasSize(1) + + underTest.onImeVisibilityChanged(isVisible = false) + assertThat(events).hasSize(2) + } + + @Test + fun onImeVisibilityChanged_falseAfterTrue_whileThrottling_doesNothing() = + testScope.runTest { + val events by collectValues(bouncerInteractor.onImeHiddenByUser) + assertThat(events).isEmpty() + underTest.onImeVisibilityChanged(isVisible = true) + setThrottling(true) + + underTest.onImeVisibilityChanged(isVisible = false) + + assertThat(events).isEmpty() + } + + @Test + fun isTextFieldFocusRequested_initiallyTrue() = + testScope.runTest { + val isTextFieldFocusRequested by collectLastValue(underTest.isTextFieldFocusRequested) + assertThat(isTextFieldFocusRequested).isTrue() + } + + @Test + fun isTextFieldFocusRequested_focusGained_becomesFalse() = + testScope.runTest { + val isTextFieldFocusRequested by collectLastValue(underTest.isTextFieldFocusRequested) + + underTest.onTextFieldFocusChanged(isFocused = true) + + assertThat(isTextFieldFocusRequested).isFalse() + } + + @Test + fun isTextFieldFocusRequested_focusLost_becomesTrue() = + testScope.runTest { + val isTextFieldFocusRequested by collectLastValue(underTest.isTextFieldFocusRequested) + underTest.onTextFieldFocusChanged(isFocused = true) + + underTest.onTextFieldFocusChanged(isFocused = false) + + assertThat(isTextFieldFocusRequested).isTrue() + } + + @Test + fun isTextFieldFocusRequested_focusLostWhileThrottling_staysFalse() = + testScope.runTest { + val isTextFieldFocusRequested by collectLastValue(underTest.isTextFieldFocusRequested) + underTest.onTextFieldFocusChanged(isFocused = true) + setThrottling(true) + + underTest.onTextFieldFocusChanged(isFocused = false) + + assertThat(isTextFieldFocusRequested).isFalse() + } + + @Test + fun isTextFieldFocusRequested_throttlingCountdownEnds_becomesTrue() = + testScope.runTest { + val isTextFieldFocusRequested by collectLastValue(underTest.isTextFieldFocusRequested) + underTest.onTextFieldFocusChanged(isFocused = true) + setThrottling(true) + underTest.onTextFieldFocusChanged(isFocused = false) + + setThrottling(false) + + assertThat(isTextFieldFocusRequested).isTrue() + } + private fun TestScope.switchToScene(toScene: SceneKey) { val currentScene by collectLastValue(sceneInteractor.desiredScene) val bouncerShown = currentScene?.key != SceneKey.Bouncer && toScene == SceneKey.Bouncer @@ -226,6 +327,35 @@ class PasswordBouncerViewModelTest : SysuiTestCase() { switchToScene(SceneKey.Bouncer) } + private suspend fun TestScope.setThrottling( + isThrottling: Boolean, + failedAttemptCount: Int = 5, + ) { + if (isThrottling) { + repeat(failedAttemptCount) { + authenticationRepository.reportAuthenticationAttempt(false) + } + val remainingTimeMs = 30_000 + authenticationRepository.setThrottleDuration(remainingTimeMs) + authenticationRepository.setThrottling( + AuthenticationThrottlingModel( + failedAttemptCount = failedAttemptCount, + remainingMs = remainingTimeMs, + ) + ) + } else { + authenticationRepository.reportAuthenticationAttempt(true) + authenticationRepository.setThrottling( + AuthenticationThrottlingModel( + failedAttemptCount = failedAttemptCount, + remainingMs = 0, + ) + ) + } + + runCurrent() + } + companion object { private const val ENTER_YOUR_PASSWORD = "Enter your password" private const val WRONG_PASSWORD = "Wrong password" diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt index 862c39c9d4cc..862c39c9d4cc 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt index c30e405ab911..c30e405ab911 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinInputViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PinInputViewModelTest.kt index 55016bb1fc07..55016bb1fc07 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinInputViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PinInputViewModelTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/communal/data/repository/CommunalWidgetRepositoryImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalWidgetRepositoryImplTest.kt index 182712a13174..182712a13174 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/communal/data/repository/CommunalWidgetRepositoryImplTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalWidgetRepositoryImplTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt index 16cfa2398fd5..16cfa2398fd5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprintTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprintTest.kt index a49629252520..a49629252520 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprintTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprintTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryRepositoryTest.kt index 97ac8c62d69d..97ac8c62d69d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryRepositoryTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryRepositoryTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorTest.kt index 910097eece52..910097eece52 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/dock/DockManagerFake.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/dock/DockManagerFake.java index 37540621557f..37540621557f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dock/DockManagerFake.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dock/DockManagerFake.java diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt index 8a35ef11a364..8a35ef11a364 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayCallbackControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayCallbackControllerTest.kt index 2c6c793c97f5..2c6c793c97f5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayCallbackControllerTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayCallbackControllerTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java index 2af6566e993a..2af6566e993a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayNotificationCountProviderTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayNotificationCountProviderTest.java index d379dc6f3dc1..d379dc6f3dc1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayNotificationCountProviderTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayNotificationCountProviderTest.java diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java index e5f997257cfa..e5f997257cfa 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStateControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayStateControllerTest.java index 6d5cd49b8af6..6d5cd49b8af6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStateControllerTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayStateControllerTest.java diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarItemsProviderTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayStatusBarItemsProviderTest.java index 7ff345cdcf7e..7ff345cdcf7e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarItemsProviderTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayStatusBarItemsProviderTest.java diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java index 39db2beb4c44..39db2beb4c44 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/HideComplicationTouchHandlerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/complication/HideComplicationTouchHandlerTest.java index 315a24bfd945..315a24bfd945 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/HideComplicationTouchHandlerTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/complication/HideComplicationTouchHandlerTest.java diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/conditions/AssistantAttentionConditionTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/conditions/AssistantAttentionConditionTest.java index e0c6ab20c6e1..e0c6ab20c6e1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dreams/conditions/AssistantAttentionConditionTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/conditions/AssistantAttentionConditionTest.java diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/conditions/DreamConditionTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/conditions/DreamConditionTest.java index 480754c17616..480754c17616 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dreams/conditions/DreamConditionTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/conditions/DreamConditionTest.java diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java index 3d1efa59a11b..3d1efa59a11b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/ShadeTouchHandlerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/ShadeTouchHandlerTest.java index 6aa821f15ab1..6aa821f15ab1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/ShadeTouchHandlerTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/ShadeTouchHandlerTest.java diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/scrim/BouncerlessScrimControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/scrim/BouncerlessScrimControllerTest.java index 017fdbe8ac01..017fdbe8ac01 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/scrim/BouncerlessScrimControllerTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/scrim/BouncerlessScrimControllerTest.java diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/scrim/ScrimManagerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/scrim/ScrimManagerTest.java index 4ee4a60fbeaf..4ee4a60fbeaf 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/scrim/ScrimManagerTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/scrim/ScrimManagerTest.java diff --git a/packages/SystemUI/tests/src/com/android/systemui/dump/LogBufferHelper.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/dump/LogBufferHelper.kt index 0538227abd3f..0538227abd3f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dump/LogBufferHelper.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dump/LogBufferHelper.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfigTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfigTest.kt index 977f1db44258..977f1db44258 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfigTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfigTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/FakeKeyguardQuickAffordanceConfig.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/FakeKeyguardQuickAffordanceConfig.kt index 548b5646f5d4..548b5646f5d4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/FakeKeyguardQuickAffordanceConfig.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/FakeKeyguardQuickAffordanceConfig.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/FlashlightQuickAffordanceConfigTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/FlashlightQuickAffordanceConfigTest.kt index 4ae144c03314..4ae144c03314 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/FlashlightQuickAffordanceConfigTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/FlashlightQuickAffordanceConfigTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigTest.kt index 7d68cc0a3560..7d68cc0a3560 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLegacySettingSyncerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLegacySettingSyncerTest.kt index 26fcb234843d..26fcb234843d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLegacySettingSyncerTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLegacySettingSyncerTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLocalUserSelectionManagerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLocalUserSelectionManagerTest.kt index 99a01858471c..99a01858471c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLocalUserSelectionManagerTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLocalUserSelectionManagerTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceRemoteUserSelectionManagerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceRemoteUserSelectionManagerTest.kt index a1c9f87ee7bc..a1c9f87ee7bc 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceRemoteUserSelectionManagerTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceRemoteUserSelectionManagerTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceConfigTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceConfigTest.kt index b15352bfe6ab..b15352bfe6ab 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceConfigTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceConfigTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/QrCodeScannerKeyguardQuickAffordanceConfigTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/QrCodeScannerKeyguardQuickAffordanceConfigTest.kt index 521dea34513e..521dea34513e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/QrCodeScannerKeyguardQuickAffordanceConfigTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/QrCodeScannerKeyguardQuickAffordanceConfigTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfigTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfigTest.kt index 02db0d7a9a50..a613ad8852f6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfigTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfigTest.kt @@ -29,17 +29,16 @@ import com.android.systemui.animation.ActivityLaunchAnimator import com.android.systemui.animation.Expandable import com.android.systemui.common.shared.model.ContentDescription import com.android.systemui.common.shared.model.Icon +import com.android.systemui.coroutines.collectLastValue import com.android.systemui.plugins.ActivityStarter import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.whenever import com.android.systemui.wallet.controller.QuickAccessWalletController import com.google.common.truth.Truth.assertThat -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.onEach -import kotlinx.coroutines.test.UnconfinedTestDispatcher -import kotlinx.coroutines.test.runBlockingTest +import kotlinx.coroutines.test.StandardTestDispatcher +import kotlinx.coroutines.test.TestDispatcher +import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test @@ -48,7 +47,6 @@ import org.mockito.Mock import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations -@OptIn(ExperimentalCoroutinesApi::class) @SmallTest @RunWith(AndroidJUnit4::class) class QuickAccessWalletKeyguardQuickAffordanceConfigTest : SysuiTestCase() { @@ -56,26 +54,32 @@ class QuickAccessWalletKeyguardQuickAffordanceConfigTest : SysuiTestCase() { @Mock private lateinit var walletController: QuickAccessWalletController @Mock private lateinit var activityStarter: ActivityStarter + private lateinit var testDispatcher: TestDispatcher + private lateinit var testScope: TestScope + private lateinit var underTest: QuickAccessWalletKeyguardQuickAffordanceConfig @Before fun setUp() { MockitoAnnotations.initMocks(this) + testDispatcher = StandardTestDispatcher() + testScope = TestScope(testDispatcher) + underTest = QuickAccessWalletKeyguardQuickAffordanceConfig( context, + testDispatcher, walletController, activityStarter, ) } @Test - fun affordance_keyguardShowing_hasWalletCard_visibleModel() = runBlockingTest { + fun affordance_keyguardShowing_hasWalletCard_visibleModel() = testScope.runTest { setUpState() - var latest: KeyguardQuickAffordanceConfig.LockScreenState? = null - val job = underTest.lockScreenState.onEach { latest = it }.launchIn(this) + val latest by collectLastValue(underTest.lockScreenState) val visibleModel = latest as KeyguardQuickAffordanceConfig.LockScreenState.Visible assertThat(visibleModel.icon) @@ -88,77 +92,61 @@ class QuickAccessWalletKeyguardQuickAffordanceConfigTest : SysuiTestCase() { ), ) ) - job.cancel() } @Test - fun affordance_keyguardShowing_hasNonPaymentCard_modelIsNone() = - runTest(UnconfinedTestDispatcher()) { + fun affordance_keyguardShowing_hasNonPaymentCard_modelIsNone() = testScope.runTest { setUpState(cardType = WalletCard.CARD_TYPE_NON_PAYMENT) - var latest: KeyguardQuickAffordanceConfig.LockScreenState? = null - val job = underTest.lockScreenState.onEach { latest = it }.launchIn(this) + val latest by collectLastValue(underTest.lockScreenState) assertThat(latest).isEqualTo(KeyguardQuickAffordanceConfig.LockScreenState.Hidden) - job.cancel() } @Test - fun affordance_keyguardShowing_hasPaymentCard_visibleModel() = - runTest(UnconfinedTestDispatcher()) { - setUpState(cardType = WalletCard.CARD_TYPE_PAYMENT) - var latest: KeyguardQuickAffordanceConfig.LockScreenState? = null - - val job = underTest.lockScreenState.onEach { latest = it }.launchIn(this) - - val visibleModel = latest as KeyguardQuickAffordanceConfig.LockScreenState.Visible - assertThat(visibleModel.icon) - .isEqualTo( - Icon.Loaded( - drawable = ICON, - contentDescription = - ContentDescription.Resource( - res = R.string.accessibility_wallet_button, - ), - ) + fun affordance_keyguardShowing_hasPaymentCard_visibleModel() = testScope.runTest { + setUpState(cardType = WalletCard.CARD_TYPE_PAYMENT) + + val latest by collectLastValue(underTest.lockScreenState) + + val visibleModel = latest as KeyguardQuickAffordanceConfig.LockScreenState.Visible + assertThat(visibleModel.icon) + .isEqualTo( + Icon.Loaded( + drawable = ICON, + contentDescription = + ContentDescription.Resource( + res = R.string.accessibility_wallet_button, + ), ) - job.cancel() - } + ) + } @Test - fun affordance_walletFeatureNotEnabled_modelIsNone() = runBlockingTest { + fun affordance_walletFeatureNotEnabled_modelIsNone() = testScope.runTest { setUpState(isWalletFeatureAvailable = false) - var latest: KeyguardQuickAffordanceConfig.LockScreenState? = null - val job = underTest.lockScreenState.onEach { latest = it }.launchIn(this) + val latest by collectLastValue(underTest.lockScreenState) assertThat(latest).isEqualTo(KeyguardQuickAffordanceConfig.LockScreenState.Hidden) - - job.cancel() } @Test - fun affordance_queryNotSuccessful_modelIsNone() = runBlockingTest { + fun affordance_queryNotSuccessful_modelIsNone() = testScope.runTest { setUpState(isWalletQuerySuccessful = false) - var latest: KeyguardQuickAffordanceConfig.LockScreenState? = null - val job = underTest.lockScreenState.onEach { latest = it }.launchIn(this) + val latest by collectLastValue(underTest.lockScreenState) assertThat(latest).isEqualTo(KeyguardQuickAffordanceConfig.LockScreenState.Hidden) - - job.cancel() } @Test - fun affordance_noSelectedCard_modelIsNone() = runBlockingTest { + fun affordance_noSelectedCard_modelIsNone() = testScope.runTest { setUpState(hasSelectedCard = false) - var latest: KeyguardQuickAffordanceConfig.LockScreenState? = null - val job = underTest.lockScreenState.onEach { latest = it }.launchIn(this) + val latest by collectLastValue(underTest.lockScreenState) assertThat(latest).isEqualTo(KeyguardQuickAffordanceConfig.LockScreenState.Hidden) - - job.cancel() } @Test @@ -179,7 +167,7 @@ class QuickAccessWalletKeyguardQuickAffordanceConfigTest : SysuiTestCase() { } @Test - fun getPickerScreenState_default() = runTest { + fun getPickerScreenState_default() = testScope.runTest { setUpState() assertThat(underTest.getPickerScreenState()) @@ -187,7 +175,7 @@ class QuickAccessWalletKeyguardQuickAffordanceConfigTest : SysuiTestCase() { } @Test - fun getPickerScreenState_unavailable() = runTest { + fun getPickerScreenState_unavailable() = testScope.runTest { setUpState( isWalletServiceAvailable = false, ) @@ -197,7 +185,7 @@ class QuickAccessWalletKeyguardQuickAffordanceConfigTest : SysuiTestCase() { } @Test - fun getPickerScreenState_disabledWhenTheFeatureIsNotEnabled() = runTest { + fun getPickerScreenState_disabledWhenTheFeatureIsNotEnabled() = testScope.runTest { setUpState( isWalletFeatureAvailable = false, ) @@ -207,7 +195,7 @@ class QuickAccessWalletKeyguardQuickAffordanceConfigTest : SysuiTestCase() { } @Test - fun getPickerScreenState_disabledWhenThereIsNoCard() = runTest { + fun getPickerScreenState_disabledWhenThereIsNoCard() = testScope.runTest { setUpState( hasSelectedCard = false, ) diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/VideoCameraQuickAffordanceConfigTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/VideoCameraQuickAffordanceConfigTest.kt index a9b9c9011636..a9b9c9011636 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/VideoCameraQuickAffordanceConfigTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/VideoCameraQuickAffordanceConfigTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt index 4587ea6dbdc8..4587ea6dbdc8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt index 45aca175657e..45aca175657e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepositoryTest.kt index 2b7221ec192c..2b7221ec192c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepositoryTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepositoryTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DevicePostureRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/DevicePostureRepositoryTest.kt index ae6c5b7b36b0..ae6c5b7b36b0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DevicePostureRepositoryTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/DevicePostureRepositoryTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepositoryTest.kt index 567e0a9717fc..567e0a9717fc 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepositoryTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepositoryTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt index 6c4bb372bc3a..6c4bb372bc3a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt index 7242cb20dc77..7242cb20dc77 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/TrustRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/TrustRepositoryTest.kt index ee47c58f4002..ee47c58f4002 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/TrustRepositoryTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/TrustRepositoryTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt index 706f94e412ac..706f94e412ac 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardLongPressInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardLongPressInteractorTest.kt index 98f0211587ea..98f0211587ea 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardLongPressInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardLongPressInteractorTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt index bc4bae0ed959..bc4bae0ed959 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt index 4f7d9444020c..4f7d9444020c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorTest.kt index b483085cf1e5..b483085cf1e5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelTest.kt index fd125e099f1b..fd125e099f1b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModelTest.kt index cf2012989624..cf2012989624 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModelTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt index d07836d3abce..d07836d3abce 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelTest.kt index ba72b4c95a44..ba72b4c95a44 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelTest.kt index 3536d5c77c93..3536d5c77c93 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelTest.kt index d0772270ed5e..d0772270ed5e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt index 6cab023d59b0..6cab023d59b0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/AutoAddSettingsRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/data/repository/AutoAddSettingsRepositoryTest.kt index d277fcab3690..d277fcab3690 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/AutoAddSettingsRepositoryTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/data/repository/AutoAddSettingsRepositoryTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/CustomTileAddedSharedPreferencesRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/data/repository/CustomTileAddedSharedPreferencesRepositoryTest.kt index 3db676d68f42..3db676d68f42 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/CustomTileAddedSharedPreferencesRepositoryTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/data/repository/CustomTileAddedSharedPreferencesRepositoryTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/InstalledTilesComponentRepositoryImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/data/repository/InstalledTilesComponentRepositoryImplTest.kt index 070e07a75d23..070e07a75d23 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/InstalledTilesComponentRepositoryImplTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/data/repository/InstalledTilesComponentRepositoryImplTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/QSSettingsRestoredBroadcastRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/data/repository/QSSettingsRestoredBroadcastRepositoryTest.kt index ff8a9bd019fb..ff8a9bd019fb 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/QSSettingsRestoredBroadcastRepositoryTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/data/repository/QSSettingsRestoredBroadcastRepositoryTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/TileSpecSettingsRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/data/repository/TileSpecSettingsRepositoryTest.kt index f7c3b213730c..f7c3b213730c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/TileSpecSettingsRepositoryTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/data/repository/TileSpecSettingsRepositoryTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/TilesSettingConverterTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/data/repository/TilesSettingConverterTest.kt index 9516c2181ac0..9516c2181ac0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/TilesSettingConverterTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/data/repository/TilesSettingConverterTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/UserAutoAddRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/data/repository/UserAutoAddRepositoryTest.kt index 36e860e37ffa..36e860e37ffa 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/UserAutoAddRepositoryTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/data/repository/UserAutoAddRepositoryTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/UserTileSpecRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/data/repository/UserTileSpecRepositoryTest.kt index d4a9fabd6806..d4a9fabd6806 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/UserTileSpecRepositoryTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/data/repository/UserTileSpecRepositoryTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/AutoAddableSettingListTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/autoaddable/AutoAddableSettingListTest.kt index 4454a3cb15fc..4454a3cb15fc 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/AutoAddableSettingListTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/autoaddable/AutoAddableSettingListTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/AutoAddableSettingTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/autoaddable/AutoAddableSettingTest.kt index d153e9d1d361..d153e9d1d361 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/AutoAddableSettingTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/autoaddable/AutoAddableSettingTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/CallbackControllerAutoAddableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/autoaddable/CallbackControllerAutoAddableTest.kt index ec139e4c515e..ec139e4c515e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/CallbackControllerAutoAddableTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/autoaddable/CallbackControllerAutoAddableTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/CastAutoAddableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/autoaddable/CastAutoAddableTest.kt index 4fae532d4174..4fae532d4174 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/CastAutoAddableTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/autoaddable/CastAutoAddableTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/DataSaverAutoAddableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/autoaddable/DataSaverAutoAddableTest.kt index 9e2d1f885e2d..9e2d1f885e2d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/DataSaverAutoAddableTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/autoaddable/DataSaverAutoAddableTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/DeviceControlsAutoAddableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/autoaddable/DeviceControlsAutoAddableTest.kt index 0116bd9575d8..0116bd9575d8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/DeviceControlsAutoAddableTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/autoaddable/DeviceControlsAutoAddableTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/HotspotAutoAddableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/autoaddable/HotspotAutoAddableTest.kt index e7ea9a66450c..e7ea9a66450c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/HotspotAutoAddableTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/autoaddable/HotspotAutoAddableTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/NightDisplayAutoAddableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/autoaddable/NightDisplayAutoAddableTest.kt index 20fd3601f9ef..20fd3601f9ef 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/NightDisplayAutoAddableTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/autoaddable/NightDisplayAutoAddableTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/ReduceBrightColorsAutoAddableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/autoaddable/ReduceBrightColorsAutoAddableTest.kt index 19ac63c36cab..19ac63c36cab 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/ReduceBrightColorsAutoAddableTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/autoaddable/ReduceBrightColorsAutoAddableTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/SafetyCenterAutoAddableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/autoaddable/SafetyCenterAutoAddableTest.kt index d645ee34619b..d645ee34619b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/SafetyCenterAutoAddableTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/autoaddable/SafetyCenterAutoAddableTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/WalletAutoAddableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/autoaddable/WalletAutoAddableTest.kt index 83ff35d8022d..83ff35d8022d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/WalletAutoAddableTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/autoaddable/WalletAutoAddableTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/WorkTileAutoAddableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/autoaddable/WorkTileAutoAddableTest.kt index adccc84e494b..adccc84e494b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/WorkTileAutoAddableTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/autoaddable/WorkTileAutoAddableTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/interactor/AutoAddInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/interactor/AutoAddInteractorTest.kt index 41a7ec03408d..41a7ec03408d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/interactor/AutoAddInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/interactor/AutoAddInteractorTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractorImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractorImplTest.kt index 8c896a6a1709..8c896a6a1709 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractorImplTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractorImplTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/interactor/FakeQSTile.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/interactor/FakeQSTile.kt index 7e0e7d1f46e8..7e0e7d1f46e8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/interactor/FakeQSTile.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/interactor/FakeQSTile.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/interactor/PanelInteractorImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/interactor/PanelInteractorImplTest.kt index 0d9711588a1f..0d9711588a1f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/interactor/PanelInteractorImplTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/interactor/PanelInteractorImplTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/interactor/RestoreReconciliationInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/interactor/RestoreReconciliationInteractorTest.kt index f73cab8a10a3..f73cab8a10a3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/interactor/RestoreReconciliationInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/interactor/RestoreReconciliationInteractorTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/shared/TileSpecTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/shared/TileSpecTest.kt index 558e7694b54c..558e7694b54c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/shared/TileSpecTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/shared/TileSpecTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/actions/QSTileIntentUserInputHandlerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/base/actions/QSTileIntentUserInputHandlerTest.kt index bd1c310ab8de..bd1c310ab8de 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/actions/QSTileIntentUserInputHandlerTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/base/actions/QSTileIntentUserInputHandlerTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/analytics/QSTileAnalyticsTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/base/analytics/QSTileAnalyticsTest.kt index 9861606fd1b1..9861606fd1b1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/analytics/QSTileAnalyticsTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/base/analytics/QSTileAnalyticsTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/interactor/DisabledByPolicyInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/base/interactor/DisabledByPolicyInteractorTest.kt index 2bdc154dd885..2bdc154dd885 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/interactor/DisabledByPolicyInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/base/interactor/DisabledByPolicyInteractorTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/logging/QSTileLoggerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/base/logging/QSTileLoggerTest.kt index 92c2d743c262..92c2d743c262 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/logging/QSTileLoggerTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/base/logging/QSTileLoggerTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/impl/airplate/domain/interactor/AirplaneModeTileDataInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/airplate/domain/interactor/AirplaneModeTileDataInteractorTest.kt index 937744db500e..937744db500e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/impl/airplate/domain/interactor/AirplaneModeTileDataInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/airplate/domain/interactor/AirplaneModeTileDataInteractorTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/impl/airplate/domain/interactor/AirplaneModeTileUserActionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/airplate/domain/interactor/AirplaneModeTileUserActionInteractorTest.kt index 81bde8188f5e..81bde8188f5e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/impl/airplate/domain/interactor/AirplaneModeTileUserActionInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/airplate/domain/interactor/AirplaneModeTileUserActionInteractorTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/impl/custom/CustomTileDefaultsRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/custom/CustomTileDefaultsRepositoryTest.kt index 89ba69fce9ad..89ba69fce9ad 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/impl/custom/CustomTileDefaultsRepositoryTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/custom/CustomTileDefaultsRepositoryTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/impl/custom/CustomTilePackageUpdatesRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/custom/CustomTilePackageUpdatesRepositoryTest.kt index 4a221134ce67..4a221134ce67 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/impl/custom/CustomTilePackageUpdatesRepositoryTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/custom/CustomTilePackageUpdatesRepositoryTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/impl/custom/data/repository/CustomTileRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/custom/data/repository/CustomTileRepositoryTest.kt index cf076c557765..cf076c557765 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/impl/custom/data/repository/CustomTileRepositoryTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/custom/data/repository/CustomTileRepositoryTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/impl/custom/domain/interactor/CustomTileInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/custom/domain/interactor/CustomTileInteractorTest.kt index eebb145ef384..eebb145ef384 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/impl/custom/domain/interactor/CustomTileInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/custom/domain/interactor/CustomTileInteractorTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/viewmodel/QSTileConfigProviderTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/viewmodel/QSTileConfigProviderTest.kt index 5eca8caa7d15..5eca8caa7d15 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/viewmodel/QSTileConfigProviderTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/viewmodel/QSTileConfigProviderTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelTest.kt index 3a0ebdbd6a17..3a0ebdbd6a17 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelUserInputTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelUserInputTest.kt index 22fb152aee44..22fb152aee44 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelUserInputTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelUserInputTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt index 42e27ba12f42..42e27ba12f42 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt index c953743fd272..18b7168098ab 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt @@ -30,6 +30,7 @@ import com.android.systemui.authentication.data.repository.FakeAuthenticationRep import com.android.systemui.authentication.shared.model.AuthenticationMethodModel import com.android.systemui.bouncer.domain.interactor.BouncerActionButtonInteractor import com.android.systemui.bouncer.ui.viewmodel.BouncerViewModel +import com.android.systemui.bouncer.ui.viewmodel.PasswordBouncerViewModel import com.android.systemui.bouncer.ui.viewmodel.PinBouncerViewModel import com.android.systemui.coroutines.collectLastValue import com.android.systemui.flags.Flags @@ -777,11 +778,11 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() { private suspend fun TestScope.dismissIme( showImeBeforeDismissing: Boolean = true, ) { - bouncerViewModel.authMethodViewModel.value?.apply { + (bouncerViewModel.authMethodViewModel.value as? PasswordBouncerViewModel)?.let { if (showImeBeforeDismissing) { - onImeVisibilityChanged(true) + it.onImeVisibilityChanged(true) } - onImeVisibilityChanged(false) + it.onImeVisibilityChanged(false) runCurrent() } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryTest.kt index ddeb05b39e53..ddeb05b39e53 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/data/repository/WindowRootViewVisibilityRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/data/repository/WindowRootViewVisibilityRepositoryTest.kt index 7ae501d05fcd..7ae501d05fcd 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/scene/data/repository/WindowRootViewVisibilityRepositoryTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/data/repository/WindowRootViewVisibilityRepositoryTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt index 7f4bbbe36768..7f4bbbe36768 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/domain/interactor/WindowRootViewVisibilityInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/WindowRootViewVisibilityInteractorTest.kt index 8be4eeb7be7a..8be4eeb7be7a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/scene/domain/interactor/WindowRootViewVisibilityInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/WindowRootViewVisibilityInteractorTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt index adc1c61da50a..3cb97e369a67 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt @@ -479,7 +479,7 @@ class SceneContainerStartableTest : SysuiTestCase() { underTest.start() runCurrent() - bouncerInteractor.onImeHidden() + bouncerInteractor.onImeHiddenByUser() runCurrent() assertThat(currentSceneKey).isEqualTo(SceneKey.Lockscreen) diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt index c89cd9e0c1f1..c89cd9e0c1f1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModelTest.kt index 77ddf15c41ad..77ddf15c41ad 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModelTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt index e2640af136a7..e2640af136a7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/smartspace/BcSmartspaceConfigProviderTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/smartspace/BcSmartspaceConfigProviderTest.kt index cb83e7c7adbc..cb83e7c7adbc 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/smartspace/BcSmartspaceConfigProviderTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/smartspace/BcSmartspaceConfigProviderTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/smartspace/DreamSmartspaceControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/smartspace/DreamSmartspaceControllerTest.kt index e09385934991..e09385934991 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/smartspace/DreamSmartspaceControllerTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/smartspace/DreamSmartspaceControllerTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenAndDreamTargetFilterTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/smartspace/LockscreenAndDreamTargetFilterTest.kt index 886c61ae29dd..886c61ae29dd 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenAndDreamTargetFilterTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/smartspace/LockscreenAndDreamTargetFilterTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenPreconditionTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/smartspace/LockscreenPreconditionTest.kt index 0b5aea7d8683..0b5aea7d8683 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenPreconditionTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/smartspace/LockscreenPreconditionTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/FakeKeyguardStateController.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/FakeKeyguardStateController.java index c669c6f6fb1c..c669c6f6fb1c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/FakeKeyguardStateController.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/FakeKeyguardStateController.java diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/airplane/data/repository/FakeAirplaneModeRepository.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/airplane/data/repository/FakeAirplaneModeRepository.kt index 638925d0a705..638925d0a705 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/airplane/data/repository/FakeAirplaneModeRepository.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/airplane/data/repository/FakeAirplaneModeRepository.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/FakeMobileIconInteractor.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/FakeMobileIconInteractor.kt index 5f4d7bf6f371..5f4d7bf6f371 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/FakeMobileIconInteractor.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/FakeMobileIconInteractor.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/FakeMobileIconsInteractor.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/FakeMobileIconsInteractor.kt index 75d1869adc7c..75d1869adc7c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/FakeMobileIconsInteractor.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/FakeMobileIconsInteractor.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/util/FakeSubscriptionManagerProxy.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/mobile/util/FakeSubscriptionManagerProxy.kt index a80238167b85..a80238167b85 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/util/FakeSubscriptionManagerProxy.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/mobile/util/FakeSubscriptionManagerProxy.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/data/repository/FakeConnectivityRepository.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/data/repository/FakeConnectivityRepository.kt index 28d632d9fcea..28d632d9fcea 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/data/repository/FakeConnectivityRepository.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/data/repository/FakeConnectivityRepository.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/FakeWifiRepository.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/FakeWifiRepository.kt index 106b54891948..106b54891948 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/FakeWifiRepository.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/FakeWifiRepository.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcherTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcherTest.kt index d06a6e26b4ce..d06a6e26b4ce 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcherTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcherTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/DisabledWifiRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/DisabledWifiRepositoryTest.kt index ce00250467f6..ce00250467f6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/DisabledWifiRepositoryTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/DisabledWifiRepositoryTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt index cf20ba87e8c2..cf20ba87e8c2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorImplTest.kt index 7fbbfc77300e..7fbbfc77300e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorImplTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorImplTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt index 791a028eef4e..791a028eef4e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt diff --git a/packages/SystemUI/res/values-night/colors.xml b/packages/SystemUI/res/values-night/colors.xml index d9385c7d24c4..bcc3c83b4560 100644 --- a/packages/SystemUI/res/values-night/colors.xml +++ b/packages/SystemUI/res/values-night/colors.xml @@ -104,4 +104,7 @@ <!-- Internet Dialog --> <color name="connected_network_primary_color">@color/material_dynamic_primary80</color> <color name="connected_network_secondary_color">@color/material_dynamic_secondary80</color> + + <!-- Keyboard shortcut helper dialog --> + <color name="ksh_key_item_color">@*android:color/system_on_surface_variant_dark</color> </resources> diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml index e124aa0eda37..5f6a39a91b8b 100644 --- a/packages/SystemUI/res/values/colors.xml +++ b/packages/SystemUI/res/values/colors.xml @@ -119,7 +119,7 @@ <!-- Keyboard shortcuts colors --> <color name="ksh_application_group_color">#fff44336</color> - <color name="ksh_key_item_color">?androidprv:attr/materialColorOnSurfaceVariant</color> + <color name="ksh_key_item_color">@*android:color/system_on_surface_variant_light</color> <color name="ksh_key_item_background">?androidprv:attr/materialColorSurfaceContainerHighest</color> <color name="instant_apps_color">#ff4d5a64</color> diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/Magnification.java b/packages/SystemUI/src/com/android/systemui/accessibility/Magnification.java index b704f3c89330..1edb551eb944 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/Magnification.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/Magnification.java @@ -71,7 +71,7 @@ public class Magnification implements CoreStartable, CommandQueue.Callbacks { private final DisplayTracker mDisplayTracker; private final AccessibilityLogger mA11yLogger; - private WindowMagnificationConnectionImpl mWindowMagnificationConnectionImpl; + private MagnificationConnectionImpl mMagnificationConnectionImpl; private SysUiState mSysUiState; @VisibleForTesting @@ -220,7 +220,7 @@ public class Magnification implements CoreStartable, CommandQueue.Callbacks { } @MainThread - void setScale(int displayId, float scale) { + void setScaleForWindowMagnification(int displayId, float scale) { final WindowMagnificationController windowMagnificationController = mMagnificationControllerSupplier.get(displayId); if (windowMagnificationController != null) { @@ -321,37 +321,37 @@ public class Magnification implements CoreStartable, CommandQueue.Callbacks { final WindowMagnifierCallback mWindowMagnifierCallback = new WindowMagnifierCallback() { @Override public void onWindowMagnifierBoundsChanged(int displayId, Rect frame) { - if (mWindowMagnificationConnectionImpl != null) { - mWindowMagnificationConnectionImpl.onWindowMagnifierBoundsChanged(displayId, frame); + if (mMagnificationConnectionImpl != null) { + mMagnificationConnectionImpl.onWindowMagnifierBoundsChanged(displayId, frame); } } @Override public void onSourceBoundsChanged(int displayId, Rect sourceBounds) { - if (mWindowMagnificationConnectionImpl != null) { - mWindowMagnificationConnectionImpl.onSourceBoundsChanged(displayId, sourceBounds); + if (mMagnificationConnectionImpl != null) { + mMagnificationConnectionImpl.onSourceBoundsChanged(displayId, sourceBounds); } } @Override public void onPerformScaleAction(int displayId, float scale, boolean updatePersistence) { - if (mWindowMagnificationConnectionImpl != null) { - mWindowMagnificationConnectionImpl.onPerformScaleAction( + if (mMagnificationConnectionImpl != null) { + mMagnificationConnectionImpl.onPerformScaleAction( displayId, scale, updatePersistence); } } @Override public void onAccessibilityActionPerformed(int displayId) { - if (mWindowMagnificationConnectionImpl != null) { - mWindowMagnificationConnectionImpl.onAccessibilityActionPerformed(displayId); + if (mMagnificationConnectionImpl != null) { + mMagnificationConnectionImpl.onAccessibilityActionPerformed(displayId); } } @Override public void onMove(int displayId) { - if (mWindowMagnificationConnectionImpl != null) { - mWindowMagnificationConnectionImpl.onMove(displayId); + if (mMagnificationConnectionImpl != null) { + mMagnificationConnectionImpl.onMove(displayId); } } @@ -394,8 +394,8 @@ public class Magnification implements CoreStartable, CommandQueue.Callbacks { @Override public void onMagnifierScale(int displayId, float scale, boolean updatePersistence) { - if (mWindowMagnificationConnectionImpl != null) { - mWindowMagnificationConnectionImpl.onPerformScaleAction( + if (mMagnificationConnectionImpl != null) { + mMagnificationConnectionImpl.onPerformScaleAction( displayId, scale, updatePersistence); } mA11yLogger.logThrottled( @@ -454,8 +454,8 @@ public class Magnification implements CoreStartable, CommandQueue.Callbacks { if (magnificationSettingsController != null) { magnificationSettingsController.closeMagnificationSettings(); } - if (mWindowMagnificationConnectionImpl != null) { - mWindowMagnificationConnectionImpl.onChangeMagnificationMode(displayId, newMode); + if (mMagnificationConnectionImpl != null) { + mMagnificationConnectionImpl.onChangeMagnificationMode(displayId, newMode); } } } @@ -500,12 +500,12 @@ public class Magnification implements CoreStartable, CommandQueue.Callbacks { } private void setWindowMagnificationConnection() { - if (mWindowMagnificationConnectionImpl == null) { - mWindowMagnificationConnectionImpl = new WindowMagnificationConnectionImpl(this, + if (mMagnificationConnectionImpl == null) { + mMagnificationConnectionImpl = new MagnificationConnectionImpl(this, mHandler); } mAccessibilityManager.setWindowMagnificationConnection( - mWindowMagnificationConnectionImpl); + mMagnificationConnectionImpl); } private void clearWindowMagnificationConnection() { diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationConnectionImpl.java b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationConnectionImpl.java index 5666851f560f..5f0d496dd5d1 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationConnectionImpl.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationConnectionImpl.java @@ -32,7 +32,7 @@ import com.android.systemui.dagger.qualifiers.Main; * * @see IWindowMagnificationConnection */ -class WindowMagnificationConnectionImpl extends IWindowMagnificationConnection.Stub { +class MagnificationConnectionImpl extends IWindowMagnificationConnection.Stub { private static final String TAG = "WindowMagnificationConnectionImpl"; @@ -40,7 +40,7 @@ class WindowMagnificationConnectionImpl extends IWindowMagnificationConnection.S private final Magnification mMagnification; private final Handler mHandler; - WindowMagnificationConnectionImpl(@NonNull Magnification magnification, + MagnificationConnectionImpl(@NonNull Magnification magnification, @Main Handler mainHandler) { mMagnification = magnification; mHandler = mainHandler; @@ -57,8 +57,8 @@ class WindowMagnificationConnectionImpl extends IWindowMagnificationConnection.S } @Override - public void setScale(int displayId, float scale) { - mHandler.post(() -> mMagnification.setScale(displayId, scale)); + public void setScaleForWindowMagnification(int displayId, float scale) { + mHandler.post(() -> mMagnification.setScaleForWindowMagnification(displayId, scale)); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt index b598631c3b57..7c46339ec103 100644 --- a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt @@ -105,9 +105,9 @@ constructor( val isUserSwitcherVisible: Boolean get() = repository.isUserSwitcherVisible - private val _onImeHidden = MutableSharedFlow<Unit>() - /** Provide the onImeHidden events from the bouncer */ - val onImeHidden: SharedFlow<Unit> = _onImeHidden + private val _onImeHiddenByUser = MutableSharedFlow<Unit>() + /** Emits a [Unit] each time the IME (keyboard) is hidden by the user. */ + val onImeHiddenByUser: SharedFlow<Unit> = _onImeHiddenByUser init { if (flags.isEnabled()) { @@ -230,9 +230,9 @@ constructor( repository.setMessage(errorMessage(authenticationInteractor.getAuthenticationMethod())) } - /** Notifies the interactor that the input method editor has been hidden. */ - suspend fun onImeHidden() { - _onImeHidden.emit(Unit) + /** Notifies that the input method editor (software keyboard) has been hidden by the user. */ + suspend fun onImeHiddenByUser() { + _onImeHiddenByUser.emit(Unit) } private fun promptMessage(authMethod: AuthenticationMethodModel): String { diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModel.kt index 80248744c25a..e379dab918ef 100644 --- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModel.kt @@ -46,9 +46,6 @@ sealed class AuthMethodBouncerViewModel( */ val animateFailure: StateFlow<Boolean> = _animateFailure.asStateFlow() - /** Whether the input method editor (for example, the software keyboard) is visible. */ - private var isImeVisible: Boolean = false - /** The authentication method that corresponds to this view model. */ abstract val authenticationMethod: AuthenticationMethodModel @@ -68,7 +65,7 @@ sealed class AuthMethodBouncerViewModel( /** * Notifies that the UI has been hidden from the user (after any transitions have completed). */ - fun onHidden() { + open fun onHidden() { clearInput() interactor.resetMessage() } @@ -79,18 +76,6 @@ sealed class AuthMethodBouncerViewModel( } /** - * Notifies that the input method editor (for example, the software keyboard) has been shown or - * hidden. - */ - suspend fun onImeVisibilityChanged(isVisible: Boolean) { - if (isImeVisible && !isVisible) { - interactor.onImeHidden() - } - - isImeVisible = isVisible - } - - /** * Notifies that the failure animation has been shown. This should be called to consume a `true` * value in [animateFailure]. */ diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModel.kt index a15698e1f90c..45d181285df7 100644 --- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModel.kt @@ -21,8 +21,11 @@ import com.android.systemui.bouncer.domain.interactor.BouncerInteractor import com.android.systemui.res.R import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.stateIn /** Holds UI state and handles user input for the password bouncer UI. */ class PasswordBouncerViewModel( @@ -45,6 +48,32 @@ class PasswordBouncerViewModel( override val throttlingMessageId = R.string.kg_too_many_failed_password_attempts_dialog_message + /** Whether the input method editor (for example, the software keyboard) is visible. */ + private var isImeVisible: Boolean = false + + /** Whether the text field element currently has focus. */ + private val isTextFieldFocused = MutableStateFlow(false) + + /** Whether the UI should request focus on the text field element. */ + val isTextFieldFocusRequested = + combine( + interactor.isThrottled, + isTextFieldFocused, + ) { isThrottled, hasFocus -> + !isThrottled && !hasFocus + } + .stateIn( + scope = viewModelScope, + started = SharingStarted.WhileSubscribed(), + initialValue = !interactor.isThrottled.value && !isTextFieldFocused.value, + ) + + override fun onHidden() { + super.onHidden() + isImeVisible = false + isTextFieldFocused.value = false + } + override fun clearInput() { _password.value = "" } @@ -72,4 +101,21 @@ class PasswordBouncerViewModel( tryAuthenticate() } } + + /** + * Notifies that the input method editor (for example, the software keyboard) has been shown or + * hidden. + */ + suspend fun onImeVisibilityChanged(isVisible: Boolean) { + if (isImeVisible && !isVisible && !interactor.isThrottled.value) { + interactor.onImeHiddenByUser() + } + + isImeVisible = isVisible + } + + /** Notifies that the password text field has gained or lost focus. */ + fun onTextFieldFocusChanged(isFocused: Boolean) { + isTextFieldFocused.value = isFocused + } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfig.kt index 7337292a9ac5..a988a5c2d67a 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfig.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfig.kt @@ -32,13 +32,19 @@ import com.android.systemui.common.shared.model.ContentDescription import com.android.systemui.common.shared.model.Icon import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application +import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.plugins.ActivityStarter import com.android.systemui.wallet.controller.QuickAccessWalletController import com.android.systemui.wallet.util.getPaymentCards +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.ExperimentalCoroutinesApi import javax.inject.Inject import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.suspendCancellableCoroutine +import kotlinx.coroutines.withContext /** Quick access wallet quick affordance data source. */ @SysUISingleton @@ -46,6 +52,7 @@ class QuickAccessWalletKeyguardQuickAffordanceConfig @Inject constructor( @Application private val context: Context, + @Background private val backgroundDispatcher: CoroutineDispatcher, private val walletController: QuickAccessWalletController, private val activityStarter: ActivityStarter, ) : KeyguardQuickAffordanceConfig { @@ -56,6 +63,7 @@ constructor( override val pickerIconResourceId = R.drawable.ic_wallet_lockscreen + @OptIn(ExperimentalCoroutinesApi::class) override val lockScreenState: Flow<KeyguardQuickAffordanceConfig.LockScreenState> = conflatedCallbackFlow { val callback = @@ -63,11 +71,7 @@ constructor( override fun onWalletCardsRetrieved(response: GetWalletCardsResponse) { val hasCards = getPaymentCards(response.walletCards)?.isNotEmpty() == true trySendWithFailureLogging( - state( - isFeatureEnabled = isWalletAvailable(), - hasCard = hasCards, - tileIcon = walletController.walletClient.tileIcon, - ), + hasCards, TAG, ) } @@ -75,7 +79,7 @@ constructor( override fun onWalletCardRetrievalError(error: GetWalletCardsError) { Log.e(TAG, "Wallet card retrieval error, message: \"${error?.message}\"") trySendWithFailureLogging( - KeyguardQuickAffordanceConfig.LockScreenState.Hidden, + null, TAG, ) } @@ -86,8 +90,12 @@ constructor( QuickAccessWalletController.WalletChangeEvent.WALLET_PREFERENCE_CHANGE, QuickAccessWalletController.WalletChangeEvent.DEFAULT_PAYMENT_APP_CHANGE ) - walletController.updateWalletPreference() - walletController.queryWalletCards(callback) + + withContext(backgroundDispatcher) { + // Both must be called on background thread + walletController.updateWalletPreference() + walletController.queryWalletCards(callback) + } awaitClose { walletController.unregisterWalletChangeObservers( @@ -95,6 +103,19 @@ constructor( QuickAccessWalletController.WalletChangeEvent.DEFAULT_PAYMENT_APP_CHANGE ) } + }.flatMapLatest { hasCards -> + // If hasCards is null, this indicates an error occurred upon card retrieval + val state = + if (hasCards == null) { + KeyguardQuickAffordanceConfig.LockScreenState.Hidden + } else { + state( + isWalletAvailable(), + hasCards, + walletController.walletClient.tileIcon, + ) + } + flowOf(state) } override suspend fun getPickerScreenState(): KeyguardQuickAffordanceConfig.PickerScreenState { @@ -131,25 +152,33 @@ constructor( } private suspend fun queryCards(): List<WalletCard> { - return suspendCancellableCoroutine { continuation -> - val callback = - object : QuickAccessWalletClient.OnWalletCardsRetrievedCallback { - override fun onWalletCardsRetrieved(response: GetWalletCardsResponse) { - continuation.resumeWith( - Result.success(getPaymentCards(response.walletCards) ?: emptyList()) - ) + return withContext(backgroundDispatcher) { + suspendCancellableCoroutine { continuation -> + val callback = + object : QuickAccessWalletClient.OnWalletCardsRetrievedCallback { + override fun onWalletCardsRetrieved(response: GetWalletCardsResponse) { + continuation.resumeWith( + Result.success(getPaymentCards(response.walletCards)) + ) + } + + override fun onWalletCardRetrievalError(error: GetWalletCardsError) { + continuation.resumeWith(Result.success(emptyList())) + } } - - override fun onWalletCardRetrievalError(error: GetWalletCardsError) { - continuation.resumeWith(Result.success(emptyList())) - } - } - walletController.queryWalletCards(callback) + // Must be called on background thread + walletController.queryWalletCards(callback) + } } } - private fun isWalletAvailable() = - with(walletController.walletClient) { isWalletServiceAvailable && isWalletFeatureAvailable } + private suspend fun isWalletAvailable() = + withContext(backgroundDispatcher) { + with(walletController.walletClient) { + // Must be called on background thread + isWalletServiceAvailable && isWalletFeatureAvailable + } + } private fun state( isFeatureEnabled: Boolean, diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractor.kt index bd73d60cda29..62a0b0ebc08c 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractor.kt @@ -131,13 +131,16 @@ constructor( when (toState) { KeyguardState.DREAMING -> TO_DREAMING_DURATION KeyguardState.AOD -> TO_AOD_DURATION + KeyguardState.LOCKSCREEN -> TO_LOCKSCREEN_DURATION else -> DEFAULT_DURATION }.inWholeMilliseconds } } + companion object { private val DEFAULT_DURATION = 500.milliseconds val TO_DREAMING_DURATION = 933.milliseconds val TO_AOD_DURATION = 1300.milliseconds + val TO_LOCKSCREEN_DURATION = DEFAULT_DURATION } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt index 152d2172ee4c..cbfd17ff7ae4 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt @@ -380,6 +380,8 @@ constructor( KeyguardState.DREAMING -> TO_DREAMING_DURATION KeyguardState.OCCLUDED -> TO_OCCLUDED_DURATION KeyguardState.AOD -> TO_AOD_DURATION + KeyguardState.DOZING -> TO_DOZING_DURATION + KeyguardState.DREAMING_LOCKSCREEN_HOSTED -> TO_DREAMING_HOSTED_DURATION else -> DEFAULT_DURATION }.inWholeMilliseconds } @@ -388,7 +390,9 @@ constructor( companion object { const val TAG = "FromLockscreenTransitionInteractor" private val DEFAULT_DURATION = 400.milliseconds + val TO_DOZING_DURATION = 500.milliseconds val TO_DREAMING_DURATION = 933.milliseconds + val TO_DREAMING_HOSTED_DURATION = 933.milliseconds val TO_OCCLUDED_DURATION = 450.milliseconds val TO_AOD_DURATION = 500.milliseconds val TO_PRIMARY_BOUNCER_DURATION = DEFAULT_DURATION diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt index 706aba3c0505..f7d1543e4650 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt @@ -72,6 +72,10 @@ constructor( val fromDreamingTransition: Flow<TransitionStep> = repository.transitions.filter { step -> step.from == DREAMING } + /** LOCKSCREEN->(any) transition information. */ + val fromLockscreenTransition: Flow<TransitionStep> = + repository.transitions.filter { step -> step.from == LOCKSCREEN } + /** (any)->Lockscreen transition information */ val anyStateToLockscreenTransition: Flow<TransitionStep> = repository.transitions.filter { step -> step.to == LOCKSCREEN } @@ -113,9 +117,16 @@ constructor( val goneToDreamingLockscreenHostedTransition: Flow<TransitionStep> = repository.transition(GONE, DREAMING_LOCKSCREEN_HOSTED) + /** GONE->LOCKSCREEN transition information. */ + val goneToLockscreenTransition: Flow<TransitionStep> = repository.transition(GONE, LOCKSCREEN) + /** LOCKSCREEN->AOD transition information. */ val lockscreenToAodTransition: Flow<TransitionStep> = repository.transition(LOCKSCREEN, AOD) + /** LOCKSCREEN->DOZING transition information. */ + val lockscreenToDozingTransition: Flow<TransitionStep> = + repository.transition(LOCKSCREEN, DOZING) + /** LOCKSCREEN->DREAMING transition information. */ val lockscreenToDreamingTransition: Flow<TransitionStep> = repository.transition(LOCKSCREEN, DREAMING) diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt index 99025acef70d..abd79ab793d5 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt @@ -30,9 +30,7 @@ import androidx.core.view.isVisible import androidx.core.view.updateLayoutParams import androidx.lifecycle.Lifecycle import androidx.lifecycle.repeatOnLifecycle -import com.android.app.animation.Interpolators import com.android.settingslib.Utils -import com.android.systemui.res.R import com.android.systemui.animation.Expandable import com.android.systemui.animation.view.LaunchableImageView import com.android.systemui.common.shared.model.Icon @@ -40,6 +38,7 @@ import com.android.systemui.common.ui.binder.IconViewBinder import com.android.systemui.keyguard.ui.viewmodel.KeyguardQuickAffordanceViewModel import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.plugins.FalsingManager +import com.android.systemui.res.R import com.android.systemui.statusbar.VibratorHelper import com.android.systemui.util.doOnEnd import kotlinx.coroutines.flow.Flow @@ -48,9 +47,7 @@ import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch -/** - * This is only for a SINGLE Quick affordance - */ +/** This is only for a SINGLE Quick affordance */ object KeyguardQuickAffordanceViewBinder { private const val EXIT_DOZE_BUTTON_REVEAL_ANIMATION_DURATION_MS = 250L @@ -135,28 +132,12 @@ object KeyguardQuickAffordanceViewBinder { vibratorHelper: VibratorHelper?, ) { if (!viewModel.isVisible) { - view.alpha = 1f - view - .animate() - .alpha(0f) - .setInterpolator(Interpolators.FAST_OUT_LINEAR_IN) - .setDuration(EXIT_DOZE_BUTTON_REVEAL_ANIMATION_DURATION_MS) - .withEndAction { view.isInvisible = true } - .start() + view.isInvisible = true return } if (!view.isVisible) { view.isVisible = true - if (viewModel.animateReveal) { - view.alpha = 0f - view - .animate() - .alpha(1f) - .setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN) - .setDuration(EXIT_DOZE_BUTTON_REVEAL_ANIMATION_DURATION_MS) - .start() - } } IconViewBinder.bind(viewModel.icon, view) @@ -216,13 +197,14 @@ object KeyguardQuickAffordanceViewBinder { view.isClickable = viewModel.isClickable if (viewModel.isClickable) { if (viewModel.useLongPress) { - val onTouchListener = KeyguardQuickAffordanceOnTouchListener( - view, - viewModel, - messageDisplayer, - vibratorHelper, - falsingManager, - ) + val onTouchListener = + KeyguardQuickAffordanceOnTouchListener( + view, + viewModel, + messageDisplayer, + vibratorHelper, + falsingManager, + ) view.setOnTouchListener(onTouchListener) view.setOnClickListener { messageDisplayer.invoke(R.string.keyguard_affordance_press_too_short) @@ -241,9 +223,7 @@ object KeyguardQuickAffordanceViewBinder { KeyguardBottomAreaVibrations.ShakeAnimationDuration.inWholeMilliseconds shakeAnimator.interpolator = CycleInterpolator(KeyguardBottomAreaVibrations.ShakeAnimationCycles) - shakeAnimator.doOnEnd { - view.translationX = 0f - } + shakeAnimator.doOnEnd { view.translationX = 0f } shakeAnimator.start() vibratorHelper?.vibrate(KeyguardBottomAreaVibrations.Shake) @@ -268,18 +248,18 @@ object KeyguardQuickAffordanceViewBinder { alphaFlow: Flow<Float>, ) { combine(viewModel.map { it.isDimmed }, alphaFlow) { isDimmed, alpha -> - if (isDimmed) DIM_ALPHA else alpha - } + if (isDimmed) DIM_ALPHA else alpha + } .collect { view.alpha = it } } private fun loadFromResources(view: View): ConfigurationBasedDimensions { return ConfigurationBasedDimensions( buttonSizePx = - Size( - view.resources.getDimensionPixelSize(R.dimen.keyguard_affordance_fixed_width), - view.resources.getDimensionPixelSize(R.dimen.keyguard_affordance_fixed_height), - ), + Size( + view.resources.getDimensionPixelSize(R.dimen.keyguard_affordance_fixed_width), + view.resources.getDimensionPixelSize(R.dimen.keyguard_affordance_fixed_height), + ), ) } @@ -337,11 +317,9 @@ object KeyguardQuickAffordanceViewBinder { } override fun onLongClickUseDefaultHapticFeedback(view: View) = false - } private data class ConfigurationBasedDimensions( val buttonSizePx: Size, ) - -}
\ No newline at end of file +} diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt index 9f46e22d645c..59c798bfca1e 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt @@ -84,6 +84,7 @@ import dagger.assisted.AssistedInject import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.DisposableHandle import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.runBlocking /** Renders the preview of the lock screen. */ @@ -158,7 +159,6 @@ constructor( init { if (keyguardBottomAreaRefactor()) { - keyguardRootViewModel.enablePreviewMode() quickAffordancesCombinedViewModel.enablePreviewMode( initiallySelectedSlotId = bundle.getString( @@ -338,26 +338,27 @@ constructor( ), ) } - @OptIn(ExperimentalCoroutinesApi::class) private fun setupKeyguardRootView(previewContext: Context, rootView: FrameLayout) { val keyguardRootView = KeyguardRootView(previewContext, null) - disposables.add( - KeyguardRootViewBinder.bind( - keyguardRootView, - keyguardRootViewModel, - configuration, - featureFlags, - occludingAppDeviceEntryMessageViewModel, - chipbarCoordinator, - screenOffAnimationController, - shadeInteractor, - null, // clock provider only needed for burn in - null, // jank monitor not required for preview mode - null, // device entry haptics not required for preview mode - null, // device entry haptics not required for preview mode + if (!keyguardBottomAreaRefactor()) { + disposables.add( + KeyguardRootViewBinder.bind( + keyguardRootView, + keyguardRootViewModel, + configuration, + featureFlags, + occludingAppDeviceEntryMessageViewModel, + chipbarCoordinator, + screenOffAnimationController, + shadeInteractor, + null, // clock provider only needed for burn in + null, // jank monitor not required for preview mode + null, // device entry haptics not required preview mode + null, // device entry haptics not required for preview mode + ) ) - ) + } rootView.addView( keyguardRootView, FrameLayout.LayoutParams( @@ -392,30 +393,30 @@ constructor( } private fun setupShortcuts(keyguardRootView: ConstraintLayout) { - keyguardRootView.findViewById<LaunchableImageView?>(R.id.start_button)?.let { + keyguardRootView.findViewById<LaunchableImageView?>(R.id.start_button)?.let { imageView -> shortcutsBindings.add( KeyguardQuickAffordanceViewBinder.bind( - it, - quickAffordancesCombinedViewModel.startButton, - keyguardRootViewModel.alpha, - falsingManager, - vibratorHelper, - ) { - indicationController.showTransientIndication(it) + view = imageView, + viewModel = quickAffordancesCombinedViewModel.startButton, + alpha = flowOf(1f), + falsingManager = falsingManager, + vibratorHelper = vibratorHelper, + ) { message -> + indicationController.showTransientIndication(message) } ) } - keyguardRootView.findViewById<LaunchableImageView?>(R.id.end_button)?.let { + keyguardRootView.findViewById<LaunchableImageView?>(R.id.end_button)?.let { imageView -> shortcutsBindings.add( KeyguardQuickAffordanceViewBinder.bind( - it, - quickAffordancesCombinedViewModel.endButton, - keyguardRootViewModel.alpha, - falsingManager, - vibratorHelper, - ) { - indicationController.showTransientIndication(it) + view = imageView, + viewModel = quickAffordancesCombinedViewModel.endButton, + alpha = flowOf(1f), + falsingManager = falsingManager, + vibratorHelper = vibratorHelper, + ) { message -> + indicationController.showTransientIndication(message) } ) } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AlignShortcutsToUdfpsSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AlignShortcutsToUdfpsSection.kt index 55df46679f6d..cd46d6cf2188 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AlignShortcutsToUdfpsSection.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AlignShortcutsToUdfpsSection.kt @@ -61,7 +61,7 @@ constructor( KeyguardQuickAffordanceViewBinder.bind( constraintLayout.requireViewById(R.id.start_button), keyguardQuickAffordancesCombinedViewModel.startButton, - keyguardRootViewModel.alpha, + keyguardQuickAffordancesCombinedViewModel.transitionAlpha, falsingManager, vibratorHelper, ) { @@ -71,7 +71,7 @@ constructor( KeyguardQuickAffordanceViewBinder.bind( constraintLayout.requireViewById(R.id.end_button), keyguardQuickAffordancesCombinedViewModel.endButton, - keyguardRootViewModel.alpha, + keyguardQuickAffordancesCombinedViewModel.transitionAlpha, falsingManager, vibratorHelper, ) { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultShortcutsSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultShortcutsSection.kt index 0f6a966aad2e..2a68f26d3ae7 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultShortcutsSection.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultShortcutsSection.kt @@ -25,14 +25,12 @@ import androidx.constraintlayout.widget.ConstraintSet.LEFT import androidx.constraintlayout.widget.ConstraintSet.PARENT_ID import androidx.constraintlayout.widget.ConstraintSet.RIGHT import com.android.systemui.Flags.keyguardBottomAreaRefactor -import com.android.systemui.res.R import com.android.systemui.dagger.qualifiers.Main -import com.android.systemui.flags.FeatureFlags -import com.android.systemui.flags.Flags import com.android.systemui.keyguard.ui.binder.KeyguardQuickAffordanceViewBinder import com.android.systemui.keyguard.ui.viewmodel.KeyguardQuickAffordancesCombinedViewModel import com.android.systemui.keyguard.ui.viewmodel.KeyguardRootViewModel import com.android.systemui.plugins.FalsingManager +import com.android.systemui.res.R import com.android.systemui.statusbar.KeyguardIndicationController import com.android.systemui.statusbar.VibratorHelper import javax.inject.Inject @@ -61,7 +59,7 @@ constructor( KeyguardQuickAffordanceViewBinder.bind( constraintLayout.requireViewById(R.id.start_button), keyguardQuickAffordancesCombinedViewModel.startButton, - keyguardRootViewModel.alpha, + keyguardQuickAffordancesCombinedViewModel.transitionAlpha, falsingManager, vibratorHelper, ) { @@ -71,7 +69,7 @@ constructor( KeyguardQuickAffordanceViewBinder.bind( constraintLayout.requireViewById(R.id.end_button), keyguardQuickAffordancesCombinedViewModel.endButton, - keyguardRootViewModel.alpha, + keyguardQuickAffordancesCombinedViewModel.transitionAlpha, falsingManager, vibratorHelper, ) { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToLockscreenTransitionViewModel.kt index 14de01b41867..1864437a7d11 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToLockscreenTransitionViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToLockscreenTransitionViewModel.kt @@ -55,6 +55,14 @@ constructor( onStep = { 1f }, ) + val shortcutsAlpha: Flow<Float> = + transitionAnimation.createFlow( + duration = 167.milliseconds, + startTime = 67.milliseconds, + onStep = { it }, + onCancel = { 0f }, + ) + val deviceEntryBackgroundViewAlpha: Flow<Float> = deviceEntryUdfpsInteractor.isUdfpsSupported.flatMapLatest { isUdfps -> if (isUdfps) { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToLockscreenTransitionViewModel.kt index 27fb8a3d2473..a728a2810916 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToLockscreenTransitionViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToLockscreenTransitionViewModel.kt @@ -22,6 +22,7 @@ import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInterac import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition import javax.inject.Inject +import kotlin.time.Duration.Companion.milliseconds import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow @@ -41,6 +42,13 @@ constructor( transitionFlow = interactor.dozingToLockscreenTransition, ) + val shortcutsAlpha: Flow<Float> = + transitionAnimation.createFlow( + duration = 150.milliseconds, + onStep = { it }, + onCancel = { 0f }, + ) + override val deviceEntryParentViewAlpha: Flow<Float> = transitionAnimation.immediatelyTransitionTo(1f) } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingHostedToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingHostedToLockscreenTransitionViewModel.kt new file mode 100644 index 000000000000..58235ae02abe --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingHostedToLockscreenTransitionViewModel.kt @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.keyguard.ui.viewmodel + +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.keyguard.domain.interactor.FromDreamingLockscreenHostedTransitionInteractor.Companion.TO_LOCKSCREEN_DURATION +import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor +import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow +import javax.inject.Inject +import kotlin.time.Duration.Companion.milliseconds +import kotlinx.coroutines.flow.Flow + +@SysUISingleton +class DreamingHostedToLockscreenTransitionViewModel +@Inject +constructor( + interactor: KeyguardTransitionInteractor, +) { + + private val transitionAnimation = + KeyguardTransitionAnimationFlow( + transitionDuration = TO_LOCKSCREEN_DURATION, + transitionFlow = interactor.dreamingLockscreenHostedToLockscreenTransition + ) + + val shortcutsAlpha: Flow<Float> = + transitionAnimation.createFlow( + duration = 250.milliseconds, + onStep = { it }, + onCancel = { 0f }, + ) +} diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt index a3b8b85fc53d..f943bdfa7550 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt @@ -96,6 +96,14 @@ constructor( onStep = { it }, ) + val shortcutsAlpha: Flow<Float> = + transitionAnimation.createFlow( + startTime = 233.milliseconds, + duration = 250.milliseconds, + onStep = { it }, + onCancel = { 0f }, + ) + val deviceEntryBackgroundViewAlpha = deviceEntryUdfpsInteractor.isUdfpsSupported.flatMapLatest { isUdfps -> if (isUdfps) { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToLockscreenTransitionViewModel.kt new file mode 100644 index 000000000000..5804a205445c --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToLockscreenTransitionViewModel.kt @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.keyguard.ui.viewmodel + +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.keyguard.domain.interactor.FromGoneTransitionInteractor.Companion.TO_LOCKSCREEN_DURATION +import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor +import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow +import javax.inject.Inject +import kotlin.time.Duration.Companion.milliseconds +import kotlinx.coroutines.flow.Flow + +@SysUISingleton +class GoneToLockscreenTransitionViewModel +@Inject +constructor( + interactor: KeyguardTransitionInteractor, +) { + + private val transitionAnimation = + KeyguardTransitionAnimationFlow( + transitionDuration = TO_LOCKSCREEN_DURATION, + transitionFlow = interactor.goneToLockscreenTransition + ) + + val shortcutsAlpha: Flow<Float> = + transitionAnimation.createFlow( + duration = 250.milliseconds, + onStep = { it }, + onCancel = { 0f }, + ) +} diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModel.kt index 02ea5508f34f..188be244be4a 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModel.kt @@ -23,6 +23,7 @@ import com.android.systemui.keyguard.domain.interactor.KeyguardQuickAffordanceIn import com.android.systemui.keyguard.domain.model.KeyguardQuickAffordanceModel import com.android.systemui.keyguard.shared.quickaffordance.ActivationState import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordancePosition +import com.android.systemui.shade.domain.interactor.ShadeInteractor import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots import javax.inject.Inject import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -32,6 +33,7 @@ import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.merge @OptIn(ExperimentalCoroutinesApi::class) class KeyguardQuickAffordancesCombinedViewModel @@ -39,6 +41,22 @@ class KeyguardQuickAffordancesCombinedViewModel constructor( private val quickAffordanceInteractor: KeyguardQuickAffordanceInteractor, private val keyguardInteractor: KeyguardInteractor, + shadeInteractor: ShadeInteractor, + aodToLockscreenTransitionViewModel: AodToLockscreenTransitionViewModel, + dozingToLockscreenTransitionViewModel: DozingToLockscreenTransitionViewModel, + dreamingHostedToLockscreenTransitionViewModel: DreamingHostedToLockscreenTransitionViewModel, + dreamingToLockscreenTransitionViewModel: DreamingToLockscreenTransitionViewModel, + goneToLockscreenTransitionViewModel: GoneToLockscreenTransitionViewModel, + occludedToLockscreenTransitionViewModel: OccludedToLockscreenTransitionViewModel, + offToLockscreenTransitionViewModel: OffToLockscreenTransitionViewModel, + primaryBouncerToLockscreenTransitionViewModel: PrimaryBouncerToLockscreenTransitionViewModel, + lockscreenToAodTransitionViewModel: LockscreenToAodTransitionViewModel, + lockscreenToDozingTransitionViewModel: LockscreenToDozingTransitionViewModel, + lockscreenToDreamingHostedTransitionViewModel: LockscreenToDreamingHostedTransitionViewModel, + lockscreenToDreamingTransitionViewModel: LockscreenToDreamingTransitionViewModel, + lockscreenToGoneTransitionViewModel: LockscreenToGoneTransitionViewModel, + lockscreenToOccludedTransitionViewModel: LockscreenToOccludedTransitionViewModel, + lockscreenToPrimaryBouncerTransitionViewModel: LockscreenToPrimaryBouncerTransitionViewModel, ) { data class PreviewMode( @@ -60,6 +78,39 @@ constructor( private val selectedPreviewSlotId = MutableStateFlow(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START) + /** alpha while fading the quick affordances out */ + private val fadeInAlpha: Flow<Float> = + merge( + aodToLockscreenTransitionViewModel.shortcutsAlpha, + dozingToLockscreenTransitionViewModel.shortcutsAlpha, + dreamingHostedToLockscreenTransitionViewModel.shortcutsAlpha, + dreamingToLockscreenTransitionViewModel.shortcutsAlpha, + goneToLockscreenTransitionViewModel.shortcutsAlpha, + occludedToLockscreenTransitionViewModel.shortcutsAlpha, + offToLockscreenTransitionViewModel.shortcutsAlpha, + primaryBouncerToLockscreenTransitionViewModel.shortcutsAlpha, + ) + + /** alpha while fading the quick affordances in */ + private val fadeOutAlpha: Flow<Float> = + merge( + lockscreenToAodTransitionViewModel.shortcutsAlpha, + lockscreenToDozingTransitionViewModel.shortcutsAlpha, + lockscreenToDreamingHostedTransitionViewModel.shortcutsAlpha, + lockscreenToDreamingTransitionViewModel.shortcutsAlpha, + lockscreenToGoneTransitionViewModel.shortcutsAlpha, + lockscreenToOccludedTransitionViewModel.shortcutsAlpha, + lockscreenToPrimaryBouncerTransitionViewModel.shortcutsAlpha, + shadeInteractor.qsExpansion.map { 1 - it }, + ) + + /** The source of truth of alpha for all of the quick affordances on lockscreen */ + val transitionAlpha: Flow<Float> = + merge( + fadeInAlpha, + fadeOutAlpha, + ) + /** * Whether quick affordances are "opaque enough" to be considered visible to and interactive by * the user. If they are not interactive, user input should not be allowed on them. @@ -73,7 +124,7 @@ constructor( * interactive/clickable unless "fully opaque" to avoid issues like in b/241830987. */ private val areQuickAffordancesFullyOpaque: Flow<Boolean> = - keyguardInteractor.keyguardAlpha + transitionAlpha .map { alpha -> alpha >= AFFORDANCE_FULLY_OPAQUE_ALPHA_THRESHOLD } .distinctUntilChanged() @@ -89,7 +140,7 @@ constructor( * Notifies that a slot with the given ID has been selected in the preview experience that is * rendering in the wallpaper picker. This is ignored for the real lock screen experience. * - * @see [KeyguardRootViewModel.enablePreviewMode] + * @see [enablePreviewMode] */ fun onPreviewSlotSelected(slotId: String) { selectedPreviewSlotId.value = slotId diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt index 524fa1ede90a..f63afebb60ab 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt @@ -47,13 +47,11 @@ import javax.inject.Inject import javax.inject.Provider import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.flatMapLatest -import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.merge import kotlinx.coroutines.flow.onStart @@ -74,16 +72,6 @@ constructor( private val aodToLockscreenTransitionViewModel: AodToLockscreenTransitionViewModel, screenOffAnimationController: ScreenOffAnimationController, ) { - - data class PreviewMode(val isInPreviewMode: Boolean = false) - - /** - * Whether this view-model instance is powering the preview experience that renders exclusively - * in the wallpaper picker application. This should _always_ be `false` for the real lock screen - * experience. - */ - private val previewMode = MutableStateFlow(PreviewMode()) - var clockControllerProvider: Provider<ClockController>? = null /** System insets that keyguard needs to stay out of */ @@ -103,14 +91,7 @@ constructor( keyguardInteractor.notificationContainerBounds /** An observable for the alpha level for the entire keyguard root view. */ - val alpha: Flow<Float> = - previewMode.flatMapLatest { - if (it.isInPreviewMode) { - flowOf(1f) - } else { - keyguardInteractor.keyguardAlpha.distinctUntilChanged() - } - } + val alpha: Flow<Float> = keyguardInteractor.keyguardAlpha.distinctUntilChanged() private fun burnIn(): Flow<BurnInModel> { val dozingAmount: Flow<Float> = @@ -147,55 +128,29 @@ constructor( val lockscreenStateAlpha: Flow<Float> = aodToLockscreenTransitionViewModel.lockscreenAlpha /** For elements that appear and move during the animation -> AOD */ - val burnInLayerAlpha: Flow<Float> = - previewMode.flatMapLatest { - if (it.isInPreviewMode) { - flowOf(1f) - } else { - goneToAodTransitionViewModel.enterFromTopAnimationAlpha - } - } + val burnInLayerAlpha: Flow<Float> = goneToAodTransitionViewModel.enterFromTopAnimationAlpha val translationY: Flow<Float> = - previewMode.flatMapLatest { - if (it.isInPreviewMode) { - flowOf(0f) - } else { - keyguardInteractor.configurationChange.flatMapLatest { _ -> - val enterFromTopAmount = - context.resources.getDimensionPixelSize( - R.dimen.keyguard_enter_from_top_translation_y - ) - combine( - keyguardInteractor.keyguardTranslationY.onStart { emit(0f) }, - burnIn().map { it.translationY.toFloat() }.onStart { emit(0f) }, - goneToAodTransitionViewModel - .enterFromTopTranslationY(enterFromTopAmount) - .onStart { emit(0f) }, - ) { keyguardTransitionY, burnInTranslationY, goneToAodTransitionTranslationY -> - // All 3 values need to be combined for a smooth translation - keyguardTransitionY + burnInTranslationY + goneToAodTransitionTranslationY - } - } + keyguardInteractor.configurationChange.flatMapLatest { _ -> + val enterFromTopAmount = + context.resources.getDimensionPixelSize( + R.dimen.keyguard_enter_from_top_translation_y + ) + combine( + keyguardInteractor.keyguardTranslationY.onStart { emit(0f) }, + burnIn().map { it.translationY.toFloat() }.onStart { emit(0f) }, + goneToAodTransitionViewModel.enterFromTopTranslationY(enterFromTopAmount).onStart { + emit(0f) + }, + ) { keyguardTransitionY, burnInTranslationY, goneToAodTransitionTranslationY -> + // All 3 values need to be combined for a smooth translation + keyguardTransitionY + burnInTranslationY + goneToAodTransitionTranslationY } } - val translationX: Flow<Float> = - previewMode.flatMapLatest { - if (it.isInPreviewMode) { - flowOf(0f) - } else { - burnIn().map { it.translationX.toFloat() } - } - } + val translationX: Flow<Float> = burnIn().map { it.translationX.toFloat() } - val scale: Flow<Pair<Float, Boolean>> = - previewMode.flatMapLatest { previewMode -> - burnIn().map { - val scale = if (previewMode.isInPreviewMode) 1f else it.scale - Pair(scale, it.scaleClockOnly) - } - } + val scale: Flow<Pair<Float, Boolean>> = burnIn().map { Pair(it.scale, it.scaleClockOnly) } /** Is the notification icon container visible? */ val isNotifIconContainerVisible: Flow<AnimatedValue<Boolean>> = @@ -238,20 +193,7 @@ constructor( } .distinctUntilChanged() - /** - * Puts this view-model in "preview mode", which means it's being used for UI that is rendering - * the lock screen preview in wallpaper picker / settings and not the real experience on the - * lock screen. - */ - fun enablePreviewMode() { - previewMode.value = PreviewMode(true) - } - fun onNotificationContainerBoundsChanged(top: Float, bottom: Float) { - // Notifications should not be visible in preview mode - if (previewMode.value.isInPreviewMode) { - return - } keyguardInteractor.setNotificationContainerBounds(NotificationContainerBounds(top, bottom)) } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToAodTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToAodTransitionViewModel.kt index 2bf12e8e33b2..8e8fd75cc1c0 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToAodTransitionViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToAodTransitionViewModel.kt @@ -57,6 +57,15 @@ constructor( onFinish = { 0f }, ), ) + + val shortcutsAlpha: Flow<Float> = + transitionAnimation.createFlow( + duration = 250.milliseconds, + onStep = { 1 - it }, + onFinish = { 0f }, + onCancel = { 1f }, + ) + override val deviceEntryParentViewAlpha: Flow<Float> = deviceEntryUdfpsInteractor.isUdfpsEnrolledAndEnabled.flatMapLatest { isUdfpsEnrolledAndEnabled -> diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDozingTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDozingTransitionViewModel.kt new file mode 100644 index 000000000000..263ed11503ba --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDozingTransitionViewModel.kt @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.keyguard.ui.viewmodel + +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.keyguard.domain.interactor.FromLockscreenTransitionInteractor.Companion.TO_DOZING_DURATION +import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor +import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow +import javax.inject.Inject +import kotlin.time.Duration.Companion.milliseconds +import kotlinx.coroutines.flow.Flow + +@SysUISingleton +class LockscreenToDozingTransitionViewModel +@Inject +constructor( + interactor: KeyguardTransitionInteractor, +) { + + private val transitionAnimation = + KeyguardTransitionAnimationFlow( + transitionDuration = TO_DOZING_DURATION, + transitionFlow = interactor.lockscreenToDozingTransition + ) + + val shortcutsAlpha: Flow<Float> = + transitionAnimation.createFlow( + duration = 250.milliseconds, + onStep = { 1 - it }, + onFinish = { 0f }, + onCancel = { 1f }, + ) +} diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingHostedTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingHostedTransitionViewModel.kt new file mode 100644 index 000000000000..17015056bda0 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingHostedTransitionViewModel.kt @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.keyguard.ui.viewmodel + +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.keyguard.domain.interactor.FromLockscreenTransitionInteractor.Companion.TO_DREAMING_HOSTED_DURATION +import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor +import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow +import javax.inject.Inject +import kotlin.time.Duration.Companion.milliseconds +import kotlinx.coroutines.flow.Flow + +@SysUISingleton +class LockscreenToDreamingHostedTransitionViewModel +@Inject +constructor( + interactor: KeyguardTransitionInteractor, +) { + + private val transitionAnimation = + KeyguardTransitionAnimationFlow( + transitionDuration = TO_DREAMING_HOSTED_DURATION, + transitionFlow = interactor.lockscreenToDreamingLockscreenHostedTransition + ) + + val shortcutsAlpha: Flow<Float> = + transitionAnimation.createFlow( + duration = 250.milliseconds, + onStep = { 1 - it }, + onFinish = { 0f }, + onCancel = { 1f }, + ) +} diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModel.kt index 52296137a3d6..401c0ff76c29 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModel.kt @@ -62,6 +62,14 @@ constructor( onStep = { 1f - it }, ) + val shortcutsAlpha: Flow<Float> = + transitionAnimation.createFlow( + duration = 250.milliseconds, + onStep = { 1 - it }, + onFinish = { 0f }, + onCancel = { 1f }, + ) + override val deviceEntryParentViewAlpha: Flow<Float> = shadeDependentFlows.transitionFlow( flowWhenShadeIsNotExpanded = lockscreenAlpha, diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGoneTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGoneTransitionViewModel.kt index 59e5aa845051..cfb4bf59c8a8 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGoneTransitionViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGoneTransitionViewModel.kt @@ -23,6 +23,7 @@ import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition import javax.inject.Inject +import kotlin.time.Duration.Companion.milliseconds import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow @@ -43,6 +44,14 @@ constructor( transitionFlow = interactor.transition(KeyguardState.LOCKSCREEN, KeyguardState.GONE), ) + val shortcutsAlpha: Flow<Float> = + transitionAnimation.createFlow( + duration = 250.milliseconds, + onStep = { 1 - it }, + onFinish = { 0f }, + onCancel = { 1f }, + ) + override val deviceEntryParentViewAlpha: Flow<Float> = transitionAnimation.immediatelyTransitionTo(0f) } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModel.kt index d49bc4994b0f..a6136f95d0f6 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModel.kt @@ -50,6 +50,14 @@ constructor( onStep = { 1f - it }, ) + val shortcutsAlpha: Flow<Float> = + transitionAnimation.createFlow( + duration = 250.milliseconds, + onStep = { 1 - it }, + onFinish = { 0f }, + onCancel = { 1f }, + ) + /** Lockscreen views y-translation */ fun lockscreenTranslationY(translatePx: Int): Flow<Float> { return transitionAnimation.createFlow( diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModel.kt index f04b67a1d4d4..07dd4ef49c5d 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModel.kt @@ -26,6 +26,7 @@ import javax.inject.Inject import kotlin.time.Duration.Companion.milliseconds import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map /** * Breaks down LOCKSCREEN->PRIMARY BOUNCER transition into discrete steps for corresponding views to @@ -46,6 +47,11 @@ constructor( interactor.transition(KeyguardState.LOCKSCREEN, KeyguardState.PRIMARY_BOUNCER), ) + val shortcutsAlpha: Flow<Float> = + interactor.transition(KeyguardState.LOCKSCREEN, KeyguardState.PRIMARY_BOUNCER).map { + 1 - it.value + } + override val deviceEntryParentViewAlpha: Flow<Float> = shadeDependentFlows.transitionFlow( flowWhenShadeIsNotExpanded = diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModel.kt index 0bdc85d05106..58be0934beca 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModel.kt @@ -58,6 +58,13 @@ constructor( ) } + val shortcutsAlpha: Flow<Float> = + transitionAnimation.createFlow( + duration = 250.milliseconds, + onStep = { it }, + onCancel = { 0f }, + ) + /** Lockscreen views alpha */ val lockscreenAlpha: Flow<Float> = transitionAnimation.createFlow( diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OffToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OffToLockscreenTransitionViewModel.kt new file mode 100644 index 000000000000..c3bc799435a8 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OffToLockscreenTransitionViewModel.kt @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.keyguard.ui.viewmodel + +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor +import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow +import javax.inject.Inject +import kotlin.time.Duration.Companion.milliseconds +import kotlinx.coroutines.flow.Flow + +@SysUISingleton +class OffToLockscreenTransitionViewModel +@Inject +constructor( + interactor: KeyguardTransitionInteractor, +) { + + private val transitionAnimation = + KeyguardTransitionAnimationFlow( + transitionDuration = 250.milliseconds, + transitionFlow = interactor.offToLockscreenTransition + ) + + val shortcutsAlpha: Flow<Float> = + transitionAnimation.createFlow( + duration = 250.milliseconds, + onStep = { it }, + onCancel = { 0f }, + ) +} diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModel.kt index 3cf793ab9dc8..7ef8374023fb 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModel.kt @@ -28,6 +28,7 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.map /** * Breaks down PRIMARY BOUNCER->LOCKSCREEN transition into discrete steps for corresponding views to @@ -57,6 +58,11 @@ constructor( } } + val shortcutsAlpha: Flow<Float> = + interactor.transition(KeyguardState.PRIMARY_BOUNCER, KeyguardState.LOCKSCREEN).map { + it.value + } + override val deviceEntryParentViewAlpha: Flow<Float> = transitionAnimation.immediatelyTransitionTo(1f) } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java index eba1c25d0e74..388418487725 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java @@ -36,11 +36,11 @@ import com.android.systemui.qs.TouchAnimator.Builder; import com.android.systemui.qs.dagger.QSScope; import com.android.systemui.qs.tileimpl.HeightOverrideable; import com.android.systemui.tuner.TunerService; +import com.android.systemui.util.concurrency.DelayableExecutor; import java.util.ArrayList; import java.util.Collection; import java.util.List; -import java.util.concurrent.Executor; import javax.inject.Inject; @@ -64,6 +64,7 @@ public class QSAnimator implements QSHost.Callback, PagedTileLayout.PageListener private static final String TAG = "QSAnimator"; + private static final int ANIMATORS_UPDATE_DELAY_MS = 100; private static final float EXPANDED_TILE_DELAY = .86f; //Non first page delays private static final float QS_TILE_LABEL_FADE_OUT_START = 0.15f; @@ -133,7 +134,7 @@ public class QSAnimator implements QSHost.Callback, PagedTileLayout.PageListener private int mLastQQSTileHeight; private float mLastPosition; private final QSHost mHost; - private final Executor mExecutor; + private final DelayableExecutor mExecutor; private boolean mShowCollapsedOnKeyguard; private int mQQSTop; @@ -144,7 +145,7 @@ public class QSAnimator implements QSHost.Callback, PagedTileLayout.PageListener public QSAnimator(@RootView View rootView, QuickQSPanel quickPanel, QSPanelController qsPanelController, QuickQSPanelController quickQSPanelController, QSHost qsTileHost, - @Main Executor executor, TunerService tunerService, + @Main DelayableExecutor executor, TunerService tunerService, QSExpansionPathInterpolator qsExpansionPathInterpolator) { mQsRootView = rootView; mQuickQsPanel = quickPanel; @@ -753,7 +754,10 @@ public class QSAnimator implements QSHost.Callback, PagedTileLayout.PageListener public void onTilesChanged() { // Give the QS panels a moment to generate their new tiles, then create all new animators // hooked up to the new views. - mExecutor.execute(mUpdateAnimators); + mExecutor.executeDelayed(mUpdateAnimators, ANIMATORS_UPDATE_DELAY_MS); + + // Also requests a lazy animators update in case the animation starts before the executor. + requestAnimatorUpdate(); } private final TouchAnimator.Listener mNonFirstPageListener = diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java index 11db69b69f13..6c930b1f3d17 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java @@ -255,6 +255,10 @@ public abstract class QSPanelControllerBase<T extends QSPanel> extends ViewContr for (QSTile tile : tiles) { addTile(tile, collapsedView); } + } else { + for (QSPanelControllerBase.TileRecord record : mRecords) { + record.tile.addCallback(record.callback); + } } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java index 69fe46aa9009..529d68407ce9 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java @@ -109,7 +109,7 @@ public abstract class QSTileImpl<TState extends State> implements QSTile, Lifecy // Only read and modified in main thread (where click events come through). private int mClickEventId = 0; - private final ArrayList<Callback> mCallbacks = new ArrayList<>(); + private final ArraySet<Callback> mCallbacks = new ArraySet<>(); private final Object mStaleListener = new Object(); protected TState mState; private TState mTmpState; @@ -444,9 +444,9 @@ public abstract class QSTileImpl<TState extends State> implements QSTile, Lifecy } private void handleStateChanged() { - if (mCallbacks.size() != 0) { + if (!mCallbacks.isEmpty()) { for (int i = 0; i < mCallbacks.size(); i++) { - mCallbacks.get(i).onStateChanged(mState); + mCallbacks.valueAt(i).onStateChanged(mState); } } } diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt index 1c5330ecd24f..d42fde617394 100644 --- a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt +++ b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt @@ -128,7 +128,7 @@ constructor( private fun automaticallySwitchScenes() { applicationScope.launch { // TODO (b/308001302): Move this to a bouncer specific interactor. - bouncerInteractor.onImeHidden.collectLatest { + bouncerInteractor.onImeHiddenByUser.collectLatest { if (sceneInteractor.desiredScene.value.key == SceneKey.Bouncer) { sceneInteractor.changeScene( scene = SceneModel(SceneKey.Lockscreen), diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordDialog.java b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordDialog.java index e7481ccd0efd..b98093e50920 100644 --- a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordDialog.java +++ b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordDialog.java @@ -32,13 +32,16 @@ import android.os.Handler; import android.os.Looper; import android.os.ResultReceiver; import android.view.Gravity; +import android.view.View; import android.view.Window; import android.view.WindowManager; +import android.view.accessibility.AccessibilityNodeInfo; import android.widget.ArrayAdapter; import android.widget.Spinner; import android.widget.Switch; import android.widget.TextView; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.systemui.mediaprojection.MediaProjectionCaptureTarget; @@ -115,6 +118,17 @@ public class ScreenRecordDialog extends SystemUIDialog { mOptions.setOnItemClickListenerInt((parent, view, position, id) -> { mAudioSwitch.setChecked(true); }); + + // disable redundant Touch & Hold accessibility action for Switch Access + mOptions.setAccessibilityDelegate(new View.AccessibilityDelegate() { + @Override + public void onInitializeAccessibilityNodeInfo(@NonNull View host, + @NonNull AccessibilityNodeInfo info) { + info.removeAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_LONG_CLICK); + super.onInitializeAccessibilityNodeInfo(host, info); + } + }); + mOptions.setLongClickable(false); } /** diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessDialog.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessDialog.java index 9f4ea27b9ee6..d13edf01cc4a 100644 --- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessDialog.java +++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessDialog.java @@ -39,6 +39,7 @@ import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.res.R; +import com.android.systemui.shade.domain.interactor.ShadeInteractor; import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper; import com.android.systemui.util.concurrency.DelayableExecutor; @@ -58,18 +59,21 @@ public class BrightnessDialog extends Activity { private final DelayableExecutor mMainExecutor; private final AccessibilityManagerWrapper mAccessibilityMgr; private Runnable mCancelTimeoutRunnable; + private final ShadeInteractor mShadeInteractor; @Inject public BrightnessDialog( BrightnessSliderController.Factory brightnessSliderfactory, BrightnessController.Factory brightnessControllerFactory, @Main DelayableExecutor mainExecutor, - AccessibilityManagerWrapper accessibilityMgr + AccessibilityManagerWrapper accessibilityMgr, + ShadeInteractor shadeInteractor ) { mToggleSliderFactory = brightnessSliderfactory; mBrightnessControllerFactory = brightnessControllerFactory; mMainExecutor = mainExecutor; mAccessibilityMgr = accessibilityMgr; + mShadeInteractor = shadeInteractor; } @@ -79,6 +83,10 @@ public class BrightnessDialog extends Activity { setWindowAttributes(); setContentView(R.layout.brightness_mirror_container); setBrightnessDialogViewAttributes(); + + if (mShadeInteractor.isQsExpanded().getValue()) { + finish(); + } } private void setWindowAttributes() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutListSearch.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutListSearch.java index 1b096b592a4a..909cff37b67d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutListSearch.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutListSearch.java @@ -493,11 +493,11 @@ public final class KeyboardShortcutListSearch { Arrays.asList( Pair.create(KeyEvent.KEYCODE_SLASH, KeyEvent.META_META_ON))), /* Back: go back to previous state (back button) */ - /* Meta + Grave, Meta + backspace, Meta + left arrow */ + /* Meta + Escape, Meta + Grave, Meta + backspace, Meta + left arrow */ new ShortcutKeyGroupMultiMappingInfo( context.getString(R.string.group_system_go_back), Arrays.asList( - Pair.create(KeyEvent.KEYCODE_GRAVE, KeyEvent.META_META_ON), + Pair.create(KeyEvent.KEYCODE_ESCAPE, KeyEvent.META_META_ON), Pair.create(KeyEvent.KEYCODE_DEL, KeyEvent.META_META_ON), Pair.create(KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.META_META_ON))), /* Access home screen: Meta + H, Meta + Enter */ @@ -612,7 +612,7 @@ public final class KeyboardShortcutListSearch { private static KeyboardShortcutMultiMappingGroup getMultiMappingInputShortcuts( Context context) { List<ShortcutMultiMappingInfo> shortcutMultiMappingInfoList = Arrays.asList( - /* Switch input language (next language): Ctrl + Space or Meta + Space */ + /* Switch input language (next language): Ctrl + Space */ new ShortcutMultiMappingInfo( context.getString(R.string.input_switch_input_language_next), null, @@ -621,14 +621,9 @@ public final class KeyboardShortcutListSearch { context.getString( R.string.input_switch_input_language_next), KeyEvent.KEYCODE_SPACE, KeyEvent.META_CTRL_ON), - null), - new ShortcutKeyGroup(new KeyboardShortcutInfo( - context.getString( - R.string.input_switch_input_language_next), - KeyEvent.KEYCODE_SPACE, KeyEvent.META_META_ON), null))), /* Switch input language (previous language): */ - /* Ctrl + Shift + Space or Meta + Shift + Space */ + /* Ctrl + Shift + Space */ new ShortcutMultiMappingInfo( context.getString(R.string.input_switch_input_language_previous), null, @@ -638,12 +633,6 @@ public final class KeyboardShortcutListSearch { R.string.input_switch_input_language_previous), KeyEvent.KEYCODE_SPACE, KeyEvent.META_CTRL_ON | KeyEvent.META_SHIFT_ON), - null), - new ShortcutKeyGroup(new KeyboardShortcutInfo( - context.getString( - R.string.input_switch_input_language_previous), - KeyEvent.KEYCODE_SPACE, - KeyEvent.META_META_ON | KeyEvent.META_SHIFT_ON), null))) ); return new KeyboardShortcutMultiMappingGroup( diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/ActiveNotificationsInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/ActiveNotificationsInteractor.kt index 31893b402e3c..e90ddf98db00 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/ActiveNotificationsInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/ActiveNotificationsInteractor.kt @@ -15,37 +15,48 @@ package com.android.systemui.statusbar.notification.domain.interactor +import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.statusbar.notification.collection.render.NotifStats import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationListRepository import com.android.systemui.statusbar.notification.shared.ActiveNotificationGroupModel import com.android.systemui.statusbar.notification.shared.ActiveNotificationModel import javax.inject.Inject +import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.map class ActiveNotificationsInteractor @Inject constructor( private val repository: ActiveNotificationListRepository, + @Background private val backgroundDispatcher: CoroutineDispatcher, ) { /** Notifications actively presented to the user in the notification stack, in order. */ val topLevelRepresentativeNotifications: Flow<List<ActiveNotificationModel>> = - repository.activeNotifications.map { store -> - store.renderList.map { key -> - val entry = - store[key] - ?: error("Could not find notification with key $key in active notif store.") - when (entry) { - is ActiveNotificationGroupModel -> entry.summary - is ActiveNotificationModel -> entry + repository.activeNotifications + .map { store -> + store.renderList.map { key -> + val entry = + store[key] + ?: error( + "Could not find notification with key $key in active notif store." + ) + when (entry) { + is ActiveNotificationGroupModel -> entry.summary + is ActiveNotificationModel -> entry + } } } - } + .flowOn(backgroundDispatcher) /** Are any notifications being actively presented in the notification stack? */ val areAnyNotificationsPresent: Flow<Boolean> = - repository.activeNotifications.map { it.renderList.isNotEmpty() }.distinctUntilChanged() + repository.activeNotifications + .map { it.renderList.isNotEmpty() } + .distinctUntilChanged() + .flowOn(backgroundDispatcher) /** * The same as [areAnyNotificationsPresent], but without flows, for easy access in synchronous @@ -59,6 +70,7 @@ constructor( repository.notifStats .map { it.hasClearableAlertingNotifs || it.hasClearableSilentNotifs } .distinctUntilChanged() + .flowOn(backgroundDispatcher) fun setNotifStats(notifStats: NotifStats) { repository.notifStats.value = notifStats diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationsKeyguardInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationsKeyguardInteractor.kt index 87b8e55dbd1a..73341dbc4999 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationsKeyguardInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationsKeyguardInteractor.kt @@ -15,19 +15,24 @@ */ package com.android.systemui.statusbar.notification.domain.interactor +import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.statusbar.notification.data.repository.NotificationsKeyguardViewStateRepository import javax.inject.Inject +import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flowOn /** Domain logic pertaining to notifications on the keyguard. */ class NotificationsKeyguardInteractor @Inject constructor( repository: NotificationsKeyguardViewStateRepository, + @Background backgroundDispatcher: CoroutineDispatcher, ) { /** Is a pulse expansion occurring? */ - val isPulseExpanding: Flow<Boolean> = repository.isPulseExpanding + val isPulseExpanding: Flow<Boolean> = repository.isPulseExpanding.flowOn(backgroundDispatcher) /** Are notifications fully hidden from view? */ - val areNotificationsFullyHidden: Flow<Boolean> = repository.areNotificationsFullyHidden + val areNotificationsFullyHidden: Flow<Boolean> = + repository.areNotificationsFullyHidden.flowOn(backgroundDispatcher) } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java index 6d8ec44ad55e..c615887d5c25 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java @@ -67,6 +67,7 @@ public final class StatusBarTouchableRegionManager implements Dumpable { private final UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController; private boolean mIsStatusBarExpanded = false; + private boolean mIsSceneContainerVisible = false; private boolean mShouldAdjustInsets = false; private View mNotificationShadeWindowView; private View mNotificationPanelView; @@ -128,11 +129,14 @@ public final class StatusBarTouchableRegionManager implements Dumpable { }); mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController; - javaAdapter.alwaysCollectFlow(shadeInteractor.isAnyExpanded(), this::onShadeOrQsExpanded); if (sceneContainerFlags.isEnabled()) { javaAdapter.alwaysCollectFlow( sceneInteractor.get().isVisible(), + this::onSceneContainerVisibilityChanged); + } else { + javaAdapter.alwaysCollectFlow( + shadeInteractor.isAnyExpanded(), this::onShadeOrQsExpanded); } @@ -164,6 +168,17 @@ public final class StatusBarTouchableRegionManager implements Dumpable { } } + private void onSceneContainerVisibilityChanged(Boolean isVisible) { + if (isVisible != mIsSceneContainerVisible) { + mIsSceneContainerVisible = isVisible; + if (isVisible) { + // make sure our state is sensible + mForceCollapsedUntilLayout = false; + } + updateTouchableRegion(); + } + } + /** * Calculates the touch region needed for heads up notifications, taking into consideration * any existing display cutouts (notch) @@ -267,6 +282,7 @@ public final class StatusBarTouchableRegionManager implements Dumpable { // since we don't want stray touches to go through the light reveal scrim to whatever is // underneath. return mIsStatusBarExpanded + || mIsSceneContainerVisible || mPrimaryBouncerInteractor.isShowing().getValue() || mAlternateBouncerInteractor.isVisibleState() || mUnlockedScreenOffAnimationController.isAnimationPlaying(); diff --git a/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt index 053148709e69..968981197b83 100644 --- a/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt +++ b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt @@ -20,10 +20,12 @@ import android.content.Context import android.hardware.devicestate.DeviceStateManager import android.os.SystemProperties import com.android.systemui.CoreStartable +import com.android.systemui.Flags import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.keyguard.LifecycleScreenStatusProvider import com.android.systemui.unfold.config.UnfoldTransitionConfig +import com.android.systemui.unfold.dagger.UnfoldBgProgressFlag import com.android.systemui.unfold.dagger.UnfoldMain import com.android.systemui.unfold.data.repository.UnfoldTransitionRepository import com.android.systemui.unfold.data.repository.UnfoldTransitionRepositoryImpl @@ -64,6 +66,10 @@ class UnfoldTransitionModule { @Provides @UnfoldTransitionATracePrefix fun tracingTagPrefix() = "systemui" + @Provides + @UnfoldBgProgressFlag + fun unfoldBgProgressFlag() = Flags.unfoldAnimationBackgroundProgress() + /** A globally available FoldStateListener that allows one to query the fold state. */ @Provides @Singleton diff --git a/packages/SystemUI/src/com/android/systemui/wallet/controller/QuickAccessWalletController.java b/packages/SystemUI/src/com/android/systemui/wallet/controller/QuickAccessWalletController.java index 0e6df6b11e7b..e031be2a72dd 100644 --- a/packages/SystemUI/src/com/android/systemui/wallet/controller/QuickAccessWalletController.java +++ b/packages/SystemUI/src/com/android/systemui/wallet/controller/QuickAccessWalletController.java @@ -19,6 +19,7 @@ package com.android.systemui.wallet.controller; import static com.android.systemui.wallet.controller.QuickAccessWalletController.WalletChangeEvent.DEFAULT_PAYMENT_APP_CHANGE; import static com.android.systemui.wallet.controller.QuickAccessWalletController.WalletChangeEvent.WALLET_PREFERENCE_CHANGE; +import android.annotation.WorkerThread; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; @@ -146,7 +147,9 @@ public class QuickAccessWalletController { /** * Update the "show wallet" preference. + * This should not be called on the main thread. */ + @WorkerThread public void updateWalletPreference() { mWalletEnabled = mQuickAccessWalletClient.isWalletServiceAvailable() && mQuickAccessWalletClient.isWalletFeatureAvailable() @@ -155,10 +158,12 @@ public class QuickAccessWalletController { /** * Query the wallet cards from {@link QuickAccessWalletClient}. + * This should not be called on the main thread. * * @param cardsRetriever a callback to retrieve wallet cards. * @param maxCards the maximum number of cards requested from the QuickAccessWallet */ + @WorkerThread public void queryWalletCards( QuickAccessWalletClient.OnWalletCardsRetrievedCallback cardsRetriever, int maxCards) { if (mClock.elapsedRealtime() - mQawClientCreatedTimeMillis @@ -182,9 +187,11 @@ public class QuickAccessWalletController { /** * Query the wallet cards from {@link QuickAccessWalletClient}. + * This should not be called on the main thread. * * @param cardsRetriever a callback to retrieve wallet cards. */ + @WorkerThread public void queryWalletCards( QuickAccessWalletClient.OnWalletCardsRetrievedCallback cardsRetriever) { queryWalletCards(cardsRetriever, /* maxCards= */ 1); diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/IWindowMagnificationConnectionTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/IWindowMagnificationConnectionTest.java index d8799e16ebdb..43952824f9a7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/IWindowMagnificationConnectionTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/IWindowMagnificationConnectionTest.java @@ -133,8 +133,8 @@ public class IWindowMagnificationConnectionTest extends SysuiTestCase { } @Test - public void setScale() throws RemoteException { - mIWindowMagnificationConnection.setScale(TEST_DISPLAY, 3.0f); + public void setScaleForWindowMagnification() throws RemoteException { + mIWindowMagnificationConnection.setScaleForWindowMagnification(TEST_DISPLAY, 3.0f); waitForIdleSync(); verify(mWindowMagnificationController).setScale(3.0f); diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt index 67c4e2688cd0..0c30d10ea563 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt @@ -51,6 +51,7 @@ import com.android.systemui.plugins.ActivityStarter import com.android.systemui.res.R import com.android.systemui.settings.UserFileManager import com.android.systemui.settings.UserTracker +import com.android.systemui.shade.domain.interactor.ShadeInteractor import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.util.FakeSharedPreferences @@ -58,8 +59,10 @@ import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.whenever import com.android.systemui.util.settings.FakeSettings import com.google.common.truth.Truth -import kotlin.math.max import kotlin.math.min +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.flow.map import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.TestScope @@ -73,6 +76,7 @@ import org.mockito.Mock import org.mockito.Mockito import org.mockito.MockitoAnnotations +@OptIn(ExperimentalCoroutinesApi::class) @SmallTest @RunWith(JUnit4::class) class KeyguardQuickAffordancesCombinedViewModelTest : SysuiTestCase() { @@ -85,6 +89,47 @@ class KeyguardQuickAffordancesCombinedViewModelTest : SysuiTestCase() { @Mock private lateinit var keyguardStateController: KeyguardStateController @Mock private lateinit var launchAnimator: DialogLaunchAnimator @Mock private lateinit var logger: KeyguardQuickAffordancesMetricsLogger + @Mock private lateinit var shadeInteractor: ShadeInteractor + @Mock + private lateinit var aodToLockscreenTransitionViewModel: AodToLockscreenTransitionViewModel + @Mock + private lateinit var dozingToLockscreenTransitionViewModel: + DozingToLockscreenTransitionViewModel + @Mock + private lateinit var dreamingHostedToLockscreenTransitionViewModel: + DreamingHostedToLockscreenTransitionViewModel + @Mock + private lateinit var dreamingToLockscreenTransitionViewModel: + DreamingToLockscreenTransitionViewModel + @Mock + private lateinit var goneToLockscreenTransitionViewModel: GoneToLockscreenTransitionViewModel + @Mock + private lateinit var occludedToLockscreenTransitionViewModel: + OccludedToLockscreenTransitionViewModel + @Mock + private lateinit var offToLockscreenTransitionViewModel: OffToLockscreenTransitionViewModel + @Mock + private lateinit var primaryBouncerToLockscreenTransitionViewModel: + PrimaryBouncerToLockscreenTransitionViewModel + @Mock + private lateinit var lockscreenToAodTransitionViewModel: LockscreenToAodTransitionViewModel + @Mock + private lateinit var lockscreenToDozingTransitionViewModel: + LockscreenToDozingTransitionViewModel + @Mock + private lateinit var lockscreenToDreamingHostedTransitionViewModel: + LockscreenToDreamingHostedTransitionViewModel + @Mock + private lateinit var lockscreenToDreamingTransitionViewModel: + LockscreenToDreamingTransitionViewModel + @Mock + private lateinit var lockscreenToGoneTransitionViewModel: LockscreenToGoneTransitionViewModel + @Mock + private lateinit var lockscreenToOccludedTransitionViewModel: + LockscreenToOccludedTransitionViewModel + @Mock + private lateinit var lockscreenToPrimaryBouncerTransitionViewModel: + LockscreenToPrimaryBouncerTransitionViewModel private lateinit var underTest: KeyguardQuickAffordancesCombinedViewModel @@ -97,6 +142,10 @@ class KeyguardQuickAffordancesCombinedViewModelTest : SysuiTestCase() { private lateinit var biometricSettingsRepository: FakeBiometricSettingsRepository private lateinit var keyguardInteractor: KeyguardInteractor + private val intendedAlphaMutableStateFlow: MutableStateFlow<Float> = MutableStateFlow(1f) + // the viewModel does a `map { 1 - it }` on this value, which is why it's different + private val intendedShadeAlphaMutableStateFlow: MutableStateFlow<Float> = MutableStateFlow(0f) + @Before fun setUp() { MockitoAnnotations.initMocks(this) @@ -191,6 +240,31 @@ class KeyguardQuickAffordancesCombinedViewModelTest : SysuiTestCase() { userHandle = UserHandle.SYSTEM, ) + intendedAlphaMutableStateFlow.value = 1f + intendedShadeAlphaMutableStateFlow.value = 0f + whenever(aodToLockscreenTransitionViewModel.shortcutsAlpha) + .thenReturn(intendedAlphaMutableStateFlow) + whenever(dozingToLockscreenTransitionViewModel.shortcutsAlpha).thenReturn(emptyFlow()) + whenever(dreamingHostedToLockscreenTransitionViewModel.shortcutsAlpha) + .thenReturn(emptyFlow()) + whenever(dreamingToLockscreenTransitionViewModel.shortcutsAlpha).thenReturn(emptyFlow()) + whenever(goneToLockscreenTransitionViewModel.shortcutsAlpha).thenReturn(emptyFlow()) + whenever(occludedToLockscreenTransitionViewModel.shortcutsAlpha).thenReturn(emptyFlow()) + whenever(offToLockscreenTransitionViewModel.shortcutsAlpha).thenReturn(emptyFlow()) + whenever(primaryBouncerToLockscreenTransitionViewModel.shortcutsAlpha) + .thenReturn(emptyFlow()) + whenever(lockscreenToAodTransitionViewModel.shortcutsAlpha) + .thenReturn(intendedAlphaMutableStateFlow) + whenever(lockscreenToDozingTransitionViewModel.shortcutsAlpha).thenReturn(emptyFlow()) + whenever(lockscreenToDreamingHostedTransitionViewModel.shortcutsAlpha) + .thenReturn(emptyFlow()) + whenever(lockscreenToDreamingTransitionViewModel.shortcutsAlpha).thenReturn(emptyFlow()) + whenever(lockscreenToGoneTransitionViewModel.shortcutsAlpha).thenReturn(emptyFlow()) + whenever(lockscreenToOccludedTransitionViewModel.shortcutsAlpha).thenReturn(emptyFlow()) + whenever(lockscreenToPrimaryBouncerTransitionViewModel.shortcutsAlpha) + .thenReturn(emptyFlow()) + whenever(shadeInteractor.qsExpansion).thenReturn(intendedShadeAlphaMutableStateFlow) + underTest = KeyguardQuickAffordancesCombinedViewModel( quickAffordanceInteractor = @@ -210,7 +284,27 @@ class KeyguardQuickAffordancesCombinedViewModelTest : SysuiTestCase() { backgroundDispatcher = testDispatcher, appContext = mContext, ), - keyguardInteractor = keyguardInteractor + keyguardInteractor = keyguardInteractor, + shadeInteractor = shadeInteractor, + aodToLockscreenTransitionViewModel = aodToLockscreenTransitionViewModel, + dozingToLockscreenTransitionViewModel = dozingToLockscreenTransitionViewModel, + dreamingHostedToLockscreenTransitionViewModel = + dreamingHostedToLockscreenTransitionViewModel, + dreamingToLockscreenTransitionViewModel = dreamingToLockscreenTransitionViewModel, + goneToLockscreenTransitionViewModel = goneToLockscreenTransitionViewModel, + occludedToLockscreenTransitionViewModel = occludedToLockscreenTransitionViewModel, + offToLockscreenTransitionViewModel = offToLockscreenTransitionViewModel, + primaryBouncerToLockscreenTransitionViewModel = + primaryBouncerToLockscreenTransitionViewModel, + lockscreenToAodTransitionViewModel = lockscreenToAodTransitionViewModel, + lockscreenToDozingTransitionViewModel = lockscreenToDozingTransitionViewModel, + lockscreenToDreamingHostedTransitionViewModel = + lockscreenToDreamingHostedTransitionViewModel, + lockscreenToDreamingTransitionViewModel = lockscreenToDreamingTransitionViewModel, + lockscreenToGoneTransitionViewModel = lockscreenToGoneTransitionViewModel, + lockscreenToOccludedTransitionViewModel = lockscreenToOccludedTransitionViewModel, + lockscreenToPrimaryBouncerTransitionViewModel = + lockscreenToPrimaryBouncerTransitionViewModel ) } @@ -526,15 +620,15 @@ class KeyguardQuickAffordancesCombinedViewModelTest : SysuiTestCase() { @Test fun isClickable_falseWhenAlphaBelowThreshold() = testScope.runTest { + intendedAlphaMutableStateFlow.value = + KeyguardQuickAffordancesCombinedViewModel.AFFORDANCE_FULLY_OPAQUE_ALPHA_THRESHOLD - + .1f + // the viewModel does a `map { 1 - it }` on this value, which is why it's different + intendedShadeAlphaMutableStateFlow.value = + KeyguardQuickAffordancesCombinedViewModel.AFFORDANCE_FULLY_OPAQUE_ALPHA_THRESHOLD + + .1f repository.setKeyguardShowing(true) val latest = collectLastValue(underTest.startButton) - repository.setKeyguardAlpha( - max( - 0f, - KeyguardQuickAffordancesCombinedViewModel - .AFFORDANCE_FULLY_OPAQUE_ALPHA_THRESHOLD - 0.1f - ), - ) val testConfig = TestConfig( @@ -561,9 +655,10 @@ class KeyguardQuickAffordancesCombinedViewModelTest : SysuiTestCase() { @Test fun isClickable_falseWhenAlphaAtZero() = testScope.runTest { + intendedAlphaMutableStateFlow.value = 0f + intendedShadeAlphaMutableStateFlow.value = 1f repository.setKeyguardShowing(true) val latest = collectLastValue(underTest.startButton) - repository.setKeyguardAlpha(0f) val testConfig = TestConfig( diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt index e6d6cf263d69..a57feda64723 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt @@ -163,23 +163,6 @@ class KeyguardRootViewModelTest : SysuiTestCase() { } @Test - fun alpha_inPreviewMode_doesNotChange() = - testScope.runTest { - val value = collectLastValue(underTest.alpha) - underTest.enablePreviewMode() - - assertThat(value()).isEqualTo(1f) - repository.setKeyguardAlpha(0.1f) - assertThat(value()).isEqualTo(1f) - repository.setKeyguardAlpha(0.5f) - assertThat(value()).isEqualTo(1f) - repository.setKeyguardAlpha(0.2f) - assertThat(value()).isEqualTo(1f) - repository.setKeyguardAlpha(0f) - assertThat(value()).isEqualTo(1f) - } - - @Test fun translationAndScaleFromBurnInNotDozing() = testScope.runTest { val translationX by collectLastValue(underTest.translationX) diff --git a/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessDialogTest.kt b/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessDialogTest.kt index 6e487cdd65b5..88c728fd1b66 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessDialogTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessDialogTest.kt @@ -28,12 +28,16 @@ import androidx.test.rule.ActivityTestRule import com.android.systemui.SysuiTestCase import com.android.systemui.activity.SingleActivityFactory import com.android.systemui.res.R +import com.android.systemui.shade.domain.interactor.ShadeInteractor import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper import com.android.systemui.util.concurrency.DelayableExecutor import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.mockito.any +import com.android.systemui.util.mockito.whenever import com.android.systemui.util.time.FakeSystemClock import com.google.common.truth.Truth.assertThat +import dagger.Lazy +import kotlinx.coroutines.flow.MutableStateFlow import org.junit.After import org.junit.Before import org.junit.Rule @@ -55,6 +59,8 @@ class BrightnessDialogTest : SysuiTestCase() { @Mock private lateinit var brightnessControllerFactory: BrightnessController.Factory @Mock private lateinit var brightnessController: BrightnessController @Mock private lateinit var accessibilityMgr: AccessibilityManagerWrapper + @Mock private lateinit var shadeInteractorLazy: Lazy<ShadeInteractor> + @Mock private lateinit var shadeInteractor: ShadeInteractor private val clock = FakeSystemClock() private val mainExecutor = FakeExecutor(clock) @@ -68,7 +74,8 @@ class BrightnessDialogTest : SysuiTestCase() { brightnessSliderControllerFactory, brightnessControllerFactory, mainExecutor, - accessibilityMgr + accessibilityMgr, + shadeInteractor ) }, /* initialTouchMode= */ false, @@ -82,6 +89,8 @@ class BrightnessDialogTest : SysuiTestCase() { .thenReturn(brightnessSliderController) `when`(brightnessSliderController.rootView).thenReturn(View(context)) `when`(brightnessControllerFactory.create(any())).thenReturn(brightnessController) + whenever(shadeInteractorLazy.get()).thenReturn(shadeInteractor) + whenever(shadeInteractor.isQsExpanded).thenReturn(MutableStateFlow(false)) } @After @@ -175,13 +184,15 @@ class BrightnessDialogTest : SysuiTestCase() { brightnessSliderControllerFactory: BrightnessSliderController.Factory, brightnessControllerFactory: BrightnessController.Factory, mainExecutor: DelayableExecutor, - accessibilityMgr: AccessibilityManagerWrapper + accessibilityMgr: AccessibilityManagerWrapper, + shadeInteractor: ShadeInteractor ) : BrightnessDialog( brightnessSliderControllerFactory, brightnessControllerFactory, mainExecutor, - accessibilityMgr + accessibilityMgr, + shadeInteractor ) { private var finishing = false diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java index 1dbb2972c6f3..62c0ebeb8c07 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java @@ -22,6 +22,8 @@ import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import static kotlinx.coroutines.test.TestCoroutineDispatchersKt.StandardTestDispatcher; + import android.content.res.Resources; import android.os.Handler; import android.os.Looper; @@ -293,8 +295,10 @@ public class QuickSettingsControllerBaseTest extends SysuiTestCase { ) ); - mActiveNotificationsInteractor = - new ActiveNotificationsInteractor(new ActiveNotificationListRepository()); + mActiveNotificationsInteractor = new ActiveNotificationsInteractor( + new ActiveNotificationListRepository(), + StandardTestDispatcher(/* scheduler = */ null, /* name = */ null) + ); KeyguardStatusView keyguardStatusView = new KeyguardStatusView(mContext); keyguardStatusView.setId(R.id.keyguard_status_view); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/RenderNotificationsListInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/RenderNotificationsListInteractorTest.kt index b86f8410fb7f..6374d5e259fc 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/RenderNotificationsListInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/RenderNotificationsListInteractorTest.kt @@ -25,14 +25,19 @@ import com.android.systemui.statusbar.notification.shared.byKey import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.test.StandardTestDispatcher +import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest import org.junit.Test @SmallTest class RenderNotificationsListInteractorTest : SysuiTestCase() { + private val backgroundDispatcher = StandardTestDispatcher() + private val testScope = TestScope(backgroundDispatcher) private val notifsRepository = ActiveNotificationListRepository() - private val notifsInteractor = ActiveNotificationsInteractor(notifsRepository) + private val notifsInteractor = + ActiveNotificationsInteractor(notifsRepository, backgroundDispatcher) private val underTest = RenderNotificationListInteractor( notifsRepository, @@ -40,21 +45,26 @@ class RenderNotificationsListInteractorTest : SysuiTestCase() { ) @Test - fun setRenderedList_preservesOrdering() = runTest { - val notifs by collectLastValue(notifsInteractor.topLevelRepresentativeNotifications) - val keys = (1..50).shuffled().map { "$it" } - val entries = - keys.map { - mock<ListEntry> { - val mockRep = mock<NotificationEntry> { - whenever(key).thenReturn(it) - whenever(sbn).thenReturn(mock()) - whenever(icons).thenReturn(mock()) + fun setRenderedList_preservesOrdering() = + testScope.runTest { + val notifs by collectLastValue(notifsInteractor.topLevelRepresentativeNotifications) + val keys = (1..50).shuffled().map { "$it" } + val entries = + keys.map { + mock<ListEntry> { + val mockRep = + mock<NotificationEntry> { + whenever(key).thenReturn(it) + whenever(sbn).thenReturn(mock()) + whenever(icons).thenReturn(mock()) + } + whenever(representativeEntry).thenReturn(mockRep) } - whenever(representativeEntry).thenReturn(mockRep) } - } - underTest.setRenderedList(entries) - assertThat(notifs).comparingElementsUsing(byKey).containsExactlyElementsIn(keys).inOrder() - } + underTest.setRenderedList(entries) + assertThat(notifs) + .comparingElementsUsing(byKey) + .containsExactlyElementsIn(keys) + .inOrder() + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java index ff5c02622e4e..755897442eb6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java @@ -35,6 +35,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static kotlinx.coroutines.flow.FlowKt.emptyFlow; +import static kotlinx.coroutines.test.TestCoroutineDispatchersKt.StandardTestDispatcher; import android.metrics.LogMaker; import android.testing.AndroidTestingRunner; @@ -169,7 +170,8 @@ public class NotificationStackScrollLayoutControllerTest extends SysuiTestCase { new ActiveNotificationListRepository(); private final ActiveNotificationsInteractor mActiveNotificationsInteractor = - new ActiveNotificationsInteractor(mActiveNotificationsRepository); + new ActiveNotificationsInteractor(mActiveNotificationsRepository, + StandardTestDispatcher(/* scheduler = */ null, /* name = */ null)); private final SeenNotificationsInteractor mSeenNotificationsInteractor = new SeenNotificationsInteractor(mActiveNotificationsRepository); diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/MainThreadUnfoldTransitionProgressProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/MainThreadUnfoldTransitionProgressProviderTest.kt new file mode 100644 index 000000000000..4e61b89b9c3e --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/MainThreadUnfoldTransitionProgressProviderTest.kt @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.unfold.progress + +import android.os.Looper +import android.testing.AndroidTestingRunner +import android.testing.TestableLooper.RunWithLooper +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.unfold.TestUnfoldTransitionProvider +import com.android.systemui.utils.os.FakeHandler +import kotlin.test.Test +import org.junit.runner.RunWith + +@RunWith(AndroidTestingRunner::class) +@SmallTest +@RunWithLooper(setAsMainLooper = true) +class MainThreadUnfoldTransitionProgressProviderTest : SysuiTestCase() { + + private val wrappedProgressProvider = TestUnfoldTransitionProvider() + private val fakeHandler = FakeHandler(Looper.getMainLooper()) + private val listener = TestUnfoldProgressListener() + + private val progressProvider = + MainThreadUnfoldTransitionProgressProvider(fakeHandler, wrappedProgressProvider) + + @Test + fun onTransitionStarted_propagated() { + progressProvider.addCallback(listener) + + wrappedProgressProvider.onTransitionStarted() + fakeHandler.dispatchQueuedMessages() + + listener.assertStarted() + } + + @Test + fun onTransitionProgress_propagated() { + progressProvider.addCallback(listener) + + wrappedProgressProvider.onTransitionStarted() + wrappedProgressProvider.onTransitionProgress(0.5f) + fakeHandler.dispatchQueuedMessages() + + listener.assertLastProgress(0.5f) + } + + @Test + fun onTransitionFinished_propagated() { + progressProvider.addCallback(listener) + + wrappedProgressProvider.onTransitionStarted() + wrappedProgressProvider.onTransitionProgress(0.5f) + wrappedProgressProvider.onTransitionFinished() + fakeHandler.dispatchQueuedMessages() + + listener.ensureTransitionFinished() + } + + @Test + fun onTransitionFinishing_propagated() { + progressProvider.addCallback(listener) + + wrappedProgressProvider.onTransitionStarted() + wrappedProgressProvider.onTransitionProgress(0.5f) + wrappedProgressProvider.onTransitionFinished() + fakeHandler.dispatchQueuedMessages() + + listener.ensureTransitionFinished() + } + + @Test + fun onTransitionStarted_afterCallbackRemoved_notPropagated() { + progressProvider.addCallback(listener) + progressProvider.removeCallback(listener) + + wrappedProgressProvider.onTransitionStarted() + fakeHandler.dispatchQueuedMessages() + + listener.assertNotStarted() + } +} diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/domain/interactor/ActiveNotificationsInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/domain/interactor/ActiveNotificationsInteractorKosmos.kt index 3d7fb6d91393..01f453570e63 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/domain/interactor/ActiveNotificationsInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/domain/interactor/ActiveNotificationsInteractorKosmos.kt @@ -17,7 +17,10 @@ package com.android.systemui.statusbar.notification.domain.interactor import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.testDispatcher import com.android.systemui.statusbar.notification.data.repository.activeNotificationListRepository val Kosmos.activeNotificationsInteractor by - Kosmos.Fixture { ActiveNotificationsInteractor(activeNotificationListRepository) } + Kosmos.Fixture { + ActiveNotificationsInteractor(activeNotificationListRepository, testDispatcher) + } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationsKeyguardInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationsKeyguardInteractorKosmos.kt index 61a38b864c40..432464e86c3f 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationsKeyguardInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationsKeyguardInteractorKosmos.kt @@ -18,11 +18,13 @@ package com.android.systemui.statusbar.notification.stack.domain.interactor import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.Kosmos.Fixture +import com.android.systemui.kosmos.testDispatcher import com.android.systemui.statusbar.notification.data.repository.notificationsKeyguardViewStateRepository import com.android.systemui.statusbar.notification.domain.interactor.NotificationsKeyguardInteractor val Kosmos.notificationsKeyguardInteractor by Fixture { NotificationsKeyguardInteractor( repository = notificationsKeyguardViewStateRepository, + backgroundDispatcher = testDispatcher, ) } diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldSharedModule.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldSharedModule.kt index 42d31b38ff76..f7fb01465a40 100644 --- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldSharedModule.kt +++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldSharedModule.kt @@ -19,8 +19,10 @@ package com.android.systemui.unfold import android.os.Handler import com.android.systemui.unfold.config.UnfoldTransitionConfig import com.android.systemui.unfold.dagger.UnfoldBg +import com.android.systemui.unfold.dagger.UnfoldBgProgressFlag import com.android.systemui.unfold.dagger.UnfoldMain import com.android.systemui.unfold.progress.FixedTimingTransitionProgressProvider +import com.android.systemui.unfold.progress.MainThreadUnfoldTransitionProgressProvider import com.android.systemui.unfold.progress.PhysicsBasedUnfoldTransitionProgressProvider import com.android.systemui.unfold.progress.UnfoldTransitionProgressForwarder import com.android.systemui.unfold.updates.DeviceFoldStateProvider @@ -36,15 +38,18 @@ import com.android.systemui.unfold.util.ScaleAwareTransitionProgressProvider import com.android.systemui.unfold.util.UnfoldKeyguardVisibilityManager import com.android.systemui.unfold.util.UnfoldKeyguardVisibilityManagerImpl import com.android.systemui.unfold.util.UnfoldKeyguardVisibilityProvider +import dagger.BindsOptionalOf import dagger.Module import dagger.Provides import java.util.Optional import javax.inject.Provider import javax.inject.Singleton +import kotlin.jvm.optionals.getOrDefault @Module( includes = [ + UnfoldFlagsModule::class, UnfoldSharedInternalModule::class, UnfoldRotationProviderInternalModule::class, HingeAngleProviderInternalModule::class, @@ -69,6 +74,16 @@ class UnfoldSharedModule { fun foldStateRepository(impl: FoldStateRepositoryImpl): FoldStateRepository = impl } +@Module +abstract class UnfoldFlagsModule { + /** + * Users of the library can bind this boolean to notify whether the progress should be + * calculated only in the background (and the main thread provider is generated by posting the + * background events in the main handler). + */ + @BindsOptionalOf @UnfoldBgProgressFlag abstract fun unfoldBgProgressFlag(): Boolean +} + /** * Needed as methods inside must be public, but their parameters can be internal (and, a public * method can't have internal parameters). Making the module internal and included in a public one @@ -87,17 +102,34 @@ internal class UnfoldSharedInternalModule { fixedTimingTransitionProgressProvider: Provider<FixedTimingTransitionProgressProvider>, foldStateProvider: FoldStateProvider, @UnfoldMain mainHandler: Handler, + mainThreadUnfoldTransitionProgressProviderFactory: + MainThreadUnfoldTransitionProgressProvider.Factory, + @UnfoldBg bgProvider: Provider<Optional<UnfoldTransitionProgressProvider>>, + @UnfoldBgProgressFlag unfoldBgProgressFlag: Optional<Boolean>, ): Optional<UnfoldTransitionProgressProvider> { - return createOptionalUnfoldTransitionProgressProvider( - config = config, - scaleAwareProviderFactory = scaleAwareProviderFactory, - tracingListener = tracingListener.create("MainThread"), - physicsBasedUnfoldTransitionProgressProvider = - physicsBasedUnfoldTransitionProgressProvider, - fixedTimingTransitionProgressProvider = fixedTimingTransitionProgressProvider, - foldStateProvider = foldStateProvider, - progressHandler = mainHandler, - ) + if (unfoldBgProgressFlag.getOrDefault(false)) { + // In this case, we wrap the background progress provider + val mainThreadProvider: Optional<UnfoldTransitionProgressProvider> = + bgProvider.get().map { + mainThreadUnfoldTransitionProgressProviderFactory.create(it) + } + mainThreadProvider.ifPresent { + it.addCallback(tracingListener.create("MainThreadFromBgProgress")) + } + return mainThreadProvider + } else { + // TODO(b/277879146): Remove this once unfold_animation_background_progress is launched. + return createOptionalUnfoldTransitionProgressProvider( + config = config, + scaleAwareProviderFactory = scaleAwareProviderFactory, + tracingListener = tracingListener.create("MainThread"), + physicsBasedUnfoldTransitionProgressProvider = + physicsBasedUnfoldTransitionProgressProvider, + fixedTimingTransitionProgressProvider = fixedTimingTransitionProgressProvider, + foldStateProvider = foldStateProvider, + progressHandler = mainHandler, + ) + } } @Provides diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/dagger/UnfoldBgProgressFlag.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/dagger/UnfoldBgProgressFlag.kt new file mode 100644 index 000000000000..0e371fa6bfb7 --- /dev/null +++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/dagger/UnfoldBgProgressFlag.kt @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.unfold.dagger + +import javax.inject.Qualifier + +/** + * Annotates the boolean representing whether we are calculating progresses in the background. + * + * Used to allow clients to provide this value, without depending on the flags directly. + */ +@Qualifier @Retention(AnnotationRetention.RUNTIME) annotation class UnfoldBgProgressFlag diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/MainThreadUnfoldTransitionProgressProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/MainThreadUnfoldTransitionProgressProvider.kt new file mode 100644 index 000000000000..9bdf3d5d5307 --- /dev/null +++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/MainThreadUnfoldTransitionProgressProvider.kt @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.unfold.progress + +import android.os.Handler +import androidx.annotation.FloatRange +import com.android.systemui.unfold.UnfoldTransitionProgressProvider +import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener +import com.android.systemui.unfold.dagger.UnfoldMain +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject + +/** + * [UnfoldTransitionProgressProvider] that forwards all progress to the main thread handler. + * + * This is needed when progress are calculated in the background, but some listeners need the + * callbacks in the main thread. + */ +class MainThreadUnfoldTransitionProgressProvider +@AssistedInject +constructor( + @UnfoldMain private val mainHandler: Handler, + @Assisted private val rootProvider: UnfoldTransitionProgressProvider +) : UnfoldTransitionProgressProvider { + + private val listenerMap = mutableMapOf<TransitionProgressListener, TransitionProgressListener>() + + override fun addCallback(listener: TransitionProgressListener) { + assertMainThread() + val proxy = TransitionProgressListerProxy(listener) + rootProvider.addCallback(proxy) + listenerMap[listener] = proxy + } + + override fun removeCallback(listener: TransitionProgressListener) { + assertMainThread() + val proxy = listenerMap.remove(listener) ?: return + rootProvider.removeCallback(proxy) + } + + private fun assertMainThread() { + check(mainHandler.looper.isCurrentThread) { + "Should be called from the main thread, but this is ${Thread.currentThread()}" + } + } + + override fun destroy() { + rootProvider.destroy() + } + + inner class TransitionProgressListerProxy(private val listener: TransitionProgressListener) : + TransitionProgressListener { + override fun onTransitionStarted() { + mainHandler.post { listener.onTransitionStarted() } + } + + override fun onTransitionProgress(@FloatRange(from = 0.0, to = 1.0) progress: Float) { + mainHandler.post { listener.onTransitionProgress(progress) } + } + + override fun onTransitionFinishing() { + mainHandler.post { listener.onTransitionFinishing() } + } + + override fun onTransitionFinished() { + mainHandler.post { listener.onTransitionFinished() } + } + } + + @AssistedFactory + interface Factory { + /** Creates a [MainThreadUnfoldTransitionProgressProvider] that wraps the [rootProvider]. */ + fun create( + rootProvider: UnfoldTransitionProgressProvider + ): MainThreadUnfoldTransitionProgressProvider + } +} diff --git a/ravenwood/README.md b/ravenwood/README.md new file mode 100644 index 000000000000..9c4fda7a50a6 --- /dev/null +++ b/ravenwood/README.md @@ -0,0 +1,28 @@ +# Ravenwood + +Ravenwood is an officially-supported lightweight unit testing environment for Android platform code that runs on the host. + +Ravenwood’s focus on Android platform use-cases, improved maintainability, and device consistency distinguishes it from Robolectric, which remains a popular choice for app testing. + +## Background + +Executing tests on a typical Android device has substantial overhead, such as flashing the build, waiting for the boot to complete, and retrying tests that fail due to general flakiness. + +In contrast, defining a lightweight unit testing environment mitigates these issues by running directly from build artifacts (no flashing required), runs immediately (no booting required), and runs in an isolated environment (less flakiness). + +## Guiding principles +Here’s a summary of the guiding principles for Ravenwood, aimed at addressing Robolectric design concerns and better supporting Android platform developers: + +* **API support for Ravenwood is opt-in.** Teams that own APIs decide exactly what, and how, they support their API functionality being available to tests. When an API hasn’t opted-in, the API signatures remain available for tests to compile against and/or mock, but they throw when called under a Ravenwood environment. + * _Contrasted with Robolectric which attempts to run API implementations as-is, causing maintenance pains as teams maintain or redesign their API internals._ +* **API support and customizations for Ravenwood appear directly inline with relevant code.** This improves maintenance of APIs by providing awareness of what code runs under Ravenwood, including the ability to replace code at a per-method level when Ravenwood-specific customization is needed. + * _Contrasted with Robolectric which maintains customized behavior in separate “Shadow” classes that are difficult for maintainers to be aware of._ +* **APIs supported under Ravenwood are tested to remain consistent with physical devices.** As teams progressively opt-in supporting APIs under Ravenwood, we’re requiring they bring along “bivalent” tests (such as the relevant CTS) to validate that Ravenwood behaves just like a physical device. + * _Contrasted with Robolectric, which has limited (and forked) testing of their environment, increasing their risk of accidental divergence over time and misleading “passing” signals._ +* **Ravenwood aims to support more “real” code.** As API owners progressively opt-in their code, they have the freedom to provide either a limited “fake” that is a faithful emulation of how a device behaves, or they can bring more “real” code that runs on physical devices. + * _Contrasted with Robolectric, where support for “real” code ends at the app process boundary, such as a call into `system_server`._ + +## More details + +* [Ravenwood for Test Authors](test-authors.md) +* [Ravenwood for API Maintainers](api-maintainers.md) diff --git a/ravenwood/api-maintainers.md b/ravenwood/api-maintainers.md new file mode 100644 index 000000000000..30e899cd3ce3 --- /dev/null +++ b/ravenwood/api-maintainers.md @@ -0,0 +1,73 @@ +# Ravenwood for API Maintainers + +By default, Android APIs aren’t opted-in to Ravenwood, and they default to throwing when called under the Ravenwood environment. + +To opt-in to supporting an API under Ravenwood, you can use the inline annotations documented below to customize your API behavior when running under Ravenwood. Because these annotations are inline in the relevant platform source code, they serve as valuable reminders to future API maintainers of Ravenwood support expectations. + +> **Note:** to ensure that API teams are well-supported during early Ravenwood onboarding, the Ravenwood team is manually maintaining an allow-list of classes that are able to use Ravenwood annotations. Please reach out to ravenwood@ so we can offer design advice and allow-list your APIs. + +These Ravenwood-specific annotations have no bearing on the status of an API being public, `@SystemApi`, `@TestApi`, `@hide`, etc. Ravenwood annotations are an orthogonal concept that are only consumed by the internal `hoststubgen` tool during a post-processing step that generates the Ravenwood runtime environment. Teams that own APIs can continue to refactor opted-in `@hide` implementation details, as long as the test-visible behavior continues passing. + +As described in our Guiding Principles, when a team opts-in an API, we’re requiring that they bring along “bivalent” tests (such as the relevant CTS) to validate that Ravenwood behaves just like a physical device. At the moment this means adding the bivalent tests to relevant `TEST_MAPPING` files to ensure they remain consistently passing over time. These bivalent tests are important because they progressively provide the foundation on which higher-level unit tests place their trust. + +## Opt-in to supporting a single method while other methods remained opt-out + +``` +@RavenwoodKeepPartialClass +public class MyManager { + @RavenwoodKeep + public static String modeToString(int mode) { + // This method implementation runs as-is on both devices and Ravenwood + } + + public static void doComplex() { + // This method implementation runs as-is on devices, but because there + // is no method-level annotation, and the class-level default is + // “keep partial”, this method is not supported under Ravenwood and + // will throw + } +} +``` + +## Opt-in an entire class with opt-out of specific methods + +``` +@RavenwoodKeepWholeClass +public class MyStruct { + public void doSimple() { + // This method implementation runs as-is on both devices and Ravenwood, + // implicitly inheriting the class-level annotation + } + + @RavenwoodThrow + public void doComplex() { + // This method implementation runs as-is on devices, but the + // method-level annotation overrides the class-level annotation, so + // this method is not supported under Ravenwood and will throw + } +} +``` + +## Replace a complex method when under Ravenwood + +``` +@RavenwoodKeepWholeClass +public class MyStruct { + @RavenwoodReplace + public void doComplex() { + // This method implementation runs as-is on devices, but the + // implementation is replaced/substituted by the + // doComplex$ravenwood() method implementation under Ravenwood + } + + public void doComplex$ravenwood() { + // This method implementation only runs under Ravenwood + } +} +``` + +## General strategies for side-stepping tricky dependencies + +The “replace” strategy described above is quite powerful, and can be used in creative ways to sidestep tricky underlying dependencies that aren’t ready yet. + +For example, consider a constructor or static initializer that relies on unsupported functionality from another team. By factoring the unsupported logic into a dedicated method, that method can then be replaced under Ravenwood to offer baseline functionality. diff --git a/ravenwood/test-authors.md b/ravenwood/test-authors.md new file mode 100644 index 000000000000..2b5bd9083a40 --- /dev/null +++ b/ravenwood/test-authors.md @@ -0,0 +1,132 @@ +# Ravenwood for Test Authors + +The Ravenwood testing environment runs inside a single Java process on the host side, and provides a limited yet growing set of Android API functionality. + +Ravenwood explicitly does not support “large” integration tests that expect a fully booted Android OS. Instead, it’s more suited for “small” and “medium” tests where your code-under-test has been factored to remove dependencies on a fully booted device. + +When writing tests under Ravenwood, all Android API symbols associated with your declared `sdk_version` are available to link against using, but unsupported APIs will throw an exception. This design choice enables mocking of unsupported APIs, and supports sharing of test code to build “bivalent” test suites that run against either Ravenwood or a traditional device. + +## Typical test structure + +Below are the typical steps needed to add a straightforward “small” unit test: + +* Define an `android_ravenwood_test` rule in your `Android.bp` file: + +``` +android_ravenwood_test { + name: "MyTestsRavenwood", + static_libs: [ + "androidx.annotation_annotation", + "androidx.test.rules", + ], + srcs: [ + "src/com/example/MyCode.java", + "tests/src/com/example/MyCodeTest.java", + ], + sdk_version: "test_current", + auto_gen_config: true, +} +``` + +* Write your unit test just like you would for an Android device: + +``` +@RunWith(AndroidJUnit4.class) +public class MyCodeTest { + @Test + public void testSimple() { + // ... + } +} +``` + +* APIs available under Ravenwood are stateless by default. If your test requires explicit states (such as defining the UID you’re running under, or requiring a main `Looper` thread), add a `RavenwoodRule` to declare that: + +``` +@RunWith(AndroidJUnit4.class) +public class MyCodeTest { + @Rule + public final RavenwoodRule mRavenwood = new RavenwoodRule.Builder() + .setProcessApp() + .setProvideMainThread(true) + .build(); +``` + +Once you’ve defined your test, you can use typical commands to execute it locally: + +``` +$ atest MyTestsRavenwood +``` + +> **Note:** There's a known bug where `atest` currently requires a connected device to run Ravenwood tests, but that device isn't used for testing. + +You can also run your new tests automatically via `TEST_MAPPING` rules like this: + +``` +{ + "ravenwood-presubmit": [ + { + "name": "MyTestsRavenwood", + "host": true + } + ] +} +``` + +## Strategies for migration/bivalent tests + +Ravenwood aims to support tests that are written in a “bivalent” way, where the same test code can run on both a real Android device and under a Ravenwood environment. + +In situations where a test method depends on API functionality not yet available under Ravenwood, we provide an annotation to quietly “ignore” that test under Ravenwood, while continuing to validate that test on real devices. Please note that your test must declare a `RavenwoodRule` for the annotation to take effect. + +Test authors are encouraged to provide a `blockedBy` or `reason` argument to help future maintainers understand why a test is being ignored, and under what conditions it might be supported in the future. + +``` +@RunWith(AndroidJUnit4.class) +public class MyCodeTest { + @Rule + public final RavenwoodRule mRavenwood = new RavenwoodRule(); + + @Test + public void testSimple() { + // Simple test that runs on both devices and Ravenwood + } + + @Test + @IgnoreUnderRavenwood(blockedBy = PackageManager.class) + public void testComplex() { + // Complex test that runs on devices, but is ignored under Ravenwood + } +} +``` + +## Strategies for unsupported APIs + +As you write tests against Ravenwood, you’ll likely discover API dependencies that aren’t supported yet. Here’s a few strategies that can help you make progress: + +* Your code-under-test may benefit from subtle dependency refactoring to reduce coupling. (For example, providing a specific `File` argument instead of deriving it internally from a `Context`.) +* Although mocking code that your team doesn’t own is a generally discouraged testing practice, it can be a valuable pressure relief valve when a dependency isn’t yet supported. + +## Strategies for debugging test development + +When writing tests you may encounter odd or hard to debug behaviors. One good place to start is at the beginning of the logs stored by atest: + +``` +$ atest MyTestsRavenwood +... +Test Logs have saved in /tmp/atest_result/20231128_094010_0e90t8v8/log +Run 'atest --history' to review test result history. +``` + +The most useful logs are in the `isolated-java-logs` text file, which can typically be tab-completed by copy-pasting the logs path mentioned in the atest output: + +``` +$ less /tmp/atest_result/20231128_133105_h9al__79/log/i*/i*/isolated-java-logs* +``` + +Here are some common known issues and recommended workarounds: + +* Some code may unconditionally interact with unsupported APIs, such as via static initializers. One strategy is to shift the logic into `@Before` methods and make it conditional by testing `RavenwoodRule.isUnderRavenwood()`. +* Some code may reference API symbols not yet present in the Ravenwood runtime, such as ART or ICU internals, or APIs from Mainline modules. One strategy is to refactor to avoid these internal dependencies, but Ravenwood aims to better support them soon. + * This may also manifest as very odd behavior, such as test not being executed at all, tracked by bug #312517322 + * This may also manifest as an obscure Mockito error claiming “Mockito can only mock non-private & non-final classes” diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java index 74538ac02289..6cac6a47c77b 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java @@ -668,7 +668,7 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo final Context uiContext = displayContext.createWindowContext( TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY, null /* options */); magnificationGestureHandler = new WindowMagnificationGestureHandler(uiContext, - mAms.getWindowMagnificationMgr(), mAms.getTraceManager(), + mAms.getMagnificationConnectionManager(), mAms.getTraceManager(), mAms.getMagnificationController(), detectControlGestures, detectTwoFingerTripleTap, diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java index 4b10111d29e1..2eecb4d3a86c 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -158,10 +158,10 @@ import com.android.internal.util.Preconditions; import com.android.server.AccessibilityManagerInternal; import com.android.server.LocalServices; import com.android.server.SystemService; +import com.android.server.accessibility.magnification.MagnificationConnectionManager; import com.android.server.accessibility.magnification.MagnificationController; import com.android.server.accessibility.magnification.MagnificationProcessor; import com.android.server.accessibility.magnification.MagnificationScaleProvider; -import com.android.server.accessibility.magnification.WindowMagnificationManager; import com.android.server.inputmethod.InputMethodManagerInternal; import com.android.server.pm.UserManagerInternal; import com.android.server.policy.WindowManagerPolicy; @@ -3442,7 +3442,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub && (userState.getMagnificationCapabilitiesLocked() != Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN) || userHasMagnificationServicesLocked(userState); - getWindowMagnificationMgr().requestConnection(connect); + getMagnificationConnectionManager().requestConnection(connect); } /** @@ -4122,17 +4122,17 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub mSecurityPolicy.enforceCallingOrSelfPermission( android.Manifest.permission.STATUS_BAR_SERVICE); - getWindowMagnificationMgr().setConnection(connection); + getMagnificationConnectionManager().setConnection(connection); } /** - * Getter of {@link WindowMagnificationManager}. + * Getter of {@link MagnificationConnectionManager}. * - * @return WindowMagnificationManager + * @return MagnificationManager */ - public WindowMagnificationManager getWindowMagnificationMgr() { + public MagnificationConnectionManager getMagnificationConnectionManager() { synchronized (mLock) { - return mMagnificationController.getWindowMagnificationMgr(); + return mMagnificationController.getMagnificationConnectionManager(); } } @@ -4423,7 +4423,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub pw.println(); } pw.append("hasWindowMagnificationConnection=").append( - String.valueOf(getWindowMagnificationMgr().isConnected())); + String.valueOf(getMagnificationConnectionManager().isConnected())); pw.println(); mMagnificationProcessor.dump(pw, getValidDisplayList()); final int userCount = mUserStates.size(); @@ -5144,7 +5144,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub for (int i = 0; i < displays.size(); i++) { final int displayId = displays.get(i).getDisplayId(); - getWindowMagnificationMgr().removeMagnificationButton(displayId); + getMagnificationConnectionManager().removeMagnificationButton(displayId); } } } diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationConnectionManager.java index 3ea805bbb4a6..5a3c070819bd 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationConnectionManager.java @@ -60,19 +60,19 @@ import java.lang.annotation.RetentionPolicy; import java.util.concurrent.atomic.AtomicLongFieldUpdater; /** - * A class to manipulate window magnification through {@link MagnificationConnectionWrapper} + * A class to manipulate magnification through {@link MagnificationConnectionWrapper} * create by {@link #setConnection(IWindowMagnificationConnection)}. To set the connection with * SysUI, call {@code StatusBarManagerInternal#requestWindowMagnificationConnection(boolean)}. * The applied magnification scale is constrained by * {@link MagnificationScaleProvider#constrainScale(float)} */ -public class WindowMagnificationManager implements +public class MagnificationConnectionManager implements PanningScalingHandler.MagnificationDelegate, WindowManagerInternal.AccessibilityControllerInternal.UiChangesForAccessibilityCallbacks { private static final boolean DBG = false; - private static final String TAG = "WindowMagnificationMgr"; + private static final String TAG = "MagnificationConnectionManager"; /** * Indicate that the magnification window is at the magnification center. @@ -208,7 +208,7 @@ public class WindowMagnificationManager implements private final AccessibilityTraceManager mTrace; private final MagnificationScaleProvider mScaleProvider; - public WindowMagnificationManager(Context context, Object lock, @NonNull Callback callback, + public MagnificationConnectionManager(Context context, Object lock, @NonNull Callback callback, AccessibilityTraceManager trace, MagnificationScaleProvider scaleProvider) { mContext = context; mLock = lock; @@ -1040,7 +1040,7 @@ public class WindowMagnificationManager implements private float mScale = MagnificationScaleProvider.MIN_SCALE; private boolean mEnabled; - private final WindowMagnificationManager mWindowMagnificationManager; + private final MagnificationConnectionManager mMagnificationConnectionManager; // Records the bounds of window magnification. private final Rect mBounds = new Rect(); // The magnified bounds on the screen. @@ -1058,11 +1058,15 @@ public class WindowMagnificationManager implements "mTrackingTypingFocusSumTime"); private volatile long mTrackingTypingFocusSumTime = 0; - WindowMagnifier(int displayId, WindowMagnificationManager windowMagnificationManager) { + WindowMagnifier(int displayId, + MagnificationConnectionManager magnificationConnectionManager) { mDisplayId = displayId; - mWindowMagnificationManager = windowMagnificationManager; + mMagnificationConnectionManager = magnificationConnectionManager; } + // TODO(b/312324808): Investigating whether + // mMagnificationConnectionManager#enableWindowMagnificationInternal requires a sync lock + @SuppressWarnings("GuardedBy") boolean enableWindowMagnificationInternal(float scale, float centerX, float centerY, @Nullable MagnificationAnimationCallback animationCallback, @WindowPosition int windowPosition, int id) { @@ -1072,8 +1076,8 @@ public class WindowMagnificationManager implements } final float normScale = MagnificationScaleProvider.constrainScale(scale); setMagnificationFrameOffsetRatioByWindowPosition(windowPosition); - if (mWindowMagnificationManager.enableWindowMagnificationInternal(mDisplayId, normScale, - centerX, centerY, mMagnificationFrameOffsetRatio.x, + if (mMagnificationConnectionManager.enableWindowMagnificationInternal(mDisplayId, + normScale, centerX, centerY, mMagnificationFrameOffsetRatio.x, mMagnificationFrameOffsetRatio.y, animationCallback)) { mScale = normScale; mEnabled = true; @@ -1096,12 +1100,15 @@ public class WindowMagnificationManager implements } } + // TODO(b/312324808): Investigating whether + // mMagnificationConnectionManager#disableWindowMagnificationInternal requires a sync lock + @SuppressWarnings("GuardedBy") boolean disableWindowMagnificationInternal( @Nullable MagnificationAnimationCallback animationResultCallback) { if (!mEnabled) { return false; } - if (mWindowMagnificationManager.disableWindowMagnificationInternal( + if (mMagnificationConnectionManager.disableWindowMagnificationInternal( mDisplayId, animationResultCallback)) { mEnabled = false; mIdOfLastServiceToControl = INVALID_SERVICE_ID; @@ -1112,6 +1119,10 @@ public class WindowMagnificationManager implements return false; } + // ErrorProne says the access of mMagnificationConnectionManager#setScaleInternal should + // be guarded by 'this.mMagnificationConnectionManager.mLock' which is the same one as + // 'mLock'. Therefore, we'll put @SuppressWarnings here. + @SuppressWarnings("GuardedBy") @GuardedBy("mLock") void setScale(float scale) { if (!mEnabled) { @@ -1119,7 +1130,8 @@ public class WindowMagnificationManager implements } final float normScale = MagnificationScaleProvider.constrainScale(scale); if (Float.compare(mScale, normScale) != 0 - && mWindowMagnificationManager.setScaleInternal(mDisplayId, scale)) { + && mMagnificationConnectionManager + .setScaleForWindowMagnificationInternal(mDisplayId, scale)) { mScale = normScale; } } @@ -1159,8 +1171,8 @@ public class WindowMagnificationManager implements } void setTrackingTypingFocusEnabled(boolean trackingTypingFocusEnabled) { - if (mWindowMagnificationManager.isWindowMagnifierEnabled(mDisplayId) - && mWindowMagnificationManager.isImeVisible(mDisplayId) + if (mMagnificationConnectionManager.isWindowMagnifierEnabled(mDisplayId) + && mMagnificationConnectionManager.isImeVisible(mDisplayId) && trackingTypingFocusEnabled) { startTrackingTypingFocusRecord(); } @@ -1206,7 +1218,7 @@ public class WindowMagnificationManager implements Slog.d(TAG, "stop and log: session duration = " + duration + ", elapsed = " + elapsed); } - mWindowMagnificationManager.logTrackingTypingFocus(duration); + mMagnificationConnectionManager.logTrackingTypingFocus(duration); mTrackingTypingFocusStartTime = 0; mTrackingTypingFocusSumTime = 0; } @@ -1216,9 +1228,14 @@ public class WindowMagnificationManager implements return mEnabled; } + // ErrorProne says the access of mMagnificationConnectionManager#moveWindowMagnifierInternal + // should be guarded by 'this.mMagnificationConnectionManager.mLock' which is the same one + // as 'mLock'. Therefore, we'll put @SuppressWarnings here. + @SuppressWarnings("GuardedBy") @GuardedBy("mLock") void move(float offsetX, float offsetY) { - mWindowMagnificationManager.moveWindowMagnifierInternal(mDisplayId, offsetX, offsetY); + mMagnificationConnectionManager.moveWindowMagnifierInternal( + mDisplayId, offsetX, offsetY); } @GuardedBy("mLock") @@ -1270,8 +1287,10 @@ public class WindowMagnificationManager implements animationCallback); } - private boolean setScaleInternal(int displayId, float scale) { - return mConnectionWrapper != null && mConnectionWrapper.setScale(displayId, scale); + @GuardedBy("mLock") + private boolean setScaleForWindowMagnificationInternal(int displayId, float scale) { + return mConnectionWrapper != null + && mConnectionWrapper.setScaleForWindowMagnification(displayId, scale); } @GuardedBy("mLock") diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationConnectionWrapper.java b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationConnectionWrapper.java index f0c44d64f5ec..20538f167656 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationConnectionWrapper.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationConnectionWrapper.java @@ -82,16 +82,16 @@ class MagnificationConnectionWrapper { return true; } - boolean setScale(int displayId, float scale) { + boolean setScaleForWindowMagnification(int displayId, float scale) { if (mTrace.isA11yTracingEnabledForTypes(FLAGS_WINDOW_MAGNIFICATION_CONNECTION)) { mTrace.logTrace(TAG + ".setScale", FLAGS_WINDOW_MAGNIFICATION_CONNECTION, "displayId=" + displayId + ";scale=" + scale); } try { - mConnection.setScale(displayId, scale); + mConnection.setScaleForWindowMagnification(displayId, scale); } catch (RemoteException e) { if (DBG) { - Slog.e(TAG, "Error calling setScale()", e); + Slog.e(TAG, "Error calling setScaleForWindowMagnification()", e); } return false; } diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java index effd8732d086..52e123a5e70c 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java @@ -77,7 +77,7 @@ import java.util.concurrent.Executor; * <b>Note</b> Updates magnification switch UI when magnification mode transition * is done and before invoking {@link TransitionCallBack#onResult}. */ -public class MagnificationController implements WindowMagnificationManager.Callback, +public class MagnificationController implements MagnificationConnectionManager.Callback, MagnificationGestureHandler.Callback, FullScreenMagnificationController.MagnificationInfoChangedCallback, WindowManagerInternal.AccessibilityControllerInternal.UiChangesForAccessibilityCallbacks { @@ -96,7 +96,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb private final AlwaysOnMagnificationFeatureFlag mAlwaysOnMagnificationFeatureFlag; private final MagnificationScaleProvider mScaleProvider; private FullScreenMagnificationController mFullScreenMagnificationController; - private WindowMagnificationManager mWindowMagnificationMgr; + private MagnificationConnectionManager mMagnificationConnectionManager; private int mMagnificationCapabilities = ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN; /** Whether the platform supports window magnification feature. */ private final boolean mSupportWindowMagnification; @@ -164,11 +164,11 @@ public class MagnificationController implements WindowMagnificationManager.Callb @VisibleForTesting public MagnificationController(AccessibilityManagerService ams, Object lock, Context context, FullScreenMagnificationController fullScreenMagnificationController, - WindowMagnificationManager windowMagnificationManager, + MagnificationConnectionManager magnificationConnectionManager, MagnificationScaleProvider scaleProvider, Executor backgroundExecutor) { this(ams, lock, context, scaleProvider, backgroundExecutor); mFullScreenMagnificationController = fullScreenMagnificationController; - mWindowMagnificationMgr = windowMagnificationManager; + mMagnificationConnectionManager = magnificationConnectionManager; } @Override @@ -179,10 +179,10 @@ public class MagnificationController implements WindowMagnificationManager.Callb if (updatePersistence) { getFullScreenMagnificationController().persistScale(displayId); } - } else if (getWindowMagnificationMgr().isWindowMagnifierEnabled(displayId)) { - getWindowMagnificationMgr().setScale(displayId, scale); + } else if (getMagnificationConnectionManager().isWindowMagnifierEnabled(displayId)) { + getMagnificationConnectionManager().setScale(displayId, scale); if (updatePersistence) { - getWindowMagnificationMgr().persistScale(displayId); + getMagnificationConnectionManager().persistScale(displayId); } } } @@ -222,15 +222,15 @@ public class MagnificationController implements WindowMagnificationManager.Callb } if (showModeSwitchButton) { - getWindowMagnificationMgr().showMagnificationButton(displayId, mode); + getMagnificationConnectionManager().showMagnificationButton(displayId, mode); } else { - getWindowMagnificationMgr().removeMagnificationButton(displayId); + getMagnificationConnectionManager().removeMagnificationButton(displayId); } if (!enableSettingsPanel) { // Whether the settings panel needs to be shown is controlled in system UI. // Here, we only guarantee that the settings panel is closed when it is not needed. - getWindowMagnificationMgr().removeMagnificationSettingsPanel(displayId); + getMagnificationConnectionManager().removeMagnificationSettingsPanel(displayId); } } @@ -284,7 +284,8 @@ public class MagnificationController implements WindowMagnificationManager.Callb final FullScreenMagnificationController screenMagnificationController = getFullScreenMagnificationController(); - final WindowMagnificationManager windowMagnificationMgr = getWindowMagnificationMgr(); + final MagnificationConnectionManager magnificationConnectionManager = + getMagnificationConnectionManager(); final float scale = getTargetModeScaleFromCurrentMagnification(displayId, targetMode); final DisableMagnificationCallback animationEndCallback = new DisableMagnificationCallback(transitionCallBack, displayId, targetMode, @@ -295,7 +296,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb if (targetMode == ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW) { screenMagnificationController.reset(displayId, animationEndCallback); } else { - windowMagnificationMgr.disableWindowMagnification(displayId, false, + magnificationConnectionManager.disableWindowMagnification(displayId, false, animationEndCallback); } } @@ -340,7 +341,8 @@ public class MagnificationController implements WindowMagnificationManager.Callb } final FullScreenMagnificationController screenMagnificationController = getFullScreenMagnificationController(); - final WindowMagnificationManager windowMagnificationMgr = getWindowMagnificationMgr(); + final MagnificationConnectionManager magnificationConnectionManager = + getMagnificationConnectionManager(); final float targetScale = Float.isNaN(config.getScale()) ? getTargetModeScaleFromCurrentMagnification(displayId, targetMode) : config.getScale(); @@ -353,14 +355,15 @@ public class MagnificationController implements WindowMagnificationManager.Callb if (targetMode == MAGNIFICATION_MODE_WINDOW) { screenMagnificationController.reset(displayId, false); if (targetActivated) { - windowMagnificationMgr.enableWindowMagnification(displayId, + magnificationConnectionManager.enableWindowMagnification(displayId, targetScale, magnificationCenter.x, magnificationCenter.y, magnificationAnimationCallback, id); } else { - windowMagnificationMgr.disableWindowMagnification(displayId, false); + magnificationConnectionManager.disableWindowMagnification(displayId, false); } } else if (targetMode == MAGNIFICATION_MODE_FULLSCREEN) { - windowMagnificationMgr.disableWindowMagnification(displayId, false, null); + magnificationConnectionManager.disableWindowMagnification( + displayId, false, null); if (targetActivated) { if (!screenMagnificationController.isRegistered(displayId)) { screenMagnificationController.register(displayId); @@ -409,7 +412,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb if (targetMode == ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW) { return getFullScreenMagnificationController().getScale(displayId); } else { - return getWindowMagnificationMgr().getScale(displayId); + return getMagnificationConnectionManager().getScale(displayId); } } @@ -441,7 +444,8 @@ public class MagnificationController implements WindowMagnificationManager.Callb mAccessibilityCallbacksDelegateArray.put(displayId, getFullScreenMagnificationController()); } else if (mode == ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW) { - mAccessibilityCallbacksDelegateArray.put(displayId, getWindowMagnificationMgr()); + mAccessibilityCallbacksDelegateArray.put( + displayId, getMagnificationConnectionManager()); } else { mAccessibilityCallbacksDelegateArray.delete(displayId); } @@ -462,13 +466,13 @@ public class MagnificationController implements WindowMagnificationManager.Callb @Override public void onRequestMagnificationSpec(int displayId, int serviceId) { - final WindowMagnificationManager windowMagnificationManager; + final MagnificationConnectionManager magnificationConnectionManager; synchronized (mLock) { updateMagnificationUIControls(displayId, ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); - windowMagnificationManager = mWindowMagnificationMgr; + magnificationConnectionManager = mMagnificationConnectionManager; } - if (windowMagnificationManager != null) { - mWindowMagnificationMgr.disableWindowMagnification(displayId, false); + if (magnificationConnectionManager != null) { + mMagnificationConnectionManager.disableWindowMagnification(displayId, false); } } @@ -491,7 +495,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb setCurrentMagnificationModeAndSwitchDelegate(displayId, ACCESSIBILITY_MAGNIFICATION_MODE_NONE); duration = SystemClock.uptimeMillis() - mWindowModeEnabledTimeArray.get(displayId); - scale = mWindowMagnificationMgr.getLastActivatedScale(displayId); + scale = mMagnificationConnectionManager.getLastActivatedScale(displayId); } logMagnificationUsageState(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW, duration, scale); } @@ -507,13 +511,14 @@ public class MagnificationController implements WindowMagnificationManager.Callb public void onSourceBoundsChanged(int displayId, Rect bounds) { if (shouldNotifyMagnificationChange(displayId, MAGNIFICATION_MODE_WINDOW)) { // notify sysui the magnification scale changed on window magnifier - mWindowMagnificationMgr.onUserMagnificationScaleChanged( - mUserId, displayId, getWindowMagnificationMgr().getScale(displayId)); + mMagnificationConnectionManager.onUserMagnificationScaleChanged( + mUserId, displayId, getMagnificationConnectionManager().getScale(displayId)); final MagnificationConfig config = new MagnificationConfig.Builder() .setMode(MAGNIFICATION_MODE_WINDOW) - .setActivated(getWindowMagnificationMgr().isWindowMagnifierEnabled(displayId)) - .setScale(getWindowMagnificationMgr().getScale(displayId)) + .setActivated( + getMagnificationConnectionManager().isWindowMagnifierEnabled(displayId)) + .setScale(getMagnificationConnectionManager().getScale(displayId)) .setCenterX(bounds.exactCenterX()) .setCenterY(bounds.exactCenterY()).build(); mAms.notifyMagnificationChanged(displayId, new Region(bounds), config); @@ -525,7 +530,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb @NonNull MagnificationConfig config) { if (shouldNotifyMagnificationChange(displayId, MAGNIFICATION_MODE_FULLSCREEN)) { // notify sysui the magnification scale changed on fullscreen magnifier - mWindowMagnificationMgr.onUserMagnificationScaleChanged( + mMagnificationConnectionManager.onUserMagnificationScaleChanged( mUserId, displayId, config.getScale()); mAms.notifyMagnificationChanged(displayId, region, config); @@ -548,8 +553,8 @@ public class MagnificationController implements WindowMagnificationManager.Callb synchronized (mLock) { final boolean fullScreenActivated = mFullScreenMagnificationController != null && mFullScreenMagnificationController.isActivated(displayId); - final boolean windowEnabled = mWindowMagnificationMgr != null - && mWindowMagnificationMgr.isWindowMagnifierEnabled(displayId); + final boolean windowEnabled = mMagnificationConnectionManager != null + && mMagnificationConnectionManager.isWindowMagnifierEnabled(displayId); final Integer transitionMode = mTransitionModes.get(displayId); if (((changeMode == MAGNIFICATION_MODE_FULLSCREEN && fullScreenActivated) || (changeMode == MAGNIFICATION_MODE_WINDOW && windowEnabled)) @@ -608,10 +613,10 @@ public class MagnificationController implements WindowMagnificationManager.Callb } private void disableWindowMagnificationIfNeeded(int displayId) { - final WindowMagnificationManager windowMagnificationManager = - getWindowMagnificationMgr(); + final MagnificationConnectionManager magnificationConnectionManager = + getMagnificationConnectionManager(); if (isActivated(displayId, ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW)) { - windowMagnificationManager.disableWindowMagnification(displayId, false); + magnificationConnectionManager.disableWindowMagnification(displayId, false); } } @@ -620,7 +625,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb synchronized (mLock) { mIsImeVisibleArray.put(displayId, shown); } - getWindowMagnificationMgr().onImeWindowVisibilityChanged(displayId, shown); + getMagnificationConnectionManager().onImeWindowVisibilityChanged(displayId, shown); logMagnificationModeWithImeOnIfNeeded(displayId); } @@ -661,7 +666,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb /** * Updates the active user ID of {@link FullScreenMagnificationController} and {@link - * WindowMagnificationManager}. + * MagnificationConnectionManager}. * * @param userId the currently active user ID */ @@ -671,10 +676,10 @@ public class MagnificationController implements WindowMagnificationManager.Callb } mUserId = userId; final FullScreenMagnificationController fullMagnificationController; - final WindowMagnificationManager windowMagnificationManager; + final MagnificationConnectionManager magnificationConnectionManager; synchronized (mLock) { fullMagnificationController = mFullScreenMagnificationController; - windowMagnificationManager = mWindowMagnificationMgr; + magnificationConnectionManager = mMagnificationConnectionManager; mAccessibilityCallbacksDelegateArray.clear(); mCurrentMagnificationModeArray.clear(); mLastMagnificationActivatedModeArray.clear(); @@ -685,8 +690,8 @@ public class MagnificationController implements WindowMagnificationManager.Callb if (fullMagnificationController != null) { fullMagnificationController.resetAllIfNeeded(false); } - if (windowMagnificationManager != null) { - windowMagnificationManager.disableAllWindowMagnifiers(); + if (magnificationConnectionManager != null) { + magnificationConnectionManager.disableAllWindowMagnifiers(); } } @@ -700,8 +705,8 @@ public class MagnificationController implements WindowMagnificationManager.Callb if (mFullScreenMagnificationController != null) { mFullScreenMagnificationController.onDisplayRemoved(displayId); } - if (mWindowMagnificationMgr != null) { - mWindowMagnificationMgr.onDisplayRemoved(displayId); + if (mMagnificationConnectionManager != null) { + mMagnificationConnectionManager.onDisplayRemoved(displayId); } mAccessibilityCallbacksDelegateArray.delete(displayId); mCurrentMagnificationModeArray.delete(displayId); @@ -728,7 +733,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb * @param enabled Enable the following typing focus feature */ public void setMagnificationFollowTypingEnabled(boolean enabled) { - getWindowMagnificationMgr().setMagnificationFollowTypingEnabled(enabled); + getMagnificationConnectionManager().setMagnificationFollowTypingEnabled(enabled); getFullScreenMagnificationController().setMagnificationFollowTypingEnabled(enabled); } @@ -805,29 +810,29 @@ public class MagnificationController implements WindowMagnificationManager.Callb } /** - * Getter of {@link WindowMagnificationManager}. + * Getter of {@link MagnificationConnectionManager}. * - * @return {@link WindowMagnificationManager}. + * @return {@link MagnificationConnectionManager}. */ - public WindowMagnificationManager getWindowMagnificationMgr() { + public MagnificationConnectionManager getMagnificationConnectionManager() { synchronized (mLock) { - if (mWindowMagnificationMgr == null) { - mWindowMagnificationMgr = new WindowMagnificationManager(mContext, + if (mMagnificationConnectionManager == null) { + mMagnificationConnectionManager = new MagnificationConnectionManager(mContext, mLock, this, mAms.getTraceManager(), mScaleProvider); } - return mWindowMagnificationMgr; + return mMagnificationConnectionManager; } } private @Nullable PointF getCurrentMagnificationCenterLocked(int displayId, int targetMode) { if (targetMode == ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN) { - if (mWindowMagnificationMgr == null - || !mWindowMagnificationMgr.isWindowMagnifierEnabled(displayId)) { + if (mMagnificationConnectionManager == null + || !mMagnificationConnectionManager.isWindowMagnifierEnabled(displayId)) { return null; } - mTempPoint.set(mWindowMagnificationMgr.getCenterX(displayId), - mWindowMagnificationMgr.getCenterY(displayId)); + mTempPoint.set(mMagnificationConnectionManager.getCenterX(displayId), + mMagnificationConnectionManager.getCenterY(displayId)); } else { if (mFullScreenMagnificationController == null || !mFullScreenMagnificationController.isActivated(displayId)) { @@ -858,10 +863,10 @@ public class MagnificationController implements WindowMagnificationManager.Callb } } else if (mode == ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW) { synchronized (mLock) { - if (mWindowMagnificationMgr == null) { + if (mMagnificationConnectionManager == null) { return false; } - isActivated = mWindowMagnificationMgr.isWindowMagnifierEnabled(displayId); + isActivated = mMagnificationConnectionManager.isWindowMagnifierEnabled(displayId); } } return isActivated; @@ -980,7 +985,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb mCurrentCenter.x, mCurrentCenter.y, mAnimate, MAGNIFICATION_GESTURE_HANDLER_ID); } else { - getWindowMagnificationMgr().enableWindowMagnification(mDisplayId, + getMagnificationConnectionManager().enableWindowMagnification(mDisplayId, mCurrentScale, mCurrentCenter.x, mCurrentCenter.y, mAnimate ? STUB_ANIMATION_CALLBACK : null, MAGNIFICATION_GESTURE_HANDLER_ID); diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationProcessor.java b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationProcessor.java index 5cf2a638fa3e..ed8f1ab3a1b2 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationProcessor.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationProcessor.java @@ -84,13 +84,13 @@ public class MagnificationProcessor { .setCenterX(fullScreenMagnificationController.getCenterX(displayId)) .setCenterY(fullScreenMagnificationController.getCenterY(displayId)); } else if (mode == MAGNIFICATION_MODE_WINDOW) { - final WindowMagnificationManager windowMagnificationManager = - mController.getWindowMagnificationMgr(); + final MagnificationConnectionManager magnificationConnectionManager = + mController.getMagnificationConnectionManager(); builder.setMode(mode) .setActivated(mController.isActivated(displayId, MAGNIFICATION_MODE_WINDOW)) - .setScale(windowMagnificationManager.getScale(displayId)) - .setCenterX(windowMagnificationManager.getCenterX(displayId)) - .setCenterY(windowMagnificationManager.getCenterY(displayId)); + .setScale(magnificationConnectionManager.getScale(displayId)) + .setCenterX(magnificationConnectionManager.getCenterX(displayId)) + .setCenterY(magnificationConnectionManager.getCenterY(displayId)); } else { // For undefined mode, set enabled to false builder.setActivated(false); @@ -135,12 +135,12 @@ public class MagnificationProcessor { } } else if (configMode == MAGNIFICATION_MODE_WINDOW) { if (configActivated) { - return mController.getWindowMagnificationMgr().enableWindowMagnification(displayId, - config.getScale(), config.getCenterX(), config.getCenterY(), + return mController.getMagnificationConnectionManager().enableWindowMagnification( + displayId, config.getScale(), config.getCenterX(), config.getCenterY(), animate ? STUB_ANIMATION_CALLBACK : null, id); } else { - return mController.getWindowMagnificationMgr() + return mController.getMagnificationConnectionManager() .disableWindowMagnification(displayId, false); } } @@ -256,7 +256,7 @@ public class MagnificationProcessor { if (currentMode == MAGNIFICATION_MODE_FULLSCREEN) { getFullscreenMagnificationRegion(displayId, outRegion, canControlMagnification); } else if (currentMode == MAGNIFICATION_MODE_WINDOW) { - mController.getWindowMagnificationMgr().getMagnificationSourceBounds(displayId, + mController.getMagnificationConnectionManager().getMagnificationSourceBounds(displayId, outRegion); } } @@ -297,8 +297,8 @@ public class MagnificationProcessor { if (mode == MAGNIFICATION_MODE_FULLSCREEN) { return mController.getFullScreenMagnificationController().reset(displayId, animate); } else if (mode == MAGNIFICATION_MODE_WINDOW) { - return mController.getWindowMagnificationMgr().disableWindowMagnification(displayId, - false, animate ? STUB_ANIMATION_CALLBACK : null); + return mController.getMagnificationConnectionManager().disableWindowMagnification( + displayId, false, animate ? STUB_ANIMATION_CALLBACK : null); } return false; } @@ -325,19 +325,20 @@ public class MagnificationProcessor { */ public void resetAllIfNeeded(int connectionId) { mController.getFullScreenMagnificationController().resetAllIfNeeded(connectionId); - mController.getWindowMagnificationMgr().resetAllIfNeeded(connectionId); + mController.getMagnificationConnectionManager().resetAllIfNeeded(connectionId); } /** * {@link FullScreenMagnificationController#isActivated(int)} - * {@link WindowMagnificationManager#isWindowMagnifierEnabled(int)} + * {@link MagnificationConnectionManager#isWindowMagnifierEnabled(int)} */ public boolean isMagnifying(int displayId) { int mode = getControllingMode(displayId); if (mode == MAGNIFICATION_MODE_FULLSCREEN) { return mController.getFullScreenMagnificationController().isActivated(displayId); } else if (mode == MAGNIFICATION_MODE_WINDOW) { - return mController.getWindowMagnificationMgr().isWindowMagnifierEnabled(displayId); + return mController.getMagnificationConnectionManager().isWindowMagnifierEnabled( + displayId); } return false; } @@ -416,22 +417,23 @@ public class MagnificationProcessor { pw.append(" SupportWindowMagnification=" + mController.supportWindowMagnification()).println(); pw.append(" WindowMagnificationConnectionState=" - + mController.getWindowMagnificationMgr().getConnectionState()).println(); + + mController.getMagnificationConnectionManager().getConnectionState()).println(); } private int getIdOfLastServiceToMagnify(int mode, int displayId) { return (mode == MAGNIFICATION_MODE_FULLSCREEN) ? mController.getFullScreenMagnificationController() .getIdOfLastServiceToMagnify(displayId) - : mController.getWindowMagnificationMgr().getIdOfLastServiceToMagnify( + : mController.getMagnificationConnectionManager().getIdOfLastServiceToMagnify( displayId); } private void dumpTrackingTypingFocusEnabledState(final PrintWriter pw, int displayId, int mode) { if (mode == MAGNIFICATION_MODE_WINDOW) { - pw.append(" TrackingTypingFocusEnabled=" + mController - .getWindowMagnificationMgr().isTrackingTypingFocusEnabled(displayId)) + pw.append(" TrackingTypingFocusEnabled=" + + mController.getMagnificationConnectionManager() + .isTrackingTypingFocusEnabled(displayId)) .println(); } } diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/PanningScalingHandler.java b/services/accessibility/java/com/android/server/accessibility/magnification/PanningScalingHandler.java index 94556282d0d3..6b48d2bacf9d 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/PanningScalingHandler.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/PanningScalingHandler.java @@ -45,6 +45,7 @@ class PanningScalingHandler extends private static final String TAG = "PanningScalingHandler"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); + // TODO(b/312372035): Revisit the scope of usage of the interface interface MagnificationDelegate { boolean processScroll(int displayId, float distanceX, float distanceY); void setScale(int displayId, float scale); diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java index 36e751181cfd..73c267a6e262 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java @@ -79,7 +79,7 @@ public class WindowMagnificationGestureHandler extends MagnificationGestureHandl private static final float MIN_SCALE = 1.0f; private static final float MAX_SCALE = MagnificationScaleProvider.MAX_SCALE; - private final WindowMagnificationManager mWindowMagnificationMgr; + private final MagnificationConnectionManager mMagnificationConnectionManager; @VisibleForTesting final DelegatingState mDelegatingState; @VisibleForTesting @@ -101,7 +101,7 @@ public class WindowMagnificationGestureHandler extends MagnificationGestureHandl private long mTripleTapAndHoldStartedTime = 0; public WindowMagnificationGestureHandler(@UiContext Context context, - WindowMagnificationManager windowMagnificationMgr, + MagnificationConnectionManager magnificationConnectionManager, AccessibilityTraceManager trace, Callback callback, boolean detectSingleFingerTripleTap, @@ -115,7 +115,7 @@ public class WindowMagnificationGestureHandler extends MagnificationGestureHandl "WindowMagnificationGestureHandler() , displayId = " + displayId + ")"); } mContext = context; - mWindowMagnificationMgr = windowMagnificationMgr; + mMagnificationConnectionManager = magnificationConnectionManager; mMotionEventDispatcherDelegate = new MotionEventDispatcherDelegate(context, (event, rawEvent, policyFlags) -> dispatchTransformedEvent(event, rawEvent, policyFlags)); @@ -128,18 +128,18 @@ public class WindowMagnificationGestureHandler extends MagnificationGestureHandl @Override public boolean processScroll(int displayId, float distanceX, float distanceY) { - return mWindowMagnificationMgr.processScroll(displayId, distanceX, - distanceY); + return mMagnificationConnectionManager.processScroll( + displayId, distanceX, distanceY); } @Override public void setScale(int displayId, float scale) { - mWindowMagnificationMgr.setScale(displayId, scale); + mMagnificationConnectionManager.setScale(displayId, scale); } @Override public float getScale(int displayId) { - return mWindowMagnificationMgr.getScale(displayId); + return mMagnificationConnectionManager.getScale(displayId); } })); @@ -167,7 +167,7 @@ public class WindowMagnificationGestureHandler extends MagnificationGestureHandl Slog.i(mLogTag, "onDestroy(); delayed = " + mDetectingState.toString()); } - mWindowMagnificationMgr.disableWindowMagnification(mDisplayId, true); + mMagnificationConnectionManager.disableWindowMagnification(mDisplayId, true); resetToDetectState(); } @@ -176,7 +176,7 @@ public class WindowMagnificationGestureHandler extends MagnificationGestureHandl final Point screenSize = mTempPoint; getScreenSize(mTempPoint); toggleMagnification(screenSize.x / 2.0f, screenSize.y / 2.0f, - WindowMagnificationManager.WINDOW_POSITION_AT_CENTER); + MagnificationConnectionManager.WINDOW_POSITION_AT_CENTER); } private void getScreenSize(Point outSize) { @@ -190,28 +190,29 @@ public class WindowMagnificationGestureHandler extends MagnificationGestureHandl } private void enableWindowMagnifier(float centerX, float centerY, - @WindowMagnificationManager.WindowPosition int windowPosition) { + @MagnificationConnectionManager.WindowPosition int windowPosition) { if (DEBUG_ALL) { Slog.i(mLogTag, "enableWindowMagnifier :" + centerX + ", " + centerY + ", " + windowPosition); } final float scale = MathUtils.constrain( - mWindowMagnificationMgr.getPersistedScale(mDisplayId), MIN_SCALE, MAX_SCALE); - mWindowMagnificationMgr.enableWindowMagnification(mDisplayId, scale, centerX, centerY, - windowPosition); + mMagnificationConnectionManager.getPersistedScale(mDisplayId), + MIN_SCALE, MAX_SCALE); + mMagnificationConnectionManager.enableWindowMagnification( + mDisplayId, scale, centerX, centerY, windowPosition); } private void disableWindowMagnifier() { if (DEBUG_ALL) { Slog.i(mLogTag, "disableWindowMagnifier()"); } - mWindowMagnificationMgr.disableWindowMagnification(mDisplayId, false); + mMagnificationConnectionManager.disableWindowMagnification(mDisplayId, false); } private void toggleMagnification(float centerX, float centerY, - @WindowMagnificationManager.WindowPosition int windowPosition) { - if (mWindowMagnificationMgr.isWindowMagnifierEnabled(mDisplayId)) { + @MagnificationConnectionManager.WindowPosition int windowPosition) { + if (mMagnificationConnectionManager.isWindowMagnifierEnabled(mDisplayId)) { disableWindowMagnifier(); } else { enableWindowMagnifier(centerX, centerY, windowPosition); @@ -223,7 +224,7 @@ public class WindowMagnificationGestureHandler extends MagnificationGestureHandl Slog.i(mLogTag, "onTripleTap()"); } toggleMagnification(up.getX(), up.getY(), - WindowMagnificationManager.WINDOW_POSITION_AT_CENTER); + MagnificationConnectionManager.WINDOW_POSITION_AT_CENTER); } @VisibleForTesting @@ -232,9 +233,9 @@ public class WindowMagnificationGestureHandler extends MagnificationGestureHandl Slog.i(mLogTag, "onTripleTapAndHold()"); } mViewportDraggingState.mEnabledBeforeDrag = - mWindowMagnificationMgr.isWindowMagnifierEnabled(mDisplayId); + mMagnificationConnectionManager.isWindowMagnifierEnabled(mDisplayId); enableWindowMagnifier(up.getX(), up.getY(), - WindowMagnificationManager.WINDOW_POSITION_AT_TOP_LEFT); + MagnificationConnectionManager.WINDOW_POSITION_AT_TOP_LEFT); mTripleTapAndHoldStartedTime = SystemClock.uptimeMillis(); transitionTo(mViewportDraggingState); } @@ -242,7 +243,7 @@ public class WindowMagnificationGestureHandler extends MagnificationGestureHandl @VisibleForTesting void releaseTripleTapAndHold() { if (!mViewportDraggingState.mEnabledBeforeDrag) { - mWindowMagnificationMgr.disableWindowMagnification(mDisplayId, true); + mMagnificationConnectionManager.disableWindowMagnification(mDisplayId, true); } transitionTo(mDetectingState); if (mTripleTapAndHoldStartedTime != 0) { @@ -331,7 +332,7 @@ public class WindowMagnificationGestureHandler extends MagnificationGestureHandl @Override public void onExit() { mPanningScalingHandler.setEnabled(false); - mWindowMagnificationMgr.persistScale(mDisplayId); + mMagnificationConnectionManager.persistScale(mDisplayId); clear(); } @@ -404,7 +405,7 @@ public class WindowMagnificationGestureHandler extends MagnificationGestureHandl if (!Float.isNaN(mLastX) && !Float.isNaN(mLastY)) { float offsetX = event.getX() - mLastX; float offsetY = event.getY() - mLastY; - mWindowMagnificationMgr.moveWindowMagnification(mDisplayId, offsetX, + mMagnificationConnectionManager.moveWindowMagnification(mDisplayId, offsetX, offsetY); } mLastX = event.getX(); @@ -522,7 +523,7 @@ public class WindowMagnificationGestureHandler extends MagnificationGestureHandl @Override public boolean shouldStopDetection(MotionEvent motionEvent) { - return !mWindowMagnificationMgr.isWindowMagnifierEnabled(mDisplayId) + return !mMagnificationConnectionManager.isWindowMagnifierEnabled(mDisplayId) && !mDetectSingleFingerTripleTap && !(mDetectTwoFingerTripleTap && Flags.enableMagnificationMultipleFingerMultipleTapGesture()); @@ -540,7 +541,8 @@ public class WindowMagnificationGestureHandler extends MagnificationGestureHandl "onGestureDetected : delayedEventQueue = " + delayedEventQueue); } if (gestureId == MagnificationGestureMatcher.GESTURE_TWO_FINGERS_DOWN_OR_SWIPE - && mWindowMagnificationMgr.pointersInWindow(mDisplayId, motionEvent) > 0) { + && mMagnificationConnectionManager + .pointersInWindow(mDisplayId, motionEvent) > 0) { transitionTo(mObservePanningScalingState); } else if (gestureId == MagnificationGestureMatcher.GESTURE_TRIPLE_TAP) { onTripleTap(motionEvent); @@ -584,7 +586,7 @@ public class WindowMagnificationGestureHandler extends MagnificationGestureHandl + ", mMagnifiedInteractionState=" + mObservePanningScalingState + ", mCurrentState=" + State.nameOf(mCurrentState) + ", mPreviousState=" + State.nameOf(mPreviousState) - + ", mWindowMagnificationMgr=" + mWindowMagnificationMgr + + ", mMagnificationConnectionManager=" + mMagnificationConnectionManager + ", mDisplayId=" + mDisplayId + '}'; } diff --git a/services/core/java/com/android/server/PinnerService.java b/services/core/java/com/android/server/PinnerService.java index 23a30f9dc2ee..c5c2b0b5dd59 100644 --- a/services/core/java/com/android/server/PinnerService.java +++ b/services/core/java/com/android/server/PinnerService.java @@ -1044,7 +1044,6 @@ public final class PinnerService extends SystemService { if (DEBUG) { Slog.d(TAG, "pin file: " + fileToPin + " use-pinlist: " + attemptPinIntrospection); } - Trace.beginSection("pinFile:" + fileToPin); ZipFile fileAsZip = null; InputStream pinRangeStream = null; try { @@ -1067,7 +1066,6 @@ public final class PinnerService extends SystemService { } finally { safeClose(pinRangeStream); safeClose(fileAsZip); // Also closes any streams we've opened - Trace.endSection(); } } diff --git a/services/core/java/com/android/server/SecurityStateManagerService.java b/services/core/java/com/android/server/SecurityStateManagerService.java new file mode 100644 index 000000000000..98039be20897 --- /dev/null +++ b/services/core/java/com/android/server/SecurityStateManagerService.java @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server; + +import static android.os.SecurityStateManager.KEY_KERNEL_VERSION; +import static android.os.SecurityStateManager.KEY_SYSTEM_SPL; +import static android.os.SecurityStateManager.KEY_VENDOR_SPL; + +import android.content.Context; +import android.content.pm.PackageManager; +import android.os.Build; +import android.os.Bundle; +import android.os.ISecurityStateManager; +import android.os.SystemProperties; +import android.os.VintfRuntimeInfo; +import android.text.TextUtils; +import android.util.Slog; +import android.webkit.WebViewProviderInfo; +import android.webkit.WebViewUpdateService; + +import com.android.internal.R; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class SecurityStateManagerService extends ISecurityStateManager.Stub { + + private static final String TAG = "SecurityStateManagerService"; + + static final String VENDOR_SECURITY_PATCH_PROPERTY_KEY = "ro.vendor.build" + + ".security_patch"; + static final Pattern KERNEL_RELEASE_PATTERN = Pattern.compile("(\\d+\\.\\d+\\.\\d+)(" + + ".*)"); + + private final Context mContext; + private final PackageManager mPackageManager; + + public SecurityStateManagerService(Context context) { + mContext = context; + mPackageManager = context.getPackageManager(); + } + + @Override + public Bundle getGlobalSecurityState() { + Bundle globalSecurityState = new Bundle(); + globalSecurityState.putString(KEY_SYSTEM_SPL, Build.VERSION.SECURITY_PATCH); + globalSecurityState.putString(KEY_VENDOR_SPL, + SystemProperties.get(VENDOR_SECURITY_PATCH_PROPERTY_KEY, "")); + String moduleMetadataProviderPackageName = + mContext.getString(R.string.config_defaultModuleMetadataProvider); + if (!moduleMetadataProviderPackageName.isEmpty()) { + globalSecurityState.putString(moduleMetadataProviderPackageName, + getSpl(moduleMetadataProviderPackageName)); + } + globalSecurityState.putString(KEY_KERNEL_VERSION, getKernelVersion()); + addWebViewPackages(globalSecurityState); + addSecurityStatePackages(globalSecurityState); + return globalSecurityState; + } + + private String getSpl(String packageName) { + if (!TextUtils.isEmpty(packageName)) { + try { + return mPackageManager.getPackageInfo(packageName, 0 /* flags */).versionName; + } catch (PackageManager.NameNotFoundException e) { + Slog.e(TAG, TextUtils.formatSimple("Failed to get SPL for package %s.", + packageName), e); + } + } + return ""; + } + + private String getKernelVersion() { + Matcher matcher = KERNEL_RELEASE_PATTERN.matcher(VintfRuntimeInfo.getKernelVersion()); + if (matcher.matches()) { + return matcher.group(1); + } + return ""; + } + + private void addWebViewPackages(Bundle bundle) { + for (WebViewProviderInfo info : WebViewUpdateService.getAllWebViewPackages()) { + String packageName = info.packageName; + bundle.putString(packageName, getSpl(packageName)); + } + } + + private void addSecurityStatePackages(Bundle bundle) { + String[] packageNames; + packageNames = mContext.getResources().getStringArray(R.array.config_securityStatePackages); + for (String packageName : packageNames) { + bundle.putString(packageName, getSpl(packageName)); + } + } +} diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java index 3135650640d4..382ee6e0c0a6 100644 --- a/services/core/java/com/android/server/Watchdog.java +++ b/services/core/java/com/android/server/Watchdog.java @@ -69,6 +69,7 @@ import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; +import java.time.Clock; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -102,13 +103,13 @@ public class Watchdog implements Dumpable { // will be half the full timeout). // // The pre-watchdog event is similar to a full watchdog except it does not crash system server. - private static final int PRE_WATCHDOG_TIMEOUT_RATIO = 2; + private static final int PRE_WATCHDOG_TIMEOUT_RATIO = 3; // These are temporally ordered: larger values as lateness increases - private static final int COMPLETED = 0; - private static final int WAITING = 1; - private static final int WAITED_UNTIL_PRE_WATCHDOG = 2; - private static final int OVERDUE = 3; + static final int COMPLETED = 0; + static final int WAITING = 1; + static final int WAITED_UNTIL_PRE_WATCHDOG = 2; + static final int OVERDUE = 3; // Track watchdog timeout history and break the crash loop if there is. private static final String TIMEOUT_HISTORY_FILE = "/data/system/watchdog-timeout-history.txt"; @@ -243,10 +244,8 @@ public class Watchdog implements Dumpable { } } - /** - * Used for checking status of handle threads and scheduling monitor callbacks. - */ - public final class HandlerChecker implements Runnable { + /** Used for checking status of handle threads and scheduling monitor callbacks. */ + public static class HandlerChecker implements Runnable { private final Handler mHandler; private final String mName; private final ArrayList<Monitor> mMonitors = new ArrayList<Monitor>(); @@ -257,11 +256,19 @@ public class Watchdog implements Dumpable { private long mStartTimeMillis; private int mPauseCount; private long mPauseEndTimeMillis; + private Clock mClock; + private Object mLock; - HandlerChecker(Handler handler, String name) { + HandlerChecker(Handler handler, String name, Object lock, Clock clock) { mHandler = handler; mName = name; + mLock = lock; mCompleted = true; + mClock = clock; + } + + HandlerChecker(Handler handler, String name, Object lock) { + this(handler, name, lock, SystemClock.uptimeClock()); } void addMonitorLocked(Monitor monitor) { @@ -284,11 +291,9 @@ public class Watchdog implements Dumpable { mMonitorQueue.clear(); } - long nowMillis = SystemClock.uptimeMillis(); - boolean isPaused = mPauseCount > 0 - || (mPauseEndTimeMillis > 0 && mPauseEndTimeMillis < nowMillis); - if ((mMonitors.size() == 0 && mHandler.getLooper().getQueue().isPolling()) - || isPaused) { + long nowMillis = mClock.millis(); + boolean isPaused = mPauseCount > 0 || mPauseEndTimeMillis > nowMillis; + if ((mMonitors.size() == 0 && isHandlerPolling()) || isPaused) { // Don't schedule until after resume OR // If the target looper has recently been polling, then // there is no reason to enqueue our checker on it since that @@ -311,11 +316,15 @@ public class Watchdog implements Dumpable { mHandler.postAtFrontOfQueue(this); } + boolean isHandlerPolling() { + return mHandler.getLooper().getQueue().isPolling(); + } + public int getCompletionStateLocked() { if (mCompleted) { return COMPLETED; } else { - long latency = SystemClock.uptimeMillis() - mStartTimeMillis; + long latency = mClock.millis() - mStartTimeMillis; if (latency < mWaitMaxMillis / PRE_WATCHDOG_TIMEOUT_RATIO) { return WAITING; } else if (latency < mWaitMaxMillis) { @@ -340,7 +349,7 @@ public class Watchdog implements Dumpable { } else { prefix = "Blocked in monitor " + mCurrentMonitor.getClass().getName(); } - long latencySeconds = (SystemClock.uptimeMillis() - mStartTimeMillis) / 1000; + long latencySeconds = (mClock.millis() - mStartTimeMillis) / 1000; return prefix + " on " + mName + " (" + getThread().getName() + ")" + " for " + latencySeconds + "s"; } @@ -372,7 +381,7 @@ public class Watchdog implements Dumpable { * the given time. */ public void pauseForLocked(int pauseMillis, String reason) { - mPauseEndTimeMillis = SystemClock.uptimeMillis() + pauseMillis; + mPauseEndTimeMillis = mClock.millis() + pauseMillis; // Mark as completed, because there's a chance we called this after the watchog // thread loop called Object#wait after 'WAITED_UNTIL_PRE_WATCHDOG'. In that case we // want to ensure the next call to #getCompletionStateLocked for this checker returns @@ -404,6 +413,11 @@ public class Watchdog implements Dumpable { Slog.wtf(TAG, "Already resumed HandlerChecker: " + mName); } } + + @Override + public String toString() { + return "CheckerHandler for " + mName; + } } final class RebootRequestReceiver extends BroadcastReceiver { @@ -453,31 +467,40 @@ public class Watchdog implements Dumpable { ServiceThread t = new ServiceThread("watchdog.monitor", android.os.Process.THREAD_PRIORITY_DEFAULT, true /*allowIo*/); t.start(); - mMonitorChecker = new HandlerChecker(new Handler(t.getLooper()), "monitor thread"); + mMonitorChecker = new HandlerChecker(new Handler(t.getLooper()), "monitor thread", mLock); mHandlerCheckers.add(withDefaultTimeout(mMonitorChecker)); - mHandlerCheckers.add(withDefaultTimeout( - new HandlerChecker(FgThread.getHandler(), "foreground thread"))); + mHandlerCheckers.add( + withDefaultTimeout( + new HandlerChecker(FgThread.getHandler(), "foreground thread", mLock))); // Add checker for main thread. We only do a quick check since there // can be UI running on the thread. - mHandlerCheckers.add(withDefaultTimeout( - new HandlerChecker(new Handler(Looper.getMainLooper()), "main thread"))); + mHandlerCheckers.add( + withDefaultTimeout( + new HandlerChecker( + new Handler(Looper.getMainLooper()), "main thread", mLock))); // Add checker for shared UI thread. - mHandlerCheckers.add(withDefaultTimeout( - new HandlerChecker(UiThread.getHandler(), "ui thread"))); + mHandlerCheckers.add( + withDefaultTimeout(new HandlerChecker(UiThread.getHandler(), "ui thread", mLock))); // And also check IO thread. - mHandlerCheckers.add(withDefaultTimeout( - new HandlerChecker(IoThread.getHandler(), "i/o thread"))); + mHandlerCheckers.add( + withDefaultTimeout(new HandlerChecker(IoThread.getHandler(), "i/o thread", mLock))); // And the display thread. - mHandlerCheckers.add(withDefaultTimeout( - new HandlerChecker(DisplayThread.getHandler(), "display thread"))); + mHandlerCheckers.add( + withDefaultTimeout( + new HandlerChecker(DisplayThread.getHandler(), "display thread", mLock))); // And the animation thread. - mHandlerCheckers.add(withDefaultTimeout( - new HandlerChecker(AnimationThread.getHandler(), "animation thread"))); + mHandlerCheckers.add( + withDefaultTimeout( + new HandlerChecker( + AnimationThread.getHandler(), "animation thread", mLock))); // And the surface animation thread. - mHandlerCheckers.add(withDefaultTimeout( - new HandlerChecker(SurfaceAnimationThread.getHandler(), - "surface animation thread"))); + mHandlerCheckers.add( + withDefaultTimeout( + new HandlerChecker( + SurfaceAnimationThread.getHandler(), + "surface animation thread", + mLock))); // Initialize monitor for Binder threads. addMonitor(new BinderThreadMonitor()); @@ -617,7 +640,7 @@ public class Watchdog implements Dumpable { public void addThread(Handler thread) { synchronized (mLock) { final String name = thread.getLooper().getThread().getName(); - mHandlerCheckers.add(withDefaultTimeout(new HandlerChecker(thread, name))); + mHandlerCheckers.add(withDefaultTimeout(new HandlerChecker(thread, name, mLock))); } } @@ -625,7 +648,7 @@ public class Watchdog implements Dumpable { synchronized (mLock) { final String name = thread.getLooper().getThread().getName(); mHandlerCheckers.add( - withCustomTimeout(new HandlerChecker(thread, name), timeoutMillis)); + withCustomTimeout(new HandlerChecker(thread, name, mLock), timeoutMillis)); } } diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java index 1928780fa090..f2d9759a7cc9 100644 --- a/services/core/java/com/android/server/am/BatteryStatsService.java +++ b/services/core/java/com/android/server/am/BatteryStatsService.java @@ -480,6 +480,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub } public void systemServicesReady() { + mStats.setPowerStatsCollectorEnabled(Flags.streamlinedBatteryStats()); mBatteryUsageStatsProvider.setPowerStatsExporterEnabled(Flags.streamlinedBatteryStats()); mWorker.systemServicesReady(); mStats.systemServicesReady(mContext); @@ -2648,7 +2649,9 @@ public final class BatteryStatsService extends IBatteryStats.Stub pw.println(" --proto: output as a binary protobuffer"); pw.println(" --model power-profile: use the power profile model" + " even if measured energy is available"); - pw.println(" --sample: collect and dump a sample of stats for debugging purpose"); + if (Flags.streamlinedBatteryStats()) { + pw.println(" --sample: collect and dump a sample of stats for debugging purpose"); + } pw.println(" <package.name>: optional name of package to filter output by."); pw.println(" -h: print this help text."); pw.println("Battery stats (batterystats) commands:"); @@ -2938,10 +2941,10 @@ public final class BatteryStatsService extends IBatteryStats.Stub mCpuWakeupStats.dump(new IndentingPrintWriter(pw, " "), SystemClock.elapsedRealtime()); return; - } else if ("--sample".equals(arg)) { + } else if (Flags.streamlinedBatteryStats() && "--sample".equals(arg)) { dumpStatsSample(pw); return; - } else if ("--aggregated".equals(arg)) { + } else if (Flags.streamlinedBatteryStats() && "--aggregated".equals(arg)) { dumpAggregatedStats(pw); return; } else if ("--store".equals(arg)) { diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java index 69e3aaf48116..f47482d3a70f 100644 --- a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java +++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java @@ -142,6 +142,7 @@ public class SettingsToPropertiesMapper { "core_experiments_team_internal", "core_graphics", "dck_framework", + "devoptions_settings", "game", "haptics", "hardware_backed_security_mainline", diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 3117072beed8..c2ca64b70037 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -10681,8 +10681,8 @@ public class AudioService extends IAudioService.Stub /** @see LoudnessCodecConfigurator#addMediaCodec(MediaCodec) */ @Override - public void addLoudnessCodecInfo(int piid, LoudnessCodecInfo codecInfo) { - mLoudnessCodecHelper.addLoudnessCodecInfo(piid, codecInfo); + public void addLoudnessCodecInfo(int piid, int mediaCodecHash, LoudnessCodecInfo codecInfo) { + mLoudnessCodecHelper.addLoudnessCodecInfo(piid, mediaCodecHash, codecInfo); } /** @see LoudnessCodecConfigurator#removeMediaCodec(MediaCodec) */ @@ -11386,6 +11386,8 @@ public class AudioService extends IAudioService.Stub static final int LOG_NB_EVENTS_SPATIAL = 30; static final int LOG_NB_EVENTS_SOUND_DOSE = 30; + static final int LOG_NB_EVENTS_LOUDNESS_CODEC = 30; + static final EventLogger sLifecycleLogger = new EventLogger(LOG_NB_EVENTS_LIFECYCLE, "audio services lifecycle"); @@ -11585,6 +11587,10 @@ public class AudioService extends IAudioService.Stub mSpatializerHelper.dump(pw); sSpatialLogger.dump(pw); + pw.println("\n"); + pw.println("\nLoudness alignment:"); + mLoudnessCodecHelper.dump(pw); + mAudioSystem.dump(pw); } diff --git a/services/core/java/com/android/server/audio/AudioServiceEvents.java b/services/core/java/com/android/server/audio/AudioServiceEvents.java index f69b9f6523cc..de8901179028 100644 --- a/services/core/java/com/android/server/audio/AudioServiceEvents.java +++ b/services/core/java/com/android/server/audio/AudioServiceEvents.java @@ -622,6 +622,55 @@ public class AudioServiceEvents { } } + static final class LoudnessEvent extends EventLogger.Event { + static final int START_PIID = 0; + + static final int STOP_PIID = 1; + + static final int CLIENT_DIED = 2; + + final int mEventType; + final int mIntValue1; + final int mIntValue2; + + private LoudnessEvent(int event, int i1, int i2) { + mEventType = event; + mIntValue1 = i1; + mIntValue2 = i2; + } + + static LoudnessEvent getStartPiid(int piid, int pid) { + return new LoudnessEvent(START_PIID, piid, pid); + } + + static LoudnessEvent getStopPiid(int piid, int pid) { + return new LoudnessEvent(STOP_PIID, piid, pid); + } + + static LoudnessEvent getClientDied(int pid) { + return new LoudnessEvent(CLIENT_DIED, 0 /* ignored */, pid); + } + + + @Override + public String eventToString() { + switch (mEventType) { + case START_PIID: + return String.format( + "Start loudness updates for piid %d for client pid %d", + mIntValue1, mIntValue2); + case STOP_PIID: + return String.format( + "Stop loudness updates for piid %d for client pid %d", + mIntValue1, mIntValue2); + case CLIENT_DIED: + return String.format("Loudness client with pid %d died", mIntValue2); + + } + return new StringBuilder("FIXME invalid event type:").append(mEventType).toString(); + } + } + /** * Class to log stream type mute/unmute events */ diff --git a/services/core/java/com/android/server/audio/LoudnessCodecHelper.java b/services/core/java/com/android/server/audio/LoudnessCodecHelper.java index 3c67e9dd116b..bbe819f22e3a 100644 --- a/services/core/java/com/android/server/audio/LoudnessCodecHelper.java +++ b/services/core/java/com/android/server/audio/LoudnessCodecHelper.java @@ -21,6 +21,11 @@ import static android.media.AudioManager.AUDIO_DEVICE_CATEGORY_HEADPHONES; import static android.media.AudioManager.AUDIO_DEVICE_CATEGORY_HEARING_AID; import static android.media.AudioManager.AUDIO_DEVICE_CATEGORY_WATCH; import static android.media.AudioPlaybackConfiguration.PLAYER_DEVICEID_INVALID; +import static android.media.LoudnessCodecInfo.CodecMetadataType.CODEC_METADATA_TYPE_MPEG_4; +import static android.media.LoudnessCodecInfo.CodecMetadataType.CODEC_METADATA_TYPE_MPEG_D; +import static android.media.MediaFormat.KEY_AAC_DRC_EFFECT_TYPE; +import static android.media.MediaFormat.KEY_AAC_DRC_HEAVY_COMPRESSION; +import static android.media.MediaFormat.KEY_AAC_DRC_TARGET_REFERENCE_LEVEL; import android.annotation.IntDef; import android.annotation.NonNull; @@ -41,7 +46,11 @@ import android.util.SparseArray; import android.util.SparseIntArray; import com.android.internal.annotations.GuardedBy; +import com.android.internal.annotations.VisibleForTesting; +import com.android.server.audio.AudioServiceEvents.LoudnessEvent; +import com.android.server.utils.EventLogger; +import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; @@ -50,6 +59,7 @@ import java.util.HashSet; import java.util.List; import java.util.Objects; import java.util.Set; +import java.util.stream.Collectors; /** * Class to handle the updates in loudness parameters and responsible to generate parameters that @@ -70,10 +80,14 @@ public class LoudnessCodecHelper { private static final String SYSTEM_PROPERTY_SPEAKER_SPL_RANGE_SIZE = "audio.loudness.builtin-speaker-spl-range-size"; - private static final int SPL_RANGE_UNKNOWN = 0; - private static final int SPL_RANGE_SMALL = 1; - private static final int SPL_RANGE_MEDIUM = 2; - private static final int SPL_RANGE_LARGE = 3; + @VisibleForTesting + static final int SPL_RANGE_UNKNOWN = 0; + @VisibleForTesting + static final int SPL_RANGE_SMALL = 1; + @VisibleForTesting + static final int SPL_RANGE_MEDIUM = 2; + @VisibleForTesting + static final int SPL_RANGE_LARGE = 3; /** The possible transducer SPL ranges as defined in CTA2075 */ @IntDef({ @@ -99,12 +113,19 @@ public class LoudnessCodecHelper { pid = (Integer) cookie; } if (pid != null) { - mLoudnessCodecHelper.removePid(pid); + if (DEBUG) { + Log.d(TAG, "Client with pid " + pid + " died, removing from receiving updates"); + } + sLogger.enqueue(LoudnessEvent.getClientDied(pid)); + mLoudnessCodecHelper.onClientPidDied(pid); } super.onCallbackDied(callback, cookie); } } + private static final EventLogger sLogger = new EventLogger( + AudioService.LOG_NB_EVENTS_LOUDNESS_CODEC, "Loudness updates"); + private final LoudnessRemoteCallbackList mLoudnessUpdateDispatchers = new LoudnessRemoteCallbackList(this); @@ -125,7 +146,8 @@ public class LoudnessCodecHelper { private final AudioService mAudioService; /** Contains the properties necessary to compute the codec loudness related parameters. */ - private static final class LoudnessCodecInputProperties { + @VisibleForTesting + static final class LoudnessCodecInputProperties { private final int mMetadataType; private final boolean mIsDownmixing; @@ -200,10 +222,53 @@ public class LoudnessCodecHelper { } PersistableBundle createLoudnessParameters() { - // TODO: create bundle with new parameters - return new PersistableBundle(); - } + PersistableBundle loudnessParams = new PersistableBundle(); + + switch (mDeviceSplRange) { + case SPL_RANGE_LARGE: + // corresponds to -31dB attenuation + loudnessParams.putInt(KEY_AAC_DRC_TARGET_REFERENCE_LEVEL, 124); + if (mMetadataType == CODEC_METADATA_TYPE_MPEG_4) { + loudnessParams.putInt(KEY_AAC_DRC_HEAVY_COMPRESSION, 0); + } else if (mMetadataType == CODEC_METADATA_TYPE_MPEG_D) { + // general compression + loudnessParams.putInt(KEY_AAC_DRC_EFFECT_TYPE, 6); + } + break; + case SPL_RANGE_MEDIUM: + // corresponds to -24dB attenuation + loudnessParams.putInt(KEY_AAC_DRC_TARGET_REFERENCE_LEVEL, 96); + if (mMetadataType == CODEC_METADATA_TYPE_MPEG_4) { + loudnessParams.putInt(KEY_AAC_DRC_HEAVY_COMPRESSION, mIsDownmixing ? 1 : 0); + } else if (mMetadataType == CODEC_METADATA_TYPE_MPEG_D) { + // general compression + loudnessParams.putInt(KEY_AAC_DRC_EFFECT_TYPE, 6); + } + break; + case SPL_RANGE_SMALL: + // corresponds to -16dB attenuation + loudnessParams.putInt(KEY_AAC_DRC_TARGET_REFERENCE_LEVEL, 64); + if (mMetadataType == CODEC_METADATA_TYPE_MPEG_4) { + loudnessParams.putInt(KEY_AAC_DRC_HEAVY_COMPRESSION, 1); + } else if (mMetadataType == CODEC_METADATA_TYPE_MPEG_D) { + // limited playback range compression + loudnessParams.putInt(KEY_AAC_DRC_EFFECT_TYPE, 3); + } + break; + default: + // corresponds to -24dB attenuation + loudnessParams.putInt(KEY_AAC_DRC_TARGET_REFERENCE_LEVEL, 96); + if (mMetadataType == CODEC_METADATA_TYPE_MPEG_4) { + loudnessParams.putInt(KEY_AAC_DRC_HEAVY_COMPRESSION, mIsDownmixing ? 1 : 0); + } else if (mMetadataType == CODEC_METADATA_TYPE_MPEG_D) { + // general compression + loudnessParams.putInt(KEY_AAC_DRC_EFFECT_TYPE, 6); + } + break; + } + return loudnessParams; + } } @GuardedBy("mLock") @@ -227,22 +292,25 @@ public class LoudnessCodecHelper { if (DEBUG) { Log.d(TAG, "startLoudnessCodecUpdates: piid " + piid + " codecInfos " + codecInfoList); } - Set<LoudnessCodecInfo> infoSet; + synchronized (mLock) { if (mStartedPiids.contains(piid)) { Log.w(TAG, "Already started loudness updates for piid " + piid); return; } - infoSet = new HashSet<>(codecInfoList); + Set<LoudnessCodecInfo> infoSet = new HashSet<>(codecInfoList); mStartedPiids.put(piid, infoSet); - mPiidToPidCache.put(piid, Binder.getCallingPid()); + int pid = Binder.getCallingPid(); + mPiidToPidCache.put(piid, pid); + + sLogger.enqueue(LoudnessEvent.getStartPiid(piid, pid)); } try (SafeCloseable ignored = ClearCallingIdentityContext.create()) { mAudioService.getActivePlaybackConfigurations().stream().filter( conf -> conf.getPlayerInterfaceId() == piid).findFirst().ifPresent( - apc -> updateCodecParametersForConfiguration(apc, infoSet)); + this::updateCodecParametersForConfiguration); } } @@ -250,20 +318,24 @@ public class LoudnessCodecHelper { if (DEBUG) { Log.d(TAG, "stopLoudnessCodecUpdates: piid " + piid); } + synchronized (mLock) { if (!mStartedPiids.contains(piid)) { Log.w(TAG, "Loudness updates are already stopped for piid " + piid); return; } mStartedPiids.remove(piid); + + sLogger.enqueue(LoudnessEvent.getStopPiid(piid, mPiidToPidCache.get(piid, -1))); mPiidToDeviceIdCache.delete(piid); mPiidToPidCache.delete(piid); } } - void addLoudnessCodecInfo(int piid, LoudnessCodecInfo info) { + void addLoudnessCodecInfo(int piid, int mediaCodecHash, LoudnessCodecInfo info) { if (DEBUG) { - Log.d(TAG, "addLoudnessCodecInfo: piid " + piid + " info " + info); + Log.d(TAG, "addLoudnessCodecInfo: piid " + piid + " mcHash " + mediaCodecHash + " info " + + info); } Set<LoudnessCodecInfo> infoSet; @@ -280,7 +352,20 @@ public class LoudnessCodecHelper { try (SafeCloseable ignored = ClearCallingIdentityContext.create()) { mAudioService.getActivePlaybackConfigurations().stream().filter( conf -> conf.getPlayerInterfaceId() == piid).findFirst().ifPresent( - apc -> updateCodecParametersForConfiguration(apc, Set.of(info))); + apc -> { + final AudioDeviceInfo deviceInfo = apc.getAudioDeviceInfo(); + if (deviceInfo != null) { + PersistableBundle updateBundle = new PersistableBundle(); + synchronized (mLock) { + updateBundle.putPersistableBundle( + Integer.toString(mediaCodecHash), + getCodecBundle_l(deviceInfo, info)); + } + if (!updateBundle.isDefinitelyEmpty()) { + dispatchNewLoudnessParameters(piid, updateBundle); + } + } + }); } } @@ -298,24 +383,6 @@ public class LoudnessCodecHelper { } } - void removePid(int pid) { - if (DEBUG) { - Log.d(TAG, "Removing pid " + pid + " from receiving updates"); - } - synchronized (mLock) { - for (int i = 0; i < mPiidToPidCache.size(); ++i) { - int piid = mPiidToPidCache.keyAt(i); - if (mPiidToPidCache.get(piid) == pid) { - if (DEBUG) { - Log.d(TAG, "Removing piid " + piid); - } - mStartedPiids.delete(piid); - mPiidToDeviceIdCache.delete(piid); - } - } - } - } - PersistableBundle getLoudnessParams(int piid, LoudnessCodecInfo codecInfo) { if (DEBUG) { Log.d(TAG, "getLoudnessParams: piid " + piid + " codecInfo " + codecInfo); @@ -381,48 +448,77 @@ public class LoudnessCodecHelper { } } - updateApcList.forEach(apc -> updateCodecParametersForConfiguration(apc, null)); + updateApcList.forEach(apc -> updateCodecParametersForConfiguration(apc)); + } + + /** Updates and dispatches the new loudness parameters for all its registered codecs. */ + void dump(PrintWriter pw) { + // Registered clients + pw.println("\nRegistered clients:\n"); + synchronized (mLock) { + for (int i = 0; i < mStartedPiids.size(); ++i) { + int piid = mStartedPiids.keyAt(i); + int pid = mPiidToPidCache.get(piid, -1); + final Set<LoudnessCodecInfo> codecInfos = mStartedPiids.get(piid); + pw.println(String.format("Player piid %d pid %d active codec types %s\n", piid, + pid, codecInfos.stream().map(Object::toString).collect( + Collectors.joining(", ")))); + } + pw.println(); + } + + sLogger.dump(pw); + pw.println(); } - /** Updates and dispatches the new loudness parameters for the {@code codecInfos} set. + private void onClientPidDied(int pid) { + synchronized (mLock) { + for (int i = 0; i < mPiidToPidCache.size(); ++i) { + int piid = mPiidToPidCache.keyAt(i); + if (mPiidToPidCache.get(piid) == pid) { + if (DEBUG) { + Log.d(TAG, "Removing piid " + piid); + } + mStartedPiids.delete(piid); + mPiidToDeviceIdCache.delete(piid); + } + } + } + } + + /** + * Updates and dispatches the new loudness parameters for the {@code codecInfos} set. * * @param apc the player configuration for which the loudness parameters are updated. - * @param codecInfos the codec info for which the parameters are updated. If {@code null}, - * send updates for all the started codecs assigned to {@code apc} */ - private void updateCodecParametersForConfiguration(AudioPlaybackConfiguration apc, - Set<LoudnessCodecInfo> codecInfos) { + private void updateCodecParametersForConfiguration(AudioPlaybackConfiguration apc) { if (DEBUG) { - Log.d(TAG, "updateCodecParametersForConfiguration apc:" + apc + " codecInfos: " - + codecInfos); + Log.d(TAG, "updateCodecParametersForConfiguration apc:" + apc); } + final PersistableBundle allBundles = new PersistableBundle(); final int piid = apc.getPlayerInterfaceId(); + synchronized (mLock) { - if (codecInfos == null) { - codecInfos = mStartedPiids.get(piid); - } + final Set<LoudnessCodecInfo> codecInfos = mStartedPiids.get(piid); final AudioDeviceInfo deviceInfo = apc.getAudioDeviceInfo(); if (codecInfos != null && deviceInfo != null) { for (LoudnessCodecInfo info : codecInfos) { - allBundles.putPersistableBundle(Integer.toString(info.mediaCodecHashCode), + allBundles.putPersistableBundle(Integer.toString(info.hashCode()), getCodecBundle_l(deviceInfo, info)); } } } if (!allBundles.isDefinitelyEmpty()) { - if (DEBUG) { - Log.d(TAG, "Dispatching for piid: " + piid + " bundle: " + allBundles); - } dispatchNewLoudnessParameters(piid, allBundles); } } private void dispatchNewLoudnessParameters(int piid, PersistableBundle bundle) { if (DEBUG) { - Log.d(TAG, "dispatchNewLoudnessParameters: piid " + piid); + Log.d(TAG, "dispatchNewLoudnessParameters: piid " + piid + " bundle: " + bundle); } final int nbDispatchers = mLoudnessUpdateDispatchers.beginBroadcast(); for (int i = 0; i < nbDispatchers; ++i) { diff --git a/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamper.java b/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamper.java index 8a884b6221a2..42ebc401335e 100644 --- a/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamper.java +++ b/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamper.java @@ -25,7 +25,7 @@ import com.android.server.display.DisplayBrightnessState; import java.io.PrintWriter; /** - * Provides max allowed brightness + * Provides brightness range constraints */ abstract class BrightnessClamper<T> { @@ -74,6 +74,7 @@ abstract class BrightnessClamper<T> { protected enum Type { THERMAL, POWER, - BEDTIME_MODE + BEDTIME_MODE, + LUX, } } diff --git a/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java b/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java index 765608e88356..01694ddee06a 100644 --- a/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java +++ b/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java @@ -68,14 +68,14 @@ public class BrightnessClamperController { private boolean mClamperApplied = false; public BrightnessClamperController(Handler handler, - ClamperChangeListener clamperChangeListener, DisplayDeviceData data, Context context, + ClamperChangeListener clamperChangeListener, DisplayDeviceData data, Context context, DisplayManagerFlags flags) { this(new Injector(), handler, clamperChangeListener, data, context, flags); } @VisibleForTesting BrightnessClamperController(Injector injector, Handler handler, - ClamperChangeListener clamperChangeListener, DisplayDeviceData data, Context context, + ClamperChangeListener clamperChangeListener, DisplayDeviceData data, Context context, DisplayManagerFlags flags) { mDeviceConfigParameterProvider = injector.getDeviceConfigParameterProvider(); mHandler = handler; @@ -147,7 +147,8 @@ public class BrightnessClamperController { * Should be moved to DisplayBrightnessState OR derived from DisplayBrightnessState * TODO: b/263362199 */ - @BrightnessInfo.BrightnessMaxReason public int getBrightnessMaxReason() { + @BrightnessInfo.BrightnessMaxReason + public int getBrightnessMaxReason() { if (mClamperType == null) { return BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE; } else if (mClamperType == Type.THERMAL) { @@ -241,12 +242,15 @@ public class BrightnessClamperController { new BrightnessThermalClamper(handler, clamperChangeListener, data)); if (flags.isPowerThrottlingClamperEnabled()) { clampers.add(new BrightnessPowerClamper(handler, clamperChangeListener, - data)); + data)); } if (flags.isBrightnessWearBedtimeModeClamperEnabled()) { clampers.add(new BrightnessWearBedtimeModeClamper(handler, context, clamperChangeListener, data)); } + if (flags.isEvenDimmerEnabled()) { + clampers.add(new BrightnessMinClamper(handler, clamperChangeListener, context)); + } return clampers; } diff --git a/services/core/java/com/android/server/display/brightness/clamper/BrightnessMinClamper.java b/services/core/java/com/android/server/display/brightness/clamper/BrightnessMinClamper.java new file mode 100644 index 000000000000..71efca12f91c --- /dev/null +++ b/services/core/java/com/android/server/display/brightness/clamper/BrightnessMinClamper.java @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.display.brightness.clamper; + +import android.content.ContentResolver; +import android.content.Context; +import android.database.ContentObserver; +import android.net.Uri; +import android.os.Handler; +import android.os.PowerManager; +import android.os.UserHandle; +import android.provider.Settings; +import android.util.Slog; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.server.display.utils.DebugUtils; + +import java.io.PrintWriter; + +/** + * Class used to prevent the screen brightness dipping below a certain value, based on current + * lux conditions. + */ +public class BrightnessMinClamper extends BrightnessClamper { + + // To enable these logs, run: + // 'adb shell setprop persist.log.tag.BrightnessMinClamper DEBUG && adb reboot' + private static final String TAG = "BrightnessMinClamper"; + private static final boolean DEBUG = DebugUtils.isDebuggable(TAG); + + private final SettingsObserver mSettingsObserver; + + ContentResolver mContentResolver; + private float mNitsLowerBound; + + @VisibleForTesting + BrightnessMinClamper(Handler handler, + BrightnessClamperController.ClamperChangeListener listener, Context context) { + super(handler, listener); + + mContentResolver = context.getContentResolver(); + mSettingsObserver = new SettingsObserver(mHandler); + mHandler.post(() -> { + start(); + }); + } + + private void recalculateLowerBound() { + final int userId = UserHandle.USER_CURRENT; + float settingNitsLowerBound = Settings.Secure.getFloatForUser( + mContentResolver, Settings.Secure.EVEN_DIMMER_MIN_NITS, + /* def= */ PowerManager.BRIGHTNESS_MIN, userId); + + boolean isActive = Settings.Secure.getIntForUser(mContentResolver, + Settings.Secure.EVEN_DIMMER_ACTIVATED, + /* def= */ 0, userId) == 1; + + // TODO: luxBasedNitsLowerBound = mMinNitsToLuxSpline(currentLux); + float luxBasedNitsLowerBound = PowerManager.BRIGHTNESS_MIN; + final float nitsLowerBound = Math.max(settingNitsLowerBound, luxBasedNitsLowerBound); + + if (mNitsLowerBound != nitsLowerBound || mIsActive != isActive) { + mIsActive = isActive; + mNitsLowerBound = nitsLowerBound; + if (DEBUG) { + Slog.i(TAG, "mIsActive: " + mIsActive); + } + // TODO: mBrightnessCap = nitsToBrightnessSpline(mNitsLowerBound); + mChangeListener.onChanged(); + } + } + + void start() { + recalculateLowerBound(); + } + + + @Override + Type getType() { + return Type.LUX; + } + + @Override + void onDeviceConfigChanged() { + // TODO + } + + @Override + void onDisplayChanged(Object displayData) { + + } + + @Override + void stop() { + mContentResolver.unregisterContentObserver(mSettingsObserver); + } + + @Override + void dump(PrintWriter pw) { + pw.println("BrightnessMinClamper:"); + pw.println(" mBrightnessCap=" + mBrightnessCap); + pw.println(" mIsActive=" + mIsActive); + pw.println(" mNitsLowerBound=" + mNitsLowerBound); + super.dump(pw); + } + + private final class SettingsObserver extends ContentObserver { + SettingsObserver(Handler handler) { + super(handler); + mContentResolver.registerContentObserver( + Settings.Secure.getUriFor(Settings.Secure.EVEN_DIMMER_MIN_NITS), + false, this); + mContentResolver.registerContentObserver( + Settings.Secure.getUriFor(Settings.Secure.EVEN_DIMMER_ACTIVATED), + false, this); + } + + @Override + public void onChange(boolean selfChange, Uri uri) { + recalculateLowerBound(); + } + } +} diff --git a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java index c71f0cf2dd91..2d5da715b585 100644 --- a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java +++ b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java @@ -78,6 +78,9 @@ public class DisplayManagerFlags { Flags.FLAG_ENABLE_POWER_THROTTLING_CLAMPER, Flags::enablePowerThrottlingClamper); + private final FlagState mEvenDimmerFlagState = new FlagState( + Flags.FLAG_EVEN_DIMMER, + Flags::evenDimmer); private final FlagState mSmallAreaDetectionFlagState = new FlagState( com.android.graphics.surfaceflinger.flags.Flags.FLAG_ENABLE_SMALL_AREA_DETECTION, com.android.graphics.surfaceflinger.flags.Flags::enableSmallAreaDetection); @@ -174,6 +177,11 @@ public class DisplayManagerFlags { return mBackUpSmoothDisplayAndForcePeakRefreshRateFlagState.isEnabled(); } + /** Returns whether brightness range is allowed to extend below traditional range. */ + public boolean isEvenDimmerEnabled() { + return mEvenDimmerFlagState.isEnabled(); + } + public boolean isSmallAreaDetectionEnabled() { return mSmallAreaDetectionFlagState.isEnabled(); } diff --git a/services/core/java/com/android/server/display/feature/display_flags.aconfig b/services/core/java/com/android/server/display/feature/display_flags.aconfig index 9dfa1ee41ad6..1b4d74cdff1f 100644 --- a/services/core/java/com/android/server/display/feature/display_flags.aconfig +++ b/services/core/java/com/android/server/display/feature/display_flags.aconfig @@ -106,6 +106,14 @@ flag { } flag { + name: "even_dimmer" + namespace: "display_manager" + description: "Feature flag for extending the brightness below traditional range" + bug: "179428400" + is_fixed_read_only: true +} + +flag { name: "brightness_int_range_user_perception" namespace: "display_manager" description: "Feature flag for converting the brightness integer range to the user perception scale" diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index aa0b9b892220..3c6887c17e97 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -26,6 +26,7 @@ import static android.app.Notification.FLAG_BUBBLE; import static android.app.Notification.FLAG_FOREGROUND_SERVICE; import static android.app.Notification.FLAG_FSI_REQUESTED_BUT_DENIED; import static android.app.Notification.FLAG_INSISTENT; +import static android.app.Notification.FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY; import static android.app.Notification.FLAG_NO_CLEAR; import static android.app.Notification.FLAG_NO_DISMISS; import static android.app.Notification.FLAG_ONGOING_EVENT; @@ -58,6 +59,7 @@ import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK; import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF; import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON; import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR; +import static android.app.Flags.lifetimeExtensionRefactor; import static android.content.Context.BIND_ALLOW_WHITELIST_MANAGEMENT; import static android.content.Context.BIND_AUTO_CREATE; import static android.content.Context.BIND_FOREGROUND_SERVICE; @@ -1224,7 +1226,7 @@ public class NotificationManagerService extends SystemService { public void onClearAll(int callingUid, int callingPid, int userId) { synchronized (mNotificationLock) { cancelAllLocked(callingUid, callingPid, userId, REASON_CANCEL_ALL, null, - /*includeCurrentProfiles*/ true); + /*includeCurrentProfiles*/ true, FLAG_ONGOING_EVENT | FLAG_NO_CLEAR); } } @@ -1498,6 +1500,7 @@ public class NotificationManagerService extends SystemService { synchronized (mNotificationLock) { NotificationRecord r = mNotificationsByKey.get(key); if (r != null) { + r.recordSmartReplied(); LogMaker logMaker = r.getLogMaker() .setCategory(MetricsEvent.SMART_REPLY_ACTION) .setSubtype(replyIndex) @@ -1804,11 +1807,22 @@ public class NotificationManagerService extends SystemService { record = findNotificationByKeyLocked(intent.getStringExtra(EXTRA_KEY)); } if (record != null) { - cancelNotification(record.getSbn().getUid(), record.getSbn().getInitialPid(), - record.getSbn().getPackageName(), record.getSbn().getTag(), - record.getSbn().getId(), 0, - FLAG_FOREGROUND_SERVICE | FLAG_USER_INITIATED_JOB, - true, record.getUserId(), REASON_TIMEOUT, null); + if (lifetimeExtensionRefactor()) { + cancelNotification(record.getSbn().getUid(), + record.getSbn().getInitialPid(), + record.getSbn().getPackageName(), record.getSbn().getTag(), + record.getSbn().getId(), 0, + FLAG_FOREGROUND_SERVICE | FLAG_USER_INITIATED_JOB + | FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY, + true, record.getUserId(), REASON_TIMEOUT, null); + } else { + cancelNotification(record.getSbn().getUid(), + record.getSbn().getInitialPid(), + record.getSbn().getPackageName(), record.getSbn().getTag(), + record.getSbn().getId(), 0, + FLAG_FOREGROUND_SERVICE | FLAG_USER_INITIATED_JOB, + true, record.getUserId(), REASON_TIMEOUT, null); + } } } } @@ -3728,8 +3742,16 @@ public class NotificationManagerService extends SystemService { @Override public void cancelNotificationWithTag(String pkg, String opPkg, String tag, int id, int userId) { + // Don't allow client applications to cancel foreground service notifs, user-initiated + // job notifs, autobundled summaries, or notifs that have been replied to. + int mustNotHaveFlags = isCallingUidSystem() ? 0 : + (FLAG_FOREGROUND_SERVICE | FLAG_USER_INITIATED_JOB | FLAG_AUTOGROUP_SUMMARY); + if (lifetimeExtensionRefactor()) { + mustNotHaveFlags |= FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY; + } + cancelNotificationInternal(pkg, opPkg, Binder.getCallingUid(), Binder.getCallingPid(), - tag, id, userId); + tag, id, userId, mustNotHaveFlags); } @Override @@ -3740,9 +3762,16 @@ public class NotificationManagerService extends SystemService { Binder.getCallingUid(), userId, true, false, "cancelAllNotifications", pkg); // Don't allow the app to cancel active FGS or UIJ notifications - cancelAllNotificationsInt(Binder.getCallingUid(), Binder.getCallingPid(), - pkg, null, 0, FLAG_FOREGROUND_SERVICE | FLAG_USER_INITIATED_JOB, - userId, REASON_APP_CANCEL_ALL); + if (lifetimeExtensionRefactor()) { + cancelAllNotificationsInt(Binder.getCallingUid(), Binder.getCallingPid(), + pkg, null, 0, FLAG_FOREGROUND_SERVICE | FLAG_USER_INITIATED_JOB + | FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY, + userId, REASON_APP_CANCEL_ALL); + } else { + cancelAllNotificationsInt(Binder.getCallingUid(), Binder.getCallingPid(), + pkg, null, 0, FLAG_FOREGROUND_SERVICE | FLAG_USER_INITIATED_JOB, + userId, REASON_APP_CANCEL_ALL); + } } @Override @@ -4808,8 +4837,16 @@ public class NotificationManagerService extends SystemService { r.getSbn().getId(), userId, reason); } } else { - cancelAllLocked(callingUid, callingPid, info.userid, - REASON_LISTENER_CANCEL_ALL, info, info.supportsProfiles()); + if (lifetimeExtensionRefactor()) { + cancelAllLocked(callingUid, callingPid, info.userid, + REASON_LISTENER_CANCEL_ALL, info, info.supportsProfiles(), + FLAG_ONGOING_EVENT | FLAG_NO_CLEAR + | FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY); + } else { + cancelAllLocked(callingUid, callingPid, info.userid, + REASON_LISTENER_CANCEL_ALL, info, info.supportsProfiles(), + FLAG_ONGOING_EVENT | FLAG_NO_CLEAR); + } } } } finally { @@ -4923,6 +4960,9 @@ public class NotificationManagerService extends SystemService { int callingUid, int callingPid, String pkg, String tag, int id, int userId, int reason) { int mustNotHaveFlags = FLAG_ONGOING_EVENT; + if (lifetimeExtensionRefactor()) { + mustNotHaveFlags |= FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY; + } cancelNotification(callingUid, callingPid, pkg, tag, id, 0 /* mustHaveFlags */, mustNotHaveFlags, true, @@ -6712,7 +6752,12 @@ public class NotificationManagerService extends SystemService { @Override public void cancelNotification(String pkg, String opPkg, int callingUid, int callingPid, String tag, int id, int userId) { - cancelNotificationInternal(pkg, opPkg, callingUid, callingPid, tag, id, userId); + // Don't allow client applications to cancel foreground service notifs, + // user-initiated job notifs or autobundled summaries. + final int mustNotHaveFlags = isCallingUidSystem() ? 0 : + (FLAG_FOREGROUND_SERVICE | FLAG_USER_INITIATED_JOB | FLAG_AUTOGROUP_SUMMARY); + cancelNotificationInternal(pkg, opPkg, callingUid, callingPid, tag, id, userId, + mustNotHaveFlags); } @Override @@ -6907,7 +6952,7 @@ public class NotificationManagerService extends SystemService { } void cancelNotificationInternal(String pkg, String opPkg, int callingUid, int callingPid, - String tag, int id, int userId) { + String tag, int id, int userId, int mustNotHaveFlags) { userId = ActivityManager.handleIncomingUser(callingPid, callingUid, userId, true, false, "cancelNotificationWithTag", pkg); @@ -6935,10 +6980,6 @@ public class NotificationManagerService extends SystemService { } } - // Don't allow client applications to cancel foreground service notifs, user-initiated job - // notifs or autobundled summaries. - final int mustNotHaveFlags = isCallingUidSystem() ? 0 : - (FLAG_FOREGROUND_SERVICE | FLAG_USER_INITIATED_JOB | FLAG_AUTOGROUP_SUMMARY); cancelNotification(uid, callingPid, pkg, tag, id, 0, mustNotHaveFlags, false, userId, REASON_APP_CANCEL, null); } @@ -7294,6 +7335,11 @@ public class NotificationManagerService extends SystemService { notification.flags &= ~FLAG_FSI_REQUESTED_BUT_DENIED; + // Apps should not create notifications that are lifetime extended. + if (lifetimeExtensionRefactor()) { + notification.flags &= ~FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY; + } + if (notification.fullScreenIntent != null) { final AttributionSource attributionSource = new AttributionSource.Builder(notificationUid).setPackageName(pkg).build(); @@ -10088,7 +10134,7 @@ public class NotificationManagerService extends SystemService { @GuardedBy("mNotificationLock") void cancelAllLocked(int callingUid, int callingPid, int userId, int reason, - ManagedServiceInfo listener, boolean includeCurrentProfiles) { + ManagedServiceInfo listener, boolean includeCurrentProfiles, int mustNotHaveFlags) { final long cancellationElapsedTimeMs = SystemClock.elapsedRealtime(); mHandler.post(new Runnable() { @Override @@ -10100,7 +10146,7 @@ public class NotificationManagerService extends SystemService { null, userId, 0, 0, reason, listenerName); FlagChecker flagChecker = (int flags) -> { - int flagsToCheck = FLAG_ONGOING_EVENT | FLAG_NO_CLEAR; + int flagsToCheck = mustNotHaveFlags; if (REASON_LISTENER_CANCEL_ALL == reason || REASON_CANCEL_ALL == reason) { flagsToCheck |= FLAG_BUBBLE; diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java index 100c63863f7f..64d3a20e9281 100644 --- a/services/core/java/com/android/server/notification/NotificationRecord.java +++ b/services/core/java/com/android/server/notification/NotificationRecord.java @@ -24,7 +24,9 @@ import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED; import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL; import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_POSITIVE; +import android.annotation.FlaggedApi; import android.annotation.Nullable; +import android.app.Flags; import android.app.KeyguardManager; import android.app.Notification; import android.app.NotificationChannel; @@ -1257,10 +1259,27 @@ public final class NotificationRecord { mStats.setExpanded(); } + /** Run when the notification is direct replied. */ public void recordDirectReplied() { + if (Flags.lifetimeExtensionRefactor()) { + // Mark the NotificationRecord as lifetime extended. + Notification notification = getSbn().getNotification(); + notification.flags |= Notification.FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY; + } + mStats.setDirectReplied(); } + + /** Run when the notification is smart replied. */ + @FlaggedApi(Flags.FLAG_LIFETIME_EXTENSION_REFACTOR) + public void recordSmartReplied() { + Notification notification = getSbn().getNotification(); + notification.flags |= Notification.FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY; + + mStats.setSmartReplied(); + } + public void recordDismissalSurface(@NotificationStats.DismissalSurface int surface) { mStats.setDismissalSurface(surface); } diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index f90bf4b47644..b89b4a2cb241 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -1566,6 +1566,7 @@ public class UserManagerService extends IUserManager.Stub { : now - userData.info.creationTime); DevicePolicyEventLogger .createEvent(DevicePolicyEnums.REQUEST_QUIET_MODE_ENABLED) + .setInt(UserJourneyLogger.getUserTypeForStatsd(userData.info.userType)) .setStrings(callingPackage) .setBoolean(enableQuietMode) .setTimePeriod(period) diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 73c422490330..30bce2f41cf7 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -22,6 +22,9 @@ import static android.Manifest.permission.SYSTEM_APPLICATION_OVERLAY; import static android.app.AppOpsManager.OP_CREATE_ACCESSIBILITY_OVERLAY; import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW; import static android.app.AppOpsManager.OP_TOAST_WINDOW; +import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; +import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE; +import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE; import static android.content.pm.PackageManager.FEATURE_AUTOMOTIVE; import static android.content.pm.PackageManager.FEATURE_HDMI_CEC; import static android.content.pm.PackageManager.FEATURE_LEANBACK; @@ -563,6 +566,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { int mShortPressOnWindowBehavior; int mPowerVolUpBehavior; boolean mStylusButtonsEnabled = true; + boolean mKidsModeEnabled; boolean mHasSoftInput = false; boolean mUseTvRouting; boolean mAllowStartActivityForLongPressOnPowerDuringSetup; @@ -887,6 +891,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { resolver.registerContentObserver(Settings.Secure.getUriFor( Settings.Secure.STYLUS_BUTTONS_ENABLED), false, this, UserHandle.USER_ALL); + resolver.registerContentObserver(Settings.Secure.getUriFor( + Settings.Secure.NAV_BAR_KIDS_MODE), false, this, + UserHandle.USER_ALL); updateSettings(); } @@ -2964,12 +2971,44 @@ public class PhoneWindowManager implements WindowManagerPolicy { mStylusButtonsEnabled = Settings.Secure.getIntForUser(resolver, Secure.STYLUS_BUTTONS_ENABLED, 1, UserHandle.USER_CURRENT) == 1; mInputManagerInternal.setStylusButtonMotionEventsEnabled(mStylusButtonsEnabled); + + final boolean kidsModeEnabled = Settings.Secure.getIntForUser(resolver, + Settings.Secure.NAV_BAR_KIDS_MODE, 0, UserHandle.USER_CURRENT) == 1; + if (mKidsModeEnabled != kidsModeEnabled) { + mKidsModeEnabled = kidsModeEnabled; + updateKidsModeSettings(); + } } if (updateRotation) { updateRotation(true); } } + private void updateKidsModeSettings() { + if (mKidsModeEnabled) { + // Needed since many Kids apps aren't optimised to support both orientations and it + // will be hard for kids to understand the app compat mode. + // TODO(229961548): Remove ignoreOrientationRequest exception for Kids Mode once + // possible. + if (mContext.getResources().getBoolean(R.bool.config_reverseDefaultRotation)) { + mWindowManagerInternal.setOrientationRequestPolicy( + true /* isIgnoreOrientationRequestDisabled */, + new int[]{SCREEN_ORIENTATION_LANDSCAPE, + SCREEN_ORIENTATION_REVERSE_LANDSCAPE}, + new int[]{SCREEN_ORIENTATION_SENSOR_LANDSCAPE, + SCREEN_ORIENTATION_SENSOR_LANDSCAPE}); + } else { + mWindowManagerInternal.setOrientationRequestPolicy( + true /* isIgnoreOrientationRequestDisabled */, + null /* fromOrientations */, null /* toOrientations */); + } + } else { + mWindowManagerInternal.setOrientationRequestPolicy( + false /* isIgnoreOrientationRequestDisabled */, + null /* fromOrientations */, null /* toOrientations */); + } + } + private DreamManagerInternal getDreamManagerInternal() { if (mDreamManagerInternal == null) { // If mDreamManagerInternal is null, attempt to re-fetch it. @@ -3433,7 +3472,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { } break; case KeyEvent.KEYCODE_DEL: - case KeyEvent.KEYCODE_GRAVE: + case KeyEvent.KEYCODE_ESCAPE: if (firstDown && event.isMetaPressed()) { logKeyboardSystemsEvent(event, KeyboardLogEvent.BACK); injectBackGesture(event.getDownTime()); @@ -3638,15 +3677,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { return true; } break; - case KeyEvent.KEYCODE_SPACE: - // Handle keyboard layout switching. (META + SPACE) - if (firstDown && event.isMetaPressed()) { - int direction = (metaState & KeyEvent.META_SHIFT_MASK) != 0 ? -1 : 1; - sendSwitchKeyboardLayout(event, direction); - logKeyboardSystemsEvent(event, KeyboardLogEvent.LANGUAGE_SWITCH); - return true; - } - break; case KeyEvent.KEYCODE_META_LEFT: case KeyEvent.KEYCODE_META_RIGHT: if (down) { @@ -3941,7 +3971,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { } return true; case KeyEvent.KEYCODE_ESCAPE: - if (down && repeatCount == 0) { + if (down + && KeyEvent.metaStateHasNoModifiers(metaState) + && repeatCount == 0) { mContext.closeSystemDialogs(); } return true; @@ -6430,6 +6462,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { pw.print(!mAllowLockscreenWhenOnDisplays.isEmpty()); pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout); pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive); + pw.print(prefix); pw.print("mKidsModeEnabled="); pw.println(mKidsModeEnabled); mHapticFeedbackVibrationProvider.dump(prefix, pw); mGlobalKeyManager.dump(prefix, pw); diff --git a/services/core/java/com/android/server/power/hint/HintManagerService.java b/services/core/java/com/android/server/power/hint/HintManagerService.java index dd39fb02573e..c17d6ab4c85b 100644 --- a/services/core/java/com/android/server/power/hint/HintManagerService.java +++ b/services/core/java/com/android/server/power/hint/HintManagerService.java @@ -51,6 +51,7 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.Arrays; import java.util.List; +import java.util.NoSuchElementException; import java.util.Objects; /** An hint service implementation that runs in System Server process. */ @@ -544,7 +545,11 @@ public final class HintManagerService extends SystemService { if (mHalSessionPtr == 0) return; mNativeWrapper.halCloseHintSession(mHalSessionPtr); mHalSessionPtr = 0; - mToken.unlinkToDeath(this, 0); + try { + mToken.unlinkToDeath(this, 0); + } catch (NoSuchElementException ignored) { + Slogf.d(TAG, "Death link does not exist for session with UID " + mUid); + } } synchronized (mLock) { ArrayMap<IBinder, ArraySet<AppHintSession>> tokenMap = mActiveSessions.get(mUid); diff --git a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java index 0491c14e52bd..b8d26d9cac42 100644 --- a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java +++ b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java @@ -286,6 +286,7 @@ public class BatteryStatsImpl extends BatteryStats { private final LongSparseArray<SamplingTimer> mKernelMemoryStats = new LongSparseArray<>(); private int[] mCpuPowerBracketMap; private final CpuPowerStatsCollector mCpuPowerStatsCollector; + private boolean mPowerStatsCollectorEnabled; public LongSparseArray<SamplingTimer> getKernelMemoryStats() { return mKernelMemoryStats; @@ -601,6 +602,10 @@ public class BatteryStatsImpl extends BatteryStats { @SuppressWarnings("GuardedBy") // errorprone false positive on getProcStateTimeCounter @VisibleForTesting public void updateProcStateCpuTimesLocked(int uid, long elapsedRealtimeMs, long uptimeMs) { + if (mPowerStatsCollectorEnabled) { + return; + } + ensureKernelSingleUidTimeReaderLocked(); final Uid u = getUidStatsLocked(uid); @@ -653,8 +658,9 @@ public class BatteryStatsImpl extends BatteryStats { */ @SuppressWarnings("GuardedBy") // errorprone false positive on getProcStateTimeCounter public void updateCpuTimesForAllUids() { - if (mCpuPowerStatsCollector != null) { + if (mPowerStatsCollectorEnabled && mCpuPowerStatsCollector != null) { mCpuPowerStatsCollector.schedule(); + return; } synchronized (BatteryStatsImpl.this) { @@ -712,7 +718,7 @@ public class BatteryStatsImpl extends BatteryStats { @GuardedBy("this") private void ensureKernelSingleUidTimeReaderLocked() { - if (mKernelSingleUidTimeReader != null) { + if (mPowerStatsCollectorEnabled || mKernelSingleUidTimeReader != null) { return; } @@ -8213,6 +8219,10 @@ public class BatteryStatsImpl extends BatteryStats { @GuardedBy("mBsi") private void ensureMultiStateCounters(long timestampMs) { + if (mBsi.mPowerStatsCollectorEnabled) { + throw new IllegalStateException("Multi-state counters used in streamlined mode"); + } + if (mProcStateTimeMs == null) { mProcStateTimeMs = new TimeInFreqMultiStateCounter(mBsi.mOnBatteryTimeBase, @@ -10511,7 +10521,7 @@ public class BatteryStatsImpl extends BatteryStats { mProcessStateTimer[uidRunningState].startRunningLocked(elapsedRealtimeMs); } - if (mBsi.trackPerProcStateCpuTimes()) { + if (!mBsi.mPowerStatsCollectorEnabled && mBsi.trackPerProcStateCpuTimes()) { mBsi.updateProcStateCpuTimesLocked(mUid, elapsedRealtimeMs, uptimeMs); LongArrayMultiStateCounter onBatteryCounter = @@ -14211,7 +14221,7 @@ public class BatteryStatsImpl extends BatteryStats { mCpuUidFreqTimeReader.onSystemReady(); } if (mCpuPowerStatsCollector != null) { - mCpuPowerStatsCollector.onSystemReady(); + mCpuPowerStatsCollector.setEnabled(mPowerStatsCollectorEnabled); } mSystemReady = true; } @@ -15232,6 +15242,15 @@ public class BatteryStatsImpl extends BatteryStats { return mCpuUidFreqTimeReader.isFastCpuTimesReader(); } + /** + * Enables or disables the PowerStatsCollector mode. + */ + public void setPowerStatsCollectorEnabled(boolean enabled) { + synchronized (this) { + mPowerStatsCollectorEnabled = enabled; + } + } + @GuardedBy("this") public void systemServicesReady(Context context) { mConstants.startObserving(context.getContentResolver()); diff --git a/services/core/java/com/android/server/power/stats/CpuPowerStatsCollector.java b/services/core/java/com/android/server/power/stats/CpuPowerStatsCollector.java index c05407cb6d17..4442845f83b2 100644 --- a/services/core/java/com/android/server/power/stats/CpuPowerStatsCollector.java +++ b/services/core/java/com/android/server/power/stats/CpuPowerStatsCollector.java @@ -35,7 +35,6 @@ import com.android.internal.os.CpuScalingPolicies; import com.android.internal.os.PowerProfile; import com.android.internal.os.PowerStats; import com.android.server.LocalServices; -import com.android.server.power.optimization.Flags; import java.io.PrintWriter; import java.util.ArrayList; @@ -273,13 +272,6 @@ public class CpuPowerStatsCollector extends PowerStatsCollector { mDefaultCpuPowerBracketsPerEnergyConsumer = defaultCpuPowerBracketsPerEnergyConsumer; } - /** - * Initializes the collector during the boot sequence. - */ - public void onSystemReady() { - setEnabled(Flags.streamlinedBatteryStats()); - } - private boolean ensureInitialized() { if (mIsInitialized) { return true; diff --git a/services/core/java/com/android/server/sensorprivacy/SensorPrivacyService.java b/services/core/java/com/android/server/sensorprivacy/SensorPrivacyService.java index 0656a6a7d3e9..59766ec7a175 100644 --- a/services/core/java/com/android/server/sensorprivacy/SensorPrivacyService.java +++ b/services/core/java/com/android/server/sensorprivacy/SensorPrivacyService.java @@ -35,6 +35,7 @@ import static android.content.Intent.FLAG_ACTIVITY_NO_USER_ACTION; import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.hardware.SensorPrivacyManager.EXTRA_ALL_SENSORS; +import static android.hardware.SensorPrivacyManager.EXTRA_NOTIFICATION_ID; import static android.hardware.SensorPrivacyManager.EXTRA_SENSOR; import static android.hardware.SensorPrivacyManager.EXTRA_TOGGLE_TYPE; import static android.hardware.SensorPrivacyManager.Sensors.CAMERA; @@ -164,6 +165,7 @@ public final class SensorPrivacyService extends SystemService { private final AppOpsManagerInternal mAppOpsManagerInternal; private final TelephonyManager mTelephonyManager; private final PackageManagerInternal mPackageManagerInternal; + private final NotificationManager mNotificationManager; private CameraPrivacyLightController mCameraPrivacyLightController; @@ -188,6 +190,7 @@ public final class SensorPrivacyService extends SystemService { mActivityTaskManager = context.getSystemService(ActivityTaskManager.class); mTelephonyManager = context.getSystemService(TelephonyManager.class); mPackageManagerInternal = getLocalService(PackageManagerInternal.class); + mNotificationManager = mContext.getSystemService(NotificationManager.class); mSensorPrivacyServiceImpl = new SensorPrivacyServiceImpl(); } @@ -288,9 +291,18 @@ public final class SensorPrivacyService extends SystemService { @Override public void onReceive(Context context, Intent intent) { setToggleSensorPrivacy( - ((UserHandle) intent.getParcelableExtra( - Intent.EXTRA_USER, android.os.UserHandle.class)).getIdentifier(), OTHER, - intent.getIntExtra(EXTRA_SENSOR, UNKNOWN), false); + intent.getParcelableExtra(Intent.EXTRA_USER, UserHandle.class) + .getIdentifier(), + OTHER, + intent.getIntExtra(EXTRA_SENSOR, UNKNOWN), + false + ); + + int notificationId = + intent.getIntExtra(EXTRA_NOTIFICATION_ID, SystemMessage.NOTE_UNKNOWN); + if (notificationId != SystemMessage.NOTE_UNKNOWN) { + mNotificationManager.cancel(notificationId); + } } }, new IntentFilter(ACTION_DISABLE_TOGGLE_SENSOR_PRIVACY), MANAGE_SENSOR_PRIVACY, null, Context.RECEIVER_EXPORTED); @@ -635,8 +647,6 @@ public final class SensorPrivacyService extends SystemService { notificationId = SystemMessage.NOTE_UNBLOCK_CAM_TOGGLE; } - NotificationManager notificationManager = - mContext.getSystemService(NotificationManager.class); NotificationChannel channel = new NotificationChannel( SENSOR_PRIVACY_CHANNEL_ID, getUiContext().getString(R.string.sensor_privacy_notification_channel_label), @@ -646,7 +656,7 @@ public final class SensorPrivacyService extends SystemService { channel.enableVibration(false); channel.setBlockable(false); - notificationManager.createNotificationChannel(channel); + mNotificationManager.createNotificationChannel(channel); Icon icon = Icon.createWithResource(getUiContext().getResources(), iconRes); @@ -669,10 +679,11 @@ public final class SensorPrivacyService extends SystemService { new Intent(ACTION_DISABLE_TOGGLE_SENSOR_PRIVACY) .setPackage(mContext.getPackageName()) .putExtra(EXTRA_SENSOR, sensor) + .putExtra(EXTRA_NOTIFICATION_ID, notificationId) .putExtra(Intent.EXTRA_USER, user), PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT); - notificationManager.notify(notificationId, + mNotificationManager.notify(notificationId, new Notification.Builder(mContext, SENSOR_PRIVACY_CHANNEL_ID) .setContentTitle(contentTitle) .setContentText(contentText) diff --git a/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java b/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java index e6273d331fce..0467d0cd351d 100644 --- a/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java +++ b/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java @@ -38,6 +38,7 @@ import android.media.tv.BroadcastInfoRequest; import android.media.tv.BroadcastInfoResponse; import android.media.tv.TvRecordingInfo; import android.media.tv.TvTrackInfo; +import android.media.tv.ad.ITvAdManager; import android.media.tv.interactive.AppLinkInfo; import android.media.tv.interactive.ITvInteractiveAppClient; import android.media.tv.interactive.ITvInteractiveAppManager; @@ -345,6 +346,7 @@ public class TvInteractiveAppManagerService extends SystemService { Slogf.d(TAG, "onStart"); } publishBinderService(Context.TV_INTERACTIVE_APP_SERVICE, new BinderService()); + publishBinderService(Context.TV_AD_SERVICE, new TvAdBinderService()); } @Override @@ -688,6 +690,12 @@ public class TvInteractiveAppManagerService extends SystemService { } return session; } + private final class TvAdBinderService extends ITvAdManager.Stub { + @Override + public void startAdService(IBinder sessionToken, int userId) { + } + + } private final class BinderService extends ITvInteractiveAppManager.Stub { diff --git a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java index 6e7cf12e0e5b..4625b4fe07ef 100644 --- a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java +++ b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java @@ -60,7 +60,6 @@ import android.widget.Toast; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.FrameworkStatsLog; -import com.android.internal.util.Preconditions; import com.android.server.UiThread; import com.android.server.am.PendingIntentRecord; import com.android.window.flags.Flags; @@ -237,6 +236,7 @@ public class BackgroundActivityStartController { private final @ActivityManager.ProcessState int mCallingUidProcState; private final boolean mIsCallingUidPersistentSystemProcess; private final BackgroundStartPrivileges mBalAllowedByPiSender; + private final BackgroundStartPrivileges mBalAllowedByPiCreatorWithHardening; private final BackgroundStartPrivileges mBalAllowedByPiCreator; private final String mRealCallingPackage; private final int mRealCallingUid; @@ -269,7 +269,7 @@ public class BackgroundActivityStartController { mRealCallingPackage = mService.getPackageNameIfUnique(realCallingUid, realCallingPid); if (originatingPendingIntent == null) { // grant BAL privileges unless explicitly opted out - mBalAllowedByPiCreator = + mBalAllowedByPiCreatorWithHardening = mBalAllowedByPiCreator = checkedOptions.getPendingIntentCreatorBackgroundActivityStartMode() == ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_DENIED ? BackgroundStartPrivileges.NONE @@ -281,8 +281,16 @@ public class BackgroundActivityStartController { : BackgroundStartPrivileges.ALLOW_BAL; } else { // for PendingIntents we restrict BAL based on target_sdk - mBalAllowedByPiCreator = getBackgroundStartPrivilegesAllowedByCreator( + mBalAllowedByPiCreatorWithHardening = getBackgroundStartPrivilegesAllowedByCreator( callingUid, callingPackage, checkedOptions); + final BackgroundStartPrivileges mBalAllowedByPiCreatorWithoutHardening = + checkedOptions.getPendingIntentCreatorBackgroundActivityStartMode() + == ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_DENIED + ? BackgroundStartPrivileges.NONE + : BackgroundStartPrivileges.ALLOW_BAL; + mBalAllowedByPiCreator = balRequireOptInByPendingIntentCreator() + ? mBalAllowedByPiCreatorWithHardening + : mBalAllowedByPiCreatorWithoutHardening; mBalAllowedByPiSender = PendingIntentRecord.getBackgroundStartPrivilegesAllowedByCaller( checkedOptions, realCallingUid, mRealCallingPackage); @@ -325,10 +333,6 @@ public class BackgroundActivityStartController { return BackgroundStartPrivileges.NONE; case ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED: // no explicit choice by the app - let us decide what to do - if (!balRequireOptInByPendingIntentCreator()) { - // if feature is disabled allow - return BackgroundStartPrivileges.ALLOW_BAL; - } if (callingPackage != null) { // determine based on the calling/creating package boolean changeEnabled = CompatChanges.isChangeEnabled( @@ -373,11 +377,6 @@ public class BackgroundActivityStartController { return mOriginatingPendingIntent != null && hasRealCaller(); } - private String dump(BalVerdict resultIfPiCreatorAllowsBal) { - Preconditions.checkState(!isPendingIntent()); - return dump(resultIfPiCreatorAllowsBal, null); - } - private boolean callerIsRealCaller() { return mCallingUid == mRealCallingUid; } @@ -402,6 +401,8 @@ public class BackgroundActivityStartController { sb.append("; inVisibleTask: ").append(mCallerApp.hasActivityInVisibleTask()); } sb.append("; balAllowedByPiCreator: ").append(mBalAllowedByPiCreator); + sb.append("; balAllowedByPiCreatorWithHardening: ") + .append(mBalAllowedByPiCreatorWithHardening); sb.append("; resultIfPiCreatorAllowsBal: ").append(resultIfPiCreatorAllowsBal); sb.append("; hasRealCaller: ").append(hasRealCaller()); sb.append("; isPendingIntent: ").append(isPendingIntent()); diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java index e6bbd52807bd..c089d107d07d 100644 --- a/services/core/java/com/android/server/wm/InsetsPolicy.java +++ b/services/core/java/com/android/server/wm/InsetsPolicy.java @@ -740,6 +740,8 @@ class InsetsPolicy { private final Handler mHandler; private final String mName; + private boolean mInsetsAnimationRunning; + Host(Handler handler, String name) { mHandler = handler; mName = name; @@ -841,5 +843,10 @@ class InsetsPolicy { public IBinder getWindowToken() { return null; } + + @Override + public void notifyAnimationRunningStateChanged(boolean running) { + mInsetsAnimationRunning = running; + } } } diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index de802b9b0e4d..5f082124dbcb 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -422,6 +422,11 @@ class Task extends TaskFragment { // TODO: remove this once the recents animation is moved to the Shell SurfaceControl mLastRecentsAnimationOverlay; + // A surface that is used by TaskFragmentOrganizer to place content on top of own activities and + // trusted TaskFragments. + @Nullable + DecorSurfaceContainer mDecorSurfaceContainer; + static final int LAYER_RANK_INVISIBLE = -1; // Ranking (from top) of this task among all visible tasks. (-1 means it's not visible) // This number will be assigned when we evaluate OOM scores for all visible tasks. @@ -1540,6 +1545,11 @@ class Task extends TaskFragment { mAtmService.getTaskChangeNotificationController().notifyTaskStackChanged(); } + if (mDecorSurfaceContainer != null && r == mDecorSurfaceContainer.mOwnerTaskFragment) { + // Remove the decor surface if the owner TaskFragment is removed; + removeDecorSurface(); + } + if (hasChild()) { updateEffectiveIntent(); @@ -2638,6 +2648,9 @@ class Task extends TaskFragment { } // If applicable let the TaskOrganizer know the Task is vanishing. setTaskOrganizer(null); + if (mDecorSurfaceContainer != null) { + mDecorSurfaceContainer.release(); + } super.removeImmediately(); mRemoving = false; @@ -3644,7 +3657,8 @@ class Task extends TaskFragment { */ TaskFragmentParentInfo getTaskFragmentParentInfo() { return new TaskFragmentParentInfo(getConfiguration(), getDisplayId(), - shouldBeVisible(null /* starting */), hasNonFinishingDirectActivity()); + shouldBeVisible(null /* starting */), hasNonFinishingDirectActivity(), + getDecorSurface()); } @Override @@ -3666,6 +3680,62 @@ class Task extends TaskFragment { } } + @Override + void assignChildLayers(@NonNull SurfaceControl.Transaction t) { + int layer = 0; + boolean decorSurfacePlaced = false; + + // We use two passes as a way to promote children which + // need Z-boosting to the end of the list. + for (int j = 0; j < mChildren.size(); ++j) { + final WindowContainer wc = mChildren.get(j); + wc.assignChildLayers(t); + if (!wc.needsZBoost()) { + // Place the decor surface under any untrusted content. + if (mDecorSurfaceContainer != null && !decorSurfacePlaced + && shouldPlaceDecorSurfaceBelowContainer(wc)) { + mDecorSurfaceContainer.assignLayer(t, layer++); + decorSurfacePlaced = true; + } + wc.assignLayer(t, layer++); + + // Place the decor surface just above the owner TaskFragment. + if (mDecorSurfaceContainer != null && !decorSurfacePlaced + && wc == mDecorSurfaceContainer.mOwnerTaskFragment) { + mDecorSurfaceContainer.assignLayer(t, layer++); + decorSurfacePlaced = true; + } + } + } + + // If not placed yet, the decor surface should be on top of all non-boosted children. + if (mDecorSurfaceContainer != null && !decorSurfacePlaced) { + mDecorSurfaceContainer.assignLayer(t, layer++); + decorSurfacePlaced = true; + } + + for (int j = 0; j < mChildren.size(); ++j) { + final WindowContainer wc = mChildren.get(j); + if (wc.needsZBoost()) { + wc.assignLayer(t, layer++); + } + } + if (mOverlayHost != null) { + mOverlayHost.setLayer(t, layer++); + } + } + + boolean shouldPlaceDecorSurfaceBelowContainer(@NonNull WindowContainer wc) { + boolean isOwnActivity = + wc.asActivityRecord() != null + && wc.asActivityRecord().isUid(effectiveUid); + boolean isTrustedTaskFragment = + wc.asTaskFragment() != null + && wc.asTaskFragment().isEmbedded() + && wc.asTaskFragment().isAllowedToBeEmbeddedInTrustedMode(); + return !isOwnActivity && !isTrustedTaskFragment; + } + boolean isTaskId(int taskId) { return mTaskId == taskId; } @@ -6673,4 +6743,77 @@ class Task extends TaskFragment { mOverlayHost.dispatchInsetsChanged(s, mTmpRect); } } + + /** + * Associates the decor surface with the given TF, or create one if there + * isn't one in the Task yet. The surface will be removed with the TF, + * and become invisible if the TF is invisible. */ + void moveOrCreateDecorSurfaceFor(TaskFragment taskFragment) { + if (mDecorSurfaceContainer != null) { + mDecorSurfaceContainer.mOwnerTaskFragment = taskFragment; + } else { + mDecorSurfaceContainer = new DecorSurfaceContainer(taskFragment); + assignChildLayers(); + sendTaskFragmentParentInfoChangedIfNeeded(); + } + } + + void removeDecorSurface() { + if (mDecorSurfaceContainer == null) { + return; + } + mDecorSurfaceContainer.release(); + mDecorSurfaceContainer = null; + sendTaskFragmentParentInfoChangedIfNeeded(); + } + + @Nullable SurfaceControl getDecorSurface() { + return mDecorSurfaceContainer != null ? mDecorSurfaceContainer.mDecorSurface : null; + } + + /** + * A decor surface that is requested by a {@code TaskFragmentOrganizer} which will be placed + * below children windows except for own Activities and TaskFragment in fully trusted mode. + */ + @VisibleForTesting + class DecorSurfaceContainer { + @VisibleForTesting + @NonNull final SurfaceControl mContainerSurface; + + @VisibleForTesting + @NonNull final SurfaceControl mDecorSurface; + + // The TaskFragment that requested the decor surface. If it is destroyed, the decor surface + // is also released. + @VisibleForTesting + @NonNull TaskFragment mOwnerTaskFragment; + + private DecorSurfaceContainer(@NonNull TaskFragment initialOwner) { + mOwnerTaskFragment = initialOwner; + mContainerSurface = makeSurface().setContainerLayer() + .setParent(mSurfaceControl) + .setName(mSurfaceControl + " - decor surface container") + .setEffectLayer() + .setHidden(false) + .setCallsite("Task.DecorSurfaceContainer") + .build(); + + mDecorSurface = makeSurface() + .setParent(mContainerSurface) + .setName(mSurfaceControl + " - decor surface") + .setHidden(false) + .setCallsite("Task.DecorSurfaceContainer") + .build(); + } + + private void assignLayer(@NonNull SurfaceControl.Transaction t, int layer) { + t.setLayer(mContainerSurface, layer); + t.setVisibility(mContainerSurface, mOwnerTaskFragment.isVisible()); + } + + private void release() { + mDecorSurface.release(); + mContainerSurface.release(); + } + } } diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java index 8bc461f05387..39b4480a7da0 100644 --- a/services/core/java/com/android/server/wm/TaskFragment.java +++ b/services/core/java/com/android/server/wm/TaskFragment.java @@ -316,7 +316,8 @@ class TaskFragment extends WindowContainer<WindowContainer> { /** Organizer that organizing this TaskFragment. */ @Nullable private ITaskFragmentOrganizer mTaskFragmentOrganizer; - private int mTaskFragmentOrganizerUid = INVALID_UID; + @VisibleForTesting + int mTaskFragmentOrganizerUid = INVALID_UID; private @Nullable String mTaskFragmentOrganizerProcessName; /** Client assigned unique token for this TaskFragment if this is created by an organizer. */ diff --git a/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java b/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java index e7a1cf106a44..707f9fc9ea5f 100644 --- a/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java +++ b/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java @@ -762,6 +762,8 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr .setTask(task) .build()); } + // Make sure the parent info changed event will be dispatched if there are no other changes. + mAtmService.mWindowManager.mWindowPlacerLocked.requestTraversal(); } boolean isSystemOrganizer(@NonNull IBinder organizerToken) { diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java index 3a711b2c7046..27cc2d6b4aac 100644 --- a/services/core/java/com/android/server/wm/TaskOrganizerController.java +++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java @@ -1182,22 +1182,6 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub { } } - @Override - public void setOrientationRequestPolicy(boolean isIgnoreOrientationRequestDisabled, - @Nullable int[] fromOrientations, @Nullable int[] toOrientations) { - enforceTaskPermission("setOrientationRequestPolicy()"); - final long origId = Binder.clearCallingIdentity(); - try { - synchronized (mGlobalLock) { - mService.mWindowManager - .setOrientationRequestPolicy(isIgnoreOrientationRequestDisabled, - fromOrientations, toOrientations); - } - } finally { - Binder.restoreCallingIdentity(origId); - } - } - public boolean handleInterceptBackPressedOnTaskRoot(Task task) { if (!shouldInterceptBackPressedOnRootTask(task)) { return false; diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java index ae171a0d8030..808a11d4adae 100644 --- a/services/core/java/com/android/server/wm/WindowManagerInternal.java +++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java @@ -993,4 +993,18 @@ public abstract class WindowManagerInternal { * @param displayId the id of display to check if there is a software navigation bar. */ public abstract boolean hasNavigationBar(int displayId); + + /** + * Controls whether the app-requested screen orientation is always respected. + * + * @param respected If {@code true}, the app requested orientation is always respected. + * Otherwise, the system might ignore the request due to + * {@link com.android.server.wm.DisplayArea#getIgnoreOrientationRequest}. + * @param fromOrientations The orientations we want to map to the correspondent orientations + * in toOrientation. + * @param toOrientations The orientations we map to the ones in fromOrientations at the same + * index + */ + public abstract void setOrientationRequestPolicy(boolean respected, + int[] fromOrientations, int[] toOrientations); } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index dd2b48bb5a3d..0d2c94d103fb 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -8523,6 +8523,15 @@ public class WindowManagerService extends IWindowManager.Stub mImeTargetChangeListener = listener; } } + + @Override + public void setOrientationRequestPolicy(boolean respected, + int[] fromOrientations, int[] toOrientations) { + synchronized (mGlobalLock) { + WindowManagerService.this.setOrientationRequestPolicy(respected, + fromOrientations, toOrientations); + } + } } private final class ImeTargetVisibilityPolicyImpl extends ImeTargetVisibilityPolicy { diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java index 208df6c768bf..2af656942a2a 100644 --- a/services/core/java/com/android/server/wm/WindowOrganizerController.java +++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java @@ -23,7 +23,9 @@ import static android.app.WindowConfiguration.WINDOW_CONFIG_BOUNDS; import static android.view.Display.DEFAULT_DISPLAY; import static android.window.TaskFragmentOperation.OP_TYPE_CLEAR_ADJACENT_TASK_FRAGMENTS; import static android.window.TaskFragmentOperation.OP_TYPE_CREATE_TASK_FRAGMENT; +import static android.window.TaskFragmentOperation.OP_TYPE_CREATE_TASK_FRAGMENT_DECOR_SURFACE; import static android.window.TaskFragmentOperation.OP_TYPE_DELETE_TASK_FRAGMENT; +import static android.window.TaskFragmentOperation.OP_TYPE_REMOVE_TASK_FRAGMENT_DECOR_SURFACE; import static android.window.TaskFragmentOperation.OP_TYPE_REORDER_TO_BOTTOM_OF_TASK; import static android.window.TaskFragmentOperation.OP_TYPE_REORDER_TO_FRONT; import static android.window.TaskFragmentOperation.OP_TYPE_REORDER_TO_TOP_OF_TASK; @@ -1468,6 +1470,16 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub } break; } + case OP_TYPE_CREATE_TASK_FRAGMENT_DECOR_SURFACE: { + final Task task = taskFragment.getTask(); + task.moveOrCreateDecorSurfaceFor(taskFragment); + break; + } + case OP_TYPE_REMOVE_TASK_FRAGMENT_DECOR_SURFACE: { + final Task task = taskFragment.getTask(); + task.removeDecorSurface(); + break; + } } return effects; } @@ -1507,6 +1519,19 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub return false; } + // TODO (b/293654166) remove the decor surface checks once we clear security reviews + if ((opType == OP_TYPE_CREATE_TASK_FRAGMENT_DECOR_SURFACE + || opType == OP_TYPE_REMOVE_TASK_FRAGMENT_DECOR_SURFACE) + && !mTaskFragmentOrganizerController.isSystemOrganizer(organizer.asBinder())) { + final Throwable exception = new SecurityException( + "Only a system organizer can perform OP_TYPE_CREATE_TASK_FRAGMENT_DECOR_SURFACE" + + " or OP_TYPE_REMOVE_TASK_FRAGMENT_DECOR_SURFACE." + ); + sendTaskFragmentOperationFailure(organizer, errorCallbackToken, taskFragment, + opType, exception); + return false; + } + final IBinder secondaryFragmentToken = operation.getSecondaryFragmentToken(); return secondaryFragmentToken == null || validateTaskFragment(mLaunchTaskFragments.get(secondaryFragmentToken), opType, diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 0a2e80606e96..1919eb33c38c 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -2112,6 +2112,15 @@ public final class SystemServer implements Dumpable { networkPolicy.bindConnectivityManager(); t.traceEnd(); + t.traceBegin("StartSecurityStateManagerService"); + try { + ServiceManager.addService(Context.SECURITY_STATE_SERVICE, + new SecurityStateManagerService(context)); + } catch (Throwable e) { + reportWtf("starting SecurityStateManagerService", e); + } + t.traceEnd(); + t.traceBegin("StartVpnManagerService"); try { vpnManager = VpnManagerService.create(context); diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessClamperControllerTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessClamperControllerTest.java index 9aa6136348b4..6ba7368f8f26 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessClamperControllerTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessClamperControllerTest.java @@ -262,8 +262,7 @@ public class BrightnessClamperControllerTest { Handler handler, BrightnessClamperController.ClamperChangeListener clamperChangeListener, BrightnessClamperController.DisplayDeviceData data, - DisplayManagerFlags flags, - Context context) { + DisplayManagerFlags flags, Context context) { mCapturedChangeListener = clamperChangeListener; return mClampers; } diff --git a/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java index 1a3a6a388392..cbc8538cf9fb 100644 --- a/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java @@ -2170,9 +2170,8 @@ public class DeviceIdleControllerTest { public void testStationaryDetection_QuickDozeOff() { setQuickDozeEnabled(false); enterDeepState(STATE_IDLE); - // Regular progression through states, so time should have increased appropriately. - mInjector.nowElapsed += mConstants.IDLE_AFTER_INACTIVE_TIMEOUT + mConstants.SENSING_TIMEOUT - + mConstants.LOCATING_TIMEOUT; + // Indicate that enough time has passed for the device to be considered stationary. + mInjector.nowElapsed += mConstants.MOTION_INACTIVE_TIMEOUT; StationaryListenerForTest stationaryListener = new StationaryListenerForTest(); diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsProviderTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsProviderTest.java index 7148b164efa9..2e0ba0083850 100644 --- a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsProviderTest.java +++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsProviderTest.java @@ -82,6 +82,15 @@ public class BatteryUsageStatsProviderTest { .isEqualTo(20 * MINUTE_IN_MS); assertThat(uidBatteryConsumer.getTimeInStateMs(UidBatteryConsumer.STATE_BACKGROUND)) .isEqualTo(40 * MINUTE_IN_MS); + assertThat(uidBatteryConsumer + .getTimeInProcessStateMs(UidBatteryConsumer.PROCESS_STATE_FOREGROUND)) + .isEqualTo(20 * MINUTE_IN_MS); + assertThat(uidBatteryConsumer + .getTimeInProcessStateMs(UidBatteryConsumer.PROCESS_STATE_BACKGROUND)) + .isEqualTo(20 * MINUTE_IN_MS); + assertThat(uidBatteryConsumer + .getTimeInProcessStateMs(UidBatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE)) + .isEqualTo(20 * MINUTE_IN_MS); assertThat(uidBatteryConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_AUDIO)) .isWithin(PRECISION).of(2.0); assertThat( diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsTest.java index 07c486c6ce58..079ea2c7832f 100644 --- a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsTest.java +++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsTest.java @@ -193,14 +193,14 @@ public class BatteryUsageStatsTest { for (UidBatteryConsumer uidBatteryConsumer : uidBatteryConsumers) { if (uidBatteryConsumer.getUid() == APP_UID1) { assertUidBatteryConsumer(uidBatteryConsumer, 2124, null, - 5321, 7432, 423, BatteryConsumer.POWER_MODEL_POWER_PROFILE, 745, + 5321, 6900, 532, 423, BatteryConsumer.POWER_MODEL_POWER_PROFILE, 745, POWER_MODEL_UNDEFINED, 956, 1167, 1478, true, 3554, 3776, 3998, 444, 3554, 15542, 3776, 17762, 3998, 19982, 444, 1110); } else if (uidBatteryConsumer.getUid() == APP_UID2) { assertUidBatteryConsumer(uidBatteryConsumer, 1332, "bar", - 1111, 2222, 333, BatteryConsumer.POWER_MODEL_POWER_PROFILE, 444, + 1111, 2220, 2, 333, BatteryConsumer.POWER_MODEL_POWER_PROFILE, 444, BatteryConsumer.POWER_MODEL_POWER_PROFILE, 555, 666, 777, true, 1777, 1888, 1999, 321, 1777, 7771, 1888, 8881, 1999, 9991, @@ -269,7 +269,7 @@ public class BatteryUsageStatsTest { .setStatsEndTimestamp(3000); addUidBatteryConsumer(builder, batteryStats, APP_UID1, "foo", - 1000, 2000, + 1000, 1500, 500, 300, BatteryConsumer.POWER_MODEL_POWER_PROFILE, 400, BatteryConsumer.POWER_MODEL_POWER_PROFILE, 500, 600, 800, 1777, 7771, 1888, 8881, 1999, 9991, 123, 456); @@ -312,13 +312,13 @@ public class BatteryUsageStatsTest { .setStatsEndTimestamp(5000); addUidBatteryConsumer(builder, batteryStats, APP_UID1, null, - 4321, 5432, + 4321, 5400, 32, 123, BatteryConsumer.POWER_MODEL_POWER_PROFILE, 345, POWER_MODEL_ENERGY_CONSUMPTION, 456, 567, 678, 1777, 7771, 1888, 8881, 1999, 9991, 321, 654); addUidBatteryConsumer(builder, batteryStats, APP_UID2, "bar", - 1111, 2222, + 1111, 2220, 2, 333, BatteryConsumer.POWER_MODEL_POWER_PROFILE, 444, BatteryConsumer.POWER_MODEL_POWER_PROFILE, 555, 666, 777, 1777, 7771, 1888, 8881, 1999, 9991, 321, 654); @@ -338,7 +338,8 @@ public class BatteryUsageStatsTest { private void addUidBatteryConsumer(BatteryUsageStats.Builder builder, MockBatteryStatsImpl batteryStats, int uid, String packageWithHighestDrain, - int timeInStateForeground, int timeInStateBackground, double screenPower, + int timeInProcessStateForeground, int timeInProcessStateBackground, + int timeInProcessStateForegroundService, double screenPower, int screenPowerModel, double cpuPower, int cpuPowerModel, double customComponentPower, int cpuDuration, int customComponentDuration, double cpuPowerForeground, int cpuDurationForeground, double cpuPowerBackground, int cpuDurationBackground, @@ -348,8 +349,10 @@ public class BatteryUsageStatsTest { builder.getOrCreateUidBatteryConsumerBuilder(batteryStatsUid); uidBuilder .setPackageWithHighestDrain(packageWithHighestDrain) - .setTimeInStateMs(UidBatteryConsumer.STATE_FOREGROUND, timeInStateForeground) - .setTimeInStateMs(UidBatteryConsumer.STATE_BACKGROUND, timeInStateBackground) + .setTimeInProcessStateMs(PROCESS_STATE_FOREGROUND, timeInProcessStateForeground) + .setTimeInProcessStateMs(PROCESS_STATE_BACKGROUND, timeInProcessStateBackground) + .setTimeInProcessStateMs(PROCESS_STATE_FOREGROUND_SERVICE, + timeInProcessStateForegroundService) .setConsumedPower( BatteryConsumer.POWER_COMPONENT_SCREEN, screenPower, screenPowerModel) .setConsumedPower( @@ -446,7 +449,7 @@ public class BatteryUsageStatsTest { for (UidBatteryConsumer uidBatteryConsumer : uidBatteryConsumers) { if (uidBatteryConsumer.getUid() == APP_UID1) { assertUidBatteryConsumer(uidBatteryConsumer, 1200, "foo", - 1000, 2000, 300, BatteryConsumer.POWER_MODEL_POWER_PROFILE, 400, + 1000, 1500, 500, 300, BatteryConsumer.POWER_MODEL_POWER_PROFILE, 400, BatteryConsumer.POWER_MODEL_POWER_PROFILE, 500, 600, 800, true, 1777, 1888, 1999, 123, 1777, 7771, 1888, 8881, 1999, 9991, 123, 456); @@ -496,8 +499,9 @@ public class BatteryUsageStatsTest { } private void assertUidBatteryConsumer(UidBatteryConsumer uidBatteryConsumer, - double consumedPower, String packageWithHighestDrain, int timeInStateForeground, - int timeInStateBackground, int screenPower, int screenPowerModel, double cpuPower, + double consumedPower, String packageWithHighestDrain, int timeInProcessStateForeground, + int timeInProcessStateBackground, int timeInProcessStateForegroundService, + int screenPower, int screenPowerModel, double cpuPower, int cpuPowerModel, double customComponentPower, int cpuDuration, int customComponentDuration, boolean processStateDataIncluded, double totalPowerForeground, double totalPowerBackground, double totalPowerFgs, @@ -509,9 +513,16 @@ public class BatteryUsageStatsTest { assertThat(uidBatteryConsumer.getPackageWithHighestDrain()).isEqualTo( packageWithHighestDrain); assertThat(uidBatteryConsumer.getTimeInStateMs( - UidBatteryConsumer.STATE_FOREGROUND)).isEqualTo(timeInStateForeground); + UidBatteryConsumer.STATE_FOREGROUND)).isEqualTo(timeInProcessStateForeground); assertThat(uidBatteryConsumer.getTimeInStateMs( - UidBatteryConsumer.STATE_BACKGROUND)).isEqualTo(timeInStateBackground); + UidBatteryConsumer.STATE_BACKGROUND)).isEqualTo( + timeInProcessStateBackground + timeInProcessStateForegroundService); + assertThat(uidBatteryConsumer.getTimeInProcessStateMs( + PROCESS_STATE_FOREGROUND)).isEqualTo(timeInProcessStateForeground); + assertThat(uidBatteryConsumer.getTimeInProcessStateMs( + PROCESS_STATE_BACKGROUND)).isEqualTo(timeInProcessStateBackground); + assertThat(uidBatteryConsumer.getTimeInProcessStateMs( + PROCESS_STATE_FOREGROUND_SERVICE)).isEqualTo(timeInProcessStateForegroundService); assertThat(uidBatteryConsumer.getConsumedPower( BatteryConsumer.POWER_COMPONENT_SCREEN)).isEqualTo(screenPower); assertThat(uidBatteryConsumer.getPowerModel( diff --git a/services/tests/servicestests/src/com/android/server/SecurityStateTest.java b/services/tests/servicestests/src/com/android/server/SecurityStateTest.java new file mode 100644 index 000000000000..fc91e47534f1 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/SecurityStateTest.java @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server; + +import static android.os.SecurityStateManager.KEY_KERNEL_VERSION; +import static android.os.SecurityStateManager.KEY_SYSTEM_SPL; +import static android.os.SecurityStateManager.KEY_VENDOR_SPL; + +import static com.android.server.SecurityStateManagerService.KERNEL_RELEASE_PATTERN; +import static com.android.server.SecurityStateManagerService.VENDOR_SECURITY_PATCH_PROPERTY_KEY; + +import static junit.framework.Assert.assertEquals; + +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.res.Resources; +import android.os.Build; +import android.os.Bundle; +import android.os.SystemProperties; +import android.os.VintfRuntimeInfo; + +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import com.android.internal.R; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +import java.util.regex.Matcher; + +@RunWith(AndroidJUnit4.class) +@SmallTest +public class SecurityStateTest { + @Rule + public MockitoRule mockitoRule = MockitoJUnit.rule(); + + @Mock + private Context mMockContext; + + @Mock + private PackageManager mMockPackageManager; + + @Mock + private Resources mMockResources; + + private static final String DEFAULT_MODULE_METADATA_PROVIDER = "com.android.modulemetadata"; + private static final String DEFAULT_MODULE_METADATA_PROVIDER_VERSION = "2023-12-01"; + private static final String DEFAULT_SECURITY_STATE_PACKAGE = "com.google.android.gms"; + private static final String DEFAULT_SECURITY_STATE_PACKAGE_VERSION = "2023-12-05"; + private static final String[] SECURITY_STATE_PACKAGES = + new String[]{DEFAULT_SECURITY_STATE_PACKAGE}; + + @Before + public void setUp() throws Exception { + when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager); + when(mMockContext.getResources()).thenReturn(mMockResources); + when(mMockContext.getString(R.string.config_defaultModuleMetadataProvider)) + .thenReturn(DEFAULT_MODULE_METADATA_PROVIDER); + when(mMockPackageManager.getPackageInfo(anyString(), anyInt())) + .thenReturn(new PackageInfo()); + PackageInfo moduleMetadataPackageInfo = new PackageInfo(); + moduleMetadataPackageInfo.versionName = DEFAULT_MODULE_METADATA_PROVIDER_VERSION; + when(mMockPackageManager.getPackageInfo(DEFAULT_MODULE_METADATA_PROVIDER, 0)) + .thenReturn(moduleMetadataPackageInfo); + PackageInfo securityStatePackageInfo = new PackageInfo(); + securityStatePackageInfo.versionName = DEFAULT_SECURITY_STATE_PACKAGE_VERSION; + when(mMockPackageManager.getPackageInfo(DEFAULT_SECURITY_STATE_PACKAGE, 0)) + .thenReturn(securityStatePackageInfo); + when(mMockResources.getStringArray(R.array.config_securityStatePackages)) + .thenReturn(SECURITY_STATE_PACKAGES); + } + + @Test + public void testGetGlobalSecurityState_returnsBundle() { + SecurityStateManagerService securityState = new SecurityStateManagerService(mMockContext); + + Bundle bundle = securityState.getGlobalSecurityState(); + + assertEquals(bundle.getString(KEY_SYSTEM_SPL), Build.VERSION.SECURITY_PATCH); + assertEquals(bundle.getString(KEY_VENDOR_SPL), + SystemProperties.get(VENDOR_SECURITY_PATCH_PROPERTY_KEY, "")); + Matcher matcher = KERNEL_RELEASE_PATTERN.matcher(VintfRuntimeInfo.getKernelVersion()); + String kernelVersion = ""; + if (matcher.matches()) { + kernelVersion = matcher.group(1); + } + assertEquals(bundle.getString(KEY_KERNEL_VERSION), kernelVersion); + assertEquals(bundle.getString(DEFAULT_MODULE_METADATA_PROVIDER), + DEFAULT_MODULE_METADATA_PROVIDER_VERSION); + assertEquals(bundle.getString(DEFAULT_SECURITY_STATE_PACKAGE), + DEFAULT_SECURITY_STATE_PACKAGE_VERSION); + } +} diff --git a/services/tests/servicestests/src/com/android/server/WatchdogTest.java b/services/tests/servicestests/src/com/android/server/WatchdogTest.java new file mode 100644 index 000000000000..34ac47e1fe96 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/WatchdogTest.java @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; + +import android.os.Handler; +import android.os.SimpleClock; + +import androidx.test.runner.AndroidJUnit4; + +import com.android.server.Watchdog.HandlerChecker; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.time.ZoneOffset; + +/** Test class for {@link Watchdog}. */ +@RunWith(AndroidJUnit4.class) +public class WatchdogTest { + private static final int TIMEOUT_MS = 10; + + private TestClock mClock; + private Handler mHandler; + private HandlerChecker mChecker; + + @Before + public void setUp() { + mClock = new TestClock(); + mHandler = mock(Handler.class); + mChecker = + new HandlerChecker(mHandler, "monitor thread", new Object(), mClock) { + @Override + public boolean isHandlerPolling() { + return false; + } + }; + } + + @Test + public void checkerPausedUntilResume() { + Watchdog.Monitor monitor = mock(Watchdog.Monitor.class); + mChecker.addMonitorLocked(monitor); + + mChecker.pauseLocked("pausing"); + mChecker.scheduleCheckLocked(TIMEOUT_MS); + verifyNoMoreInteractions(mHandler); + assertEquals(Watchdog.COMPLETED, mChecker.getCompletionStateLocked()); + + mChecker.resumeLocked("resuming"); + mChecker.scheduleCheckLocked(10); + assertEquals(Watchdog.WAITING, mChecker.getCompletionStateLocked()); + } + + @Test + public void checkerPausedUntilDeadline() { + Watchdog.Monitor monitor = mock(Watchdog.Monitor.class); + mChecker.addMonitorLocked(monitor); + + mChecker.pauseForLocked(10, "pausing"); + mChecker.scheduleCheckLocked(TIMEOUT_MS); + verifyNoMoreInteractions(mHandler); + assertEquals(Watchdog.COMPLETED, mChecker.getCompletionStateLocked()); + + mClock.advanceBy(5); + verifyNoMoreInteractions(mHandler); + assertEquals(Watchdog.COMPLETED, mChecker.getCompletionStateLocked()); + + // Above the 10s timeout. Watchdog should not be paused anymore. + mClock.advanceBy(6); + mChecker.scheduleCheckLocked(TIMEOUT_MS); + assertEquals(Watchdog.WAITING, mChecker.getCompletionStateLocked()); + } + + @Test + public void checkerPausedDuringScheduledRun() { + Watchdog.Monitor monitor = mock(Watchdog.Monitor.class); + mChecker.addMonitorLocked(monitor); + + mChecker.scheduleCheckLocked(TIMEOUT_MS); + mClock.advanceBy(5); + mChecker.pauseForLocked(10, "pausing"); + verifyNoMoreInteractions(mHandler); + assertEquals(Watchdog.COMPLETED, mChecker.getCompletionStateLocked()); + + // Above the 10s timeout. Watchdog should not be paused anymore. + mClock.advanceBy(11); + mChecker.scheduleCheckLocked(TIMEOUT_MS); + assertEquals(Watchdog.WAITING, mChecker.getCompletionStateLocked()); + } + + @Test + public void blockedThread() { + mChecker.scheduleCheckLocked(TIMEOUT_MS); + assertEquals(mChecker.getCompletionStateLocked(), Watchdog.WAITING); + + mClock.advanceBy(6); + assertEquals(Watchdog.WAITED_UNTIL_PRE_WATCHDOG, mChecker.getCompletionStateLocked()); + + // Above the 10s timeout. + mClock.advanceBy(6); + assertEquals(Watchdog.OVERDUE, mChecker.getCompletionStateLocked()); + } + + @Test + public void checkNothingBlocked() { + Watchdog.Monitor monitor = mock(Watchdog.Monitor.class); + mChecker.addMonitorLocked(monitor); + + mChecker.scheduleCheckLocked(TIMEOUT_MS); + // scheduleCheckLocked calls #postAtFrontOfQueue which will call mChecker.run(). + mChecker.run(); + assertEquals(Watchdog.COMPLETED, mChecker.getCompletionStateLocked()); + verify(monitor).monitor(); + } + + private static class TestClock extends SimpleClock { + long mNowMillis = 1; + + TestClock() { + super(ZoneOffset.UTC); + } + + @Override + public long millis() { + return mNowMillis; + } + + public void advanceBy(long millis) { + mNowMillis += millis; + } + } +} diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java index 82efdd3ce40a..800350a7d326 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java @@ -85,9 +85,9 @@ import com.android.internal.compat.IPlatformCompat; import com.android.server.LocalServices; import com.android.server.accessibility.AccessibilityManagerService.AccessibilityDisplayListener; import com.android.server.accessibility.magnification.FullScreenMagnificationController; +import com.android.server.accessibility.magnification.MagnificationConnectionManager; import com.android.server.accessibility.magnification.MagnificationController; import com.android.server.accessibility.magnification.MagnificationProcessor; -import com.android.server.accessibility.magnification.WindowMagnificationManager; import com.android.server.accessibility.test.MessageCapturingHandler; import com.android.server.pm.UserManagerInternal; import com.android.server.wm.ActivityTaskManagerInternal; @@ -156,7 +156,7 @@ public class AccessibilityManagerServiceTest { @Mock private UserManagerInternal mMockUserManagerInternal; @Mock private IBinder mMockBinder; @Mock private IAccessibilityServiceClient mMockServiceClient; - @Mock private WindowMagnificationManager mMockWindowMagnificationMgr; + @Mock private MagnificationConnectionManager mMockMagnificationConnectionManager; @Mock private MagnificationController mMockMagnificationController; @Mock private FullScreenMagnificationController mMockFullScreenMagnificationController; @Mock private ProxyManager mProxyManager; @@ -180,8 +180,8 @@ public class AccessibilityManagerServiceTest { UserManagerInternal.class, mMockUserManagerInternal); mInputFilter = Mockito.mock(FakeInputFilter.class); - when(mMockMagnificationController.getWindowMagnificationMgr()).thenReturn( - mMockWindowMagnificationMgr); + when(mMockMagnificationController.getMagnificationConnectionManager()).thenReturn( + mMockMagnificationConnectionManager); when(mMockMagnificationController.getFullScreenMagnificationController()).thenReturn( mMockFullScreenMagnificationController); when(mMockMagnificationController.supportWindowMagnification()).thenReturn(true); @@ -530,7 +530,7 @@ public class AccessibilityManagerServiceTest { // Invokes client change to trigger onUserStateChanged. mA11yms.onClientChangeLocked(/* serviceInfoChanged= */false); - verify(mMockWindowMagnificationMgr).requestConnection(true); + verify(mMockMagnificationConnectionManager).requestConnection(true); } @SmallTest @@ -547,7 +547,7 @@ public class AccessibilityManagerServiceTest { // Invokes client change to trigger onUserStateChanged. mA11yms.onClientChangeLocked(/* serviceInfoChanged= */false); - verify(mMockWindowMagnificationMgr).requestConnection(true); + verify(mMockMagnificationConnectionManager).requestConnection(true); } @SmallTest @@ -565,7 +565,7 @@ public class AccessibilityManagerServiceTest { // Invokes client change to trigger onUserStateChanged. mA11yms.onClientChangeLocked(/* serviceInfoChanged= */false); - verify(mMockWindowMagnificationMgr).requestConnection(false); + verify(mMockMagnificationConnectionManager).requestConnection(false); } @SmallTest @@ -583,7 +583,7 @@ public class AccessibilityManagerServiceTest { // Invokes client change to trigger onUserStateChanged. mA11yms.onClientChangeLocked(/* serviceInfoChanged= */false); - verify(mMockWindowMagnificationMgr).requestConnection(true); + verify(mMockMagnificationConnectionManager).requestConnection(true); } @SmallTest @@ -602,7 +602,7 @@ public class AccessibilityManagerServiceTest { // Invokes client change to trigger onUserStateChanged. mA11yms.onClientChangeLocked(/* serviceInfoChanged= */false); - verify(mMockWindowMagnificationMgr).requestConnection(false); + verify(mMockMagnificationConnectionManager).requestConnection(false); } @SmallTest @@ -616,7 +616,7 @@ public class AccessibilityManagerServiceTest { // Invokes client change to trigger onUserStateChanged. mA11yms.onClientChangeLocked(/* serviceInfoChanged= */false); - verify(mMockWindowMagnificationMgr).requestConnection(true); + verify(mMockMagnificationConnectionManager).requestConnection(true); } @SmallTest @@ -630,7 +630,8 @@ public class AccessibilityManagerServiceTest { // Invokes client change to trigger onUserStateChanged. mA11yms.onClientChangeLocked(/* serviceInfoChanged= */false); - verify(mMockWindowMagnificationMgr, atLeastOnce()).removeMagnificationButton(anyInt()); + verify(mMockMagnificationConnectionManager, atLeastOnce()) + .removeMagnificationButton(anyInt()); } @SmallTest @@ -644,7 +645,7 @@ public class AccessibilityManagerServiceTest { // Invokes client change to trigger onUserStateChanged. mA11yms.onClientChangeLocked(/* serviceInfoChanged= */false); - verify(mMockWindowMagnificationMgr, never()).removeMagnificationButton(anyInt()); + verify(mMockMagnificationConnectionManager, never()).removeMagnificationButton(anyInt()); } @SmallTest @@ -659,7 +660,8 @@ public class AccessibilityManagerServiceTest { // Invokes client change to trigger onUserStateChanged. mA11yms.onClientChangeLocked(/* serviceInfoChanged= */false); - verify(mMockWindowMagnificationMgr, atLeastOnce()).removeMagnificationButton(anyInt()); + verify(mMockMagnificationConnectionManager, atLeastOnce()) + .removeMagnificationButton(anyInt()); } @SmallTest @@ -674,7 +676,7 @@ public class AccessibilityManagerServiceTest { // Invokes client change to trigger onUserStateChanged. mA11yms.onClientChangeLocked(/* serviceInfoChanged= */false); - verify(mMockWindowMagnificationMgr, never()).removeMagnificationButton(anyInt()); + verify(mMockMagnificationConnectionManager, never()).removeMagnificationButton(anyInt()); } @Test diff --git a/services/tests/servicestests/src/com/android/server/accessibility/MagnificationProcessorTest.java b/services/tests/servicestests/src/com/android/server/accessibility/MagnificationProcessorTest.java index a02807fe766c..7829fcc4b44d 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/MagnificationProcessorTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/MagnificationProcessorTest.java @@ -39,9 +39,9 @@ import android.accessibilityservice.MagnificationConfig; import android.graphics.Region; import com.android.server.accessibility.magnification.FullScreenMagnificationController; +import com.android.server.accessibility.magnification.MagnificationConnectionManager; import com.android.server.accessibility.magnification.MagnificationController; import com.android.server.accessibility.magnification.MagnificationProcessor; -import com.android.server.accessibility.magnification.WindowMagnificationManager; import org.junit.Before; import org.junit.Test; @@ -66,21 +66,21 @@ public class MagnificationProcessorTest { @Mock private FullScreenMagnificationController mMockFullScreenMagnificationController; @Mock - private WindowMagnificationManager mMockWindowMagnificationManager; + private MagnificationConnectionManager mMockMagnificationConnectionManager; FullScreenMagnificationControllerStub mFullScreenMagnificationControllerStub; - WindowMagnificationManagerStub mWindowMagnificationManagerStub; + MagnificationManagerStub mMagnificationManagerStub; @Before public void setup() { MockitoAnnotations.initMocks(this); mFullScreenMagnificationControllerStub = new FullScreenMagnificationControllerStub( mMockFullScreenMagnificationController); - mWindowMagnificationManagerStub = new WindowMagnificationManagerStub( - mMockWindowMagnificationManager); + mMagnificationManagerStub = new MagnificationManagerStub( + mMockMagnificationConnectionManager); when(mMockMagnificationController.getFullScreenMagnificationController()).thenReturn( mMockFullScreenMagnificationController); - when(mMockMagnificationController.getWindowMagnificationMgr()).thenReturn( - mMockWindowMagnificationManager); + when(mMockMagnificationController.getMagnificationConnectionManager()).thenReturn( + mMockMagnificationConnectionManager); mMagnificationProcessor = new MagnificationProcessor(mMockMagnificationController); } @@ -194,7 +194,7 @@ public class MagnificationProcessorTest { doAnswer((invocation) -> { ((Region) invocation.getArguments()[1]).set(region); return null; - }).when(mMockWindowMagnificationManager).getMagnificationSourceBounds(eq(TEST_DISPLAY), + }).when(mMockMagnificationConnectionManager).getMagnificationSourceBounds(eq(TEST_DISPLAY), any()); final Region result = new Region(); @@ -286,7 +286,7 @@ public class MagnificationProcessorTest { mMagnificationProcessor.resetCurrentMagnification(TEST_DISPLAY, /* animate= */false); - verify(mMockWindowMagnificationManager).disableWindowMagnification(TEST_DISPLAY, false, + verify(mMockMagnificationConnectionManager).disableWindowMagnification(TEST_DISPLAY, false, null); } @@ -296,7 +296,7 @@ public class MagnificationProcessorTest { mMagnificationProcessor.resetAllIfNeeded(connectionId); verify(mMockFullScreenMagnificationController).resetAllIfNeeded(eq(connectionId)); - verify(mMockWindowMagnificationManager).resetAllIfNeeded(eq(connectionId)); + verify(mMockMagnificationConnectionManager).resetAllIfNeeded(eq(connectionId)); } @Test @@ -450,7 +450,7 @@ public class MagnificationProcessorTest { .setActivated(false).build(); mMagnificationProcessor.setMagnificationConfig(TEST_DISPLAY, config, false, SERVICE_ID); - verify(mMockWindowMagnificationManager) + verify(mMockMagnificationConnectionManager) .disableWindowMagnification(eq(TEST_DISPLAY), anyBoolean()); } @@ -481,11 +481,11 @@ public class MagnificationProcessorTest { mFullScreenMagnificationControllerStub.resetAndStubMethods(); mMockFullScreenMagnificationController.setScaleAndCenter(displayId, config.getScale(), config.getCenterX(), config.getCenterY(), false, SERVICE_ID); - mWindowMagnificationManagerStub.deactivateIfNeed(); + mMagnificationManagerStub.deactivateIfNeed(); } else if (config.getMode() == MAGNIFICATION_MODE_WINDOW) { - mWindowMagnificationManagerStub.resetAndStubMethods(); - mMockWindowMagnificationManager.enableWindowMagnification(displayId, config.getScale(), - config.getCenterX(), config.getCenterY()); + mMagnificationManagerStub.resetAndStubMethods(); + mMockMagnificationConnectionManager.enableWindowMagnification( + displayId, config.getScale(), config.getCenterX(), config.getCenterY()); mFullScreenMagnificationControllerStub.deactivateIfNeed(); } } @@ -568,26 +568,26 @@ public class MagnificationProcessorTest { } } - private static class WindowMagnificationManagerStub { - private final WindowMagnificationManager mWindowMagnificationManager; + private static class MagnificationManagerStub { + private final MagnificationConnectionManager mMagnificationConnectionManager; private float mScale = 1.0f; private float mCenterX = 0; private float mCenterY = 0; private boolean mIsEnabled = false; - WindowMagnificationManagerStub( - WindowMagnificationManager windowMagnificationManager) { - mWindowMagnificationManager = windowMagnificationManager; + MagnificationManagerStub( + MagnificationConnectionManager magnificationConnectionManager) { + mMagnificationConnectionManager = magnificationConnectionManager; } private void stubMethods() { - doAnswer(invocation -> mScale).when(mWindowMagnificationManager).getScale( + doAnswer(invocation -> mScale).when(mMagnificationConnectionManager).getScale( TEST_DISPLAY); - doAnswer(invocation -> mCenterX).when(mWindowMagnificationManager).getCenterX( + doAnswer(invocation -> mCenterX).when(mMagnificationConnectionManager).getCenterX( TEST_DISPLAY); - doAnswer(invocation -> mCenterY).when(mWindowMagnificationManager).getCenterY( + doAnswer(invocation -> mCenterY).when(mMagnificationConnectionManager).getCenterY( TEST_DISPLAY); - doAnswer(invocation -> mIsEnabled).when(mWindowMagnificationManager) + doAnswer(invocation -> mIsEnabled).when(mMagnificationConnectionManager) .isWindowMagnifierEnabled(TEST_DISPLAY); Answer enableWindowMagnificationStubAnswer = invocation -> { @@ -598,10 +598,10 @@ public class MagnificationProcessorTest { return true; }; doAnswer(enableWindowMagnificationStubAnswer).when( - mWindowMagnificationManager).enableWindowMagnification(eq(TEST_DISPLAY), + mMagnificationConnectionManager).enableWindowMagnification(eq(TEST_DISPLAY), anyFloat(), anyFloat(), anyFloat()); doAnswer(enableWindowMagnificationStubAnswer).when( - mWindowMagnificationManager).enableWindowMagnification(eq(TEST_DISPLAY), + mMagnificationConnectionManager).enableWindowMagnification(eq(TEST_DISPLAY), anyFloat(), anyFloat(), anyFloat(), any(), anyInt()); Answer disableWindowMagnificationStubAnswer = invocation -> { @@ -609,15 +609,15 @@ public class MagnificationProcessorTest { return true; }; doAnswer(disableWindowMagnificationStubAnswer).when( - mWindowMagnificationManager).disableWindowMagnification(eq(TEST_DISPLAY), + mMagnificationConnectionManager).disableWindowMagnification(eq(TEST_DISPLAY), anyBoolean()); doAnswer(disableWindowMagnificationStubAnswer).when( - mWindowMagnificationManager).disableWindowMagnification(eq(TEST_DISPLAY), + mMagnificationConnectionManager).disableWindowMagnification(eq(TEST_DISPLAY), anyBoolean(), any()); } public void resetAndStubMethods() { - Mockito.reset(mWindowMagnificationManager); + Mockito.reset(mMagnificationConnectionManager); stubMethods(); } diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationManagerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationConnectionManagerTest.java index 24ad976f6e45..3843e2507df6 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationConnectionManagerTest.java @@ -33,8 +33,6 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertNotNull; -import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; import static java.lang.Float.NaN; @@ -76,7 +74,7 @@ import org.mockito.invocation.InvocationOnMock; /** * Tests for WindowMagnificationManager. */ -public class WindowMagnificationManagerTest { +public class MagnificationConnectionManagerTest { private static final int CURRENT_USER_ID = UserHandle.USER_SYSTEM; private static final int SERVICE_ID = 1; @@ -91,9 +89,9 @@ public class WindowMagnificationManagerTest { @Mock private MagnificationAnimationCallback mAnimationCallback; @Mock - private WindowMagnificationManager.Callback mMockCallback; + private MagnificationConnectionManager.Callback mMockCallback; private MockContentResolver mResolver; - private WindowMagnificationManager mWindowMagnificationManager; + private MagnificationConnectionManager mMagnificationConnectionManager; @Before public void setUp() throws RemoteException { @@ -102,7 +100,7 @@ public class WindowMagnificationManagerTest { LocalServices.addService(StatusBarManagerInternal.class, mMockStatusBarManagerInternal); mResolver = new MockContentResolver(); mMockConnection = new MockWindowMagnificationConnection(); - mWindowMagnificationManager = new WindowMagnificationManager(mContext, new Object(), + mMagnificationConnectionManager = new MagnificationConnectionManager(mContext, new Object(), mMockCallback, mMockTrace, new MagnificationScaleProvider(mContext)); when(mContext.getContentResolver()).thenReturn(mResolver); @@ -122,11 +120,11 @@ public class WindowMagnificationManagerTest { final Context context = ApplicationProvider.getApplicationContext(); context.getMainThreadHandler().postDelayed( () -> { - mWindowMagnificationManager.setConnection( + mMagnificationConnectionManager.setConnection( connect ? mMockConnection.getConnection() : null); }, 10); } else { - mWindowMagnificationManager.setConnection( + mMagnificationConnectionManager.setConnection( connect ? mMockConnection.getConnection() : null); } return true; @@ -135,17 +133,17 @@ public class WindowMagnificationManagerTest { @Test public void setConnection_connectionIsNull_wrapperIsNullAndLinkToDeath() { - mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); - assertNotNull(mWindowMagnificationManager.mConnectionWrapper); + mMagnificationConnectionManager.setConnection(mMockConnection.getConnection()); + assertTrue(mMagnificationConnectionManager.isConnected()); verify(mMockConnection.asBinder()).linkToDeath(any(IBinder.DeathRecipient.class), eq(0)); } @Test public void setConnection_connectionIsNull_setMirrorWindowCallbackAndHasWrapper() throws RemoteException { - mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); + mMagnificationConnectionManager.setConnection(mMockConnection.getConnection()); - assertNotNull(mWindowMagnificationManager.mConnectionWrapper); + assertTrue(mMagnificationConnectionManager.isConnected()); verify(mMockConnection.asBinder()).linkToDeath(any(IBinder.DeathRecipient.class), eq(0)); verify(mMockConnection.getConnection()).setConnectionCallback( any(IWindowMagnificationConnectionCallback.class)); @@ -153,31 +151,31 @@ public class WindowMagnificationManagerTest { @Test public void binderDied_hasConnection_wrapperIsNullAndUnlinkToDeath() { - mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); + mMagnificationConnectionManager.setConnection(mMockConnection.getConnection()); mMockConnection.getDeathRecipient().binderDied(); - assertNull(mWindowMagnificationManager.mConnectionWrapper); + assertFalse(mMagnificationConnectionManager.isConnected()); verify(mMockConnection.asBinder()).unlinkToDeath(mMockConnection.getDeathRecipient(), 0); } /** - * This test simulates {@link WindowMagnificationManager#setConnection} is called by thread A - * and then the former connection is called by thread B. In this situation we should keep the + * This test simulates {@link MagnificationConnectionManager#setConnection} is called by thread + * A and then the former connection is called by thread B. In this situation we should keep the * new connection. */ @Test public void setSecondConnectionAndFormerConnectionBinderDead_hasWrapperAndNotCallUnlinkToDeath() throws RemoteException { - mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); + mMagnificationConnectionManager.setConnection(mMockConnection.getConnection()); MockWindowMagnificationConnection secondConnection = new MockWindowMagnificationConnection(); - mWindowMagnificationManager.setConnection(secondConnection.getConnection()); + mMagnificationConnectionManager.setConnection(secondConnection.getConnection()); mMockConnection.getDeathRecipient().binderDied(); - assertNotNull(mWindowMagnificationManager.mConnectionWrapper); + assertTrue(mMagnificationConnectionManager.isConnected()); verify(mMockConnection.asBinder()).unlinkToDeath(mMockConnection.getDeathRecipient(), 0); verify(secondConnection.asBinder(), never()).unlinkToDeath( secondConnection.getDeathRecipient(), 0); @@ -185,20 +183,20 @@ public class WindowMagnificationManagerTest { @Test public void setNullConnection_hasConnection_wrapperIsNull() throws RemoteException { - mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); + mMagnificationConnectionManager.setConnection(mMockConnection.getConnection()); - mWindowMagnificationManager.setConnection(null); + mMagnificationConnectionManager.setConnection(null); - assertNull(mWindowMagnificationManager.mConnectionWrapper); + assertFalse(mMagnificationConnectionManager.isConnected()); verify(mMockConnection.getConnection()).setConnectionCallback(null); } @Test public void enableWithAnimation_hasConnection_enableWindowMagnification() throws RemoteException { - mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); + mMagnificationConnectionManager.setConnection(mMockConnection.getConnection()); - mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 2f, 200f, 300f); + mMagnificationConnectionManager.enableWindowMagnification(TEST_DISPLAY, 2f, 200f, 300f); verify(mMockConnection.getConnection()).enableWindowMagnification(eq(TEST_DISPLAY), eq(2f), eq(200f), eq(300f), eq(0f), eq(0f), notNull()); @@ -207,9 +205,9 @@ public class WindowMagnificationManagerTest { @Test public void enableWithCallback_hasConnection_enableWindowMagnification() throws RemoteException { - mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); + mMagnificationConnectionManager.setConnection(mMockConnection.getConnection()); - mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 2f, 200f, 300f, + mMagnificationConnectionManager.enableWindowMagnification(TEST_DISPLAY, 2f, 200f, 300f, mAnimationCallback, SERVICE_ID); verify(mMockConnection.getConnection()).enableWindowMagnification(eq(TEST_DISPLAY), eq(2f), @@ -221,10 +219,10 @@ public class WindowMagnificationManagerTest { @Test public void disable_hasConnectionAndEnabled_disableWindowMagnification() throws RemoteException { - mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); - mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3f, NaN, NaN); + mMagnificationConnectionManager.setConnection(mMockConnection.getConnection()); + mMagnificationConnectionManager.enableWindowMagnification(TEST_DISPLAY, 3f, NaN, NaN); - mWindowMagnificationManager.disableWindowMagnification(TEST_DISPLAY, false); + mMagnificationConnectionManager.disableWindowMagnification(TEST_DISPLAY, false); verify(mMockConnection.getConnection()).disableWindowMagnification(eq(TEST_DISPLAY), notNull()); @@ -233,10 +231,10 @@ public class WindowMagnificationManagerTest { @Test public void disableWithCallback_hasConnectionAndEnabled_disableWindowMagnification() throws RemoteException { - mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); - mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3f, NaN, NaN); + mMagnificationConnectionManager.setConnection(mMockConnection.getConnection()); + mMagnificationConnectionManager.enableWindowMagnification(TEST_DISPLAY, 3f, NaN, NaN); - mWindowMagnificationManager.disableWindowMagnification(TEST_DISPLAY, false, + mMagnificationConnectionManager.disableWindowMagnification(TEST_DISPLAY, false, mAnimationCallback); verify(mMockConnection.getConnection()).disableWindowMagnification(eq(TEST_DISPLAY), @@ -246,28 +244,28 @@ public class WindowMagnificationManagerTest { @Test public void isWindowMagnifierEnabled_hasConnectionAndEnabled_returnExpectedValue() { - mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); - assertFalse(mWindowMagnificationManager.isWindowMagnifierEnabled(TEST_DISPLAY)); + mMagnificationConnectionManager.setConnection(mMockConnection.getConnection()); + assertFalse(mMagnificationConnectionManager.isWindowMagnifierEnabled(TEST_DISPLAY)); - mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 2f, NaN, NaN); + mMagnificationConnectionManager.enableWindowMagnification(TEST_DISPLAY, 2f, NaN, NaN); - assertTrue(mWindowMagnificationManager.isWindowMagnifierEnabled(TEST_DISPLAY)); + assertTrue(mMagnificationConnectionManager.isWindowMagnifierEnabled(TEST_DISPLAY)); } @Test public void getPersistedScale() { - mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); + mMagnificationConnectionManager.setConnection(mMockConnection.getConnection()); - assertEquals(mWindowMagnificationManager.getPersistedScale(TEST_DISPLAY), 2.5f); + assertEquals(mMagnificationConnectionManager.getPersistedScale(TEST_DISPLAY), 2.5f); } @Test public void persistScale_setValue_expectedValueInProvider() { - mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); - mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 2.0f, NaN, NaN); - mWindowMagnificationManager.setScale(TEST_DISPLAY, 2.5f); + mMagnificationConnectionManager.setConnection(mMockConnection.getConnection()); + mMagnificationConnectionManager.enableWindowMagnification(TEST_DISPLAY, 2.0f, NaN, NaN); + mMagnificationConnectionManager.setScale(TEST_DISPLAY, 2.5f); - mWindowMagnificationManager.persistScale(TEST_DISPLAY); + mMagnificationConnectionManager.persistScale(TEST_DISPLAY); assertEquals(Settings.Secure.getFloatForUser(mResolver, Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, 0f, @@ -276,11 +274,12 @@ public class WindowMagnificationManagerTest { @Test public void persistScale_setValueWhenScaleIsOne_nothingChanged() { - mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); - final float persistedScale = mWindowMagnificationManager.getPersistedScale(TEST_DISPLAY); + mMagnificationConnectionManager.setConnection(mMockConnection.getConnection()); + final float persistedScale = + mMagnificationConnectionManager.getPersistedScale(TEST_DISPLAY); - mWindowMagnificationManager.setScale(TEST_DISPLAY, 1.0f); - mWindowMagnificationManager.persistScale(TEST_DISPLAY); + mMagnificationConnectionManager.setScale(TEST_DISPLAY, 1.0f); + mMagnificationConnectionManager.persistScale(TEST_DISPLAY); assertEquals(Settings.Secure.getFloatForUser(mResolver, Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, 0f, @@ -289,50 +288,53 @@ public class WindowMagnificationManagerTest { @Test public void scaleSetterGetter_enabledOnTestDisplay_expectedValue() { - mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); - mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 2.0f, NaN, NaN); + mMagnificationConnectionManager.setConnection(mMockConnection.getConnection()); + mMagnificationConnectionManager.enableWindowMagnification(TEST_DISPLAY, 2.0f, NaN, NaN); - mWindowMagnificationManager.setScale(TEST_DISPLAY, 2.5f); + mMagnificationConnectionManager.setScale(TEST_DISPLAY, 2.5f); - assertEquals(mWindowMagnificationManager.getScale(TEST_DISPLAY), 2.5f); + assertEquals(mMagnificationConnectionManager.getScale(TEST_DISPLAY), 2.5f); } @Test public void scaleSetterGetter_scaleIsOutOfRang_getNormalizeValue() { - mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); - mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 2.5f, NaN, NaN); + mMagnificationConnectionManager.setConnection(mMockConnection.getConnection()); + mMagnificationConnectionManager.enableWindowMagnification(TEST_DISPLAY, 2.5f, NaN, NaN); - mWindowMagnificationManager.setScale(TEST_DISPLAY, 10.0f); + mMagnificationConnectionManager.setScale(TEST_DISPLAY, 10.0f); - assertEquals(mWindowMagnificationManager.getScale(TEST_DISPLAY), + assertEquals(mMagnificationConnectionManager.getScale(TEST_DISPLAY), MagnificationScaleProvider.MAX_SCALE); } @FlakyTest(bugId = 297879435) @Test public void logTrackingTypingFocus_processScroll_logDuration() { - WindowMagnificationManager spyWindowMagnificationManager = spy(mWindowMagnificationManager); - spyWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, 50f, 50f); - spyWindowMagnificationManager.onImeWindowVisibilityChanged(TEST_DISPLAY, /* shown */ true); + MagnificationConnectionManager spyMagnificationConnectionManager = spy( + mMagnificationConnectionManager); + spyMagnificationConnectionManager.enableWindowMagnification( + TEST_DISPLAY, 3.0f, 50f, 50f); + spyMagnificationConnectionManager.onImeWindowVisibilityChanged( + TEST_DISPLAY, /* shown */ true); - spyWindowMagnificationManager.processScroll(TEST_DISPLAY, 10f, 10f); + spyMagnificationConnectionManager.processScroll(TEST_DISPLAY, 10f, 10f); - verify(spyWindowMagnificationManager).logTrackingTypingFocus(anyLong()); + verify(spyMagnificationConnectionManager).logTrackingTypingFocus(anyLong()); } @Test public void onRectangleOnScreenRequested_trackingDisabledByOnDrag_withoutMovingMagnifier() throws RemoteException { - mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); - mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, 50f, 50f); - mWindowMagnificationManager.onImeWindowVisibilityChanged(TEST_DISPLAY, true); + mMagnificationConnectionManager.setConnection(mMockConnection.getConnection()); + mMagnificationConnectionManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, 50f, 50f); + mMagnificationConnectionManager.onImeWindowVisibilityChanged(TEST_DISPLAY, true); final Region outRegion = new Region(); - mWindowMagnificationManager.getMagnificationSourceBounds(TEST_DISPLAY, outRegion); + mMagnificationConnectionManager.getMagnificationSourceBounds(TEST_DISPLAY, outRegion); final Rect requestedRect = outRegion.getBounds(); requestedRect.offsetTo(requestedRect.right + 10, requestedRect.bottom + 10); mMockConnection.getConnectionCallback().onMove(TEST_DISPLAY); - mWindowMagnificationManager.onRectangleOnScreenRequested(TEST_DISPLAY, + mMagnificationConnectionManager.onRectangleOnScreenRequested(TEST_DISPLAY, requestedRect.left, requestedRect.top, requestedRect.right, requestedRect.bottom); verify(mMockConnection.getConnection(), never()) @@ -345,16 +347,16 @@ public class WindowMagnificationManagerTest { throws RemoteException { final float distanceX = 10f; final float distanceY = 10f; - mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); - mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, 50f, 50f); - mWindowMagnificationManager.onImeWindowVisibilityChanged(TEST_DISPLAY, true); + mMagnificationConnectionManager.setConnection(mMockConnection.getConnection()); + mMagnificationConnectionManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, 50f, 50f); + mMagnificationConnectionManager.onImeWindowVisibilityChanged(TEST_DISPLAY, true); final Region outRegion = new Region(); - mWindowMagnificationManager.getMagnificationSourceBounds(TEST_DISPLAY, outRegion); + mMagnificationConnectionManager.getMagnificationSourceBounds(TEST_DISPLAY, outRegion); final Rect requestedRect = outRegion.getBounds(); requestedRect.offsetTo(requestedRect.right + 10, requestedRect.bottom + 10); - mWindowMagnificationManager.processScroll(TEST_DISPLAY, distanceX, distanceY); + mMagnificationConnectionManager.processScroll(TEST_DISPLAY, distanceX, distanceY); - mWindowMagnificationManager.onRectangleOnScreenRequested(TEST_DISPLAY, + mMagnificationConnectionManager.onRectangleOnScreenRequested(TEST_DISPLAY, requestedRect.left, requestedRect.top, requestedRect.right, requestedRect.bottom); verify(mMockConnection.getConnection(), never()) @@ -364,15 +366,15 @@ public class WindowMagnificationManagerTest { @Test public void onRectangleOnScreenRequested_requestRectangleInBound_withoutMovingMagnifier() throws RemoteException { - mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); - mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, 50f, 50f); - mWindowMagnificationManager.onImeWindowVisibilityChanged(TEST_DISPLAY, true); + mMagnificationConnectionManager.setConnection(mMockConnection.getConnection()); + mMagnificationConnectionManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, 50f, 50f); + mMagnificationConnectionManager.onImeWindowVisibilityChanged(TEST_DISPLAY, true); final Region outRegion = new Region(); - mWindowMagnificationManager.getMagnificationSourceBounds(TEST_DISPLAY, outRegion); + mMagnificationConnectionManager.getMagnificationSourceBounds(TEST_DISPLAY, outRegion); final Rect requestedRect = outRegion.getBounds(); requestedRect.inset(-10, -10); - mWindowMagnificationManager.onRectangleOnScreenRequested(TEST_DISPLAY, + mMagnificationConnectionManager.onRectangleOnScreenRequested(TEST_DISPLAY, requestedRect.left, requestedRect.top, requestedRect.right, requestedRect.bottom); verify(mMockConnection.getConnection(), never()) @@ -381,14 +383,14 @@ public class WindowMagnificationManagerTest { @Test public void onRectangleOnScreenRequested_imeVisibilityDefaultInvisible_withoutMovingMagnifier() throws RemoteException { - mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); - mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, 50f, 50f); + mMagnificationConnectionManager.setConnection(mMockConnection.getConnection()); + mMagnificationConnectionManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, 50f, 50f); final Region outRegion = new Region(); - mWindowMagnificationManager.getMagnificationSourceBounds(TEST_DISPLAY, outRegion); + mMagnificationConnectionManager.getMagnificationSourceBounds(TEST_DISPLAY, outRegion); final Rect requestedRect = outRegion.getBounds(); requestedRect.offsetTo(requestedRect.right + 10, requestedRect.bottom + 10); - mWindowMagnificationManager.onRectangleOnScreenRequested(TEST_DISPLAY, + mMagnificationConnectionManager.onRectangleOnScreenRequested(TEST_DISPLAY, requestedRect.left, requestedRect.top, requestedRect.right, requestedRect.bottom); verify(mMockConnection.getConnection(), never()) @@ -398,15 +400,15 @@ public class WindowMagnificationManagerTest { @Test public void onRectangleOnScreenRequested_trackingEnabledByDefault_movingMagnifier() throws RemoteException { - mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); - mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, 50f, 50f); - mWindowMagnificationManager.onImeWindowVisibilityChanged(TEST_DISPLAY, true); + mMagnificationConnectionManager.setConnection(mMockConnection.getConnection()); + mMagnificationConnectionManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, 50f, 50f); + mMagnificationConnectionManager.onImeWindowVisibilityChanged(TEST_DISPLAY, true); final Region outRegion = new Region(); - mWindowMagnificationManager.getMagnificationSourceBounds(TEST_DISPLAY, outRegion); + mMagnificationConnectionManager.getMagnificationSourceBounds(TEST_DISPLAY, outRegion); final Rect requestedRect = outRegion.getBounds(); requestedRect.offsetTo(requestedRect.right + 10, requestedRect.bottom + 10); - mWindowMagnificationManager.onRectangleOnScreenRequested(TEST_DISPLAY, + mMagnificationConnectionManager.onRectangleOnScreenRequested(TEST_DISPLAY, requestedRect.left, requestedRect.top, requestedRect.right, requestedRect.bottom); verify(mMockConnection.getConnection()).moveWindowMagnifierToPosition(eq(TEST_DISPLAY), @@ -417,16 +419,16 @@ public class WindowMagnificationManagerTest { @Test public void onRectangleOnScreenRequested_imeInvisible_withoutMovingMagnifier() throws RemoteException { - mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); - mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, 50f, 50f); - mWindowMagnificationManager.onImeWindowVisibilityChanged(TEST_DISPLAY, true); + mMagnificationConnectionManager.setConnection(mMockConnection.getConnection()); + mMagnificationConnectionManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, 50f, 50f); + mMagnificationConnectionManager.onImeWindowVisibilityChanged(TEST_DISPLAY, true); final Region outRegion = new Region(); - mWindowMagnificationManager.getMagnificationSourceBounds(TEST_DISPLAY, outRegion); + mMagnificationConnectionManager.getMagnificationSourceBounds(TEST_DISPLAY, outRegion); final Rect requestedRect = outRegion.getBounds(); requestedRect.offsetTo(requestedRect.right + 10, requestedRect.bottom + 10); - mWindowMagnificationManager.onImeWindowVisibilityChanged(TEST_DISPLAY, false); + mMagnificationConnectionManager.onImeWindowVisibilityChanged(TEST_DISPLAY, false); - mWindowMagnificationManager.onRectangleOnScreenRequested(TEST_DISPLAY, + mMagnificationConnectionManager.onRectangleOnScreenRequested(TEST_DISPLAY, requestedRect.left, requestedRect.top, requestedRect.right, requestedRect.bottom); verify(mMockConnection.getConnection(), never()) @@ -436,17 +438,17 @@ public class WindowMagnificationManagerTest { @Test public void onRectangleOnScreenRequested_trackingEnabledByDragAndReset_movingMagnifier() throws RemoteException { - mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); - mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, 50f, 50f); - mWindowMagnificationManager.onImeWindowVisibilityChanged(TEST_DISPLAY, true); + mMagnificationConnectionManager.setConnection(mMockConnection.getConnection()); + mMagnificationConnectionManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, 50f, 50f); + mMagnificationConnectionManager.onImeWindowVisibilityChanged(TEST_DISPLAY, true); mMockConnection.getConnectionCallback().onMove(TEST_DISPLAY); - mWindowMagnificationManager.onImeWindowVisibilityChanged(TEST_DISPLAY, true); + mMagnificationConnectionManager.onImeWindowVisibilityChanged(TEST_DISPLAY, true); final Region outRegion = new Region(); - mWindowMagnificationManager.getMagnificationSourceBounds(TEST_DISPLAY, outRegion); + mMagnificationConnectionManager.getMagnificationSourceBounds(TEST_DISPLAY, outRegion); final Rect requestedRect = outRegion.getBounds(); requestedRect.offsetTo(requestedRect.right + 10, requestedRect.bottom + 10); - mWindowMagnificationManager.onRectangleOnScreenRequested(TEST_DISPLAY, + mMagnificationConnectionManager.onRectangleOnScreenRequested(TEST_DISPLAY, requestedRect.left, requestedRect.top, requestedRect.right, requestedRect.bottom); verify(mMockConnection.getConnection()).moveWindowMagnifierToPosition(eq(TEST_DISPLAY), @@ -456,58 +458,58 @@ public class WindowMagnificationManagerTest { @Test public void onRectangleOnScreenRequested_followTypingIsDisabled_withoutMovingMagnifier() { - mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); - mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, 50f, 50f); - mWindowMagnificationManager.onImeWindowVisibilityChanged(TEST_DISPLAY, true); + mMagnificationConnectionManager.setConnection(mMockConnection.getConnection()); + mMagnificationConnectionManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, 50f, 50f); + mMagnificationConnectionManager.onImeWindowVisibilityChanged(TEST_DISPLAY, true); final Region beforeRegion = new Region(); - mWindowMagnificationManager.getMagnificationSourceBounds(TEST_DISPLAY, beforeRegion); + mMagnificationConnectionManager.getMagnificationSourceBounds(TEST_DISPLAY, beforeRegion); final Rect requestedRect = beforeRegion.getBounds(); requestedRect.offsetTo(requestedRect.right + 10, requestedRect.bottom + 10); - mWindowMagnificationManager.setMagnificationFollowTypingEnabled(false); + mMagnificationConnectionManager.setMagnificationFollowTypingEnabled(false); - mWindowMagnificationManager.onRectangleOnScreenRequested(TEST_DISPLAY, + mMagnificationConnectionManager.onRectangleOnScreenRequested(TEST_DISPLAY, requestedRect.left, requestedRect.top, requestedRect.right, requestedRect.bottom); final Region afterRegion = new Region(); - mWindowMagnificationManager.getMagnificationSourceBounds(TEST_DISPLAY, afterRegion); + mMagnificationConnectionManager.getMagnificationSourceBounds(TEST_DISPLAY, afterRegion); assertEquals(afterRegion, beforeRegion); } @Test public void onRectangleOnScreenRequested_trackingDisabled_withoutMovingMagnifier() { - mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); - mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, 50f, 50f); - mWindowMagnificationManager.onImeWindowVisibilityChanged(TEST_DISPLAY, true); - mWindowMagnificationManager.setTrackingTypingFocusEnabled(TEST_DISPLAY, false); + mMagnificationConnectionManager.setConnection(mMockConnection.getConnection()); + mMagnificationConnectionManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, 50f, 50f); + mMagnificationConnectionManager.onImeWindowVisibilityChanged(TEST_DISPLAY, true); + mMagnificationConnectionManager.setTrackingTypingFocusEnabled(TEST_DISPLAY, false); final Region beforeRegion = new Region(); - mWindowMagnificationManager.getMagnificationSourceBounds(TEST_DISPLAY, beforeRegion); + mMagnificationConnectionManager.getMagnificationSourceBounds(TEST_DISPLAY, beforeRegion); final Rect requestedRect = beforeRegion.getBounds(); requestedRect.offsetTo(requestedRect.right + 10, requestedRect.bottom + 10); - mWindowMagnificationManager.onRectangleOnScreenRequested(TEST_DISPLAY, + mMagnificationConnectionManager.onRectangleOnScreenRequested(TEST_DISPLAY, requestedRect.left, requestedRect.top, requestedRect.right, requestedRect.bottom); final Region afterRegion = new Region(); - mWindowMagnificationManager.getMagnificationSourceBounds(TEST_DISPLAY, afterRegion); + mMagnificationConnectionManager.getMagnificationSourceBounds(TEST_DISPLAY, afterRegion); assertEquals(afterRegion, beforeRegion); } @Test public void onRectangleOnScreenRequested_trackingDisabledAndEnabledMagnifier_movingMagnifier() throws RemoteException { - mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); - mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, 50f, 50f); - mWindowMagnificationManager.onImeWindowVisibilityChanged(TEST_DISPLAY, true); - mWindowMagnificationManager.setTrackingTypingFocusEnabled(TEST_DISPLAY, false); + mMagnificationConnectionManager.setConnection(mMockConnection.getConnection()); + mMagnificationConnectionManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, 50f, 50f); + mMagnificationConnectionManager.onImeWindowVisibilityChanged(TEST_DISPLAY, true); + mMagnificationConnectionManager.setTrackingTypingFocusEnabled(TEST_DISPLAY, false); final Region beforeRegion = new Region(); - mWindowMagnificationManager.getMagnificationSourceBounds(TEST_DISPLAY, beforeRegion); + mMagnificationConnectionManager.getMagnificationSourceBounds(TEST_DISPLAY, beforeRegion); final Rect requestedRect = beforeRegion.getBounds(); requestedRect.offsetTo(requestedRect.right + 10, requestedRect.bottom + 10); - mWindowMagnificationManager.disableWindowMagnification(TEST_DISPLAY, false); + mMagnificationConnectionManager.disableWindowMagnification(TEST_DISPLAY, false); // Enabling a window magnifier again will turn on the tracking typing focus functionality. - mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, NaN, NaN, NaN); + mMagnificationConnectionManager.enableWindowMagnification(TEST_DISPLAY, NaN, NaN, NaN); - mWindowMagnificationManager.onRectangleOnScreenRequested(TEST_DISPLAY, + mMagnificationConnectionManager.onRectangleOnScreenRequested(TEST_DISPLAY, requestedRect.left, requestedRect.top, requestedRect.right, requestedRect.bottom); verify(mMockConnection.getConnection()).moveWindowMagnifierToPosition(eq(TEST_DISPLAY), @@ -517,43 +519,43 @@ public class WindowMagnificationManagerTest { @Test public void moveWindowMagnifier_enabled_invokeConnectionMethod() throws RemoteException { - mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); - mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 2f, NaN, NaN); + mMagnificationConnectionManager.setConnection(mMockConnection.getConnection()); + mMagnificationConnectionManager.enableWindowMagnification(TEST_DISPLAY, 2f, NaN, NaN); - mWindowMagnificationManager.moveWindowMagnification(TEST_DISPLAY, 200, 300); + mMagnificationConnectionManager.moveWindowMagnification(TEST_DISPLAY, 200, 300); verify(mMockConnection.getConnection()).moveWindowMagnifier(TEST_DISPLAY, 200, 300); } @Test public void showMagnificationButton_hasConnection_invokeConnectionMethod() throws RemoteException { - mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); + mMagnificationConnectionManager.setConnection(mMockConnection.getConnection()); - mWindowMagnificationManager.showMagnificationButton(TEST_DISPLAY, + mMagnificationConnectionManager.showMagnificationButton(TEST_DISPLAY, Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); verify(mMockConnection.getConnection()).showMagnificationButton(TEST_DISPLAY, Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); - mWindowMagnificationManager.removeMagnificationButton(TEST_DISPLAY); + mMagnificationConnectionManager.removeMagnificationButton(TEST_DISPLAY); verify(mMockConnection.getConnection()).removeMagnificationButton(TEST_DISPLAY); } @Test public void removeMagnificationSettingsPanel_hasConnection_invokeConnectionMethod() throws RemoteException { - mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); + mMagnificationConnectionManager.setConnection(mMockConnection.getConnection()); - mWindowMagnificationManager.removeMagnificationSettingsPanel(TEST_DISPLAY); + mMagnificationConnectionManager.removeMagnificationSettingsPanel(TEST_DISPLAY); verify(mMockConnection.getConnection()).removeMagnificationSettingsPanel(TEST_DISPLAY); } @Test public void onUserMagnificationScaleChanged_hasConnection_invokeConnectionMethod() throws RemoteException { - mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); + mMagnificationConnectionManager.setConnection(mMockConnection.getConnection()); final float testScale = 3f; - mWindowMagnificationManager.onUserMagnificationScaleChanged( + mMagnificationConnectionManager.onUserMagnificationScaleChanged( CURRENT_USER_ID, TEST_DISPLAY, testScale); verify(mMockConnection.getConnection()).onUserMagnificationScaleChanged( eq(CURRENT_USER_ID), eq(TEST_DISPLAY), eq(testScale)); @@ -561,8 +563,8 @@ public class WindowMagnificationManagerTest { @Test public void pointersInWindow_magnifierEnabled_returnCorrectValue() throws RemoteException { - mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); - mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, NaN, NaN); + mMagnificationConnectionManager.setConnection(mMockConnection.getConnection()); + mMagnificationConnectionManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, NaN, NaN); mMockConnection.getConnectionCallback().onWindowMagnifierBoundsChanged(TEST_DISPLAY, new Rect(0, 0, 500, 500)); PointF[] pointersLocation = new PointF[2]; @@ -570,15 +572,15 @@ public class WindowMagnificationManagerTest { pointersLocation[1] = new PointF(300, 400); MotionEvent event = generatePointersDownEvent(pointersLocation); - assertEquals(mWindowMagnificationManager.pointersInWindow(TEST_DISPLAY, event), 1); + assertEquals(mMagnificationConnectionManager.pointersInWindow(TEST_DISPLAY, event), 1); } @Test public void onPerformScaleAction_magnifierEnabled_notifyAction() throws RemoteException { final float newScale = 4.0f; final boolean updatePersistence = true; - mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); - mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, NaN, NaN); + mMagnificationConnectionManager.setConnection(mMockConnection.getConnection()); + mMagnificationConnectionManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, NaN, NaN); mMockConnection.getConnectionCallback().onPerformScaleAction( TEST_DISPLAY, newScale, updatePersistence); @@ -590,8 +592,8 @@ public class WindowMagnificationManagerTest { @Test public void onAccessibilityActionPerformed_magnifierEnabled_notifyAction() throws RemoteException { - mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); - mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, NaN, NaN); + mMagnificationConnectionManager.setConnection(mMockConnection.getConnection()); + mMagnificationConnectionManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, NaN, NaN); mMockConnection.getConnectionCallback().onAccessibilityActionPerformed(TEST_DISPLAY); @@ -600,22 +602,22 @@ public class WindowMagnificationManagerTest { @Test public void binderDied_windowMagnifierIsEnabled_resetState() throws RemoteException { - mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); - mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3f, NaN, NaN); + mMagnificationConnectionManager.setConnection(mMockConnection.getConnection()); + mMagnificationConnectionManager.enableWindowMagnification(TEST_DISPLAY, 3f, NaN, NaN); mMockConnection.getDeathRecipient().binderDied(); - assertFalse(mWindowMagnificationManager.isWindowMagnifierEnabled(TEST_DISPLAY)); + assertFalse(mMagnificationConnectionManager.isWindowMagnifierEnabled(TEST_DISPLAY)); } @Test public void requestConnectionToNull_disableAllMagnifiersAndRequestWindowMagnificationConnection() throws RemoteException { - assertTrue(mWindowMagnificationManager.requestConnection(true)); - mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3f, NaN, NaN); + assertTrue(mMagnificationConnectionManager.requestConnection(true)); + mMagnificationConnectionManager.enableWindowMagnification(TEST_DISPLAY, 3f, NaN, NaN); - assertTrue(mWindowMagnificationManager.requestConnection(false)); + assertTrue(mMagnificationConnectionManager.requestConnection(false)); verify(mMockConnection.getConnection()).disableWindowMagnification(TEST_DISPLAY, null); verify(mMockStatusBarManagerInternal).requestWindowMagnificationConnection(false); @@ -623,40 +625,40 @@ public class WindowMagnificationManagerTest { @Test public void requestConnection_requestWindowMagnificationConnection() throws RemoteException { - assertTrue(mWindowMagnificationManager.requestConnection(true)); + assertTrue(mMagnificationConnectionManager.requestConnection(true)); verify(mMockStatusBarManagerInternal).requestWindowMagnificationConnection(true); } @Test public void isConnected_requestConnection_expectedValue() throws RemoteException { - mWindowMagnificationManager.requestConnection(true); - assertTrue(mWindowMagnificationManager.isConnected()); + mMagnificationConnectionManager.requestConnection(true); + assertTrue(mMagnificationConnectionManager.isConnected()); - mWindowMagnificationManager.requestConnection(false); - assertFalse(mWindowMagnificationManager.isConnected()); + mMagnificationConnectionManager.requestConnection(false); + assertFalse(mMagnificationConnectionManager.isConnected()); } @Test public void requestConnection_registerAndUnregisterBroadcastReceiver() { - assertTrue(mWindowMagnificationManager.requestConnection(true)); + assertTrue(mMagnificationConnectionManager.requestConnection(true)); verify(mContext).registerReceiver(any(BroadcastReceiver.class), any(IntentFilter.class)); - assertTrue(mWindowMagnificationManager.requestConnection(false)); + assertTrue(mMagnificationConnectionManager.requestConnection(false)); verify(mContext).unregisterReceiver(any(BroadcastReceiver.class)); } @Test public void requestConnectionToNull_expectedGetterResults() { - mWindowMagnificationManager.requestConnection(true); - mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3f, 1, 1); + mMagnificationConnectionManager.requestConnection(true); + mMagnificationConnectionManager.enableWindowMagnification(TEST_DISPLAY, 3f, 1, 1); - mWindowMagnificationManager.requestConnection(false); + mMagnificationConnectionManager.requestConnection(false); - assertEquals(1f, mWindowMagnificationManager.getScale(TEST_DISPLAY), 0); - assertTrue(Float.isNaN(mWindowMagnificationManager.getCenterX(TEST_DISPLAY))); - assertTrue(Float.isNaN(mWindowMagnificationManager.getCenterY(TEST_DISPLAY))); + assertEquals(1f, mMagnificationConnectionManager.getScale(TEST_DISPLAY), 0); + assertTrue(Float.isNaN(mMagnificationConnectionManager.getCenterX(TEST_DISPLAY))); + assertTrue(Float.isNaN(mMagnificationConnectionManager.getCenterY(TEST_DISPLAY))); final Region bounds = new Region(); - mWindowMagnificationManager.getMagnificationSourceBounds(TEST_DISPLAY, bounds); + mMagnificationConnectionManager.getMagnificationSourceBounds(TEST_DISPLAY, bounds); assertTrue(bounds.isEmpty()); } @@ -664,9 +666,10 @@ public class WindowMagnificationManagerTest { public void enableWindowMagnification_connecting_invokeConnectionMethodAfterConnected() throws RemoteException { stubSetConnection(true); - mWindowMagnificationManager.requestConnection(true); + mMagnificationConnectionManager.requestConnection(true); - assertTrue(mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3f, 1, 1)); + assertTrue(mMagnificationConnectionManager.enableWindowMagnification( + TEST_DISPLAY, 3f, 1, 1)); // Invoke enableWindowMagnification if the connection is connected. verify(mMockConnection.getConnection()).enableWindowMagnification( @@ -676,69 +679,73 @@ public class WindowMagnificationManagerTest { @Test public void resetAllMagnification_enabledBySameId_windowMagnifiersDisabled() { - mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); - mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3f, - 100f, 200f, null, WindowMagnificationManager.WINDOW_POSITION_AT_CENTER, SERVICE_ID); - mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY_2, 3f, - 100f, 200f, null, WindowMagnificationManager.WINDOW_POSITION_AT_CENTER, SERVICE_ID); - assertTrue(mWindowMagnificationManager.isWindowMagnifierEnabled(TEST_DISPLAY)); - assertTrue(mWindowMagnificationManager.isWindowMagnifierEnabled(TEST_DISPLAY_2)); + mMagnificationConnectionManager.setConnection(mMockConnection.getConnection()); + mMagnificationConnectionManager.enableWindowMagnification(TEST_DISPLAY, 3f, + 100f, 200f, null, + MagnificationConnectionManager.WINDOW_POSITION_AT_CENTER, SERVICE_ID); + mMagnificationConnectionManager.enableWindowMagnification(TEST_DISPLAY_2, 3f, + 100f, 200f, null, + MagnificationConnectionManager.WINDOW_POSITION_AT_CENTER, SERVICE_ID); + assertTrue(mMagnificationConnectionManager.isWindowMagnifierEnabled(TEST_DISPLAY)); + assertTrue(mMagnificationConnectionManager.isWindowMagnifierEnabled(TEST_DISPLAY_2)); - mWindowMagnificationManager.resetAllIfNeeded(SERVICE_ID); + mMagnificationConnectionManager.resetAllIfNeeded(SERVICE_ID); - assertFalse(mWindowMagnificationManager.isWindowMagnifierEnabled(TEST_DISPLAY)); - assertFalse(mWindowMagnificationManager.isWindowMagnifierEnabled(TEST_DISPLAY_2)); + assertFalse(mMagnificationConnectionManager.isWindowMagnifierEnabled(TEST_DISPLAY)); + assertFalse(mMagnificationConnectionManager.isWindowMagnifierEnabled(TEST_DISPLAY_2)); } @Test public void resetAllMagnification_enabledByDifferentId_windowMagnifierDisabled() { final int serviceId2 = SERVICE_ID + 1; - mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); - mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3f, - 100f, 200f, null, WindowMagnificationManager.WINDOW_POSITION_AT_CENTER, SERVICE_ID); - mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY_2, 3f, - 100f, 200f, null, WindowMagnificationManager.WINDOW_POSITION_AT_CENTER, serviceId2); - assertTrue(mWindowMagnificationManager.isWindowMagnifierEnabled(TEST_DISPLAY)); - assertTrue(mWindowMagnificationManager.isWindowMagnifierEnabled(TEST_DISPLAY_2)); + mMagnificationConnectionManager.setConnection(mMockConnection.getConnection()); + mMagnificationConnectionManager.enableWindowMagnification(TEST_DISPLAY, 3f, + 100f, 200f, null, + MagnificationConnectionManager.WINDOW_POSITION_AT_CENTER, SERVICE_ID); + mMagnificationConnectionManager.enableWindowMagnification(TEST_DISPLAY_2, 3f, + 100f, 200f, null, + MagnificationConnectionManager.WINDOW_POSITION_AT_CENTER, serviceId2); + assertTrue(mMagnificationConnectionManager.isWindowMagnifierEnabled(TEST_DISPLAY)); + assertTrue(mMagnificationConnectionManager.isWindowMagnifierEnabled(TEST_DISPLAY_2)); - mWindowMagnificationManager.resetAllIfNeeded(SERVICE_ID); + mMagnificationConnectionManager.resetAllIfNeeded(SERVICE_ID); - assertFalse(mWindowMagnificationManager.isWindowMagnifierEnabled(TEST_DISPLAY)); - assertTrue(mWindowMagnificationManager.isWindowMagnifierEnabled(TEST_DISPLAY_2)); + assertFalse(mMagnificationConnectionManager.isWindowMagnifierEnabled(TEST_DISPLAY)); + assertTrue(mMagnificationConnectionManager.isWindowMagnifierEnabled(TEST_DISPLAY_2)); } @Test public void onScreenOff_windowMagnifierIsEnabled_removeButtonAndDisableWindowMagnification() throws RemoteException { - mWindowMagnificationManager.requestConnection(true); - mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 2.5f, NaN, NaN); + mMagnificationConnectionManager.requestConnection(true); + mMagnificationConnectionManager.enableWindowMagnification(TEST_DISPLAY, 2.5f, NaN, NaN); - mWindowMagnificationManager.mScreenStateReceiver.onReceive(mContext, + mMagnificationConnectionManager.mScreenStateReceiver.onReceive(mContext, new Intent(Intent.ACTION_SCREEN_OFF)); verify(mMockConnection.getConnection()).removeMagnificationButton(TEST_DISPLAY); verify(mMockConnection.getConnection()).disableWindowMagnification(TEST_DISPLAY, null); - assertFalse(mWindowMagnificationManager.isWindowMagnifierEnabled(TEST_DISPLAY)); + assertFalse(mMagnificationConnectionManager.isWindowMagnifierEnabled(TEST_DISPLAY)); } @Test public void centerGetter_enabledOnTestDisplay_expectedValues() { - mWindowMagnificationManager.requestConnection(true); - mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3f, 100f, 200f); + mMagnificationConnectionManager.requestConnection(true); + mMagnificationConnectionManager.enableWindowMagnification(TEST_DISPLAY, 3f, 100f, 200f); - assertEquals(mWindowMagnificationManager.getCenterX(TEST_DISPLAY), 100f); - assertEquals(mWindowMagnificationManager.getCenterY(TEST_DISPLAY), 200f); + assertEquals(mMagnificationConnectionManager.getCenterX(TEST_DISPLAY), 100f); + assertEquals(mMagnificationConnectionManager.getCenterY(TEST_DISPLAY), 200f); } @Test public void centerGetter_enabledOnTestDisplayWindowAtCenter_expectedValues() throws RemoteException { - mWindowMagnificationManager.requestConnection(true); - mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3f, - 100f, 200f, WindowMagnificationManager.WINDOW_POSITION_AT_CENTER); + mMagnificationConnectionManager.requestConnection(true); + mMagnificationConnectionManager.enableWindowMagnification(TEST_DISPLAY, 3f, + 100f, 200f, MagnificationConnectionManager.WINDOW_POSITION_AT_CENTER); - assertEquals(mWindowMagnificationManager.getCenterX(TEST_DISPLAY), 100f); - assertEquals(mWindowMagnificationManager.getCenterY(TEST_DISPLAY), 200f); + assertEquals(mMagnificationConnectionManager.getCenterX(TEST_DISPLAY), 100f); + assertEquals(mMagnificationConnectionManager.getCenterY(TEST_DISPLAY), 200f); verify(mMockConnection.getConnection()).enableWindowMagnification(eq(TEST_DISPLAY), eq(3f), eq(100f), eq(200f), eq(0f), eq(0f), notNull()); @@ -747,12 +754,12 @@ public class WindowMagnificationManagerTest { @Test public void centerGetter_enabledOnTestDisplayWindowAtLeftTop_expectedValues() throws RemoteException { - mWindowMagnificationManager.requestConnection(true); - mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3f, - 100f, 200f, WindowMagnificationManager.WINDOW_POSITION_AT_TOP_LEFT); + mMagnificationConnectionManager.requestConnection(true); + mMagnificationConnectionManager.enableWindowMagnification(TEST_DISPLAY, 3f, + 100f, 200f, MagnificationConnectionManager.WINDOW_POSITION_AT_TOP_LEFT); - assertEquals(mWindowMagnificationManager.getCenterX(TEST_DISPLAY), 100f); - assertEquals(mWindowMagnificationManager.getCenterY(TEST_DISPLAY), 200f); + assertEquals(mMagnificationConnectionManager.getCenterX(TEST_DISPLAY), 100f); + assertEquals(mMagnificationConnectionManager.getCenterY(TEST_DISPLAY), 200f); verify(mMockConnection.getConnection()).enableWindowMagnification(eq(TEST_DISPLAY), eq(3f), eq(100f), eq(200f), eq(-1f), eq(-1f), notNull()); @@ -760,48 +767,48 @@ public class WindowMagnificationManagerTest { @Test public void magnifierGetters_disabled_expectedValues() { - mWindowMagnificationManager.requestConnection(true); - mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3f, - 100f, 200f, WindowMagnificationManager.WINDOW_POSITION_AT_CENTER); + mMagnificationConnectionManager.requestConnection(true); + mMagnificationConnectionManager.enableWindowMagnification(TEST_DISPLAY, 3f, + 100f, 200f, MagnificationConnectionManager.WINDOW_POSITION_AT_CENTER); - mWindowMagnificationManager.disableWindowMagnification(TEST_DISPLAY, false); + mMagnificationConnectionManager.disableWindowMagnification(TEST_DISPLAY, false); - assertEquals(1f, mWindowMagnificationManager.getScale(TEST_DISPLAY), 0); - assertTrue(Float.isNaN(mWindowMagnificationManager.getCenterX(TEST_DISPLAY))); - assertTrue(Float.isNaN(mWindowMagnificationManager.getCenterY(TEST_DISPLAY))); + assertEquals(1f, mMagnificationConnectionManager.getScale(TEST_DISPLAY), 0); + assertTrue(Float.isNaN(mMagnificationConnectionManager.getCenterX(TEST_DISPLAY))); + assertTrue(Float.isNaN(mMagnificationConnectionManager.getCenterY(TEST_DISPLAY))); final Region bounds = new Region(); - mWindowMagnificationManager.getMagnificationSourceBounds(TEST_DISPLAY, bounds); + mMagnificationConnectionManager.getMagnificationSourceBounds(TEST_DISPLAY, bounds); assertTrue(bounds.isEmpty()); } @Test public void onDisplayRemoved_enabledOnTestDisplay_disabled() { - mWindowMagnificationManager.requestConnection(true); - mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3f, 100f, 200f); + mMagnificationConnectionManager.requestConnection(true); + mMagnificationConnectionManager.enableWindowMagnification(TEST_DISPLAY, 3f, 100f, 200f); - mWindowMagnificationManager.onDisplayRemoved(TEST_DISPLAY); + mMagnificationConnectionManager.onDisplayRemoved(TEST_DISPLAY); - assertFalse(mWindowMagnificationManager.isWindowMagnifierEnabled(TEST_DISPLAY)); + assertFalse(mMagnificationConnectionManager.isWindowMagnifierEnabled(TEST_DISPLAY)); } @Test public void onWindowMagnificationActivationState_magnifierEnabled_notifyActivatedState() { - mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); - mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, NaN, NaN); + mMagnificationConnectionManager.setConnection(mMockConnection.getConnection()); + mMagnificationConnectionManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, NaN, NaN); verify(mMockCallback).onWindowMagnificationActivationState(TEST_DISPLAY, true); } @Test public void onWindowMagnificationActivationState_magnifierDisabled_notifyDeactivatedState() { - mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); - mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, NaN, NaN); - mWindowMagnificationManager.disableWindowMagnification(TEST_DISPLAY, false); + mMagnificationConnectionManager.setConnection(mMockConnection.getConnection()); + mMagnificationConnectionManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, NaN, NaN); + mMagnificationConnectionManager.disableWindowMagnification(TEST_DISPLAY, false); verify(mMockCallback).onWindowMagnificationActivationState(TEST_DISPLAY, false); Mockito.reset(mMockCallback); - mWindowMagnificationManager.disableWindowMagnification(TEST_DISPLAY, false); + mMagnificationConnectionManager.disableWindowMagnification(TEST_DISPLAY, false); verify(mMockCallback, never()).onWindowMagnificationActivationState(eq(TEST_DISPLAY), anyBoolean()); diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationConnectionWrapperTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationConnectionWrapperTest.java index cfd0289e5650..8f85f11b7c49 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationConnectionWrapperTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationConnectionWrapperTest.java @@ -39,7 +39,7 @@ import org.mockito.MockitoAnnotations; /** * Tests for MagnificationConnectionWrapper. We don't test {@code * MagnificationConnectionWrapper#linkToDeath(IBinder.DeathRecipient)} since it's tested in - * {@link WindowMagnificationManagerTest}. + * {@link MagnificationConnectionManagerTest}. */ public class MagnificationConnectionWrapperTest { @@ -73,9 +73,9 @@ public class MagnificationConnectionWrapperTest { } @Test - public void setScale() throws RemoteException { - mConnectionWrapper.setScale(TEST_DISPLAY, 3.0f); - verify(mConnection).setScale(TEST_DISPLAY, 3.0f); + public void setScaleForWindowMagnification() throws RemoteException { + mConnectionWrapper.setScaleForWindowMagnification(TEST_DISPLAY, 3.0f); + verify(mConnection).setScaleForWindowMagnification(TEST_DISPLAY, 3.0f); } @Test 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 d4c6fad99645..e8cdf35dee13 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 @@ -131,7 +131,7 @@ public class MagnificationControllerTest { private ArgumentCaptor<MagnificationAnimationCallback> mCallbackArgumentCaptor; private MockWindowMagnificationConnection mMockConnection; - private WindowMagnificationManager mWindowMagnificationManager; + private MagnificationConnectionManager mMagnificationConnectionManager; private MockContentResolver mMockResolver; private MagnificationController mMagnificationController; private final WindowMagnificationMgrCallbackDelegate @@ -205,13 +205,14 @@ public class MagnificationControllerTest { )); mScreenMagnificationController.register(TEST_DISPLAY); - mWindowMagnificationManager = spy(new WindowMagnificationManager(mContext, globalLock, - mWindowMagnificationCallbackDelegate, mTraceManager, mScaleProvider)); + mMagnificationConnectionManager = spy( + new MagnificationConnectionManager(mContext, globalLock, + mWindowMagnificationCallbackDelegate, mTraceManager, mScaleProvider)); mMockConnection = new MockWindowMagnificationConnection(true); - mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); + mMagnificationConnectionManager.setConnection(mMockConnection.getConnection()); mMagnificationController = spy(new MagnificationController(mService, globalLock, mContext, - mScreenMagnificationController, mWindowMagnificationManager, mScaleProvider, + mScreenMagnificationController, mMagnificationConnectionManager, mScaleProvider, ConcurrentUtils.DIRECT_EXECUTOR)); mMagnificationController.setMagnificationCapabilities( Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ALL); @@ -254,8 +255,10 @@ public class MagnificationControllerTest { mCallbackArgumentCaptor.getValue().onResult(true); mMockConnection.invokeCallbacks(); verify(mTransitionCallBack).onResult(TEST_DISPLAY, true); - assertEquals(MAGNIFIED_CENTER_X, mWindowMagnificationManager.getCenterX(TEST_DISPLAY), 0); - assertEquals(MAGNIFIED_CENTER_Y, mWindowMagnificationManager.getCenterY(TEST_DISPLAY), 0); + assertEquals(MAGNIFIED_CENTER_X, + mMagnificationConnectionManager.getCenterX(TEST_DISPLAY), 0); + assertEquals(MAGNIFIED_CENTER_Y, + mMagnificationConnectionManager.getCenterY(TEST_DISPLAY), 0); } @Test @@ -297,8 +300,10 @@ public class MagnificationControllerTest { mMockConnection.invokeCallbacks(); verify(mTransitionCallBack).onResult(TEST_DISPLAY, true); - assertEquals(MAGNIFIED_CENTER_X, mWindowMagnificationManager.getCenterX(TEST_DISPLAY), 0); - assertEquals(MAGNIFIED_CENTER_Y, mWindowMagnificationManager.getCenterY(TEST_DISPLAY), 0); + assertEquals(MAGNIFIED_CENTER_X, + mMagnificationConnectionManager.getCenterX(TEST_DISPLAY), 0); + assertEquals(MAGNIFIED_CENTER_Y, + mMagnificationConnectionManager.getCenterY(TEST_DISPLAY), 0); } @Test @@ -316,7 +321,7 @@ public class MagnificationControllerTest { // The first time is triggered when window mode is activated. // The second time is triggered when activating the window mode again. // The third time is triggered when the transition is completed. - verify(mWindowMagnificationManager, times(3)).showMagnificationButton(eq(TEST_DISPLAY), + verify(mMagnificationConnectionManager, times(3)).showMagnificationButton(eq(TEST_DISPLAY), eq(MODE_WINDOW)); } @@ -330,7 +335,7 @@ public class MagnificationControllerTest { mTransitionCallBack); mMockConnection.invokeCallbacks(); - assertFalse(mWindowMagnificationManager.isWindowMagnifierEnabled(TEST_DISPLAY)); + assertFalse(mMagnificationConnectionManager.isWindowMagnifierEnabled(TEST_DISPLAY)); verify(mScreenMagnificationController).setScaleAndCenter(TEST_DISPLAY, DEFAULT_SCALE, MAGNIFIED_CENTER_X, MAGNIFIED_CENTER_Y, true, MAGNIFICATION_GESTURE_HANDLER_ID); @@ -350,7 +355,7 @@ public class MagnificationControllerTest { mTransitionCallBack); mMockConnection.invokeCallbacks(); - assertFalse(mWindowMagnificationManager.isWindowMagnifierEnabled(TEST_DISPLAY)); + assertFalse(mMagnificationConnectionManager.isWindowMagnifierEnabled(TEST_DISPLAY)); verify(mScreenMagnificationController).setScaleAndCenter(TEST_DISPLAY, DEFAULT_SCALE, magnificationBounds.exactCenterX(), magnificationBounds.exactCenterY(), true, MAGNIFICATION_GESTURE_HANDLER_ID); @@ -386,11 +391,11 @@ public class MagnificationControllerTest { mTransitionCallBack); // Enable window magnification while animating. - mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, DEFAULT_SCALE, + mMagnificationConnectionManager.enableWindowMagnification(TEST_DISPLAY, DEFAULT_SCALE, Float.NaN, Float.NaN, null, TEST_SERVICE_ID); mMockConnection.invokeCallbacks(); - assertTrue(mWindowMagnificationManager.isWindowMagnifierEnabled(TEST_DISPLAY)); + assertTrue(mMagnificationConnectionManager.isWindowMagnifierEnabled(TEST_DISPLAY)); verify(mScreenMagnificationController, never()).setScaleAndCenter(TEST_DISPLAY, DEFAULT_SCALE, MAGNIFIED_CENTER_X, MAGNIFIED_CENTER_Y, true, MAGNIFICATION_GESTURE_HANDLER_ID); @@ -408,8 +413,10 @@ public class MagnificationControllerTest { verify(mScreenMagnificationController).reset(eq(TEST_DISPLAY), eq(false)); mMockConnection.invokeCallbacks(); - assertEquals(MAGNIFIED_CENTER_X, mWindowMagnificationManager.getCenterX(TEST_DISPLAY), 0); - assertEquals(MAGNIFIED_CENTER_Y, mWindowMagnificationManager.getCenterY(TEST_DISPLAY), 0); + assertEquals(MAGNIFIED_CENTER_X, + mMagnificationConnectionManager.getCenterX(TEST_DISPLAY), 0); + assertEquals(MAGNIFIED_CENTER_Y, + mMagnificationConnectionManager.getCenterY(TEST_DISPLAY), 0); } @Test @@ -438,7 +445,7 @@ public class MagnificationControllerTest { animate, TEST_SERVICE_ID); mMockConnection.invokeCallbacks(); - assertFalse(mWindowMagnificationManager.isWindowMagnifierEnabled(TEST_DISPLAY)); + assertFalse(mMagnificationConnectionManager.isWindowMagnifierEnabled(TEST_DISPLAY)); verify(mScreenMagnificationController).setScaleAndCenter(eq(TEST_DISPLAY), eq(DEFAULT_SCALE), eq(MAGNIFIED_CENTER_X), eq(MAGNIFIED_CENTER_Y), any(MagnificationAnimationCallback.class), eq(TEST_SERVICE_ID)); @@ -564,7 +571,7 @@ public class MagnificationControllerTest { mMagnificationController.onDisplayRemoved(TEST_DISPLAY); verify(mScreenMagnificationController).onDisplayRemoved(TEST_DISPLAY); - verify(mWindowMagnificationManager).onDisplayRemoved(TEST_DISPLAY); + verify(mMagnificationConnectionManager).onDisplayRemoved(TEST_DISPLAY); verify(mScaleProvider).onDisplayRemoved(TEST_DISPLAY); } @@ -573,7 +580,7 @@ public class MagnificationControllerTest { mMagnificationController.updateUserIdIfNeeded(SECOND_USER_ID); verify(mScreenMagnificationController).resetAllIfNeeded(false); - verify(mWindowMagnificationManager).disableAllWindowMagnifiers(); + verify(mMagnificationConnectionManager).disableAllWindowMagnifiers(); verify(mScaleProvider).onUserChanged(SECOND_USER_ID); } @@ -584,7 +591,7 @@ public class MagnificationControllerTest { mMagnificationController.onRequestMagnificationSpec(TEST_DISPLAY, TEST_SERVICE_ID); mMockConnection.invokeCallbacks(); - assertFalse(mWindowMagnificationManager.isWindowMagnifierEnabled(TEST_DISPLAY)); + assertFalse(mMagnificationConnectionManager.isWindowMagnifierEnabled(TEST_DISPLAY)); } @Test @@ -594,11 +601,11 @@ public class MagnificationControllerTest { // The first time is trigger when fullscreen mode is activated. // The second time is triggered when magnification spec is changed. - verify(mWindowMagnificationManager, times(2)).showMagnificationButton(eq(TEST_DISPLAY), + verify(mMagnificationConnectionManager, times(2)).showMagnificationButton(eq(TEST_DISPLAY), eq(MODE_FULLSCREEN)); // Never call removeMagnificationSettingsPanel if it is allowed to show the settings panel // in current capability and mode, and the magnification is activated. - verify(mWindowMagnificationManager, never()).removeMagnificationSettingsPanel( + verify(mMagnificationConnectionManager, never()).removeMagnificationSettingsPanel( eq(TEST_DISPLAY)); } @@ -625,8 +632,8 @@ public class MagnificationControllerTest { mMagnificationController.onPerformScaleAction(TEST_DISPLAY, newScale, updatePersistence); - verify(mWindowMagnificationManager).setScale(eq(TEST_DISPLAY), eq(newScale)); - verify(mWindowMagnificationManager, never()).persistScale(eq(TEST_DISPLAY)); + verify(mMagnificationConnectionManager).setScale(eq(TEST_DISPLAY), eq(newScale)); + verify(mMagnificationConnectionManager, never()).persistScale(eq(TEST_DISPLAY)); } @Test @@ -669,7 +676,7 @@ public class MagnificationControllerTest { assertEquals(config.getCenterY(), actualConfig.getCenterY(), 0); assertEquals(config.getScale(), actualConfig.getScale(), 0); - verify(mWindowMagnificationManager).onUserMagnificationScaleChanged( + verify(mMagnificationConnectionManager).onUserMagnificationScaleChanged( /* userId= */ anyInt(), eq(TEST_DISPLAY), eq(config.getScale())); } @@ -677,11 +684,11 @@ public class MagnificationControllerTest { public void onSourceBoundChanged_windowEnabled_notifyMagnificationChanged() throws RemoteException { setMagnificationEnabled(MODE_WINDOW); - reset(mWindowMagnificationManager); + reset(mMagnificationConnectionManager); mMagnificationController.onSourceBoundsChanged(TEST_DISPLAY, TEST_RECT); - verify(mWindowMagnificationManager).onUserMagnificationScaleChanged( + verify(mMagnificationConnectionManager).onUserMagnificationScaleChanged( /* userId= */ anyInt(), eq(TEST_DISPLAY), eq(DEFAULT_SCALE)); } @@ -780,11 +787,11 @@ public class MagnificationControllerTest { // The first time is triggered when window mode is activated. // The second time is triggered when accessibility action performed. - verify(mWindowMagnificationManager, times(2)).showMagnificationButton(eq(TEST_DISPLAY), + verify(mMagnificationConnectionManager, times(2)).showMagnificationButton(eq(TEST_DISPLAY), eq(MODE_WINDOW)); // Never call removeMagnificationSettingsPanel if it is allowed to show the settings panel // in current capability and mode, and the magnification is activated. - verify(mWindowMagnificationManager, never()).removeMagnificationSettingsPanel( + verify(mMagnificationConnectionManager, never()).removeMagnificationSettingsPanel( eq(TEST_DISPLAY)); } @@ -799,10 +806,11 @@ public class MagnificationControllerTest { // The first time is triggered when window mode is activated. // The second time is triggered when accessibility action performed. - verify(mWindowMagnificationManager, times(2)).removeMagnificationButton(eq(TEST_DISPLAY)); + verify(mMagnificationConnectionManager, times(2)) + .removeMagnificationButton(eq(TEST_DISPLAY)); // Never call removeMagnificationSettingsPanel if it is allowed to show the settings panel // in current capability and mode, and the magnification is activated. - verify(mWindowMagnificationManager, never()).removeMagnificationSettingsPanel( + verify(mMagnificationConnectionManager, never()).removeMagnificationSettingsPanel( eq(TEST_DISPLAY)); } @@ -816,7 +824,7 @@ public class MagnificationControllerTest { public void deactivateWindowMagnification_windowActivated_triggerCallbackAndLogUsage() throws RemoteException { setMagnificationEnabled(MODE_WINDOW); - mWindowMagnificationManager.disableWindowMagnification(TEST_DISPLAY, /* clear= */ true); + mMagnificationConnectionManager.disableWindowMagnification(TEST_DISPLAY, /* clear= */ true); verify(mMagnificationController).onWindowMagnificationActivationState( eq(TEST_DISPLAY), eq(false)); @@ -828,7 +836,7 @@ public class MagnificationControllerTest { public void setPreferenceMagnificationFollowTypingEnabled_setPrefDisabled_disableAll() { mMagnificationController.setMagnificationFollowTypingEnabled(false); - verify(mWindowMagnificationManager).setMagnificationFollowTypingEnabled(eq(false)); + verify(mMagnificationConnectionManager).setMagnificationFollowTypingEnabled(eq(false)); verify(mScreenMagnificationController).setMagnificationFollowTypingEnabled(eq(false)); } @@ -850,7 +858,7 @@ public class MagnificationControllerTest { verify(mScreenMagnificationController).onRectangleOnScreenRequested(eq(TEST_DISPLAY), eq(TEST_RECT.left), eq(TEST_RECT.top), eq(TEST_RECT.right), eq(TEST_RECT.bottom)); - verify(mWindowMagnificationManager, never()).onRectangleOnScreenRequested(anyInt(), + verify(mMagnificationConnectionManager, never()).onRectangleOnScreenRequested(anyInt(), anyInt(), anyInt(), anyInt(), anyInt()); } @@ -867,7 +875,7 @@ public class MagnificationControllerTest { verify(mScreenMagnificationController, never()).onRectangleOnScreenRequested(anyInt(), anyInt(), anyInt(), anyInt(), anyInt()); - verify(mWindowMagnificationManager, never()).onRectangleOnScreenRequested(anyInt(), + verify(mMagnificationConnectionManager, never()).onRectangleOnScreenRequested(anyInt(), anyInt(), anyInt(), anyInt(), anyInt()); } @@ -880,7 +888,7 @@ public class MagnificationControllerTest { verify(mScreenMagnificationController, never()).onRectangleOnScreenRequested( eq(TEST_DISPLAY), anyInt(), anyInt(), anyInt(), anyInt()); - verify(mWindowMagnificationManager, never()).onRectangleOnScreenRequested(anyInt(), + verify(mMagnificationConnectionManager, never()).onRectangleOnScreenRequested(anyInt(), anyInt(), anyInt(), anyInt(), anyInt()); } @@ -895,7 +903,7 @@ public class MagnificationControllerTest { verify(mScreenMagnificationController, never()).onRectangleOnScreenRequested( eq(TEST_DISPLAY), anyInt(), anyInt(), anyInt(), anyInt()); - verify(mWindowMagnificationManager, never()).onRectangleOnScreenRequested(anyInt(), + verify(mMagnificationConnectionManager, never()).onRectangleOnScreenRequested(anyInt(), anyInt(), anyInt(), anyInt(), anyInt()); } @@ -970,7 +978,8 @@ public class MagnificationControllerTest { mMagnificationController.onFullScreenMagnificationActivationState(TEST_DISPLAY, true); - verify(mWindowMagnificationManager).disableWindowMagnification(eq(TEST_DISPLAY), eq(false)); + verify(mMagnificationConnectionManager) + .disableWindowMagnification(eq(TEST_DISPLAY), eq(false)); } @Test @@ -983,11 +992,11 @@ public class MagnificationControllerTest { // The first time is triggered when fullscreen mode is activated. // The second time is triggered when magnification spec is changed. // The third time is triggered when user interaction changed. - verify(mWindowMagnificationManager, times(3)).showMagnificationButton(eq(TEST_DISPLAY), + verify(mMagnificationConnectionManager, times(3)).showMagnificationButton(eq(TEST_DISPLAY), eq(MODE_FULLSCREEN)); // Never call removeMagnificationSettingsPanel if it is allowed to show the settings panel // in current capability and mode, and the magnification is activated. - verify(mWindowMagnificationManager, never()).removeMagnificationSettingsPanel( + verify(mMagnificationConnectionManager, never()).removeMagnificationSettingsPanel( eq(TEST_DISPLAY)); } @@ -1001,11 +1010,11 @@ public class MagnificationControllerTest { // The first time is triggered when fullscreen mode is activated. // The second time is triggered when magnification spec is changed. // The third time is triggered when user interaction changed. - verify(mWindowMagnificationManager, times(3)).showMagnificationButton(eq(TEST_DISPLAY), + verify(mMagnificationConnectionManager, times(3)).showMagnificationButton(eq(TEST_DISPLAY), eq(MODE_FULLSCREEN)); // Never call removeMagnificationSettingsPanel if it is allowed to show the settings panel // in current capability and mode, and the magnification is activated. - verify(mWindowMagnificationManager, never()).removeMagnificationSettingsPanel( + verify(mMagnificationConnectionManager, never()).removeMagnificationSettingsPanel( eq(TEST_DISPLAY)); } @@ -1018,11 +1027,11 @@ public class MagnificationControllerTest { // The first time is triggered when the window mode is activated. // The second time is triggered when user interaction changed. - verify(mWindowMagnificationManager, times(2)).showMagnificationButton(eq(TEST_DISPLAY), + verify(mMagnificationConnectionManager, times(2)).showMagnificationButton(eq(TEST_DISPLAY), eq(MODE_WINDOW)); // Never call removeMagnificationSettingsPanel if it is allowed to show the settings panel // in current capability and mode, and the magnification is activated. - verify(mWindowMagnificationManager, never()).removeMagnificationSettingsPanel( + verify(mMagnificationConnectionManager, never()).removeMagnificationSettingsPanel( eq(TEST_DISPLAY)); } @@ -1035,11 +1044,11 @@ public class MagnificationControllerTest { // The first time is triggered when the window mode is activated. // The second time is triggered when user interaction changed. - verify(mWindowMagnificationManager, times(2)).showMagnificationButton(eq(TEST_DISPLAY), + verify(mMagnificationConnectionManager, times(2)).showMagnificationButton(eq(TEST_DISPLAY), eq(MODE_WINDOW)); // Never call removeMagnificationSettingsPanel if it is allowed to show the settings panel // in current capability and mode, and the magnification is activated. - verify(mWindowMagnificationManager, never()).removeMagnificationSettingsPanel( + verify(mMagnificationConnectionManager, never()).removeMagnificationSettingsPanel( eq(TEST_DISPLAY)); } @@ -1053,11 +1062,11 @@ public class MagnificationControllerTest { mMagnificationController.onTouchInteractionStart(TEST_DISPLAY, MODE_FULLSCREEN); mMagnificationController.onTouchInteractionEnd(TEST_DISPLAY, MODE_FULLSCREEN); - verify(mWindowMagnificationManager, never()).showMagnificationButton(eq(TEST_DISPLAY), + verify(mMagnificationConnectionManager, never()).showMagnificationButton(eq(TEST_DISPLAY), eq(MODE_FULLSCREEN)); // The first time is triggered when fullscreen mode is activated. // The second time is triggered when magnification spec is changed. - verify(mWindowMagnificationManager, times(2)).removeMagnificationSettingsPanel( + verify(mMagnificationConnectionManager, times(2)).removeMagnificationSettingsPanel( eq(TEST_DISPLAY)); } @@ -1071,9 +1080,9 @@ public class MagnificationControllerTest { mMagnificationController.onTouchInteractionStart(TEST_DISPLAY, MODE_FULLSCREEN); mMagnificationController.onTouchInteractionEnd(TEST_DISPLAY, MODE_FULLSCREEN); - verify(mWindowMagnificationManager, never()).showMagnificationButton(eq(TEST_DISPLAY), + verify(mMagnificationConnectionManager, never()).showMagnificationButton(eq(TEST_DISPLAY), eq(MODE_FULLSCREEN)); - verify(mWindowMagnificationManager, times(2)).removeMagnificationSettingsPanel( + verify(mMagnificationConnectionManager, times(2)).removeMagnificationSettingsPanel( eq(TEST_DISPLAY)); } @@ -1082,11 +1091,11 @@ public class MagnificationControllerTest { throws RemoteException { setMagnificationEnabled(MODE_WINDOW); - verify(mWindowMagnificationManager).showMagnificationButton(eq(TEST_DISPLAY), + verify(mMagnificationConnectionManager).showMagnificationButton(eq(TEST_DISPLAY), eq(MODE_WINDOW)); // Never call removeMagnificationSettingsPanel if it is allowed to show the settings panel // in current capability and mode, and the magnification is activated. - verify(mWindowMagnificationManager, never()).removeMagnificationSettingsPanel( + verify(mMagnificationConnectionManager, never()).removeMagnificationSettingsPanel( eq(TEST_DISPLAY)); } @@ -1100,11 +1109,11 @@ public class MagnificationControllerTest { // The first time is triggered when fullscreen mode is activated. // The second time is triggered when magnification spec is changed. // The third time is triggered when fullscreen mode activation state is updated. - verify(mWindowMagnificationManager, times(3)).showMagnificationButton(eq(TEST_DISPLAY), + verify(mMagnificationConnectionManager, times(3)).showMagnificationButton(eq(TEST_DISPLAY), eq(MODE_FULLSCREEN)); // Never call removeMagnificationSettingsPanel if it is allowed to show the settings panel // in current capability and mode, and the magnification is activated. - verify(mWindowMagnificationManager, never()).removeMagnificationSettingsPanel( + verify(mMagnificationConnectionManager, never()).removeMagnificationSettingsPanel( eq(TEST_DISPLAY)); } @@ -1113,10 +1122,10 @@ public class MagnificationControllerTest { throws RemoteException { setMagnificationEnabled(MODE_WINDOW); - mWindowMagnificationManager.disableWindowMagnification(TEST_DISPLAY, false); + mMagnificationConnectionManager.disableWindowMagnification(TEST_DISPLAY, false); - verify(mWindowMagnificationManager).removeMagnificationButton(eq(TEST_DISPLAY)); - verify(mWindowMagnificationManager).removeMagnificationSettingsPanel(eq(TEST_DISPLAY)); + verify(mMagnificationConnectionManager).removeMagnificationButton(eq(TEST_DISPLAY)); + verify(mMagnificationConnectionManager).removeMagnificationSettingsPanel(eq(TEST_DISPLAY)); } @Test @@ -1126,8 +1135,8 @@ public class MagnificationControllerTest { setMagnificationEnabled(MODE_FULLSCREEN); mScreenMagnificationController.reset(TEST_DISPLAY, /* animate= */ true); - verify(mWindowMagnificationManager).removeMagnificationButton(eq(TEST_DISPLAY)); - verify(mWindowMagnificationManager).removeMagnificationSettingsPanel(eq(TEST_DISPLAY)); + verify(mMagnificationConnectionManager).removeMagnificationButton(eq(TEST_DISPLAY)); + verify(mMagnificationConnectionManager).removeMagnificationSettingsPanel(eq(TEST_DISPLAY)); } @Test @@ -1142,10 +1151,10 @@ public class MagnificationControllerTest { // The first time is triggered when fullscreen mode is activated. // The second time is triggered when magnification spec is changed. // The third time is triggered when the disable-magnification callback is triggered. - verify(mWindowMagnificationManager, times(3)).showMagnificationButton(eq(TEST_DISPLAY), + verify(mMagnificationConnectionManager, times(3)).showMagnificationButton(eq(TEST_DISPLAY), eq(MODE_FULLSCREEN)); // It is triggered when the disable-magnification callback is triggered. - verify(mWindowMagnificationManager).removeMagnificationSettingsPanel(eq(TEST_DISPLAY)); + verify(mMagnificationConnectionManager).removeMagnificationSettingsPanel(eq(TEST_DISPLAY)); } @Test @@ -1163,10 +1172,10 @@ public class MagnificationControllerTest { // The first time is triggered when window mode is activated. // The second time is triggered when the disable-magnification callback is triggered. - verify(mWindowMagnificationManager, times(2)).showMagnificationButton(eq(TEST_DISPLAY), + verify(mMagnificationConnectionManager, times(2)).showMagnificationButton(eq(TEST_DISPLAY), eq(MODE_WINDOW)); // It is triggered when the disable-magnification callback is triggered. - verify(mWindowMagnificationManager).removeMagnificationSettingsPanel(eq(TEST_DISPLAY)); + verify(mMagnificationConnectionManager).removeMagnificationSettingsPanel(eq(TEST_DISPLAY)); } @Test @@ -1174,9 +1183,9 @@ public class MagnificationControllerTest { throws RemoteException { setMagnificationEnabled(MODE_WINDOW); - mWindowMagnificationManager.disableWindowMagnification(TEST_DISPLAY, false); + mMagnificationConnectionManager.disableWindowMagnification(TEST_DISPLAY, false); - verify(mWindowMagnificationManager).removeMagnificationSettingsPanel(eq(TEST_DISPLAY)); + verify(mMagnificationConnectionManager).removeMagnificationSettingsPanel(eq(TEST_DISPLAY)); } @Test @@ -1185,7 +1194,7 @@ public class MagnificationControllerTest { setMagnificationEnabled(MODE_FULLSCREEN); mScreenMagnificationController.reset(TEST_DISPLAY, /* animate= */ true); - verify(mWindowMagnificationManager).removeMagnificationSettingsPanel(eq(TEST_DISPLAY)); + verify(mMagnificationConnectionManager).removeMagnificationSettingsPanel(eq(TEST_DISPLAY)); } @Test @@ -1260,17 +1269,17 @@ public class MagnificationControllerTest { private void activateMagnifier(int displayId, int mode, float centerX, float centerY) throws RemoteException { - final boolean windowMagnifying = mWindowMagnificationManager.isWindowMagnifierEnabled( + final boolean windowMagnifying = mMagnificationConnectionManager.isWindowMagnifierEnabled( displayId); if (windowMagnifying) { - mWindowMagnificationManager.disableWindowMagnification(displayId, false); + mMagnificationConnectionManager.disableWindowMagnification(displayId, false); mMockConnection.invokeCallbacks(); } if (mode == MODE_FULLSCREEN) { mScreenMagnificationController.setScaleAndCenter(displayId, DEFAULT_SCALE, centerX, centerY, true, AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID); } else { - mWindowMagnificationManager.enableWindowMagnification(displayId, DEFAULT_SCALE, + mMagnificationConnectionManager.enableWindowMagnification(displayId, DEFAULT_SCALE, centerX, centerY, null, TEST_SERVICE_ID); mMockConnection.invokeCallbacks(); } @@ -1304,10 +1313,10 @@ public class MagnificationControllerTest { } private static class WindowMagnificationMgrCallbackDelegate implements - WindowMagnificationManager.Callback { - private WindowMagnificationManager.Callback mCallback; + MagnificationConnectionManager.Callback { + private MagnificationConnectionManager.Callback mCallback; - public void setDelegate(WindowMagnificationManager.Callback callback) { + public void setDelegate(MagnificationConnectionManager.Callback callback) { mCallback = callback; } diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationGestureHandlerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationGestureHandlerTest.java index 612a091a6b1b..c4be51f9ecbd 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationGestureHandlerTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationGestureHandlerTest.java @@ -92,7 +92,7 @@ public class WindowMagnificationGestureHandlerTest { public final TestableContext mContext = new TestableContext( InstrumentationRegistry.getInstrumentation().getContext()); - private WindowMagnificationManager mWindowMagnificationManager; + private MagnificationConnectionManager mMagnificationConnectionManager; private MockWindowMagnificationConnection mMockConnection; private SpyWindowMagnificationGestureHandler mWindowMagnificationGestureHandler; private WindowMagnificationGestureHandler mMockWindowMagnificationGestureHandler; @@ -104,23 +104,23 @@ public class WindowMagnificationGestureHandlerTest { @Before public void setUp() throws RemoteException { MockitoAnnotations.initMocks(this); - mWindowMagnificationManager = new WindowMagnificationManager(mContext, new Object(), - mock(WindowMagnificationManager.Callback.class), mMockTrace, + mMagnificationConnectionManager = new MagnificationConnectionManager(mContext, new Object(), + mock(MagnificationConnectionManager.Callback.class), mMockTrace, new MagnificationScaleProvider(mContext)); mMockConnection = new MockWindowMagnificationConnection(); mWindowMagnificationGestureHandler = new SpyWindowMagnificationGestureHandler( - mContext, mWindowMagnificationManager, mMockTrace, mMockCallback, + mContext, mMagnificationConnectionManager, mMockTrace, mMockCallback, /** detectSingleFingerTripleTap= */ true, /** detectTwoFingerTripleTap= */ true, /** detectShortcutTrigger= */ true, DISPLAY_0); mMockWindowMagnificationGestureHandler = mWindowMagnificationGestureHandler.getMockGestureHandler(); - mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); + mMagnificationConnectionManager.setConnection(mMockConnection.getConnection()); mWindowMagnificationGestureHandler.setNext(strictMock(EventStreamTransformation.class)); } @After public void tearDown() { - mWindowMagnificationManager.disableWindowMagnification(DISPLAY_0, true); + mMagnificationConnectionManager.disableWindowMagnification(DISPLAY_0, true); } @Test @@ -378,7 +378,7 @@ public class WindowMagnificationGestureHandlerTest { } break; case STATE_SHOW_MAGNIFIER_SHORTCUT: { - mWindowMagnificationManager.disableWindowMagnification(DISPLAY_0, false); + mMagnificationConnectionManager.disableWindowMagnification(DISPLAY_0, false); } break; case STATE_TWO_FINGERS_DOWN: { @@ -423,7 +423,7 @@ public class WindowMagnificationGestureHandlerTest { } private boolean isWindowMagnifierEnabled(int displayId) { - return mWindowMagnificationManager.isWindowMagnifierEnabled(displayId); + return mMagnificationConnectionManager.isWindowMagnifierEnabled(displayId); } private static String stateToString(int state) { @@ -495,13 +495,14 @@ public class WindowMagnificationGestureHandlerTest { private final WindowMagnificationGestureHandler mMockWindowMagnificationGestureHandler; SpyWindowMagnificationGestureHandler(@UiContext Context context, - WindowMagnificationManager windowMagnificationMgr, + MagnificationConnectionManager magnificationConnectionManager, AccessibilityTraceManager trace, Callback callback, boolean detectSingleFingerTripleTap, boolean detectTwoFingerTripleTap, boolean detectShortcutTrigger, int displayId) { - super(context, windowMagnificationMgr, trace, callback, detectSingleFingerTripleTap, - detectTwoFingerTripleTap, detectShortcutTrigger, displayId); + super(context, magnificationConnectionManager, trace, callback, + detectSingleFingerTripleTap, detectTwoFingerTripleTap, + detectShortcutTrigger, displayId); mMockWindowMagnificationGestureHandler = mock(WindowMagnificationGestureHandler.class); } diff --git a/services/tests/servicestests/src/com/android/server/audio/LoudnessCodecHelperTest.java b/services/tests/servicestests/src/com/android/server/audio/LoudnessCodecHelperTest.java index 749b07d16ebe..9c8276aac4dd 100644 --- a/services/tests/servicestests/src/com/android/server/audio/LoudnessCodecHelperTest.java +++ b/services/tests/servicestests/src/com/android/server/audio/LoudnessCodecHelperTest.java @@ -19,6 +19,16 @@ import static android.media.AudioManager.GET_DEVICES_OUTPUTS; import static android.media.AudioPlaybackConfiguration.PLAYER_UPDATE_DEVICE_ID; import static android.media.LoudnessCodecInfo.CodecMetadataType.CODEC_METADATA_TYPE_MPEG_4; import static android.media.LoudnessCodecInfo.CodecMetadataType.CODEC_METADATA_TYPE_MPEG_D; +import static android.media.MediaFormat.KEY_AAC_DRC_EFFECT_TYPE; +import static android.media.MediaFormat.KEY_AAC_DRC_HEAVY_COMPRESSION; +import static android.media.MediaFormat.KEY_AAC_DRC_TARGET_REFERENCE_LEVEL; + +import static com.android.server.audio.LoudnessCodecHelper.SPL_RANGE_LARGE; +import static com.android.server.audio.LoudnessCodecHelper.SPL_RANGE_MEDIUM; +import static com.android.server.audio.LoudnessCodecHelper.SPL_RANGE_SMALL; +import static com.android.server.audio.LoudnessCodecHelper.SPL_RANGE_UNKNOWN; + +import static junit.framework.Assert.assertEquals; import static org.junit.Assume.assumeTrue; import static org.mockito.ArgumentMatchers.any; @@ -34,11 +44,15 @@ import android.media.ILoudnessCodecUpdatesDispatcher; import android.media.LoudnessCodecInfo; import android.media.PlayerBase; import android.os.IBinder; +import android.os.PersistableBundle; import android.platform.test.annotations.Presubmit; import android.util.Log; import androidx.test.ext.junit.runners.AndroidJUnit4; +import com.android.server.audio.LoudnessCodecHelper.DeviceSplRange; +import com.android.server.audio.LoudnessCodecHelper.LoudnessCodecInputProperties; + import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -84,8 +98,7 @@ public class LoudnessCodecHelperTest { mLoudnessHelper.registerLoudnessCodecUpdatesDispatcher(mDispatcher); mLoudnessHelper.startLoudnessCodecUpdates(mInitialApcPiid, - List.of(getLoudnessInfo(/*mediaCodecHash=*/111, /*isDownmixing=*/true, - CODEC_METADATA_TYPE_MPEG_4))); + List.of(getLoudnessInfo(/*isDownmixing=*/true, CODEC_METADATA_TYPE_MPEG_4))); verify(mDispatcher).dispatchLoudnessCodecParameterChange(eq(mInitialApcPiid), any()); } @@ -96,8 +109,7 @@ public class LoudnessCodecHelperTest { mLoudnessHelper.unregisterLoudnessCodecUpdatesDispatcher(mDispatcher); mLoudnessHelper.startLoudnessCodecUpdates(mInitialApcPiid, - List.of(getLoudnessInfo(/*mediaCodecHash=*/222, /*isDownmixing=*/false, - CODEC_METADATA_TYPE_MPEG_D))); + List.of(getLoudnessInfo(/*isDownmixing=*/false, CODEC_METADATA_TYPE_MPEG_D))); verify(mDispatcher, times(0)).dispatchLoudnessCodecParameterChange(eq(mInitialApcPiid), any()); @@ -108,11 +120,9 @@ public class LoudnessCodecHelperTest { mLoudnessHelper.registerLoudnessCodecUpdatesDispatcher(mDispatcher); mLoudnessHelper.startLoudnessCodecUpdates(mInitialApcPiid, - List.of(getLoudnessInfo(/*mediaCodecHash=*/111, /*isDownmixing=*/true, - CODEC_METADATA_TYPE_MPEG_4))); - mLoudnessHelper.addLoudnessCodecInfo(mInitialApcPiid, - getLoudnessInfo(/*mediaCodecHash=*/222, /*isDownmixing=*/true, - CODEC_METADATA_TYPE_MPEG_D)); + List.of(getLoudnessInfo(/*isDownmixing=*/true, CODEC_METADATA_TYPE_MPEG_4))); + mLoudnessHelper.addLoudnessCodecInfo(mInitialApcPiid, /*mediaCodecHash=*/222, + getLoudnessInfo(/*isDownmixing=*/true, CODEC_METADATA_TYPE_MPEG_D)); verify(mDispatcher, times(2)).dispatchLoudnessCodecParameterChange(eq(mInitialApcPiid), any()); @@ -124,11 +134,10 @@ public class LoudnessCodecHelperTest { mLoudnessHelper.registerLoudnessCodecUpdatesDispatcher(mDispatcher); mLoudnessHelper.startLoudnessCodecUpdates(mInitialApcPiid, - List.of(getLoudnessInfo(/*mediaCodecHash=*/111, /*isDownmixing=*/true, + List.of(getLoudnessInfo(/*isDownmixing=*/true, CODEC_METADATA_TYPE_MPEG_4))); - mLoudnessHelper.addLoudnessCodecInfo(newPiid, - getLoudnessInfo(/*mediaCodecHash=*/222, /*isDownmixing=*/true, - CODEC_METADATA_TYPE_MPEG_D)); + mLoudnessHelper.addLoudnessCodecInfo(newPiid, /*mediaCodecHash=*/222, + getLoudnessInfo(/*isDownmixing=*/true, CODEC_METADATA_TYPE_MPEG_D)); verify(mDispatcher, times(1)).dispatchLoudnessCodecParameterChange(eq(mInitialApcPiid), any()); @@ -140,12 +149,10 @@ public class LoudnessCodecHelperTest { mLoudnessHelper.registerLoudnessCodecUpdatesDispatcher(mDispatcher); mLoudnessHelper.startLoudnessCodecUpdates(mInitialApcPiid, - List.of(getLoudnessInfo(/*mediaCodecHash=*/111, /*isDownmixing=*/true, - CODEC_METADATA_TYPE_MPEG_4))); + List.of(getLoudnessInfo(/*isDownmixing=*/true, CODEC_METADATA_TYPE_MPEG_4))); //does not trigger dispatch since active apc list does not contain newPiid mLoudnessHelper.startLoudnessCodecUpdates(newPiid, - List.of(getLoudnessInfo(/*mediaCodecHash=*/222, /*isDownmixing=*/true, - CODEC_METADATA_TYPE_MPEG_D))); + List.of(getLoudnessInfo(/*isDownmixing=*/true, CODEC_METADATA_TYPE_MPEG_D))); verify(mDispatcher, times(1)).dispatchLoudnessCodecParameterChange(eq(mInitialApcPiid), any()); @@ -157,9 +164,8 @@ public class LoudnessCodecHelperTest { @Test public void updateCodecParameters_noStartedPiids_noDispatch() throws Exception { mLoudnessHelper.registerLoudnessCodecUpdatesDispatcher(mDispatcher); - mLoudnessHelper.addLoudnessCodecInfo(mInitialApcPiid, - getLoudnessInfo(/*mediaCodecHash=*/222, /*isDownmixing=*/true, - CODEC_METADATA_TYPE_MPEG_D)); + mLoudnessHelper.addLoudnessCodecInfo(mInitialApcPiid, /*mediaCodecHash=*/222, + getLoudnessInfo(/*isDownmixing=*/true, CODEC_METADATA_TYPE_MPEG_D)); mLoudnessHelper.updateCodecParameters(getApcListForPiids(mInitialApcPiid)); @@ -170,8 +176,8 @@ public class LoudnessCodecHelperTest { @Test public void updateCodecParameters_removedCodecInfo_noDispatch() throws Exception { - final LoudnessCodecInfo info = getLoudnessInfo(/*mediaCodecHash=*/111, - /*isDownmixing=*/true, CODEC_METADATA_TYPE_MPEG_4); + final LoudnessCodecInfo info = getLoudnessInfo(/*isDownmixing=*/true, + CODEC_METADATA_TYPE_MPEG_4); mLoudnessHelper.registerLoudnessCodecUpdatesDispatcher(mDispatcher); mLoudnessHelper.startLoudnessCodecUpdates(mInitialApcPiid, List.of(info)); @@ -186,8 +192,8 @@ public class LoudnessCodecHelperTest { @Test public void updateCodecParameters_stoppedPiids_noDispatch() throws Exception { - final LoudnessCodecInfo info = getLoudnessInfo(/*mediaCodecHash=*/111, - /*isDownmixing=*/true, CODEC_METADATA_TYPE_MPEG_4); + final LoudnessCodecInfo info = getLoudnessInfo(/*isDownmixing=*/true, + CODEC_METADATA_TYPE_MPEG_4); mLoudnessHelper.registerLoudnessCodecUpdatesDispatcher(mDispatcher); mLoudnessHelper.startLoudnessCodecUpdates(mInitialApcPiid, List.of(info)); @@ -200,6 +206,108 @@ public class LoudnessCodecHelperTest { any()); } + @Test + public void checkParcelableBundle_forMpeg4CodecInputProperties() { + PersistableBundle loudnessParameters = createInputProperties( + CODEC_METADATA_TYPE_MPEG_4, /*isDownmixing*/true, + SPL_RANGE_SMALL).createLoudnessParameters(); + assertEquals(64, loudnessParameters.getInt(KEY_AAC_DRC_TARGET_REFERENCE_LEVEL)); + assertEquals(1, loudnessParameters.getInt(KEY_AAC_DRC_HEAVY_COMPRESSION)); + + loudnessParameters = createInputProperties( + CODEC_METADATA_TYPE_MPEG_4, /*isDownmixing*/false, + SPL_RANGE_SMALL).createLoudnessParameters(); + assertEquals(64, loudnessParameters.getInt(KEY_AAC_DRC_TARGET_REFERENCE_LEVEL)); + assertEquals(1, loudnessParameters.getInt(KEY_AAC_DRC_HEAVY_COMPRESSION)); + + loudnessParameters = createInputProperties( + CODEC_METADATA_TYPE_MPEG_4, /*isDownmixing*/true, + SPL_RANGE_MEDIUM).createLoudnessParameters(); + assertEquals(96, loudnessParameters.getInt(KEY_AAC_DRC_TARGET_REFERENCE_LEVEL)); + assertEquals(1, loudnessParameters.getInt(KEY_AAC_DRC_HEAVY_COMPRESSION)); + + loudnessParameters = createInputProperties( + CODEC_METADATA_TYPE_MPEG_4, /*isDownmixing*/false, + SPL_RANGE_MEDIUM).createLoudnessParameters(); + assertEquals(96, loudnessParameters.getInt(KEY_AAC_DRC_TARGET_REFERENCE_LEVEL)); + assertEquals(0, loudnessParameters.getInt(KEY_AAC_DRC_HEAVY_COMPRESSION)); + + loudnessParameters = createInputProperties( + CODEC_METADATA_TYPE_MPEG_4, /*isDownmixing*/true, + SPL_RANGE_LARGE).createLoudnessParameters(); + assertEquals(124, loudnessParameters.getInt(KEY_AAC_DRC_TARGET_REFERENCE_LEVEL)); + assertEquals(0, loudnessParameters.getInt(KEY_AAC_DRC_HEAVY_COMPRESSION)); + + loudnessParameters = createInputProperties( + CODEC_METADATA_TYPE_MPEG_4, /*isDownmixing*/false, + SPL_RANGE_LARGE).createLoudnessParameters(); + assertEquals(124, loudnessParameters.getInt(KEY_AAC_DRC_TARGET_REFERENCE_LEVEL)); + assertEquals(0, loudnessParameters.getInt(KEY_AAC_DRC_HEAVY_COMPRESSION)); + + loudnessParameters = createInputProperties( + CODEC_METADATA_TYPE_MPEG_4, /*isDownmixing*/true, + SPL_RANGE_UNKNOWN).createLoudnessParameters(); + assertEquals(96, loudnessParameters.getInt(KEY_AAC_DRC_TARGET_REFERENCE_LEVEL)); + assertEquals(1, loudnessParameters.getInt(KEY_AAC_DRC_HEAVY_COMPRESSION)); + + loudnessParameters = createInputProperties( + CODEC_METADATA_TYPE_MPEG_4, /*isDownmixing*/false, + SPL_RANGE_UNKNOWN).createLoudnessParameters(); + assertEquals(96, loudnessParameters.getInt(KEY_AAC_DRC_TARGET_REFERENCE_LEVEL)); + assertEquals(0, loudnessParameters.getInt(KEY_AAC_DRC_HEAVY_COMPRESSION)); + } + + @Test + public void checkParcelableBundle_forMpegDCodecInputProperties() { + PersistableBundle loudnessParameters = createInputProperties( + CODEC_METADATA_TYPE_MPEG_D, /*isDownmixing*/true, + SPL_RANGE_SMALL).createLoudnessParameters(); + assertEquals(64, loudnessParameters.getInt(KEY_AAC_DRC_TARGET_REFERENCE_LEVEL)); + assertEquals(3, loudnessParameters.getInt(KEY_AAC_DRC_EFFECT_TYPE)); + + loudnessParameters = createInputProperties( + CODEC_METADATA_TYPE_MPEG_D, /*isDownmixing*/false, + SPL_RANGE_SMALL).createLoudnessParameters(); + assertEquals(64, loudnessParameters.getInt(KEY_AAC_DRC_TARGET_REFERENCE_LEVEL)); + assertEquals(3, loudnessParameters.getInt(KEY_AAC_DRC_EFFECT_TYPE)); + + loudnessParameters = createInputProperties( + CODEC_METADATA_TYPE_MPEG_D, /*isDownmixing*/true, + SPL_RANGE_MEDIUM).createLoudnessParameters(); + assertEquals(96, loudnessParameters.getInt(KEY_AAC_DRC_TARGET_REFERENCE_LEVEL)); + assertEquals(6, loudnessParameters.getInt(KEY_AAC_DRC_EFFECT_TYPE)); + + loudnessParameters = createInputProperties( + CODEC_METADATA_TYPE_MPEG_D, /*isDownmixing*/false, + SPL_RANGE_MEDIUM).createLoudnessParameters(); + assertEquals(96, loudnessParameters.getInt(KEY_AAC_DRC_TARGET_REFERENCE_LEVEL)); + assertEquals(6, loudnessParameters.getInt(KEY_AAC_DRC_EFFECT_TYPE)); + + loudnessParameters = createInputProperties( + CODEC_METADATA_TYPE_MPEG_D, /*isDownmixing*/true, + SPL_RANGE_LARGE).createLoudnessParameters(); + assertEquals(124, loudnessParameters.getInt(KEY_AAC_DRC_TARGET_REFERENCE_LEVEL)); + assertEquals(6, loudnessParameters.getInt(KEY_AAC_DRC_EFFECT_TYPE)); + + loudnessParameters = createInputProperties( + CODEC_METADATA_TYPE_MPEG_D, /*isDownmixing*/false, + SPL_RANGE_LARGE).createLoudnessParameters(); + assertEquals(124, loudnessParameters.getInt(KEY_AAC_DRC_TARGET_REFERENCE_LEVEL)); + assertEquals(6, loudnessParameters.getInt(KEY_AAC_DRC_EFFECT_TYPE)); + + loudnessParameters = createInputProperties( + CODEC_METADATA_TYPE_MPEG_D, /*isDownmixing*/true, + SPL_RANGE_UNKNOWN).createLoudnessParameters(); + assertEquals(96, loudnessParameters.getInt(KEY_AAC_DRC_TARGET_REFERENCE_LEVEL)); + assertEquals(6, loudnessParameters.getInt(KEY_AAC_DRC_EFFECT_TYPE)); + + loudnessParameters = createInputProperties( + CODEC_METADATA_TYPE_MPEG_D, /*isDownmixing*/false, + SPL_RANGE_UNKNOWN).createLoudnessParameters(); + assertEquals(96, loudnessParameters.getInt(KEY_AAC_DRC_TARGET_REFERENCE_LEVEL)); + assertEquals(6, loudnessParameters.getInt(KEY_AAC_DRC_EFFECT_TYPE)); + } + private List<AudioPlaybackConfiguration> getApcListForPiids(int... piids) { final ArrayList<AudioPlaybackConfiguration> apcList = new ArrayList<>(); @@ -220,11 +328,15 @@ public class LoudnessCodecHelperTest { return apcList; } - private static LoudnessCodecInfo getLoudnessInfo(int mediaCodecHash, boolean isDownmixing, - int metadataType) { + private static LoudnessCodecInputProperties createInputProperties( + int metadataType, boolean isDownmixing, @DeviceSplRange int splRange) { + return new LoudnessCodecInputProperties.Builder().setMetadataType( + metadataType).setIsDownmixing(isDownmixing).setDeviceSplRange(splRange).build(); + } + + private static LoudnessCodecInfo getLoudnessInfo(boolean isDownmixing, int metadataType) { LoudnessCodecInfo info = new LoudnessCodecInfo(); info.isDownmixing = isDownmixing; - info.mediaCodecHashCode = mediaCodecHash; info.metadataType = metadataType; return info; diff --git a/services/tests/servicestests/src/com/android/server/usage/IntervalStatsTests.java b/services/tests/servicestests/src/com/android/server/usage/IntervalStatsTests.java index 2be3f1e81897..517f48346b30 100644 --- a/services/tests/servicestests/src/com/android/server/usage/IntervalStatsTests.java +++ b/services/tests/servicestests/src/com/android/server/usage/IntervalStatsTests.java @@ -21,8 +21,11 @@ import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertTrue; import static junit.framework.Assert.fail; +import android.app.usage.Flags; import android.app.usage.UsageEvents; +import android.app.usage.UsageStatsManager; import android.content.res.Configuration; +import android.os.PersistableBundle; import android.test.suitebuilder.annotation.SmallTest; import androidx.test.runner.AndroidJUnit4; @@ -99,6 +102,17 @@ public class IntervalStatsTests { case UsageEvents.Event.LOCUS_ID_SET: event.mLocusId = "locus" + (i % 7); //"random" locus break; + case UsageEvents.Event.USER_INTERACTION: + if (Flags.userInteractionTypeApi()) { + // "random" user interaction extras. + PersistableBundle extras = new PersistableBundle(); + extras.putString(UsageStatsManager.EXTRA_EVENT_CATEGORY, + "fake.namespace.category" + (i % 13)); + extras.putString(UsageStatsManager.EXTRA_EVENT_ACTION, + "fakeaction" + (i % 13)); + event.mExtras = extras; + } + break; } intervalStats.addEvent(event); diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java index 09ffe71a6758..ee08fd26d631 100755 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -28,6 +28,7 @@ import static android.app.Notification.FLAG_AUTO_CANCEL; import static android.app.Notification.FLAG_BUBBLE; import static android.app.Notification.FLAG_CAN_COLORIZE; import static android.app.Notification.FLAG_FOREGROUND_SERVICE; +import static android.app.Notification.FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY; import static android.app.Notification.FLAG_NO_CLEAR; import static android.app.Notification.FLAG_ONGOING_EVENT; import static android.app.Notification.FLAG_ONLY_ALERT_ONCE; @@ -320,6 +321,11 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { private static final int SECONDARY_DISPLAY_ID = 42; private static final int TEST_PROFILE_USERHANDLE = 12; + private static final String ACTION_NOTIFICATION_TIMEOUT = + NotificationManagerService.class.getSimpleName() + ".TIMEOUT"; + private static final String EXTRA_KEY = "key"; + private static final String SCHEME_TIMEOUT = "timeout"; + private final int mUid = Binder.getCallingUid(); private final @UserIdInt int mUserId = UserHandle.getUserId(mUid); @@ -442,6 +448,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { MultiRateLimiter mToastRateLimiter; BroadcastReceiver mPackageIntentReceiver; BroadcastReceiver mUserSwitchIntentReceiver; + BroadcastReceiver mNotificationTimeoutReceiver; NotificationRecordLoggerFake mNotificationRecordLogger = new NotificationRecordLoggerFake(); TestableNotificationManagerService.StrongAuthTrackerFake mStrongAuthTracker; @@ -677,6 +684,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { verify(mContext, atLeastOnce()).registerReceiverAsUser(broadcastReceiverCaptor.capture(), any(), intentFilterCaptor.capture(), any(), any()); verify(mContext, atLeastOnce()).registerReceiver(broadcastReceiverCaptor.capture(), + intentFilterCaptor.capture(), anyInt()); + verify(mContext, atLeastOnce()).registerReceiver(broadcastReceiverCaptor.capture(), intentFilterCaptor.capture()); List<BroadcastReceiver> broadcastReceivers = broadcastReceiverCaptor.getAllValues(); List<IntentFilter> intentFilters = intentFilterCaptor.getAllValues(); @@ -695,9 +704,14 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { mUserSwitchIntentReceiver = broadcastReceivers.get(i); } } + if (filter.hasAction(ACTION_NOTIFICATION_TIMEOUT) + && filter.hasDataScheme(SCHEME_TIMEOUT)) { + mNotificationTimeoutReceiver = broadcastReceivers.get(i); + } } assertNotNull("package intent receiver should exist", mPackageIntentReceiver); assertNotNull("User-switch receiver should exist", mUserSwitchIntentReceiver); + assertNotNull("Notification timeout receiver should exist", mNotificationTimeoutReceiver); // Pretend the shortcut exists List<ShortcutInfo> shortcutInfos = new ArrayList<>(); @@ -2430,6 +2444,59 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { } @Test + public void testCancelWithTagDoesNotCancelLifetimeExtended() throws Exception { + mSetFlagsRule.enableFlags(android.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR); + final NotificationRecord notif = generateNotificationRecord(null); + notif.getSbn().getNotification().flags = + Notification.FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY; + mService.addNotification(notif); + final StatusBarNotification sbn = notif.getSbn(); + + assertThat(mBinderService.getActiveNotifications(sbn.getPackageName()).length).isEqualTo(1); + assertThat(mService.getNotificationRecordCount()).isEqualTo(1); + + mBinderService.cancelNotificationWithTag(PKG, PKG, sbn.getTag(), sbn.getId(), + sbn.getUserId()); + waitForIdle(); + + assertThat(mBinderService.getActiveNotifications(sbn.getPackageName()).length).isEqualTo(1); + assertThat(mService.getNotificationRecordCount()).isEqualTo(1); + + mSetFlagsRule.disableFlags(android.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR); + mBinderService.cancelNotificationWithTag(PKG, PKG, sbn.getTag(), sbn.getId(), + sbn.getUserId()); + waitForIdle(); + + assertThat(mBinderService.getActiveNotifications(sbn.getPackageName()).length).isEqualTo(0); + assertThat(mService.getNotificationRecordCount()).isEqualTo(0); + } + + @Test + public void testCancelAllDoesNotCancelLifetimeExtended() throws Exception { + mSetFlagsRule.enableFlags(android.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR); + // Adds a lifetime extended notification. + final NotificationRecord notif = generateNotificationRecord(mTestNotificationChannel, 1, + null, false); + notif.getSbn().getNotification().flags = + Notification.FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY; + mService.addNotification(notif); + // Adds a second, non-lifetime extended notification. + final NotificationRecord notifCancelable = generateNotificationRecord( + mTestNotificationChannel, 2, null, false); + mService.addNotification(notifCancelable); + // Verify that both notifications have been posted and are active. + assertThat(mBinderService.getActiveNotifications(PKG).length).isEqualTo(2); + + mBinderService.cancelAllNotifications(PKG, notif.getSbn().getUserId()); + waitForIdle(); + + // The non-lifetime extended notification, with id = 2, has been cancelled. + StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG); + assertThat(notifs.length).isEqualTo(1); + assertThat(notifs[0].getId()).isEqualTo(1); + } + + @Test public void testCancelNotificationWithTag_fromApp_cannotCancelFgsChild() throws Exception { when(mAmi.applyForegroundServiceNotification( @@ -2832,6 +2899,24 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { } @Test + public void testCancelNotificationsFromListener_clearAll_NoClearLifetimeExt() + throws Exception { + mSetFlagsRule.enableFlags(android.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR); + + final NotificationRecord notif = generateNotificationRecord( + mTestNotificationChannel, 1, null, false); + notif.getNotification().flags = FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY; + mService.addNotification(notif); + + mService.getBinderService().cancelNotificationsFromListener(null, null); + waitForIdle(); + + StatusBarNotification[] notifs = + mBinderService.getActiveNotifications(notif.getSbn().getPackageName()); + assertThat(notifs.length).isEqualTo(1); + } + + @Test public void testCancelNotificationsFromListener_byKey_GroupWithOngoingParent() throws Exception { final NotificationRecord parent = generateNotificationRecord( @@ -3036,6 +3121,22 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { } @Test + public void testCancelNotificationsFromListener_byKey_NoClearLifetimeExt() + throws Exception { + mSetFlagsRule.enableFlags(android.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR); + final NotificationRecord notif = generateNotificationRecord( + mTestNotificationChannel, 3, null, false); + notif.getNotification().flags |= FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY; + mService.addNotification(notif); + String[] keys = {notif.getSbn().getKey()}; + mService.getBinderService().cancelNotificationsFromListener(null, keys); + waitForIdle(); + StatusBarNotification[] notifs = + mBinderService.getActiveNotifications(notif.getSbn().getPackageName()); + assertEquals(1, notifs.length); + } + + @Test public void testGroupInstanceIds() throws Exception { final NotificationRecord group1 = generateNotificationRecord( mTestNotificationChannel, 1, "group1", true); @@ -5298,6 +5399,79 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { anyInt()); } + private void simulateNotificationTimeoutBroadcast(String notificationKey) { + final Bundle extras = new Bundle(); + extras.putString(EXTRA_KEY, notificationKey); + final Intent intent = new Intent(ACTION_NOTIFICATION_TIMEOUT); + intent.putExtras(extras); + mNotificationTimeoutReceiver.onReceive(getContext(), intent); + } + + @Test + public void testTimeout_CancelsNotification() throws Exception { + final NotificationRecord notif = generateNotificationRecord( + mTestNotificationChannel, 1, null, false); + mService.addNotification(notif); + + simulateNotificationTimeoutBroadcast(notif.getKey()); + waitForIdle(); + + // Check that the notification was cancelled. + StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG); + assertThat(notifsAfter.length).isEqualTo(0); + assertThat(mService.getNotificationRecord(notif.getKey())).isNull(); + } + + @Test + public void testTimeout_NoCancelForegroundServiceNotification() throws Exception { + // Creates a notification with FLAG_FOREGROUND_SERVICE + final NotificationRecord notif = generateNotificationRecord(null); + notif.getSbn().getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE; + mService.addNotification(notif); + + simulateNotificationTimeoutBroadcast(notif.getKey()); + waitForIdle(); + + // Check that the notification was not cancelled. + StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG); + assertThat(notifsAfter.length).isEqualTo(1); + assertThat(mService.getNotificationRecord(notif.getKey())).isEqualTo(notif); + } + + @Test + public void testTimeout_NoCancelUserInitJobNotification() throws Exception { + // Create a notification with FLAG_USER_INITIATED_JOB + final NotificationRecord notif = generateNotificationRecord(null); + notif.getSbn().getNotification().flags = Notification.FLAG_USER_INITIATED_JOB; + mService.addNotification(notif); + + simulateNotificationTimeoutBroadcast(notif.getKey()); + waitForIdle(); + + // Check that the notification was not cancelled. + StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG); + assertThat(notifsAfter.length).isEqualTo(1); + assertThat(mService.getNotificationRecord(notif.getKey())).isEqualTo(notif); + } + + @Test + public void testTimeout_NoCancelLifetimeExtensionNotification() throws Exception { + mSetFlagsRule.enableFlags(android.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR); + // Create a notification with FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY + final NotificationRecord notif = generateNotificationRecord(null); + notif.getSbn().getNotification().flags = + Notification.FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY; + mService.addNotification(notif); + + simulateNotificationTimeoutBroadcast(notif.getKey()); + waitForIdle(); + + // Check that the notification was not cancelled. + StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG); + assertThat(notifsAfter.length).isEqualTo(1); + assertThat(mService.getNotificationRecord(notif.getKey())).isEqualTo(notif); + } + @Test public void testBumpFGImportance_channelChangePreOApp() throws Exception { String preOPkg = PKG_N_MR1; @@ -7913,6 +8087,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { @Test public void testOnNotificationSmartReplySent() { + mSetFlagsRule.enableFlags(android.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR); final int replyIndex = 2; final String reply = "Hello"; final boolean modifiedBeforeSending = true; @@ -7930,6 +8105,10 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { assertEquals(1, mNotificationRecordLogger.numCalls()); assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_SMART_REPLIED, mNotificationRecordLogger.event(0)); + // Check that r.recordSmartReplied was called. + assertThat(r.getSbn().getNotification().flags & FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY) + .isGreaterThan(0); + assertThat(r.getStats().hasSmartReplied()).isTrue(); } @Test @@ -13116,6 +13295,20 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { eq("package"), anyString(), anyInt(), anyBoolean()); } + @Test + public void testFixNotification_clearsLifetimeExtendedFlag() throws Exception { + mSetFlagsRule.enableFlags(android.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR); + Notification n = new Notification.Builder(mContext, "test") + .setFlag(FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY, true) + .build(); + + assertThat(n.flags & FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY).isGreaterThan(0); + + mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true); + + assertThat(n.flags & FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY).isEqualTo(0); + } + private NotificationRecord createAndPostNotification(Notification.Builder nb, String testName) throws RemoteException { StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, testName, mUid, 0, diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java index f83a1df358bd..670d09795e12 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java @@ -29,6 +29,8 @@ import static android.service.notification.NotificationListenerService.Ranking.U import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL; import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_POSITIVE; +import static com.google.common.truth.Truth.assertThat; + import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertNotNull; @@ -44,6 +46,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import android.app.ActivityManager; +import android.app.Flags; import android.app.Notification; import android.app.Notification.Builder; import android.app.NotificationChannel; @@ -64,6 +67,7 @@ import android.os.Build; import android.os.Bundle; import android.os.UserHandle; import android.os.Vibrator; +import android.platform.test.flag.junit.SetFlagsRule; import android.provider.Settings; import android.service.notification.Adjustment; import android.service.notification.StatusBarNotification; @@ -80,6 +84,7 @@ import com.android.server.UiServiceTestCase; import com.android.server.uri.UriGrantsManagerInternal; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; @@ -122,6 +127,9 @@ public class NotificationRecordTest extends UiServiceTestCase { private static final NotificationRecord.Light CUSTOM_LIGHT = new NotificationRecord.Light(1, 2, 3); + @Rule + public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); + @Before public void setUp() { MockitoAnnotations.initMocks(this); @@ -651,6 +659,7 @@ public class NotificationRecordTest extends UiServiceTestCase { @Test public void testNotificationStats() { + mSetFlagsRule.enableFlags(Flags.FLAG_LIFETIME_EXTENSION_REFACTOR); StatusBarNotification sbn = getNotification(PKG_O, true /* noisy */, true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */, false /* lights */, false /* defaultLights */, groupId /* group */); @@ -690,6 +699,37 @@ public class NotificationRecordTest extends UiServiceTestCase { record.recordDirectReplied(); assertTrue(record.getStats().hasDirectReplied()); + + record.recordSmartReplied(); + assertThat(record.getStats().hasSmartReplied()).isTrue(); + } + + @Test + public void testDirectRepliedAddsLifetimeExtensionFlag() { + mSetFlagsRule.enableFlags(Flags.FLAG_LIFETIME_EXTENSION_REFACTOR); + + StatusBarNotification sbn = getNotification(PKG_O, true /* noisy */, + true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */, + false /* lights */, false /* defaultLights */, groupId /* group */); + NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel); + + record.recordDirectReplied(); + assertThat(record.getSbn().getNotification().flags + & Notification.FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY).isGreaterThan(0); + } + + @Test + public void testSmartRepliedAddsLifetimeExtensionFlag() { + mSetFlagsRule.enableFlags(Flags.FLAG_LIFETIME_EXTENSION_REFACTOR); + + StatusBarNotification sbn = getNotification(PKG_O, true /* noisy */, + true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */, + false /* lights */, false /* defaultLights */, groupId /* group */); + NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel); + + record.recordSmartReplied(); + assertThat(record.getSbn().getNotification().flags + & Notification.FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY).isGreaterThan(0); } @Test diff --git a/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java b/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java index 2c35cf0c4151..8d236eda5dc5 100644 --- a/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java +++ b/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java @@ -110,24 +110,6 @@ public class ModifierShortcutTests extends ShortcutKeyTestBase { } /** - * META + SPACE to switch keyboard layout. - */ - @Test - public void testMetaSpace() { - sendKeyCombination(new int[]{KEYCODE_META_LEFT, KEYCODE_SPACE}, 0); - mPhoneWindowManager.assertSwitchKeyboardLayout(1); - } - - /** - * META + SHIFT + SPACE to switch keyboard layout backwards. - */ - @Test - public void testMetaShiftSpace() { - sendKeyCombination(new int[]{KEYCODE_META_LEFT, KEYCODE_SHIFT_LEFT, KEYCODE_SPACE}, 0); - mPhoneWindowManager.assertSwitchKeyboardLayout(-1); - } - - /** * CTRL + ALT + Z to enable accessibility service. */ @Test diff --git a/services/tests/wmtests/src/com/android/server/policy/ShortcutLoggingTests.java b/services/tests/wmtests/src/com/android/server/policy/ShortcutLoggingTests.java index 71098aa5e883..2d7f044baf18 100644 --- a/services/tests/wmtests/src/com/android/server/policy/ShortcutLoggingTests.java +++ b/services/tests/wmtests/src/com/android/server/policy/ShortcutLoggingTests.java @@ -30,13 +30,13 @@ import androidx.test.filters.MediumTest; import com.android.internal.annotations.Keep; import com.android.server.input.KeyboardMetricsCollector.KeyboardLogEvent; +import junitparams.JUnitParamsRunner; +import junitparams.Parameters; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import junitparams.JUnitParamsRunner; -import junitparams.Parameters; - @Presubmit @MediumTest @RunWith(JUnitParamsRunner.class) @@ -71,8 +71,8 @@ public class ShortcutLoggingTests extends ShortcutKeyTestBase { KeyboardLogEvent.RECENT_APPS, KeyEvent.KEYCODE_TAB, ALT_ON}, {"BACK key -> Go back", new int[]{KeyEvent.KEYCODE_BACK}, KeyboardLogEvent.BACK, KeyEvent.KEYCODE_BACK, 0}, - {"Meta + `(grave) -> Go back", new int[]{META_KEY, KeyEvent.KEYCODE_GRAVE}, - KeyboardLogEvent.BACK, KeyEvent.KEYCODE_GRAVE, META_ON}, + {"Meta + Escape -> Go back", new int[]{META_KEY, KeyEvent.KEYCODE_ESCAPE}, + KeyboardLogEvent.BACK, KeyEvent.KEYCODE_ESCAPE, META_ON}, {"Meta + Left arrow -> Go back", new int[]{META_KEY, KeyEvent.KEYCODE_DPAD_LEFT}, KeyboardLogEvent.BACK, KeyEvent.KEYCODE_DPAD_LEFT, META_ON}, {"Meta + Del -> Go back", new int[]{META_KEY, KeyEvent.KEYCODE_DEL}, @@ -132,13 +132,6 @@ public class ShortcutLoggingTests extends ShortcutKeyTestBase { {"LANGUAGE_SWITCH key -> Switch Keyboard Language", new int[]{KeyEvent.KEYCODE_LANGUAGE_SWITCH}, KeyboardLogEvent.LANGUAGE_SWITCH, KeyEvent.KEYCODE_LANGUAGE_SWITCH, 0}, - {"Meta + Space -> Switch Keyboard Language", - new int[]{META_KEY, KeyEvent.KEYCODE_SPACE}, - KeyboardLogEvent.LANGUAGE_SWITCH, KeyEvent.KEYCODE_SPACE, META_ON}, - {"Meta + Shift + Space -> Switch Keyboard Language", - new int[]{META_KEY, SHIFT_KEY, KeyEvent.KEYCODE_SPACE}, - KeyboardLogEvent.LANGUAGE_SWITCH, KeyEvent.KEYCODE_SPACE, - META_ON | SHIFT_ON}, {"META key -> Open App Drawer in Accessibility mode", new int[]{META_KEY}, KeyboardLogEvent.ACCESSIBILITY_ALL_APPS, META_KEY, META_ON}, {"Meta + Alt -> Toggle CapsLock", new int[]{META_KEY, ALT_KEY}, diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java index 8a90f127f4eb..06f29c262b42 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java @@ -25,7 +25,9 @@ import static android.view.WindowManager.TRANSIT_CLOSE; import static android.view.WindowManager.TRANSIT_NONE; import static android.view.WindowManager.TRANSIT_OPEN; import static android.window.TaskFragmentOperation.OP_TYPE_CREATE_TASK_FRAGMENT; +import static android.window.TaskFragmentOperation.OP_TYPE_CREATE_TASK_FRAGMENT_DECOR_SURFACE; import static android.window.TaskFragmentOperation.OP_TYPE_DELETE_TASK_FRAGMENT; +import static android.window.TaskFragmentOperation.OP_TYPE_REMOVE_TASK_FRAGMENT_DECOR_SURFACE; import static android.window.TaskFragmentOperation.OP_TYPE_REORDER_TO_BOTTOM_OF_TASK; import static android.window.TaskFragmentOperation.OP_TYPE_REORDER_TO_FRONT; import static android.window.TaskFragmentOperation.OP_TYPE_REORDER_TO_TOP_OF_TASK; @@ -1759,6 +1761,40 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase { } @Test + public void testApplyTransaction_createTaskFragmentDecorSurface() { + // TODO(b/293654166) remove system organizer requirement once security review is cleared. + mController.unregisterOrganizer(mIOrganizer); + mController.registerOrganizerInternal(mIOrganizer, true /* isSystemOrganizer */); + final Task task = createTask(mDisplayContent); + + final TaskFragment tf = createTaskFragment(task); + final TaskFragmentOperation operation = new TaskFragmentOperation.Builder( + OP_TYPE_CREATE_TASK_FRAGMENT_DECOR_SURFACE).build(); + mTransaction.addTaskFragmentOperation(tf.getFragmentToken(), operation); + + assertApplyTransactionAllowed(mTransaction); + + verify(task).moveOrCreateDecorSurfaceFor(tf); + } + + @Test + public void testApplyTransaction_removeTaskFragmentDecorSurface() { + // TODO(b/293654166) remove system organizer requirement once security review is cleared. + mController.unregisterOrganizer(mIOrganizer); + mController.registerOrganizerInternal(mIOrganizer, true /* isSystemOrganizer */); + final Task task = createTask(mDisplayContent); + final TaskFragment tf = createTaskFragment(task); + + final TaskFragmentOperation operation = new TaskFragmentOperation.Builder( + OP_TYPE_REMOVE_TASK_FRAGMENT_DECOR_SURFACE).build(); + mTransaction.addTaskFragmentOperation(tf.getFragmentToken(), operation); + + assertApplyTransactionAllowed(mTransaction); + + verify(task).removeDecorSurface(); + } + + @Test public void testApplyTransaction_reorderToBottomOfTask_failsIfNotSystemOrganizer() { testApplyTransaction_reorder_failsIfNotSystemOrganizer_common( OP_TYPE_REORDER_TO_BOTTOM_OF_TASK); @@ -1966,7 +2002,8 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase { /** Setups the mock Task as the parent of the given TaskFragment. */ private static void setupMockParent(TaskFragment taskFragment, Task mockParent) { doReturn(mockParent).when(taskFragment).getTask(); - doReturn(new TaskFragmentParentInfo(new Configuration(), DEFAULT_DISPLAY, true, true)) + doReturn(new TaskFragmentParentInfo( + new Configuration(), DEFAULT_DISPLAY, true, true, null /* decorSurface */)) .when(mockParent).getTaskFragmentParentInfo(); // Task needs to be visible diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java index 5e531b4cbc4f..da7612b17dc9 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java @@ -63,6 +63,7 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.same; import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.clearInvocations; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import android.app.ActivityManager; @@ -82,6 +83,7 @@ import android.util.DisplayMetrics; import android.util.Xml; import android.view.Display; import android.view.DisplayInfo; +import android.view.SurfaceControl; import android.window.TaskFragmentOrganizer; import androidx.test.filters.MediumTest; @@ -1619,6 +1621,185 @@ public class TaskTests extends WindowTestsBase { assertFalse(task.isDragResizing()); } + @Test + public void testMoveOrCreateDecorSurface() { + final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run); + final Task task = new TaskBuilder(mSupervisor).setCreateActivity(true).build(); + final ActivityRecord activity = task.getTopMostActivity(); + final TaskFragment fragment = createTaskFragmentWithEmbeddedActivity(task, organizer); + doNothing().when(task).sendTaskFragmentParentInfoChangedIfNeeded(); + + // Decor surface should not be present initially. + assertNull(task.mDecorSurfaceContainer); + assertNull(task.getDecorSurface()); + assertNull(task.getTaskFragmentParentInfo().getDecorSurface()); + + // Decor surface should be created. + clearInvocations(task); + task.moveOrCreateDecorSurfaceFor(fragment); + + assertNotNull(task.mDecorSurfaceContainer); + assertNotNull(task.getDecorSurface()); + verify(task).sendTaskFragmentParentInfoChangedIfNeeded(); + assertNotNull(task.getTaskFragmentParentInfo().getDecorSurface()); + assertEquals(fragment, task.mDecorSurfaceContainer.mOwnerTaskFragment); + + // Decor surface should be removed. + clearInvocations(task); + task.removeDecorSurface(); + + assertNull(task.mDecorSurfaceContainer); + assertNull(task.getDecorSurface()); + verify(task).sendTaskFragmentParentInfoChangedIfNeeded(); + assertNull(task.getTaskFragmentParentInfo().getDecorSurface()); + } + + @Test + public void testMoveOrCreateDecorSurface_whenOwnerTaskFragmentRemoved() { + final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run); + final Task task = new TaskBuilder(mSupervisor).setCreateActivity(true).build(); + final ActivityRecord activity = task.getTopMostActivity(); + final TaskFragment fragment1 = createTaskFragmentWithEmbeddedActivity(task, organizer); + final TaskFragment fragment2 = createTaskFragmentWithEmbeddedActivity(task, organizer); + doNothing().when(task).sendTaskFragmentParentInfoChangedIfNeeded(); + + task.moveOrCreateDecorSurfaceFor(fragment1); + + assertNotNull(task.mDecorSurfaceContainer); + assertNotNull(task.getDecorSurface()); + assertEquals(fragment1, task.mDecorSurfaceContainer.mOwnerTaskFragment); + + // Transfer ownership + task.moveOrCreateDecorSurfaceFor(fragment2); + + assertNotNull(task.mDecorSurfaceContainer); + assertNotNull(task.getDecorSurface()); + assertEquals(fragment2, task.mDecorSurfaceContainer.mOwnerTaskFragment); + + // Safe surface should be removed when the owner TaskFragment is removed. + task.removeChild(fragment2); + + verify(task).removeDecorSurface(); + assertNull(task.mDecorSurfaceContainer); + assertNull(task.getDecorSurface()); + } + + @Test + public void testAssignChildLayers_decorSurfacePlacement() { + final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run); + final Task task = new TaskBuilder(mSupervisor).setCreateActivity(true).build(); + final ActivityRecord unembeddedActivity = task.getTopMostActivity(); + + final TaskFragment fragment1 = createTaskFragmentWithEmbeddedActivity(task, organizer); + final TaskFragment fragment2 = createTaskFragmentWithEmbeddedActivity(task, organizer); + final SurfaceControl.Transaction t = mock(SurfaceControl.Transaction.class); + + doNothing().when(task).sendTaskFragmentParentInfoChangedIfNeeded(); + spyOn(unembeddedActivity); + spyOn(fragment1); + spyOn(fragment2); + + // Initially, the decor surface should not be placed. + task.assignChildLayers(t); + verify(unembeddedActivity).assignLayer(t, 0); + verify(fragment1).assignLayer(t, 1); + verify(fragment2).assignLayer(t, 2); + + clearInvocations(t); + clearInvocations(unembeddedActivity); + clearInvocations(fragment1); + clearInvocations(fragment2); + + // The decor surface should be placed just above the owner TaskFragment. + doReturn(true).when(unembeddedActivity).isUid(task.effectiveUid); + doReturn(true).when(fragment1).isAllowedToBeEmbeddedInTrustedMode(); + doReturn(true).when(fragment2).isAllowedToBeEmbeddedInTrustedMode(); + doReturn(true).when(fragment1).isVisible(); + + task.moveOrCreateDecorSurfaceFor(fragment1); + task.assignChildLayers(t); + + verify(unembeddedActivity).assignLayer(t, 0); + verify(fragment1).assignLayer(t, 1); + verify(t).setLayer(task.mDecorSurfaceContainer.mContainerSurface, 2); + verify(fragment2).assignLayer(t, 3); + verify(t).setVisibility(task.mDecorSurfaceContainer.mContainerSurface, true); + verify(t, never()).setLayer(eq(task.getDecorSurface()), anyInt()); + + clearInvocations(t); + clearInvocations(unembeddedActivity); + clearInvocations(fragment1); + clearInvocations(fragment2); + + // The decor surface should be invisible if the owner TaskFragment is invisible. + doReturn(true).when(unembeddedActivity).isUid(task.effectiveUid); + doReturn(true).when(fragment1).isAllowedToBeEmbeddedInTrustedMode(); + doReturn(true).when(fragment2).isAllowedToBeEmbeddedInTrustedMode(); + doReturn(false).when(fragment1).isVisible(); + + task.assignChildLayers(t); + + verify(unembeddedActivity).assignLayer(t, 0); + verify(fragment1).assignLayer(t, 1); + verify(t).setLayer(task.mDecorSurfaceContainer.mContainerSurface, 2); + verify(fragment2).assignLayer(t, 3); + verify(t).setVisibility(task.mDecorSurfaceContainer.mContainerSurface, false); + verify(t, never()).setLayer(eq(task.getDecorSurface()), anyInt()); + + clearInvocations(t); + clearInvocations(unembeddedActivity); + clearInvocations(fragment1); + clearInvocations(fragment2); + + // The decor surface should be placed on below activity from a different UID. + doReturn(false).when(unembeddedActivity).isUid(task.effectiveUid); + doReturn(true).when(fragment1).isAllowedToBeEmbeddedInTrustedMode(); + doReturn(true).when(fragment2).isAllowedToBeEmbeddedInTrustedMode(); + doReturn(true).when(fragment1).isVisible(); + + task.assignChildLayers(t); + + verify(t).setLayer(task.mDecorSurfaceContainer.mContainerSurface, 0); + verify(unembeddedActivity).assignLayer(t, 1); + verify(fragment1).assignLayer(t, 2); + verify(fragment2).assignLayer(t, 3); + verify(t).setVisibility(task.mDecorSurfaceContainer.mContainerSurface, true); + verify(t, never()).setLayer(eq(task.getDecorSurface()), anyInt()); + + clearInvocations(t); + clearInvocations(unembeddedActivity); + clearInvocations(fragment1); + clearInvocations(fragment2); + + // The decor surface should be placed below untrusted embedded TaskFragment. + doReturn(true).when(unembeddedActivity).isUid(task.effectiveUid); + doReturn(true).when(fragment1).isAllowedToBeEmbeddedInTrustedMode(); + doReturn(false).when(fragment2).isAllowedToBeEmbeddedInTrustedMode(); + doReturn(true).when(fragment1).isVisible(); + + task.assignChildLayers(t); + + verify(unembeddedActivity).assignLayer(t, 0); + verify(fragment1).assignLayer(t, 1); + verify(t).setLayer(task.mDecorSurfaceContainer.mContainerSurface, 2); + verify(fragment2).assignLayer(t, 3); + verify(t).setVisibility(task.mDecorSurfaceContainer.mContainerSurface, true); + verify(t, never()).setLayer(eq(task.getDecorSurface()), anyInt()); + + clearInvocations(t); + clearInvocations(unembeddedActivity); + clearInvocations(fragment1); + clearInvocations(fragment2); + + // The decor surface should not be placed after removal. + task.removeDecorSurface(); + task.assignChildLayers(t); + + verify(unembeddedActivity).assignLayer(t, 0); + verify(fragment1).assignLayer(t, 1); + verify(fragment2).assignLayer(t, 2); + } + private Task getTestTask() { return new TaskBuilder(mSupervisor).setCreateActivity(true).build(); } diff --git a/telephony/java/android/telephony/CellularIdentifierDisclosure.java b/telephony/java/android/telephony/CellularIdentifierDisclosure.java new file mode 100644 index 000000000000..7b2db6d59819 --- /dev/null +++ b/telephony/java/android/telephony/CellularIdentifierDisclosure.java @@ -0,0 +1,161 @@ +/* + * 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.telephony; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.os.Parcel; +import android.os.Parcelable; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.Objects; + +/** + * A single occurrence of a cellular identifier being disclosed in the clear before a security + * context is established. + * + * @hide + */ +public final class CellularIdentifierDisclosure implements Parcelable { + private static final String TAG = "CellularIdentifierDisclosure"; + + private @NasProtocolMessage int mNasProtocolMessage; + private @CellularIdentifier int mCellularIdentifier; + private String mPlmn; + private boolean mIsEmergency; + + public CellularIdentifierDisclosure(@NasProtocolMessage int nasProtocolMessage, + @CellularIdentifier int cellularIdentifier, String plmn, boolean isEmergency) { + mNasProtocolMessage = nasProtocolMessage; + mCellularIdentifier = cellularIdentifier; + mPlmn = plmn; + mIsEmergency = isEmergency; + } + + private CellularIdentifierDisclosure(Parcel in) { + readFromParcel(in); + } + + public @NasProtocolMessage int getNasProtocolMessage() { + return mNasProtocolMessage; + } + + public @CellularIdentifier int getCellularIdentifier() { + return mCellularIdentifier; + } + + public String getPlmn() { + return mPlmn; + } + + public boolean isEmergency() { + return mIsEmergency; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeInt(mNasProtocolMessage); + out.writeInt(mCellularIdentifier); + out.writeBoolean(mIsEmergency); + out.writeString8(mPlmn); + } + + public static final Parcelable.Creator<CellularIdentifierDisclosure> CREATOR = + new Parcelable.Creator<CellularIdentifierDisclosure>() { + public CellularIdentifierDisclosure createFromParcel(Parcel in) { + return new CellularIdentifierDisclosure(in); + } + + public CellularIdentifierDisclosure[] newArray(int size) { + return new CellularIdentifierDisclosure[size]; + } + }; + + @Override + public String toString() { + return TAG + ":{ mNasProtocolMessage = " + mNasProtocolMessage + + " mCellularIdentifier = " + mCellularIdentifier + " mIsEmergency = " + + mIsEmergency + " mPlmn = " + mPlmn; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof CellularIdentifierDisclosure)) return false; + CellularIdentifierDisclosure that = (CellularIdentifierDisclosure) o; + return mNasProtocolMessage == that.mNasProtocolMessage + && mCellularIdentifier == that.mCellularIdentifier + && mIsEmergency == that.mIsEmergency && mPlmn.equals(that.mPlmn); + } + + @Override + public int hashCode() { + return Objects.hash(mNasProtocolMessage, mCellularIdentifier, mIsEmergency, + mPlmn); + } + + private void readFromParcel(@NonNull Parcel in) { + mNasProtocolMessage = in.readInt(); + mCellularIdentifier = in.readInt(); + mIsEmergency = in.readBoolean(); + mPlmn = in.readString8(); + } + + public static final int NAS_PROTOCOL_MESSAGE_UNKNOWN = 0; + public static final int NAS_PROTOCOL_MESSAGE_ATTACH_REQUEST = 1; + public static final int NAS_PROTOCOL_MESSAGE_IDENTITY_RESPONSE = 2; + public static final int NAS_PROTOCOL_MESSAGE_DETACH_REQUEST = 3; + public static final int NAS_PROTOCOL_MESSAGE_TRACKING_AREA_UPDATE_REQUEST = 4; + public static final int NAS_PROTOCOL_MESSAGE_LOCATION_UPDATE_REQUEST = 5; + public static final int NAS_PROTOCOL_MESSAGE_AUTHENTICATION_AND_CIPHERING_RESPONSE = 6; + public static final int NAS_PROTOCOL_MESSAGE_REGISTRATION_REQUEST = 7; + public static final int NAS_PROTOCOL_MESSAGE_DEREGISTRATION_REQUEST = 8; + public static final int NAS_PROTOCOL_MESSAGE_CM_REESTABLISHMENT_REQUEST = 9; + public static final int NAS_PROTOCOL_MESSAGE_CM_SERVICE_REQUEST = 10; + public static final int NAS_PROTOCOL_MESSAGE_IMSI_DETACH_INDICATION = 11; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = {"NAS_PROTOCOL_MESSAGE_"}, value = {NAS_PROTOCOL_MESSAGE_UNKNOWN, + NAS_PROTOCOL_MESSAGE_ATTACH_REQUEST, NAS_PROTOCOL_MESSAGE_IDENTITY_RESPONSE, + NAS_PROTOCOL_MESSAGE_DETACH_REQUEST, NAS_PROTOCOL_MESSAGE_TRACKING_AREA_UPDATE_REQUEST, + NAS_PROTOCOL_MESSAGE_LOCATION_UPDATE_REQUEST, + NAS_PROTOCOL_MESSAGE_AUTHENTICATION_AND_CIPHERING_RESPONSE, + NAS_PROTOCOL_MESSAGE_REGISTRATION_REQUEST, NAS_PROTOCOL_MESSAGE_DEREGISTRATION_REQUEST, + NAS_PROTOCOL_MESSAGE_CM_REESTABLISHMENT_REQUEST, + NAS_PROTOCOL_MESSAGE_CM_SERVICE_REQUEST, NAS_PROTOCOL_MESSAGE_IMSI_DETACH_INDICATION}) + public @interface NasProtocolMessage { + } + + public static final int CELLULAR_IDENTIFIER_UNKNOWN = 0; + public static final int CELLULAR_IDENTIFIER_IMSI = 1; + public static final int CELLULAR_IDENTIFIER_IMEI = 2; + public static final int CELLULAR_IDENTIFIER_SUCI = 3; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = {"CELLULAR_IDENTIFIER_"}, value = {CELLULAR_IDENTIFIER_UNKNOWN, + CELLULAR_IDENTIFIER_IMSI, CELLULAR_IDENTIFIER_IMEI, CELLULAR_IDENTIFIER_SUCI}) + public @interface CellularIdentifier { + } +} diff --git a/tools/aapt2/Android.bp b/tools/aapt2/Android.bp index 412aa9bf88ab..275a0e21fedd 100644 --- a/tools/aapt2/Android.bp +++ b/tools/aapt2/Android.bp @@ -92,10 +92,6 @@ cc_library_host_static { srcs: [ "compile/IdAssigner.cpp", "compile/InlineXmlFormatParser.cpp", - "compile/NinePatch.cpp", - "compile/Png.cpp", - "compile/PngChunkFilter.cpp", - "compile/PngCrunch.cpp", "compile/PseudolocaleGenerator.cpp", "compile/Pseudolocalizer.cpp", "compile/XmlIdCollector.cpp", @@ -112,9 +108,7 @@ cc_library_host_static { "format/binary/XmlFlattener.cpp", "format/proto/ProtoDeserialize.cpp", "format/proto/ProtoSerialize.cpp", - "io/BigBufferStream.cpp", "io/File.cpp", - "io/FileStream.cpp", "io/FileSystem.cpp", "io/StringStream.cpp", "io/Util.cpp", diff --git a/tools/aapt2/LoadedApk.cpp b/tools/aapt2/LoadedApk.cpp index 6b1fd9ff11eb..d6502d82848f 100644 --- a/tools/aapt2/LoadedApk.cpp +++ b/tools/aapt2/LoadedApk.cpp @@ -18,12 +18,12 @@ #include "ResourceValues.h" #include "ValueVisitor.h" +#include "androidfw/BigBufferStream.h" #include "format/Archive.h" #include "format/binary/TableFlattener.h" #include "format/binary/XmlFlattener.h" #include "format/proto/ProtoDeserialize.h" #include "format/proto/ProtoSerialize.h" -#include "io/BigBufferStream.h" #include "io/Util.h" #include "xml/XmlDom.h" @@ -48,7 +48,7 @@ static ApkFormat DetermineApkFormat(io::IFileCollection* apk) { } // First try in proto format. - std::unique_ptr<io::InputStream> manifest_in = manifest_file->OpenInputStream(); + std::unique_ptr<android::InputStream> manifest_in = manifest_file->OpenInputStream(); if (manifest_in != nullptr) { pb::XmlNode pb_node; io::ProtoInputStreamReader proto_reader(manifest_in.get()); @@ -102,7 +102,7 @@ std::unique_ptr<LoadedApk> LoadedApk::LoadProtoApkFromFileCollection( io::IFile* table_file = collection->FindFile(kProtoResourceTablePath); if (table_file != nullptr) { pb::ResourceTable pb_table; - std::unique_ptr<io::InputStream> in = table_file->OpenInputStream(); + std::unique_ptr<android::InputStream> in = table_file->OpenInputStream(); if (in == nullptr) { diag->Error(android::DiagMessage(source) << "failed to open " << kProtoResourceTablePath); return {}; @@ -129,7 +129,7 @@ std::unique_ptr<LoadedApk> LoadedApk::LoadProtoApkFromFileCollection( return {}; } - std::unique_ptr<io::InputStream> manifest_in = manifest_file->OpenInputStream(); + std::unique_ptr<android::InputStream> manifest_in = manifest_file->OpenInputStream(); if (manifest_in == nullptr) { diag->Error(android::DiagMessage(source) << "failed to open " << kAndroidManifestPath); return {}; @@ -262,7 +262,7 @@ bool LoadedApk::WriteToArchive(IAaptContext* context, ResourceTable* split_table return false; } - io::BigBufferInputStream input_stream(&buffer); + android::BigBufferInputStream input_stream(&buffer); if (!io::CopyInputStreamToArchive(context, &input_stream, path, @@ -296,7 +296,7 @@ bool LoadedApk::WriteToArchive(IAaptContext* context, ResourceTable* split_table } uint32_t compression_flags = file->WasCompressed() ? ArchiveEntry::kCompress : 0u; - io::BigBufferInputStream manifest_buffer_in(&buffer); + android::BigBufferInputStream manifest_buffer_in(&buffer); if (!io::CopyInputStreamToArchive(context, &manifest_buffer_in, path, compression_flags, writer)) { return false; @@ -321,7 +321,7 @@ std::unique_ptr<xml::XmlResource> LoadedApk::LoadXml(const std::string& file_pat std::unique_ptr<xml::XmlResource> doc; if (format_ == ApkFormat::kProto) { - std::unique_ptr<io::InputStream> in = file->OpenInputStream(); + std::unique_ptr<android::InputStream> in = file->OpenInputStream(); if (!in) { diag->Error(android::DiagMessage() << "failed to open file"); return nullptr; diff --git a/tools/aapt2/Main.cpp b/tools/aapt2/Main.cpp index a0b4dab9b8e5..b351d6ee4f33 100644 --- a/tools/aapt2/Main.cpp +++ b/tools/aapt2/Main.cpp @@ -27,6 +27,7 @@ #include "Diagnostics.h" #include "android-base/stringprintf.h" #include "android-base/utf8.h" +#include "androidfw/FileStream.h" #include "androidfw/IDiagnostics.h" #include "androidfw/StringPiece.h" #include "cmd/ApkInfo.h" @@ -37,7 +38,6 @@ #include "cmd/Dump.h" #include "cmd/Link.h" #include "cmd/Optimize.h" -#include "io/FileStream.h" #include "trace/TraceBuffer.h" #include "util/Files.h" #include "util/Util.h" @@ -99,7 +99,7 @@ class MainCommand : public Command { */ class DaemonCommand : public Command { public: - explicit DaemonCommand(io::FileOutputStream* out, android::IDiagnostics* diagnostics) + explicit DaemonCommand(android::FileOutputStream* out, android::IDiagnostics* diagnostics) : Command("daemon", "m"), out_(out), diagnostics_(diagnostics) { SetDescription("Runs aapt in daemon mode. Each subsequent line is a single parameter to the\n" "command. The end of an invocation is signaled by providing an empty line."); @@ -147,7 +147,7 @@ class DaemonCommand : public Command { } private: - io::FileOutputStream* out_; + android::FileOutputStream* out_; android::IDiagnostics* diagnostics_; std::optional<std::string> trace_folder_; }; @@ -167,7 +167,7 @@ int MainImpl(int argc, char** argv) { // Use a smaller buffer so that there is less latency for printing to stdout. constexpr size_t kStdOutBufferSize = 1024u; - aapt::io::FileOutputStream fout(STDOUT_FILENO, kStdOutBufferSize); + android::FileOutputStream fout(STDOUT_FILENO, kStdOutBufferSize); aapt::text::Printer printer(&fout); aapt::StdErrDiagnostics diagnostics; diff --git a/tools/aapt2/cmd/Compile.cpp b/tools/aapt2/cmd/Compile.cpp index 728ba8aa4fdd..031dd5bb139c 100644 --- a/tools/aapt2/cmd/Compile.cpp +++ b/tools/aapt2/cmd/Compile.cpp @@ -25,13 +25,16 @@ #include "android-base/errors.h" #include "android-base/file.h" #include "android-base/utf8.h" +#include "androidfw/BigBufferStream.h" #include "androidfw/ConfigDescription.h" +#include "androidfw/FileStream.h" #include "androidfw/IDiagnostics.h" +#include "androidfw/Image.h" +#include "androidfw/Png.h" #include "androidfw/StringPiece.h" #include "cmd/Util.h" #include "compile/IdAssigner.h" #include "compile/InlineXmlFormatParser.h" -#include "compile/Png.h" #include "compile/PseudolocaleGenerator.h" #include "compile/XmlIdCollector.h" #include "format/Archive.h" @@ -39,8 +42,6 @@ #include "format/proto/ProtoSerialize.h" #include "google/protobuf/io/coded_stream.h" #include "google/protobuf/io/zero_copy_stream_impl_lite.h" -#include "io/BigBufferStream.h" -#include "io/FileStream.h" #include "io/FileSystem.h" #include "io/StringStream.h" #include "io/Util.h" @@ -52,9 +53,9 @@ #include "xml/XmlDom.h" #include "xml/XmlPullParser.h" -using ::aapt::io::FileInputStream; using ::aapt::text::Printer; using ::android::ConfigDescription; +using ::android::FileInputStream; using ::android::StringPiece; using ::android::base::SystemErrorCodeToString; using ::google::protobuf::io::CopyingOutputStreamAdaptor; @@ -241,7 +242,7 @@ static bool CompileTable(IAaptContext* context, const CompileOptions& options, } if (options.generate_text_symbols_path) { - io::FileOutputStream fout_text(options.generate_text_symbols_path.value()); + android::FileOutputStream fout_text(options.generate_text_symbols_path.value()); if (fout_text.HadError()) { context->GetDiagnostics()->Error(android::DiagMessage() @@ -307,7 +308,7 @@ static bool CompileTable(IAaptContext* context, const CompileOptions& options, } static bool WriteHeaderAndDataToWriter(StringPiece output_path, const ResourceFile& file, - io::KnownSizeInputStream* in, IArchiveWriter* writer, + android::KnownSizeInputStream* in, IArchiveWriter* writer, android::IDiagnostics* diag) { TRACE_CALL(); // Start the entry so we can write the header. @@ -448,7 +449,7 @@ static bool CompileXml(IAaptContext* context, const CompileOptions& options, } if (options.generate_text_symbols_path) { - io::FileOutputStream fout_text(options.generate_text_symbols_path.value()); + android::FileOutputStream fout_text(options.generate_text_symbols_path.value()); if (fout_text.HadError()) { context->GetDiagnostics()->Error(android::DiagMessage() @@ -498,21 +499,22 @@ static bool CompilePng(IAaptContext* context, const CompileOptions& options, } android::BigBuffer crunched_png_buffer(4096); - io::BigBufferOutputStream crunched_png_buffer_out(&crunched_png_buffer); + android::BigBufferOutputStream crunched_png_buffer_out(&crunched_png_buffer); // Ensure that we only keep the chunks we care about if we end up // using the original PNG instead of the crunched one. const StringPiece content(reinterpret_cast<const char*>(data->data()), data->size()); - PngChunkFilter png_chunk_filter(content); - std::unique_ptr<Image> image = ReadPng(context, path_data.source, &png_chunk_filter); + android::PngChunkFilter png_chunk_filter(content); + android::SourcePathDiagnostics source_diag(path_data.source, context->GetDiagnostics()); + auto image = android::ReadPng(&png_chunk_filter, &source_diag); if (!image) { return false; } - std::unique_ptr<NinePatch> nine_patch; + std::unique_ptr<android::NinePatch> nine_patch; if (path_data.extension == "9.png") { std::string err; - nine_patch = NinePatch::Create(image->rows.get(), image->width, image->height, &err); + nine_patch = android::NinePatch::Create(image->rows.get(), image->width, image->height, &err); if (!nine_patch) { context->GetDiagnostics()->Error(android::DiagMessage() << err); return false; @@ -537,7 +539,8 @@ static bool CompilePng(IAaptContext* context, const CompileOptions& options, } // Write the crunched PNG. - if (!WritePng(context, image.get(), nine_patch.get(), &crunched_png_buffer_out, {})) { + if (!android::WritePng(image.get(), nine_patch.get(), &crunched_png_buffer_out, {}, + &source_diag, context->IsVerbose())) { return false; } @@ -557,7 +560,7 @@ static bool CompilePng(IAaptContext* context, const CompileOptions& options, png_chunk_filter.Rewind(); android::BigBuffer filtered_png_buffer(4096); - io::BigBufferOutputStream filtered_png_buffer_out(&filtered_png_buffer); + android::BigBufferOutputStream filtered_png_buffer_out(&filtered_png_buffer); io::Copy(&filtered_png_buffer_out, &png_chunk_filter); buffer.AppendBuffer(std::move(filtered_png_buffer)); } @@ -567,7 +570,7 @@ static bool CompilePng(IAaptContext* context, const CompileOptions& options, // This will help catch exotic cases where the new code may generate larger PNGs. std::stringstream legacy_stream{std::string(content)}; android::BigBuffer legacy_buffer(4096); - Png png(context->GetDiagnostics()); + android::Png png(context->GetDiagnostics()); if (!png.process(path_data.source, &legacy_stream, &legacy_buffer, {})) { return false; } @@ -578,7 +581,7 @@ static bool CompilePng(IAaptContext* context, const CompileOptions& options, } } - io::BigBufferInputStream buffer_in(&buffer); + android::BigBufferInputStream buffer_in(&buffer); return WriteHeaderAndDataToWriter(output_path, res_file, &buffer_in, writer, context->GetDiagnostics()); } diff --git a/tools/aapt2/cmd/Compile_test.cpp b/tools/aapt2/cmd/Compile_test.cpp index 8880089d0e20..9337cb913a0b 100644 --- a/tools/aapt2/cmd/Compile_test.cpp +++ b/tools/aapt2/cmd/Compile_test.cpp @@ -341,7 +341,7 @@ TEST_F(CompilerTest, RelativePathTest) { // Check resources.pb contains relative sources. io::IFile* proto_file = apk.get()->GetFileCollection()->FindFile("resources.pb"); - std::unique_ptr<io::InputStream> proto_stream = proto_file->OpenInputStream(); + std::unique_ptr<android::InputStream> proto_stream = proto_file->OpenInputStream(); io::ProtoInputStreamReader proto_reader(proto_stream.get()); pb::ResourceTable pb_table; proto_reader.ReadMessage(&pb_table); diff --git a/tools/aapt2/cmd/Convert.cpp b/tools/aapt2/cmd/Convert.cpp index 387dcfe2ddf3..c132792d374b 100644 --- a/tools/aapt2/cmd/Convert.cpp +++ b/tools/aapt2/cmd/Convert.cpp @@ -24,13 +24,13 @@ #include "android-base/file.h" #include "android-base/macros.h" #include "android-base/stringprintf.h" +#include "androidfw/BigBufferStream.h" #include "androidfw/StringPiece.h" #include "cmd/Util.h" #include "format/binary/TableFlattener.h" #include "format/binary/XmlFlattener.h" #include "format/proto/ProtoDeserialize.h" #include "format/proto/ProtoSerialize.h" -#include "io/BigBufferStream.h" #include "io/Util.h" #include "process/IResourceTableConsumer.h" #include "process/SymbolTable.h" @@ -80,7 +80,7 @@ class BinaryApkSerializer : public IApkSerializer { return false; } - io::BigBufferInputStream input_stream(&buffer); + android::BigBufferInputStream input_stream(&buffer); return io::CopyInputStreamToArchive(context_, &input_stream, path, compression_flags, writer); } @@ -91,14 +91,14 @@ class BinaryApkSerializer : public IApkSerializer { return false; } - io::BigBufferInputStream input_stream(&buffer); + android::BigBufferInputStream input_stream(&buffer); return io::CopyInputStreamToArchive(context_, &input_stream, kApkResourceTablePath, ArchiveEntry::kAlign, writer); } bool SerializeFile(FileReference* file, IArchiveWriter* writer) override { if (file->type == ResourceFile::Type::kProtoXml) { - unique_ptr<io::InputStream> in = file->file->OpenInputStream(); + unique_ptr<android::InputStream> in = file->file->OpenInputStream(); if (in == nullptr) { context_->GetDiagnostics()->Error(android::DiagMessage(source_) << "failed to open file " << *file->path); diff --git a/tools/aapt2/cmd/Dump.cpp b/tools/aapt2/cmd/Dump.cpp index 864af06f187e..6fa9ecbfa544 100644 --- a/tools/aapt2/cmd/Dump.cpp +++ b/tools/aapt2/cmd/Dump.cpp @@ -19,19 +19,18 @@ #include <cinttypes> #include <vector> -#include "android-base/stringprintf.h" -#include "androidfw/ConfigDescription.h" -#include "androidfw/StringPiece.h" - #include "Debug.h" #include "Diagnostics.h" #include "LoadedApk.h" #include "Util.h" +#include "android-base/stringprintf.h" +#include "androidfw/ConfigDescription.h" +#include "androidfw/FileStream.h" +#include "androidfw/StringPiece.h" #include "format/Container.h" #include "format/binary/BinaryResourceParser.h" #include "format/binary/XmlFlattener.h" #include "format/proto/ProtoDeserialize.h" -#include "io/FileStream.h" #include "io/ZipArchive.h" #include "process/IResourceTableConsumer.h" #include "text/Printer.h" @@ -145,7 +144,7 @@ int DumpAPCCommand::Action(const std::vector<std::string>& args) { bool error = false; for (auto container : args) { - io::FileInputStream input(container); + android::FileInputStream input(container); if (input.HadError()) { context.GetDiagnostics()->Error(android::DiagMessage(container) << "failed to open file: " << input.GetError()); diff --git a/tools/aapt2/cmd/Dump.h b/tools/aapt2/cmd/Dump.h index 76d33d7aa3b2..119a59b28317 100644 --- a/tools/aapt2/cmd/Dump.h +++ b/tools/aapt2/cmd/Dump.h @@ -17,7 +17,7 @@ #ifndef AAPT2_DUMP_H #define AAPT2_DUMP_H -#include <io/FileStream.h> +#include <androidfw/FileStream.h> #include <io/ZipArchive.h> #include "Command.h" diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp index c638873873dc..9ca546fc8d89 100644 --- a/tools/aapt2/cmd/Link.cpp +++ b/tools/aapt2/cmd/Link.cpp @@ -35,6 +35,8 @@ #include "android-base/expected.h" #include "android-base/file.h" #include "android-base/stringprintf.h" +#include "androidfw/BigBufferStream.h" +#include "androidfw/FileStream.h" #include "androidfw/IDiagnostics.h" #include "androidfw/Locale.h" #include "androidfw/StringPiece.h" @@ -48,8 +50,6 @@ #include "format/binary/XmlFlattener.h" #include "format/proto/ProtoDeserialize.h" #include "format/proto/ProtoSerialize.h" -#include "io/BigBufferStream.h" -#include "io/FileStream.h" #include "io/FileSystem.h" #include "io/Util.h" #include "io/ZipArchive.h" @@ -73,8 +73,8 @@ #include "util/Files.h" #include "xml/XmlDom.h" -using ::aapt::io::FileInputStream; using ::android::ConfigDescription; +using ::android::FileInputStream; using ::android::StringPiece; using ::android::base::expected; using ::android::base::StringPrintf; @@ -263,7 +263,7 @@ static bool FlattenXml(IAaptContext* context, const xml::XmlResource& xml_res, S return false; } - io::BigBufferInputStream input_stream(&buffer); + android::BigBufferInputStream input_stream(&buffer); return io::CopyInputStreamToArchive(context, &input_stream, path, ArchiveEntry::kCompress, writer); } break; @@ -284,7 +284,7 @@ static bool FlattenXml(IAaptContext* context, const xml::XmlResource& xml_res, S static std::unique_ptr<xml::XmlResource> LoadXml(const std::string& path, android::IDiagnostics* diag) { TRACE_CALL(); - FileInputStream fin(path); + android::FileInputStream fin(path); if (fin.HadError()) { diag->Error(android::DiagMessage(path) << "failed to load XML file: " << fin.GetError()); return {}; @@ -687,7 +687,7 @@ bool ResourceFileFlattener::Flatten(ResourceTable* table, IArchiveWriter* archiv static bool WriteStableIdMapToPath(android::IDiagnostics* diag, const std::unordered_map<ResourceName, ResourceId>& id_map, const std::string& id_map_path) { - io::FileOutputStream fout(id_map_path); + android::FileOutputStream fout(id_map_path); if (fout.HadError()) { diag->Error(android::DiagMessage(id_map_path) << "failed to open: " << fout.GetError()); return false; @@ -1197,7 +1197,7 @@ class Linker { return false; } - io::BigBufferInputStream input_stream(&buffer); + android::BigBufferInputStream input_stream(&buffer); return io::CopyInputStreamToArchive(context_, &input_stream, kApkResourceTablePath, ArchiveEntry::kAlign, writer); } break; @@ -1221,7 +1221,7 @@ class Linker { } std::string out_path; - std::unique_ptr<io::FileOutputStream> fout; + std::unique_ptr<android::FileOutputStream> fout; if (options_.generate_java_class_path) { out_path = options_.generate_java_class_path.value(); file::AppendPath(&out_path, file::PackageToPath(out_package)); @@ -1233,7 +1233,7 @@ class Linker { file::AppendPath(&out_path, "R.java"); - fout = util::make_unique<io::FileOutputStream>(out_path); + fout = util::make_unique<android::FileOutputStream>(out_path); if (fout->HadError()) { context_->GetDiagnostics()->Error(android::DiagMessage() << "failed writing to '" << out_path @@ -1242,9 +1242,9 @@ class Linker { } } - std::unique_ptr<io::FileOutputStream> fout_text; + std::unique_ptr<android::FileOutputStream> fout_text; if (out_text_symbols_path) { - fout_text = util::make_unique<io::FileOutputStream>(out_text_symbols_path.value()); + fout_text = util::make_unique<android::FileOutputStream>(out_text_symbols_path.value()); if (fout_text->HadError()) { context_->GetDiagnostics()->Error(android::DiagMessage() << "failed writing to '" << out_text_symbols_path.value() @@ -1386,7 +1386,7 @@ class Linker { file::AppendPath(&out_path, "Manifest.java"); - io::FileOutputStream fout(out_path); + android::FileOutputStream fout(out_path); if (fout.HadError()) { context_->GetDiagnostics()->Error(android::DiagMessage() << "failed to open '" << out_path << "': " << fout.GetError()); @@ -1412,7 +1412,7 @@ class Linker { } const std::string& out_path = out.value(); - io::FileOutputStream fout(out_path); + android::FileOutputStream fout(out_path); if (fout.HadError()) { context_->GetDiagnostics()->Error(android::DiagMessage() << "failed to open '" << out_path << "': " << fout.GetError()); @@ -1601,7 +1601,7 @@ class Linker { } } - std::unique_ptr<io::InputStream> input_stream = file->OpenInputStream(); + std::unique_ptr<android::InputStream> input_stream = file->OpenInputStream(); if (input_stream == nullptr) { context_->GetDiagnostics()->Error(android::DiagMessage(src) << "failed to open file"); return false; diff --git a/tools/aapt2/cmd/Optimize.cpp b/tools/aapt2/cmd/Optimize.cpp index f045dad6d11a..762441ee1872 100644 --- a/tools/aapt2/cmd/Optimize.cpp +++ b/tools/aapt2/cmd/Optimize.cpp @@ -30,6 +30,7 @@ #include "ValueVisitor.h" #include "android-base/file.h" #include "android-base/stringprintf.h" +#include "androidfw/BigBufferStream.h" #include "androidfw/ConfigDescription.h" #include "androidfw/IDiagnostics.h" #include "androidfw/ResourceTypes.h" @@ -39,7 +40,6 @@ #include "filter/AbiFilter.h" #include "format/binary/TableFlattener.h" #include "format/binary/XmlFlattener.h" -#include "io/BigBufferStream.h" #include "io/Util.h" #include "optimize/MultiApkGenerator.h" #include "optimize/Obfuscator.h" @@ -249,7 +249,7 @@ class Optimizer { return false; } - io::BigBufferInputStream manifest_buffer_in(&manifest_buffer); + android::BigBufferInputStream manifest_buffer_in(&manifest_buffer); if (!io::CopyInputStreamToArchive(context_, &manifest_buffer_in, "AndroidManifest.xml", ArchiveEntry::kCompress, writer)) { return false; @@ -297,7 +297,7 @@ class Optimizer { return false; } - io::BigBufferInputStream table_buffer_in(&table_buffer); + android::BigBufferInputStream table_buffer_in(&table_buffer); return io::CopyInputStreamToArchive(context_, &table_buffer_in, "resources.arsc", ArchiveEntry::kAlign, writer); } diff --git a/tools/aapt2/dump/DumpManifest.cpp b/tools/aapt2/dump/DumpManifest.cpp index a2b48187c24f..a5962292b5b0 100644 --- a/tools/aapt2/dump/DumpManifest.cpp +++ b/tools/aapt2/dump/DumpManifest.cpp @@ -29,8 +29,8 @@ #include "SdkConstants.h" #include "ValueVisitor.h" #include "androidfw/ConfigDescription.h" +#include "androidfw/FileStream.h" #include "io/File.h" -#include "io/FileStream.h" #include "process/IResourceTableConsumer.h" #include "xml/XmlDom.h" diff --git a/tools/aapt2/format/Archive.cpp b/tools/aapt2/format/Archive.cpp index e9a93d8b12ad..91768a09ea59 100644 --- a/tools/aapt2/format/Archive.cpp +++ b/tools/aapt2/format/Archive.cpp @@ -91,7 +91,7 @@ class DirectoryWriter : public IArchiveWriter { return true; } - bool WriteFile(StringPiece path, uint32_t flags, io::InputStream* in) override { + bool WriteFile(StringPiece path, uint32_t flags, android::InputStream* in) override { if (!StartEntry(path, flags)) { return false; } @@ -182,7 +182,7 @@ class ZipFileWriter : public IArchiveWriter { return true; } - bool WriteFile(StringPiece path, uint32_t flags, io::InputStream* in) override { + bool WriteFile(StringPiece path, uint32_t flags, android::InputStream* in) override { while (true) { if (!StartEntry(path, flags)) { return false; diff --git a/tools/aapt2/format/Archive.h b/tools/aapt2/format/Archive.h index 6cde753a255d..3c3d0ab74c52 100644 --- a/tools/aapt2/format/Archive.h +++ b/tools/aapt2/format/Archive.h @@ -24,9 +24,9 @@ #include "androidfw/BigBuffer.h" #include "androidfw/IDiagnostics.h" +#include "androidfw/Streams.h" #include "androidfw/StringPiece.h" #include "google/protobuf/io/zero_copy_stream_impl_lite.h" -#include "io/Io.h" #include "util/Files.h" namespace aapt { @@ -46,7 +46,7 @@ class IArchiveWriter : public ::google::protobuf::io::CopyingOutputStream { public: virtual ~IArchiveWriter() = default; - virtual bool WriteFile(android::StringPiece path, uint32_t flags, io::InputStream* in) = 0; + virtual bool WriteFile(android::StringPiece path, uint32_t flags, android::InputStream* in) = 0; // Starts a new entry and allows caller to write bytes to it sequentially. // Only use StartEntry if code you do not control needs to write to a CopyingOutputStream. diff --git a/tools/aapt2/format/Archive_test.cpp b/tools/aapt2/format/Archive_test.cpp index fd50af92ceee..df105f8a83e5 100644 --- a/tools/aapt2/format/Archive_test.cpp +++ b/tools/aapt2/format/Archive_test.cpp @@ -95,7 +95,7 @@ void VerifyDirectory(const std::string& path, const std::string& file, const uin void VerifyZipFile(const std::string& output_path, const std::string& file, const uint8_t array[]) { std::unique_ptr<io::ZipFileCollection> zip = io::ZipFileCollection::Create(output_path, nullptr); - std::unique_ptr<io::InputStream> stream = zip->FindFile(file)->OpenInputStream(); + std::unique_ptr<android::InputStream> stream = zip->FindFile(file)->OpenInputStream(); std::vector<uint8_t> buffer; const void* data; diff --git a/tools/aapt2/format/Container.cpp b/tools/aapt2/format/Container.cpp index 1ff6c4996b91..cb4a225c73e7 100644 --- a/tools/aapt2/format/Container.cpp +++ b/tools/aapt2/format/Container.cpp @@ -94,7 +94,7 @@ bool ContainerWriter::AddResTableEntry(const pb::ResourceTable& table) { } bool ContainerWriter::AddResFileEntry(const pb::internal::CompiledFile& file, - io::KnownSizeInputStream* in) { + android::KnownSizeInputStream* in) { if (current_entry_count_ >= total_entry_count_) { error_ = "too many entries being serialized"; return false; @@ -264,7 +264,7 @@ std::string ContainerReaderEntry::GetError() const { return reader_->GetError(); } -ContainerReader::ContainerReader(io::InputStream* in) +ContainerReader::ContainerReader(android::InputStream* in) : in_(in), adaptor_(in), coded_in_(&adaptor_), diff --git a/tools/aapt2/format/Container.h b/tools/aapt2/format/Container.h index 121c592537bf..c5d567697a5a 100644 --- a/tools/aapt2/format/Container.h +++ b/tools/aapt2/format/Container.h @@ -22,9 +22,9 @@ #include "Resources.pb.h" #include "ResourcesInternal.pb.h" #include "androidfw/BigBuffer.h" +#include "androidfw/Streams.h" #include "google/protobuf/io/coded_stream.h" #include "google/protobuf/io/zero_copy_stream.h" -#include "io/Io.h" #include "io/Util.h" namespace aapt { @@ -39,7 +39,7 @@ class ContainerWriter { explicit ContainerWriter(::google::protobuf::io::ZeroCopyOutputStream* out, size_t entry_count); bool AddResTableEntry(const pb::ResourceTable& table); - bool AddResFileEntry(const pb::internal::CompiledFile& file, io::KnownSizeInputStream* in); + bool AddResFileEntry(const pb::internal::CompiledFile& file, android::KnownSizeInputStream* in); bool HadError() const; std::string GetError() const; @@ -79,7 +79,7 @@ class ContainerReaderEntry { class ContainerReader { public: - explicit ContainerReader(io::InputStream* in); + explicit ContainerReader(android::InputStream* in); ContainerReaderEntry* Next(); @@ -91,7 +91,7 @@ class ContainerReader { friend class ContainerReaderEntry; - io::InputStream* in_; + android::InputStream* in_; io::ZeroCopyInputAdaptor adaptor_; ::google::protobuf::io::CodedInputStream coded_in_; size_t total_entry_count_; diff --git a/tools/aapt2/io/Data.h b/tools/aapt2/io/Data.h index db91a77a5ae6..29f523aeff1b 100644 --- a/tools/aapt2/io/Data.h +++ b/tools/aapt2/io/Data.h @@ -20,15 +20,14 @@ #include <memory> #include "android-base/macros.h" +#include "androidfw/Streams.h" #include "utils/FileMap.h" -#include "io/Io.h" - namespace aapt { namespace io { // Interface for a block of contiguous memory. An instance of this interface owns the data. -class IData : public KnownSizeInputStream { +class IData : public android::KnownSizeInputStream { public: virtual ~IData() = default; diff --git a/tools/aapt2/io/File.cpp b/tools/aapt2/io/File.cpp index b4f1ff3a5b49..4dfdb5bb8ad9 100644 --- a/tools/aapt2/io/File.cpp +++ b/tools/aapt2/io/File.cpp @@ -39,7 +39,7 @@ std::unique_ptr<IData> FileSegment::OpenAsData() { return {}; } -std::unique_ptr<io::InputStream> FileSegment::OpenInputStream() { +std::unique_ptr<android::InputStream> FileSegment::OpenInputStream() { return OpenAsData(); } diff --git a/tools/aapt2/io/File.h b/tools/aapt2/io/File.h index 673d1b75e660..248756b51f2e 100644 --- a/tools/aapt2/io/File.h +++ b/tools/aapt2/io/File.h @@ -43,7 +43,7 @@ class IFile { // Returns nullptr on failure. virtual std::unique_ptr<IData> OpenAsData() = 0; - virtual std::unique_ptr<io::InputStream> OpenInputStream() = 0; + virtual std::unique_ptr<android::InputStream> OpenInputStream() = 0; // Returns the source of this file. This is for presentation to the user and // may not be a valid file system path (for example, it may contain a '@' sign to separate @@ -78,7 +78,7 @@ class FileSegment : public IFile { : file_(file), offset_(offset), len_(len) {} std::unique_ptr<IData> OpenAsData() override; - std::unique_ptr<io::InputStream> OpenInputStream() override; + std::unique_ptr<android::InputStream> OpenInputStream() override; const android::Source& GetSource() const override { return file_->GetSource(); diff --git a/tools/aapt2/io/FileSystem.cpp b/tools/aapt2/io/FileSystem.cpp index 6a692e497816..03fabcc4dcce 100644 --- a/tools/aapt2/io/FileSystem.cpp +++ b/tools/aapt2/io/FileSystem.cpp @@ -22,9 +22,9 @@ #include <sys/stat.h> #include "android-base/errors.h" +#include "androidfw/FileStream.h" #include "androidfw/Source.h" #include "androidfw/StringPiece.h" -#include "io/FileStream.h" #include "util/Files.h" #include "util/Util.h" #include "utils/FileMap.h" @@ -49,8 +49,8 @@ std::unique_ptr<IData> RegularFile::OpenAsData() { return {}; } -std::unique_ptr<io::InputStream> RegularFile::OpenInputStream() { - return util::make_unique<FileInputStream>(source_.path); +std::unique_ptr<android::InputStream> RegularFile::OpenInputStream() { + return util::make_unique<android::FileInputStream>(source_.path); } const android::Source& RegularFile::GetSource() const { diff --git a/tools/aapt2/io/FileSystem.h b/tools/aapt2/io/FileSystem.h index f975196b9cfa..d6ecfebab67d 100644 --- a/tools/aapt2/io/FileSystem.h +++ b/tools/aapt2/io/FileSystem.h @@ -30,7 +30,7 @@ class RegularFile : public IFile { explicit RegularFile(const android::Source& source); std::unique_ptr<IData> OpenAsData() override; - std::unique_ptr<io::InputStream> OpenInputStream() override; + std::unique_ptr<android::InputStream> OpenInputStream() override; const android::Source& GetSource() const override; bool GetModificationTime(struct tm* buf) const override; diff --git a/tools/aapt2/io/StringStream.cpp b/tools/aapt2/io/StringStream.cpp index 9c497882b99b..bb3911b20175 100644 --- a/tools/aapt2/io/StringStream.cpp +++ b/tools/aapt2/io/StringStream.cpp @@ -51,6 +51,23 @@ size_t StringInputStream::TotalSize() const { return str_.size(); } +bool StringInputStream::ReadFullyAtOffset(void* data, size_t byte_count, off64_t offset) { + if (byte_count == 0) { + return true; + } + if (offset < 0) { + return false; + } + if (offset > std::numeric_limits<off64_t>::max() - byte_count) { + return false; + } + if (offset + byte_count > str_.size()) { + return false; + } + memcpy(data, str_.data() + offset, byte_count); + return true; +} + StringOutputStream::StringOutputStream(std::string* str, size_t buffer_capacity) : str_(str), buffer_capacity_(buffer_capacity), diff --git a/tools/aapt2/io/StringStream.h b/tools/aapt2/io/StringStream.h index f7bdecca0dee..7e1abe583170 100644 --- a/tools/aapt2/io/StringStream.h +++ b/tools/aapt2/io/StringStream.h @@ -17,17 +17,16 @@ #ifndef AAPT_IO_STRINGSTREAM_H #define AAPT_IO_STRINGSTREAM_H -#include "io/Io.h" - #include <memory> #include "android-base/macros.h" +#include "androidfw/Streams.h" #include "androidfw/StringPiece.h" namespace aapt { namespace io { -class StringInputStream : public KnownSizeInputStream { +class StringInputStream : public android::KnownSizeInputStream { public: explicit StringInputStream(android::StringPiece str); @@ -47,6 +46,8 @@ class StringInputStream : public KnownSizeInputStream { size_t TotalSize() const override; + bool ReadFullyAtOffset(void* data, size_t byte_count, off64_t offset) override; + private: DISALLOW_COPY_AND_ASSIGN(StringInputStream); @@ -54,7 +55,7 @@ class StringInputStream : public KnownSizeInputStream { size_t offset_; }; -class StringOutputStream : public OutputStream { +class StringOutputStream : public android::OutputStream { public: explicit StringOutputStream(std::string* str, size_t buffer_capacity = 4096u); diff --git a/tools/aapt2/io/Util.cpp b/tools/aapt2/io/Util.cpp index 79d8d527fe8b..9616e479eda0 100644 --- a/tools/aapt2/io/Util.cpp +++ b/tools/aapt2/io/Util.cpp @@ -26,8 +26,9 @@ using ::google::protobuf::io::ZeroCopyOutputStream; namespace aapt { namespace io { -bool CopyInputStreamToArchive(IAaptContext* context, InputStream* in, std::string_view out_path, - uint32_t compression_flags, IArchiveWriter* writer) { +bool CopyInputStreamToArchive(IAaptContext* context, android::InputStream* in, + std::string_view out_path, uint32_t compression_flags, + IArchiveWriter* writer) { TRACE_CALL(); if (context->IsVerbose()) { context->GetDiagnostics()->Note(android::DiagMessage() @@ -91,7 +92,7 @@ bool CopyProtoToArchive(IAaptContext* context, ::google::protobuf::Message* prot return false; } -bool Copy(OutputStream* out, InputStream* in) { +bool Copy(android::OutputStream* out, android::InputStream* in) { TRACE_CALL(); const void* in_buffer; size_t in_len; @@ -110,7 +111,7 @@ bool Copy(OutputStream* out, InputStream* in) { return !in->HadError(); } -bool Copy(OutputStream* out, StringPiece in) { +bool Copy(android::OutputStream* out, StringPiece in) { const char* in_buffer = in.data(); size_t in_len = in.size(); while (in_len != 0) { @@ -129,7 +130,7 @@ bool Copy(OutputStream* out, StringPiece in) { return true; } -bool Copy(ZeroCopyOutputStream* out, InputStream* in) { +bool Copy(ZeroCopyOutputStream* out, android::InputStream* in) { OutputStreamAdaptor adaptor(out); return Copy(&adaptor, in); } diff --git a/tools/aapt2/io/Util.h b/tools/aapt2/io/Util.h index 685f522a2e71..25aa8f8d1916 100644 --- a/tools/aapt2/io/Util.h +++ b/tools/aapt2/io/Util.h @@ -19,18 +19,19 @@ #include <string_view> +#include "androidfw/Streams.h" #include "format/Archive.h" #include "google/protobuf/io/coded_stream.h" #include "google/protobuf/message.h" #include "io/File.h" -#include "io/Io.h" #include "process/IResourceTableConsumer.h" namespace aapt { namespace io { -bool CopyInputStreamToArchive(IAaptContext* context, InputStream* in, std::string_view out_path, - uint32_t compression_flags, IArchiveWriter* writer); +bool CopyInputStreamToArchive(IAaptContext* context, android::InputStream* in, + std::string_view out_path, uint32_t compression_flags, + IArchiveWriter* writer); bool CopyFileToArchive(IAaptContext* context, IFile* file, std::string_view out_path, uint32_t compression_flags, IArchiveWriter* writer); @@ -44,11 +45,11 @@ bool CopyProtoToArchive(IAaptContext* context, ::google::protobuf::Message* prot // Copies the data from in to out. Returns false if there was an error. // If there was an error, check the individual streams' HadError/GetError methods. -bool Copy(OutputStream* out, InputStream* in); -bool Copy(OutputStream* out, android::StringPiece in); -bool Copy(::google::protobuf::io::ZeroCopyOutputStream* out, InputStream* in); +bool Copy(android::OutputStream* out, android::InputStream* in); +bool Copy(android::OutputStream* out, android::StringPiece in); +bool Copy(::google::protobuf::io::ZeroCopyOutputStream* out, android::InputStream* in); -class OutputStreamAdaptor : public io::OutputStream { +class OutputStreamAdaptor : public android::OutputStream { public: explicit OutputStreamAdaptor(::google::protobuf::io::ZeroCopyOutputStream* out) : out_(out) { } @@ -84,7 +85,7 @@ class OutputStreamAdaptor : public io::OutputStream { class ZeroCopyInputAdaptor : public ::google::protobuf::io::ZeroCopyInputStream { public: - explicit ZeroCopyInputAdaptor(io::InputStream* in) : in_(in) { + explicit ZeroCopyInputAdaptor(android::InputStream* in) : in_(in) { } bool Next(const void** data, int* size) override { @@ -119,12 +120,13 @@ class ZeroCopyInputAdaptor : public ::google::protobuf::io::ZeroCopyInputStream private: DISALLOW_COPY_AND_ASSIGN(ZeroCopyInputAdaptor); - io::InputStream* in_; + android::InputStream* in_; }; class ProtoInputStreamReader { public: - explicit ProtoInputStreamReader(io::InputStream* in) : in_(in) { } + explicit ProtoInputStreamReader(android::InputStream* in) : in_(in) { + } /** Deserializes a Message proto from the current position in the input stream.*/ template <typename T> bool ReadMessage(T *message) { @@ -135,7 +137,7 @@ class ProtoInputStreamReader { } private: - io::InputStream* in_; + android::InputStream* in_; }; } // namespace io diff --git a/tools/aapt2/io/ZipArchive.cpp b/tools/aapt2/io/ZipArchive.cpp index cb5bbe96b8b7..e44d61e08899 100644 --- a/tools/aapt2/io/ZipArchive.cpp +++ b/tools/aapt2/io/ZipArchive.cpp @@ -63,7 +63,7 @@ std::unique_ptr<IData> ZipFile::OpenAsData() { } } -std::unique_ptr<io::InputStream> ZipFile::OpenInputStream() { +std::unique_ptr<android::InputStream> ZipFile::OpenInputStream() { return OpenAsData(); } diff --git a/tools/aapt2/io/ZipArchive.h b/tools/aapt2/io/ZipArchive.h index ac125d097983..a53c4a2e39f8 100644 --- a/tools/aapt2/io/ZipArchive.h +++ b/tools/aapt2/io/ZipArchive.h @@ -35,7 +35,7 @@ class ZipFile : public IFile { ZipFile(::ZipArchiveHandle handle, const ::ZipEntry& entry, const android::Source& source); std::unique_ptr<IData> OpenAsData() override; - std::unique_ptr<io::InputStream> OpenInputStream() override; + std::unique_ptr<android::InputStream> OpenInputStream() override; const android::Source& GetSource() const override; bool WasCompressed() override; bool GetModificationTime(struct tm* buf) const override; diff --git a/tools/aapt2/java/ClassDefinition.cpp b/tools/aapt2/java/ClassDefinition.cpp index 98f3bd2018b0..db7aa35d5ad4 100644 --- a/tools/aapt2/java/ClassDefinition.cpp +++ b/tools/aapt2/java/ClassDefinition.cpp @@ -111,7 +111,7 @@ constexpr static const char* sWarningHeader = " */\n\n"; void ClassDefinition::WriteJavaFile(const ClassDefinition* def, StringPiece package, bool final, - bool strip_api_annotations, io::OutputStream* out) { + bool strip_api_annotations, android::OutputStream* out) { Printer printer(out); printer.Print(sWarningHeader).Print("package ").Print(package).Println(";"); printer.Println(); diff --git a/tools/aapt2/java/ClassDefinition.h b/tools/aapt2/java/ClassDefinition.h index 63c99821a836..84e3f33db941 100644 --- a/tools/aapt2/java/ClassDefinition.h +++ b/tools/aapt2/java/ClassDefinition.h @@ -241,7 +241,7 @@ enum class ClassQualifier { kNone, kStatic }; class ClassDefinition : public ClassMember { public: static void WriteJavaFile(const ClassDefinition* def, android::StringPiece package, bool final, - bool strip_api_annotations, io::OutputStream* out); + bool strip_api_annotations, android::OutputStream* out); ClassDefinition(android::StringPiece name, ClassQualifier qualifier, bool createIfEmpty) : name_(name), qualifier_(qualifier), create_if_empty_(createIfEmpty) { diff --git a/tools/aapt2/java/JavaClassGenerator.cpp b/tools/aapt2/java/JavaClassGenerator.cpp index 7665d0e8d9cb..58f656458177 100644 --- a/tools/aapt2/java/JavaClassGenerator.cpp +++ b/tools/aapt2/java/JavaClassGenerator.cpp @@ -37,8 +37,8 @@ #include "java/ClassDefinition.h" #include "process/SymbolTable.h" -using ::aapt::io::OutputStream; using ::aapt::text::Printer; +using ::android::OutputStream; using ::android::StringPiece; using ::android::base::StringPrintf; diff --git a/tools/aapt2/java/JavaClassGenerator.h b/tools/aapt2/java/JavaClassGenerator.h index 234df04472ce..9909eeccb6ac 100644 --- a/tools/aapt2/java/JavaClassGenerator.h +++ b/tools/aapt2/java/JavaClassGenerator.h @@ -19,11 +19,10 @@ #include <string> -#include "androidfw/StringPiece.h" - #include "ResourceTable.h" #include "ResourceValues.h" -#include "io/Io.h" +#include "androidfw/Streams.h" +#include "androidfw/StringPiece.h" #include "process/IResourceTableConsumer.h" #include "process/SymbolTable.h" #include "text/Printer.h" @@ -70,12 +69,12 @@ class JavaClassGenerator { // All symbols technically belong to a single package, but linked libraries will // have their names mangled, denoting that they came from a different package. // We need to generate these symbols in a separate file. Returns true on success. - bool Generate(android::StringPiece package_name_to_generate, io::OutputStream* out, - io::OutputStream* out_r_txt = nullptr); + bool Generate(android::StringPiece package_name_to_generate, android::OutputStream* out, + android::OutputStream* out_r_txt = nullptr); bool Generate(android::StringPiece package_name_to_generate, - android::StringPiece output_package_name, io::OutputStream* out, - io::OutputStream* out_r_txt = nullptr); + android::StringPiece output_package_name, android::OutputStream* out, + android::OutputStream* out_r_txt = nullptr); const std::string& GetError() const; diff --git a/tools/aapt2/java/ProguardRules.cpp b/tools/aapt2/java/ProguardRules.cpp index 80a46d553960..aef48fc102d7 100644 --- a/tools/aapt2/java/ProguardRules.cpp +++ b/tools/aapt2/java/ProguardRules.cpp @@ -29,8 +29,8 @@ #include "util/Util.h" #include "xml/XmlDom.h" -using ::aapt::io::OutputStream; using ::aapt::text::Printer; +using ::android::OutputStream; namespace aapt { namespace proguard { diff --git a/tools/aapt2/java/ProguardRules.h b/tools/aapt2/java/ProguardRules.h index 267f7ede274a..876ef48042f5 100644 --- a/tools/aapt2/java/ProguardRules.h +++ b/tools/aapt2/java/ProguardRules.h @@ -26,8 +26,8 @@ #include "ResourceTable.h" #include "ValueVisitor.h" #include "androidfw/Source.h" +#include "androidfw/Streams.h" #include "androidfw/StringPiece.h" -#include "io/Io.h" #include "process/IResourceTableConsumer.h" #include "xml/XmlDom.h" @@ -69,7 +69,7 @@ class KeepSet { } private: - friend void WriteKeepSet(const KeepSet& keep_set, io::OutputStream* out, bool minimal_keep, + friend void WriteKeepSet(const KeepSet& keep_set, android::OutputStream* out, bool minimal_keep, bool no_location_reference); friend bool CollectLocations(const UsageLocation& location, const KeepSet& keep_set, @@ -89,7 +89,7 @@ bool CollectProguardRules(IAaptContext* context, xml::XmlResource* res, KeepSet* bool CollectResourceReferences(IAaptContext* context, ResourceTable* table, KeepSet* keep_set); -void WriteKeepSet(const KeepSet& keep_set, io::OutputStream* out, bool minimal_keep, +void WriteKeepSet(const KeepSet& keep_set, android::OutputStream* out, bool minimal_keep, bool no_location_reference); bool CollectLocations(const UsageLocation& location, const KeepSet& keep_set, diff --git a/tools/aapt2/test/Common.h b/tools/aapt2/test/Common.h index e48668cf96a3..04379804d8ee 100644 --- a/tools/aapt2/test/Common.h +++ b/tools/aapt2/test/Common.h @@ -90,7 +90,7 @@ class TestFile : public io::IFile { return {}; } - std::unique_ptr<io::InputStream> OpenInputStream() override { + std::unique_ptr<android::InputStream> OpenInputStream() override { return OpenAsData(); } diff --git a/tools/aapt2/test/Fixture.cpp b/tools/aapt2/test/Fixture.cpp index 428372f31d0d..b91abe572306 100644 --- a/tools/aapt2/test/Fixture.cpp +++ b/tools/aapt2/test/Fixture.cpp @@ -20,6 +20,7 @@ #include <android-base/file.h> #include <android-base/stringprintf.h> #include <android-base/utf8.h> +#include <androidfw/FileStream.h> #include <androidfw/StringPiece.h> #include <dirent.h> #include <gmock/gmock.h> @@ -28,7 +29,6 @@ #include "Diagnostics.h" #include "cmd/Compile.h" #include "cmd/Link.h" -#include "io/FileStream.h" #include "util/Files.h" using testing::Eq; diff --git a/tools/aapt2/text/Printer.cpp b/tools/aapt2/text/Printer.cpp index 8e491aca794d..c2fa8cccd536 100644 --- a/tools/aapt2/text/Printer.cpp +++ b/tools/aapt2/text/Printer.cpp @@ -20,7 +20,7 @@ #include "io/Util.h" -using ::aapt::io::OutputStream; +using ::android::OutputStream; using ::android::StringPiece; namespace aapt { diff --git a/tools/aapt2/text/Printer.h b/tools/aapt2/text/Printer.h index f7ad98bfd981..44f0fc546c7c 100644 --- a/tools/aapt2/text/Printer.h +++ b/tools/aapt2/text/Printer.h @@ -18,17 +18,16 @@ #define AAPT_TEXT_PRINTER_H #include "android-base/macros.h" +#include "androidfw/Streams.h" #include "androidfw/StringPiece.h" -#include "io/Io.h" - namespace aapt { namespace text { // An indenting Printer that helps write formatted text to the OutputStream. class Printer { public: - explicit Printer(::aapt::io::OutputStream* out) : out_(out) { + explicit Printer(android::OutputStream* out) : out_(out) { } Printer& Print(android::StringPiece str); @@ -41,7 +40,7 @@ class Printer { private: DISALLOW_COPY_AND_ASSIGN(Printer); - ::aapt::io::OutputStream* out_; + android::OutputStream* out_; int indent_level_ = 0; bool needs_indent_ = false; bool error_ = false; diff --git a/tools/aapt2/xml/XmlDom.cpp b/tools/aapt2/xml/XmlDom.cpp index 8dea8ea52f92..49807db26bb7 100644 --- a/tools/aapt2/xml/XmlDom.cpp +++ b/tools/aapt2/xml/XmlDom.cpp @@ -30,7 +30,7 @@ #include "XmlPullParser.h" #include "util/Util.h" -using ::aapt::io::InputStream; +using ::android::InputStream; using ::android::StringPiece; using ::android::StringPiece16; diff --git a/tools/aapt2/xml/XmlDom.h b/tools/aapt2/xml/XmlDom.h index c253b0a1f4a9..9668b6a6e8ef 100644 --- a/tools/aapt2/xml/XmlDom.h +++ b/tools/aapt2/xml/XmlDom.h @@ -24,8 +24,8 @@ #include "Resource.h" #include "ResourceValues.h" #include "androidfw/IDiagnostics.h" +#include "androidfw/Streams.h" #include "androidfw/StringPiece.h" -#include "io/Io.h" #include "util/Util.h" #include "xml/XmlUtil.h" @@ -152,7 +152,7 @@ class XmlResource { }; // Inflates an XML DOM from an InputStream, logging errors to the logger. -std::unique_ptr<XmlResource> Inflate(io::InputStream* in, android::IDiagnostics* diag, +std::unique_ptr<XmlResource> Inflate(android::InputStream* in, android::IDiagnostics* diag, const android::Source& source); // Inflates an XML DOM from a binary ResXMLTree. diff --git a/tools/aapt2/xml/XmlPullParser.cpp b/tools/aapt2/xml/XmlPullParser.cpp index d79446bfae6f..203832d2dbe8 100644 --- a/tools/aapt2/xml/XmlPullParser.cpp +++ b/tools/aapt2/xml/XmlPullParser.cpp @@ -21,7 +21,7 @@ #include "xml/XmlPullParser.h" #include "xml/XmlUtil.h" -using ::aapt::io::InputStream; +using ::android::InputStream; using ::android::StringPiece; namespace aapt { diff --git a/tools/aapt2/xml/XmlPullParser.h b/tools/aapt2/xml/XmlPullParser.h index fe4cd018d808..655e6dc93e75 100644 --- a/tools/aapt2/xml/XmlPullParser.h +++ b/tools/aapt2/xml/XmlPullParser.h @@ -27,11 +27,10 @@ #include <string> #include <vector> +#include "Resource.h" #include "android-base/macros.h" +#include "androidfw/Streams.h" #include "androidfw/StringPiece.h" - -#include "Resource.h" -#include "io/Io.h" #include "process/IResourceTableConsumer.h" #include "xml/XmlUtil.h" @@ -66,7 +65,7 @@ class XmlPullParser : public IPackageDeclStack { static bool SkipCurrentElement(XmlPullParser* parser); static bool IsGoodEvent(Event event); - explicit XmlPullParser(io::InputStream* in); + explicit XmlPullParser(android::InputStream* in); ~XmlPullParser(); /** @@ -179,7 +178,7 @@ class XmlPullParser : public IPackageDeclStack { std::vector<Attribute> attributes; }; - io::InputStream* in_; + android::InputStream* in_; XML_Parser parser_; std::queue<EventData> event_queue_; std::string error_; diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/DelegatingFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/DelegatingFilter.kt index 45f61c5b2c22..cdd24e809ff8 100644 --- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/DelegatingFilter.kt +++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/DelegatingFilter.kt @@ -19,7 +19,7 @@ package com.android.hoststubgen.filters * Base class for an [OutputFilter] that uses another filter as a fallback. */ abstract class DelegatingFilter( - // fallback shouldn't be used by subclasses, so make it private. + // fallback shouldn't be used by subclasses directly, so make it private. // They should instead be calling into `super` or `outermostFilter`. private val fallback: OutputFilter ) : OutputFilter() { @@ -27,11 +27,21 @@ abstract class DelegatingFilter( fallback.outermostFilter = this } + /** + * Returns the outermost filter in a filter chain. + * + * When methods in a subclass needs to refer to a policy on an item (class, fields, methods) + * that are not the "subject" item -- e.g. + * in [ClassWidePolicyPropagatingFilter.getPolicyForField], when it checks the + * class policy -- [outermostFilter] must be used, rather than the super's method. + * The former will always return the correct policy, but the later won't consult outer + * filters than the current filter. + */ override var outermostFilter: OutputFilter = this get() = field set(value) { field = value - // Propagate the inner filters. + // Propagate to the inner filters. fallback.outermostFilter = value } diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ImplicitOutputFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ImplicitOutputFilter.kt index 84856aca84cc..ea7d1d0ff391 100644 --- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ImplicitOutputFilter.kt +++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ImplicitOutputFilter.kt @@ -149,7 +149,7 @@ class ImplicitOutputFilter( val fallback = super.getPolicyForField(className, fieldName) val cn = classes.getClass(className) - val classPolicy = super.getPolicyForClass(className) + val classPolicy = outermostFilter.getPolicyForClass(className) log.d("Class ${cn.name} Class policy: $classPolicy") if (classPolicy.policy.needsInImpl) { |