diff options
182 files changed, 2253 insertions, 1500 deletions
diff --git a/Android.bp b/Android.bp index 7f4cd849ab77..6653bd44966b 100644 --- a/Android.bp +++ b/Android.bp @@ -577,25 +577,6 @@ platform_compat_config { src: ":framework-annotation-proc", } -// A library including just UnsupportedAppUsage.java classes. -// -// Provided for target so that libraries can use it without depending on -// the whole of framework or the core platform API. -// -// Built for host so that the annotation processor can also use this annotation. -java_library { - name: "unsupportedappusage-annotation", - host_supported: true, - srcs: [ - "core/java/android/annotation/IntDef.java", - ], - static_libs: [ - "art.module.api.annotations", - ], - - sdk_version: "core_current", -} - // A temporary build target that is conditionally included on the bootclasspath if // android.test.base library has been removed and which provides support for // maintaining backwards compatibility for APKs that target pre-P and depend on @@ -971,7 +952,6 @@ filegroup { "core/java/android/content/pm/InstallationFileLocation.aidl", "core/java/android/content/pm/IDataLoaderStatusListener.aidl", "core/java/android/content/pm/IPackageInstallerSessionFileSystemConnector.aidl", - "core/java/android/content/pm/NamedParcelFileDescriptor.aidl", ], path: "core/java", } diff --git a/apex/Android.bp b/apex/Android.bp index e8f6e6bf2c46..2f4294588d7a 100644 --- a/apex/Android.bp +++ b/apex/Android.bp @@ -88,18 +88,30 @@ java_defaults { name: "framework-module-stubs-lib-defaults-publicapi", installable: false, sdk_version: "module_current", + dist: { + targets: ["sdk", "win_sdk"], + dir: "apistubs/android/public", + }, } java_defaults { name: "framework-module-stubs-lib-defaults-systemapi", installable: false, sdk_version: "module_current", + dist: { + targets: ["sdk", "win_sdk"], + dir: "apistubs/android/system", + }, } java_defaults { name: "framework-module-stubs-lib-defaults-module_libs_api", installable: false, sdk_version: "module_current", + dist: { + targets: ["sdk", "win_sdk"], + dir: "apistubs/android/module-lib", + }, } // The defaults for module_libs comes in two parts - defaults for API checks @@ -153,4 +165,8 @@ stubs_defaults { // module java_library system_server stub libs. java_defaults { name: "service-module-stubs-defaults", + dist: { + targets: ["sdk", "win_sdk"], + dir: "apistubs/android/system-server", + }, } diff --git a/apex/media/framework/api/current.txt b/apex/media/framework/api/current.txt index 839fb5143196..9cec748e7b8e 100644 --- a/apex/media/framework/api/current.txt +++ b/apex/media/framework/api/current.txt @@ -29,7 +29,7 @@ package android.media { method public boolean advance(@NonNull android.media.MediaParser.SeekableInputReader) throws java.io.IOException; method @NonNull public static android.media.MediaParser create(@NonNull android.media.MediaParser.OutputConsumer, @NonNull java.lang.String...); method @NonNull public static android.media.MediaParser createByName(@NonNull String, @NonNull android.media.MediaParser.OutputConsumer); - method @Nullable public String getParserName(); + method @NonNull public String getParserName(); method @NonNull public static java.util.List<java.lang.String> getParserNames(@NonNull android.media.MediaFormat); method public void release(); method public void seek(@NonNull android.media.MediaParser.SeekPoint); @@ -65,6 +65,7 @@ package android.media { field public static final String PARSER_NAME_OGG = "android.media.mediaparser.OggParser"; field public static final String PARSER_NAME_PS = "android.media.mediaparser.PsParser"; field public static final String PARSER_NAME_TS = "android.media.mediaparser.TsParser"; + field public static final String PARSER_NAME_UNKNOWN = "android.media.mediaparser.UNKNOWN"; field public static final String PARSER_NAME_WAV = "android.media.mediaparser.WavParser"; } diff --git a/apex/media/framework/java/android/media/MediaParser.java b/apex/media/framework/java/android/media/MediaParser.java index 5f86ed621084..c0e3d55b45a6 100644 --- a/apex/media/framework/java/android/media/MediaParser.java +++ b/apex/media/framework/java/android/media/MediaParser.java @@ -452,6 +452,7 @@ public final class MediaParser { @StringDef( prefix = {"PARSER_NAME_"}, value = { + PARSER_NAME_UNKNOWN, PARSER_NAME_MATROSKA, PARSER_NAME_FMP4, PARSER_NAME_MP4, @@ -469,6 +470,7 @@ public final class MediaParser { }) public @interface ParserName {} + public static final String PARSER_NAME_UNKNOWN = "android.media.mediaparser.UNKNOWN"; public static final String PARSER_NAME_MATROSKA = "android.media.mediaparser.MatroskaParser"; public static final String PARSER_NAME_FMP4 = "android.media.mediaparser.FragmentedMp4Parser"; public static final String PARSER_NAME_MP4 = "android.media.mediaparser.Mp4Parser"; @@ -836,14 +838,14 @@ public final class MediaParser { * Returns the name of the backing parser implementation. * * <p>If this instance was creating using {@link #createByName}, the provided name is returned. - * If this instance was created using {@link #create}, this method will return null until the - * first call to {@link #advance}, after which the name of the backing parser implementation is - * returned. + * If this instance was created using {@link #create}, this method will return {@link + * #PARSER_NAME_UNKNOWN} until the first call to {@link #advance}, after which the name of the + * backing parser implementation is returned. * * @return The name of the backing parser implementation, or null if the backing parser * implementation has not yet been selected. */ - @Nullable + @NonNull @ParserName public String getParserName() { return mExtractorName; @@ -880,7 +882,7 @@ public final class MediaParser { // TODO: Apply parameters when creating extractor instances. if (mExtractor == null) { - if (mExtractorName != null) { + if (!mExtractorName.equals(PARSER_NAME_UNKNOWN)) { mExtractor = EXTRACTOR_FACTORIES_BY_NAME.get(mExtractorName).createInstance(); mExtractor.init(new ExtractorOutputAdapter()); } else { @@ -974,9 +976,7 @@ public final class MediaParser { mParserParameters = new HashMap<>(); mOutputConsumer = outputConsumer; mParserNamesPool = parserNamesPool; - if (!sniff) { - mExtractorName = parserNamesPool[0]; - } + mExtractorName = sniff ? PARSER_NAME_UNKNOWN : parserNamesPool[0]; mPositionHolder = new PositionHolder(); mDataSource = new InputReadingDataSource(); removePendingSeek(); diff --git a/apex/permission/framework/Android.bp b/apex/permission/framework/Android.bp index 3fefeb51aa11..793247e88614 100644 --- a/apex/permission/framework/Android.bp +++ b/apex/permission/framework/Android.bp @@ -31,6 +31,10 @@ java_library { "com.android.permission", "test_com.android.permission", ], + permitted_packages: [ + "android.permission", + "android.app.role", + ], hostdex: true, installable: true, visibility: [ diff --git a/api/current.txt b/api/current.txt index 857ca6f03db9..2a13e2edca98 100644 --- a/api/current.txt +++ b/api/current.txt @@ -24356,7 +24356,7 @@ package android.media { } public final class AudioMetadata { - method @NonNull public static android.media.AudioMetadata.Map createMap(); + method @NonNull public static android.media.AudioMetadataMap createMap(); } public static class AudioMetadata.Format { @@ -24374,16 +24374,16 @@ package android.media { method @NonNull public Class<T> getValueClass(); } - public static interface AudioMetadata.Map extends android.media.AudioMetadata.ReadMap { + public interface AudioMetadataMap extends android.media.AudioMetadataReadMap { method @Nullable public <T> T remove(@NonNull android.media.AudioMetadata.Key<T>); method @Nullable public <T> T set(@NonNull android.media.AudioMetadata.Key<T>, @NonNull T); } - public static interface AudioMetadata.ReadMap { + public interface AudioMetadataReadMap { method public <T> boolean containsKey(@NonNull android.media.AudioMetadata.Key<T>); - method @NonNull public android.media.AudioMetadata.Map dup(); + method @NonNull public android.media.AudioMetadataMap dup(); method @Nullable public <T> T get(@NonNull android.media.AudioMetadata.Key<T>); - method public int size(); + method @IntRange(from=0) public int size(); } public final class AudioPlaybackCaptureConfiguration { @@ -24698,7 +24698,7 @@ package android.media { } public static interface AudioTrack.OnCodecFormatChangedListener { - method public void onCodecFormatChanged(@NonNull android.media.AudioTrack, @Nullable android.media.AudioMetadata.ReadMap); + method public void onCodecFormatChanged(@NonNull android.media.AudioTrack, @Nullable android.media.AudioMetadataReadMap); } public static interface AudioTrack.OnPlaybackPositionUpdateListener { @@ -26399,7 +26399,7 @@ package android.media { method public boolean advance(@NonNull android.media.MediaParser.SeekableInputReader) throws java.io.IOException; method @NonNull public static android.media.MediaParser create(@NonNull android.media.MediaParser.OutputConsumer, @NonNull java.lang.String...); method @NonNull public static android.media.MediaParser createByName(@NonNull String, @NonNull android.media.MediaParser.OutputConsumer); - method @Nullable public String getParserName(); + method @NonNull public String getParserName(); method @NonNull public static java.util.List<java.lang.String> getParserNames(@NonNull android.media.MediaFormat); method public void release(); method public void seek(@NonNull android.media.MediaParser.SeekPoint); @@ -26435,6 +26435,7 @@ package android.media { field public static final String PARSER_NAME_OGG = "android.media.mediaparser.OggParser"; field public static final String PARSER_NAME_PS = "android.media.mediaparser.PsParser"; field public static final String PARSER_NAME_TS = "android.media.mediaparser.TsParser"; + field public static final String PARSER_NAME_UNKNOWN = "android.media.mediaparser.UNKNOWN"; field public static final String PARSER_NAME_WAV = "android.media.mediaparser.WavParser"; } @@ -30346,6 +30347,7 @@ package android.net { method @Nullable public android.net.NetworkSpecifier getNetworkSpecifier(); method public boolean hasCapability(int); method public boolean hasTransport(int); + method public boolean satisfiedBy(@Nullable android.net.NetworkCapabilities); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkRequest> CREATOR; } @@ -37144,11 +37146,10 @@ package android.os { field public static final int EFFECT_TICK = 2; // 0x2 } - public static class VibrationEffect.Composition { - ctor public VibrationEffect.Composition(); - method @Nullable public android.os.VibrationEffect.Composition addPrimitive(int); - method @Nullable public android.os.VibrationEffect.Composition addPrimitive(int, @FloatRange(from=0.0f, to=1.0f) float); - method @Nullable public android.os.VibrationEffect.Composition addPrimitive(int, @FloatRange(from=0.0f, to=1.0f) float, @IntRange(from=0) int); + public static final class VibrationEffect.Composition { + method @NonNull public android.os.VibrationEffect.Composition addPrimitive(int); + method @NonNull public android.os.VibrationEffect.Composition addPrimitive(int, @FloatRange(from=0.0f, to=1.0f) float); + method @NonNull public android.os.VibrationEffect.Composition addPrimitive(int, @FloatRange(from=0.0f, to=1.0f) float, @IntRange(from=0) int); method @NonNull public android.os.VibrationEffect compose(); field public static final int PRIMITIVE_CLICK = 1; // 0x1 field public static final int PRIMITIVE_QUICK_FALL = 6; // 0x6 @@ -37158,9 +37159,9 @@ package android.os { } public abstract class Vibrator { - method @Nullable public Boolean areAllEffectsSupported(@NonNull int...); - method public boolean areAllPrimitivesSupported(@NonNull int...); - method @Nullable public boolean[] areEffectsSupported(@NonNull int...); + method public final int areAllEffectsSupported(@NonNull int...); + method public final boolean areAllPrimitivesSupported(@NonNull int...); + method @NonNull public int[] areEffectsSupported(@NonNull int...); method @NonNull public boolean[] arePrimitivesSupported(@NonNull int...); method @RequiresPermission(android.Manifest.permission.VIBRATE) public abstract void cancel(); method public abstract boolean hasAmplitudeControl(); @@ -37171,6 +37172,9 @@ package android.os { method @Deprecated @RequiresPermission(android.Manifest.permission.VIBRATE) public void vibrate(long[], int, android.media.AudioAttributes); method @RequiresPermission(android.Manifest.permission.VIBRATE) public void vibrate(android.os.VibrationEffect); method @RequiresPermission(android.Manifest.permission.VIBRATE) public void vibrate(android.os.VibrationEffect, android.media.AudioAttributes); + field public static final int VIBRATION_EFFECT_SUPPORT_NO = 2; // 0x2 + field public static final int VIBRATION_EFFECT_SUPPORT_UNKNOWN = 0; // 0x0 + field public static final int VIBRATION_EFFECT_SUPPORT_YES = 1; // 0x1 } public class WorkSource implements android.os.Parcelable { @@ -55756,7 +55760,7 @@ package android.view { field public int softInputMode; field @Deprecated public int systemUiVisibility; field public android.os.IBinder token; - field @android.view.ViewDebug.ExportedProperty(mapping={@android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION, to="BASE_APPLICATION"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_APPLICATION, to="APPLICATION"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING, to="APPLICATION_STARTING"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION, to="DRAWN_APPLICATION"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL, to="APPLICATION_PANEL"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA, to="APPLICATION_MEDIA"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL, to="APPLICATION_SUB_PANEL"), @android.view.ViewDebug.IntToString(from=0x3ed, to="APPLICATION_ABOVE_SUB_PANEL"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG, to="APPLICATION_ATTACHED_DIALOG"), @android.view.ViewDebug.IntToString(from=0x3ec, to="APPLICATION_MEDIA_OVERLAY"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR, to="STATUS_BAR"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_SEARCH_BAR, to="SEARCH_BAR"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_PHONE, to="PHONE"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, to="SYSTEM_ALERT"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_TOAST, to="TOAST"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY, to="SYSTEM_OVERLAY"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_PRIORITY_PHONE, to="PRIORITY_PHONE"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG, to="SYSTEM_DIALOG"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG, to="KEYGUARD_DIALOG"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR, to="SYSTEM_ERROR"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD, to="INPUT_METHOD"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG, to="INPUT_METHOD_DIALOG"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_WALLPAPER, to="WALLPAPER"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL, to="STATUS_BAR_PANEL"), @android.view.ViewDebug.IntToString(from=0x7df, to="SECURE_SYSTEM_OVERLAY"), @android.view.ViewDebug.IntToString(from=0x7e0, to="DRAG"), @android.view.ViewDebug.IntToString(from=0x7e1, to="STATUS_BAR_SUB_PANEL"), @android.view.ViewDebug.IntToString(from=0x7e2, to="POINTER"), @android.view.ViewDebug.IntToString(from=0x7e3, to="NAVIGATION_BAR"), @android.view.ViewDebug.IntToString(from=0x7e4, to="VOLUME_OVERLAY"), @android.view.ViewDebug.IntToString(from=0x7e5, to="BOOT_PROGRESS"), @android.view.ViewDebug.IntToString(from=0x7e6, to="INPUT_CONSUMER"), @android.view.ViewDebug.IntToString(from=0x7e7, to="DREAM"), @android.view.ViewDebug.IntToString(from=0x7e8, to="NAVIGATION_BAR_PANEL"), @android.view.ViewDebug.IntToString(from=0x7ea, to="DISPLAY_OVERLAY"), @android.view.ViewDebug.IntToString(from=0x7eb, to="MAGNIFICATION_OVERLAY"), @android.view.ViewDebug.IntToString(from=0x7f5, to="PRESENTATION"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION, to="PRIVATE_PRESENTATION"), @android.view.ViewDebug.IntToString(from=0x7ef, to="VOICE_INTERACTION"), @android.view.ViewDebug.IntToString(from=0x7f1, to="VOICE_INTERACTION_STARTING"), @android.view.ViewDebug.IntToString(from=0x7f2, to="DOCK_DIVIDER"), @android.view.ViewDebug.IntToString(from=0x7f3, to="QS_DIALOG"), @android.view.ViewDebug.IntToString(from=0x7f4, to="SCREENSHOT"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, to="APPLICATION_OVERLAY")}) public int type; + field @android.view.ViewDebug.ExportedProperty(mapping={@android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION, to="BASE_APPLICATION"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_APPLICATION, to="APPLICATION"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING, to="APPLICATION_STARTING"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION, to="DRAWN_APPLICATION"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL, to="APPLICATION_PANEL"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA, to="APPLICATION_MEDIA"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL, to="APPLICATION_SUB_PANEL"), @android.view.ViewDebug.IntToString(from=0x3ed, to="APPLICATION_ABOVE_SUB_PANEL"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG, to="APPLICATION_ATTACHED_DIALOG"), @android.view.ViewDebug.IntToString(from=0x3ec, to="APPLICATION_MEDIA_OVERLAY"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR, to="STATUS_BAR"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_SEARCH_BAR, to="SEARCH_BAR"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_PHONE, to="PHONE"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, to="SYSTEM_ALERT"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_TOAST, to="TOAST"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY, to="SYSTEM_OVERLAY"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_PRIORITY_PHONE, to="PRIORITY_PHONE"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG, to="SYSTEM_DIALOG"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG, to="KEYGUARD_DIALOG"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR, to="SYSTEM_ERROR"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD, to="INPUT_METHOD"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG, to="INPUT_METHOD_DIALOG"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_WALLPAPER, to="WALLPAPER"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL, to="STATUS_BAR_PANEL"), @android.view.ViewDebug.IntToString(from=0x7df, to="SECURE_SYSTEM_OVERLAY"), @android.view.ViewDebug.IntToString(from=0x7e0, to="DRAG"), @android.view.ViewDebug.IntToString(from=0x7e1, to="STATUS_BAR_SUB_PANEL"), @android.view.ViewDebug.IntToString(from=0x7e2, to="POINTER"), @android.view.ViewDebug.IntToString(from=0x7e3, to="NAVIGATION_BAR"), @android.view.ViewDebug.IntToString(from=0x7e4, to="VOLUME_OVERLAY"), @android.view.ViewDebug.IntToString(from=0x7e5, to="BOOT_PROGRESS"), @android.view.ViewDebug.IntToString(from=0x7e6, to="INPUT_CONSUMER"), @android.view.ViewDebug.IntToString(from=0x7e8, to="NAVIGATION_BAR_PANEL"), @android.view.ViewDebug.IntToString(from=0x7ea, to="DISPLAY_OVERLAY"), @android.view.ViewDebug.IntToString(from=0x7eb, to="MAGNIFICATION_OVERLAY"), @android.view.ViewDebug.IntToString(from=0x7f5, to="PRESENTATION"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION, to="PRIVATE_PRESENTATION"), @android.view.ViewDebug.IntToString(from=0x7ef, to="VOICE_INTERACTION"), @android.view.ViewDebug.IntToString(from=0x7f1, to="VOICE_INTERACTION_STARTING"), @android.view.ViewDebug.IntToString(from=0x7f2, to="DOCK_DIVIDER"), @android.view.ViewDebug.IntToString(from=0x7f3, to="QS_DIALOG"), @android.view.ViewDebug.IntToString(from=0x7f4, to="SCREENSHOT"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, to="APPLICATION_OVERLAY")}) public int type; field public float verticalMargin; field @android.view.ViewDebug.ExportedProperty public float verticalWeight; field public int windowAnimations; diff --git a/api/system-current.txt b/api/system-current.txt index b9153d96a56a..156d81e7ba2a 100755 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -4178,11 +4178,11 @@ package android.media { method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void addOnPreferredDeviceForStrategyChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.AudioManager.OnPreferredDeviceForStrategyChangedListener) throws java.lang.SecurityException; method public void clearAudioServerStateCallback(); method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int dispatchAudioFocusChange(@NonNull android.media.AudioFocusInfo, int, @NonNull android.media.audiopolicy.AudioPolicy); - method @IntRange(from=0) public int getAdditionalOutputDeviceDelay(@NonNull android.media.AudioDeviceInfo); + method @IntRange(from=0) public long getAdditionalOutputDeviceDelay(@NonNull android.media.AudioDeviceInfo); method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static java.util.List<android.media.audiopolicy.AudioProductStrategy> getAudioProductStrategies(); method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static java.util.List<android.media.audiopolicy.AudioVolumeGroup> getAudioVolumeGroups(); method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public java.util.List<android.media.AudioDeviceAttributes> getDevicesForAttributes(@NonNull android.media.AudioAttributes); - method @IntRange(from=0) public int getMaxAdditionalOutputDeviceDelay(@NonNull android.media.AudioDeviceInfo); + method @IntRange(from=0) public long getMaxAdditionalOutputDeviceDelay(@NonNull android.media.AudioDeviceInfo); method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getMaxVolumeIndexForAttributes(@NonNull android.media.AudioAttributes); method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getMinVolumeIndexForAttributes(@NonNull android.media.AudioAttributes); method @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public android.media.AudioDeviceAttributes getPreferredDeviceForStrategy(@NonNull android.media.audiopolicy.AudioProductStrategy); @@ -4197,7 +4197,7 @@ package android.media { method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, @NonNull android.media.AudioAttributes, int, int) throws java.lang.IllegalArgumentException; method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.MODIFY_AUDIO_ROUTING}) public int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, @NonNull android.media.AudioAttributes, int, int, android.media.audiopolicy.AudioPolicy) throws java.lang.IllegalArgumentException; method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int requestAudioFocus(@NonNull android.media.AudioFocusRequest, @Nullable android.media.audiopolicy.AudioPolicy); - method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public boolean setAdditionalOutputDeviceDelay(@NonNull android.media.AudioDeviceInfo, @IntRange(from=0) int); + method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public boolean setAdditionalOutputDeviceDelay(@NonNull android.media.AudioDeviceInfo, @IntRange(from=0) long); method public void setAudioServerStateCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.AudioManager.AudioServerStateCallback); method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setFocusRequestResult(@NonNull android.media.AudioFocusInfo, int, @NonNull android.media.audiopolicy.AudioPolicy); method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public boolean setPreferredDeviceForStrategy(@NonNull android.media.audiopolicy.AudioProductStrategy, @NonNull android.media.AudioDeviceAttributes); @@ -4272,17 +4272,11 @@ package android.media { } public static class AudioTrack.TunerConfiguration { + ctor @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public AudioTrack.TunerConfiguration(@IntRange(from=1) int, @IntRange(from=1) int); method @IntRange(from=1) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getContentId(); method @IntRange(from=1) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getSyncId(); } - public static class AudioTrack.TunerConfiguration.Builder { - ctor public AudioTrack.TunerConfiguration.Builder(); - method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public android.media.AudioTrack.TunerConfiguration build(); - method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public android.media.AudioTrack.TunerConfiguration.Builder setContentId(@IntRange(from=1) int); - method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public android.media.AudioTrack.TunerConfiguration.Builder setSyncId(@IntRange(from=1) int); - } - public class HwAudioSource { method public boolean isPlaying(); method public void start(); @@ -6210,14 +6204,14 @@ package android.net { method public void onRemoveKeepalivePacketFilter(int); method public void onSaveAcceptUnvalidated(boolean); method public void onSignalStrengthThresholdsUpdated(@NonNull int[]); - method public void onStartSocketKeepalive(int, int, @NonNull android.net.KeepalivePacketData); + method public void onStartSocketKeepalive(int, @IntRange(from=10, to=3600) int, @NonNull android.net.KeepalivePacketData); method public void onStopSocketKeepalive(int); - method public void onValidationStatus(int, @Nullable String); + method public void onValidationStatus(int, @Nullable android.net.Uri); method @NonNull public android.net.Network register(); - method public void sendLinkProperties(@NonNull android.net.LinkProperties); - method public void sendNetworkCapabilities(@NonNull android.net.NetworkCapabilities); - method public void sendNetworkScore(int); - method public void sendSocketKeepaliveEvent(int, int); + method public final void sendLinkProperties(@NonNull android.net.LinkProperties); + method public final void sendNetworkCapabilities(@NonNull android.net.NetworkCapabilities); + method public final void sendNetworkScore(@IntRange(from=0, to=99) int); + method public final void sendSocketKeepaliveEvent(int, int); method public void setConnected(); method public void unregister(); field public static final int VALIDATION_STATUS_NOT_VALID = 2; // 0x2 @@ -6235,7 +6229,7 @@ package android.net { field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkAgentConfig> CREATOR; } - public static class NetworkAgentConfig.Builder { + public static final class NetworkAgentConfig.Builder { ctor public NetworkAgentConfig.Builder(); method @NonNull public android.net.NetworkAgentConfig build(); method @NonNull public android.net.NetworkAgentConfig.Builder setExplicitlySelected(boolean); @@ -6303,7 +6297,6 @@ package android.net { public class NetworkRequest implements android.os.Parcelable { method @Nullable public String getRequestorPackageName(); method public int getRequestorUid(); - method public boolean satisfiedBy(@Nullable android.net.NetworkCapabilities); } public static class NetworkRequest.Builder { @@ -8394,12 +8387,12 @@ package android.os { public class RecoverySystem { method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void cancelScheduledUpdate(android.content.Context) throws java.io.IOException; - method @RequiresPermission(android.Manifest.permission.RECOVERY) public static boolean clearPrepareForUnattendedUpdate(@NonNull android.content.Context) throws java.io.IOException; + method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void clearPrepareForUnattendedUpdate(@NonNull android.content.Context) throws java.io.IOException; method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void installPackage(android.content.Context, java.io.File, boolean) throws java.io.IOException; method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void prepareForUnattendedUpdate(@NonNull android.content.Context, @NonNull String, @Nullable android.content.IntentSender) throws java.io.IOException; method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void processPackage(android.content.Context, java.io.File, android.os.RecoverySystem.ProgressListener, android.os.Handler) throws java.io.IOException; method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void processPackage(android.content.Context, java.io.File, android.os.RecoverySystem.ProgressListener) throws java.io.IOException; - method @RequiresPermission(android.Manifest.permission.RECOVERY) public static boolean rebootAndApply(@NonNull android.content.Context, @NonNull String, @NonNull String) throws java.io.IOException; + method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void rebootAndApply(@NonNull android.content.Context, @NonNull String, @NonNull String) throws java.io.IOException; method @RequiresPermission(allOf={android.Manifest.permission.RECOVERY, android.Manifest.permission.REBOOT}) public static void rebootWipeAb(android.content.Context, java.io.File, String) throws java.io.IOException; method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void scheduleUpdateOnBoot(android.content.Context, java.io.File) throws java.io.IOException; method public static boolean verifyPackageCompatibility(java.io.File) throws java.io.IOException; @@ -12712,9 +12705,6 @@ package android.view.contentcapture { public final class ContentCaptureManager { method public boolean isContentCaptureFeatureEnabled(); - } - - public abstract class ContentCaptureSession implements java.lang.AutoCloseable { field public static final int NO_SESSION_ID = 0; // 0x0 } diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl index 8b8ebe80f01f..e476993f003f 100644 --- a/core/java/android/app/IActivityTaskManager.aidl +++ b/core/java/android/app/IActivityTaskManager.aidl @@ -298,13 +298,6 @@ interface IActivityTaskManager { void reportSizeConfigurations(in IBinder token, in int[] horizontalSizeConfiguration, in int[] verticalSizeConfigurations, in int[] smallestWidthConfigurations); - /** - * Dismisses PiP - * @param animate True if the dismissal should be animated. - * @param animationDuration The duration of the resize animation in milliseconds or -1 if the - * default animation duration should be used. - */ - void dismissPip(boolean animate, int animationDuration); void suppressResizeConfigChanges(boolean suppress); void moveTasksToFullscreenStack(int fromStackId, boolean onTop); boolean moveTopActivityToPinnedStack(int stackId, in Rect bounds); diff --git a/core/java/android/content/pm/DataLoaderParams.java b/core/java/android/content/pm/DataLoaderParams.java index 99c0907f1844..a791026d44cd 100644 --- a/core/java/android/content/pm/DataLoaderParams.java +++ b/core/java/android/content/pm/DataLoaderParams.java @@ -17,12 +17,8 @@ package android.content.pm; import android.annotation.NonNull; -import android.annotation.Nullable; import android.annotation.SystemApi; import android.content.ComponentName; -import android.os.ParcelFileDescriptor; - -import java.util.Map; /** * This class represents the parameters used to configure a Data Loader. @@ -44,7 +40,7 @@ public class DataLoaderParams { */ public static final @NonNull DataLoaderParams forStreaming(@NonNull ComponentName componentName, @NonNull String arguments) { - return new DataLoaderParams(DataLoaderType.STREAMING, componentName, arguments, null); + return new DataLoaderParams(DataLoaderType.STREAMING, componentName, arguments); } /** @@ -55,29 +51,17 @@ public class DataLoaderParams { */ public static final @NonNull DataLoaderParams forIncremental( @NonNull ComponentName componentName, @NonNull String arguments) { - return new DataLoaderParams(DataLoaderType.INCREMENTAL, componentName, arguments, null); + return new DataLoaderParams(DataLoaderType.INCREMENTAL, componentName, arguments); } /** @hide */ public DataLoaderParams(@NonNull @DataLoaderType int type, @NonNull ComponentName componentName, - @NonNull String arguments, @Nullable Map<String, ParcelFileDescriptor> namedFds) { + @NonNull String arguments) { DataLoaderParamsParcel data = new DataLoaderParamsParcel(); data.type = type; data.packageName = componentName.getPackageName(); data.className = componentName.getClassName(); data.arguments = arguments; - if (namedFds == null || namedFds.isEmpty()) { - data.dynamicArgs = new NamedParcelFileDescriptor[0]; - } else { - data.dynamicArgs = new NamedParcelFileDescriptor[namedFds.size()]; - int i = 0; - for (Map.Entry<String, ParcelFileDescriptor> namedFd : namedFds.entrySet()) { - data.dynamicArgs[i] = new NamedParcelFileDescriptor(); - data.dynamicArgs[i].name = namedFd.getKey(); - data.dynamicArgs[i].fd = namedFd.getValue(); - i += 1; - } - } mData = data; } diff --git a/core/java/android/content/pm/DataLoaderParamsParcel.aidl b/core/java/android/content/pm/DataLoaderParamsParcel.aidl index e05843b4d4e9..d40012fd5718 100644 --- a/core/java/android/content/pm/DataLoaderParamsParcel.aidl +++ b/core/java/android/content/pm/DataLoaderParamsParcel.aidl @@ -17,7 +17,6 @@ package android.content.pm; import android.content.pm.DataLoaderType; -import android.content.pm.NamedParcelFileDescriptor; /** * Class for holding data loader configuration parameters. @@ -28,5 +27,4 @@ parcelable DataLoaderParamsParcel { @utf8InCpp String packageName; @utf8InCpp String className; @utf8InCpp String arguments; - NamedParcelFileDescriptor[] dynamicArgs; } diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 20ddba41bda1..1dadbda1918b 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -1837,6 +1837,12 @@ public class PackageParser { pkg.coreApp = parser.getAttributeBooleanValue(null, "coreApp", false); + final boolean isolatedSplits = sa.getBoolean( + com.android.internal.R.styleable.AndroidManifest_isolatedSplits, false); + if (isolatedSplits) { + pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_ISOLATED_SPLIT_LOADING; + } + pkg.mCompileSdkVersion = sa.getInteger( com.android.internal.R.styleable.AndroidManifest_compileSdkVersion, 0); pkg.applicationInfo.compileSdkVersion = pkg.mCompileSdkVersion; @@ -1912,10 +1918,6 @@ public class PackageParser { pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE; } - if (sa.getBoolean(com.android.internal.R.styleable.AndroidManifest_isolatedSplits, false)) { - pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_ISOLATED_SPLIT_LOADING; - } - // Resource boolean are -1, so 1 means we don't know the value. int supportsSmallScreens = 1; int supportsNormalScreens = 1; diff --git a/core/java/android/content/pm/parsing/ParsingPackageImpl.java b/core/java/android/content/pm/parsing/ParsingPackageImpl.java index 079a47056c24..894ad5584922 100644 --- a/core/java/android/content/pm/parsing/ParsingPackageImpl.java +++ b/core/java/android/content/pm/parsing/ParsingPackageImpl.java @@ -433,6 +433,10 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable { R.styleable.AndroidManifest_compileSdkVersion, 0)); setCompileSdkVersionCodename(manifestArray.getNonConfigurationString( R.styleable.AndroidManifest_compileSdkVersionCodename, 0)); + + setIsolatedSplitLoading(manifestArray.getBoolean( + R.styleable.AndroidManifest_isolatedSplits, false)); + } } diff --git a/core/java/android/content/pm/parsing/ParsingPackageUtils.java b/core/java/android/content/pm/parsing/ParsingPackageUtils.java index ec771286d980..e90ccdffa8a8 100644 --- a/core/java/android/content/pm/parsing/ParsingPackageUtils.java +++ b/core/java/android/content/pm/parsing/ParsingPackageUtils.java @@ -386,15 +386,14 @@ public class ParsingPackageUtils { return input.error(PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME); } - TypedArray manifestArray = res.obtainAttributes(parser, R.styleable.AndroidManifest); + final TypedArray manifestArray = res.obtainAttributes(parser, R.styleable.AndroidManifest); try { - boolean isCoreApp = parser.getAttributeBooleanValue(null, "coreApp", false); - - ParsingPackage pkg = mCallback.startParsingPackage(pkgName, apkPath, codePath, - manifestArray, isCoreApp); - - ParseResult<ParsingPackage> result = parseBaseApkTags(input, pkg, manifestArray, - res, parser, flags); + final boolean isCoreApp = + parser.getAttributeBooleanValue(null, "coreApp", false); + final ParsingPackage pkg = mCallback.startParsingPackage( + pkgName, apkPath, codePath, manifestArray, isCoreApp); + final ParseResult<ParsingPackage> result = + parseBaseApkTags(input, pkg, manifestArray, res, parser, flags); if (result.isError()) { return result; } @@ -620,14 +619,12 @@ public class ParsingPackageUtils { return sharedUserResult; } - pkg.setInstallLocation(anInt(PackageParser.PARSE_DEFAULT_INSTALL_LOCATION, + pkg.setInstallLocation(anInteger(PackageParser.PARSE_DEFAULT_INSTALL_LOCATION, R.styleable.AndroidManifest_installLocation, sa)) - .setTargetSandboxVersion(anInt(PackageParser.PARSE_DEFAULT_TARGET_SANDBOX, + .setTargetSandboxVersion(anInteger(PackageParser.PARSE_DEFAULT_TARGET_SANDBOX, R.styleable.AndroidManifest_targetSandboxVersion, sa)) /* Set the global "on SD card" flag */ - .setExternalStorage((flags & PackageParser.PARSE_EXTERNAL_STORAGE) != 0) - .setIsolatedSplitLoading( - bool(false, R.styleable.AndroidManifest_isolatedSplits, sa)); + .setExternalStorage((flags & PackageParser.PARSE_EXTERNAL_STORAGE) != 0); boolean foundApp = false; final int depth = parser.getDepth(); @@ -2658,6 +2655,10 @@ public class ParsingPackageUtils { return sa.getInt(attribute, defaultValue); } + private static int anInteger(int defaultValue, @StyleableRes int attribute, TypedArray sa) { + return sa.getInteger(attribute, defaultValue); + } + private static int anInt(@StyleableRes int attribute, TypedArray sa) { return sa.getInt(attribute, 0); } @@ -2688,6 +2689,6 @@ public class ParsingPackageUtils { boolean hasFeature(String feature); ParsingPackage startParsingPackage(String packageName, String baseCodePath, String codePath, - TypedArray manifestArray, boolean isCoreApp); + @NonNull TypedArray manifestArray, boolean isCoreApp); } } diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 2a323e5ec97d..7332ede0b997 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -705,6 +705,36 @@ public class ConnectivityManager { @Deprecated public static final int TYPE_TEST = 18; // TODO: Remove this once NetworkTypes are unused. + /** + * @deprecated Use {@link NetworkCapabilities} instead. + * @hide + */ + @Deprecated + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = { "TYPE_" }, value = { + TYPE_NONE, + TYPE_MOBILE, + TYPE_WIFI, + TYPE_MOBILE_MMS, + TYPE_MOBILE_SUPL, + TYPE_MOBILE_DUN, + TYPE_MOBILE_HIPRI, + TYPE_WIMAX, + TYPE_BLUETOOTH, + TYPE_DUMMY, + TYPE_ETHERNET, + TYPE_MOBILE_FOTA, + TYPE_MOBILE_IMS, + TYPE_MOBILE_CBS, + TYPE_WIFI_P2P, + TYPE_MOBILE_IA, + TYPE_MOBILE_EMERGENCY, + TYPE_PROXY, + TYPE_VPN, + TYPE_TEST + }) + public @interface LegacyNetworkType {} + // Deprecated constants for return values of startUsingNetworkFeature. They used to live // in com.android.internal.telephony.PhoneConstants until they were made inaccessible. private static final int DEPRECATED_PHONE_CONSTANT_APN_ALREADY_ACTIVE = 0; diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java index 5c754a1b9733..8119df921745 100644 --- a/core/java/android/net/NetworkAgent.java +++ b/core/java/android/net/NetworkAgent.java @@ -16,6 +16,8 @@ package android.net; +import android.annotation.IntDef; +import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; @@ -32,18 +34,52 @@ import android.util.Log; import com.android.internal.util.AsyncChannel; import com.android.internal.util.Protocol; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Objects; import java.util.concurrent.atomic.AtomicBoolean; /** - * A Utility class for handling for communicating between bearer-specific + * A utility class for handling for communicating between bearer-specific * code and ConnectivityService. * + * An agent manages the life cycle of a network. A network starts its + * life cycle when {@link register} is called on NetworkAgent. The network + * is then connecting. When full L3 connectivity has been established, + * the agent shoud call {@link setConnected} to inform the system that + * this network is ready to use. When the network disconnects its life + * ends and the agent should call {@link unregister}, at which point the + * system will clean up and free resources. + * Any reconnection becomes a new logical network, so after a network + * is disconnected the agent cannot be used any more. Network providers + * should create a new NetworkAgent instance to handle new connections. + * * A bearer may have more than one NetworkAgent if it can simultaneously * support separate networks (IMS / Internet / MMS Apns on cellular, or * perhaps connections with different SSID or P2P for Wi-Fi). * + * This class supports methods to start and stop sending keepalive packets. + * Keepalive packets are typically sent at periodic intervals over a network + * with NAT when there is no other traffic to avoid the network forcefully + * closing the connection. NetworkAgents that manage technologies that + * have hardware support for keepalive should implement the related + * methods to save battery life. NetworkAgent that cannot get support + * without waking up the CPU should not, as this would be prohibitive in + * terms of battery - these agents should simply not override the related + * methods, which results in the implementation returning + * {@link SocketKeepalive.ERROR_UNSUPPORTED} as appropriate. + * + * Keepalive packets need to be sent at relatively frequent intervals + * (a few seconds to a few minutes). As the contents of keepalive packets + * depend on the current network status, hardware needs to be configured + * to send them and has a limited amount of memory to do so. The HAL + * formalizes this as slots that an implementation can configure to send + * the correct packets. Devices typically have a small number of slots + * per radio technology, and the specific number of slots for each + * technology is specified in configuration files. + * {@see SocketKeepalive} for details. + * * @hide */ @SystemApi @@ -65,7 +101,7 @@ public abstract class NetworkAgent { private final String LOG_TAG; private static final boolean DBG = true; private static final boolean VDBG = false; - private final ArrayList<Message>mPreConnectedQueue = new ArrayList<Message>(); + private final ArrayList<Message> mPreConnectedQueue = new ArrayList<Message>(); private volatile long mLastBwRefreshTime = 0; private static final long BW_REFRESH_MIN_WIN_MS = 500; private boolean mBandwidthUpdateScheduled = false; @@ -74,6 +110,8 @@ public abstract class NetworkAgent { // into the internal API of ConnectivityService. @NonNull private NetworkInfo mNetworkInfo; + @NonNull + private final Object mRegisterLock = new Object(); /** * The ID of the {@link NetworkProvider} that created this object, or @@ -158,6 +196,14 @@ public abstract class NetworkAgent { */ public static final int VALIDATION_STATUS_NOT_VALID = 2; + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = { "VALIDATION_STATUS_" }, value = { + VALIDATION_STATUS_VALID, + VALIDATION_STATUS_NOT_VALID + }) + public @interface ValidationStatus {} + // TODO: remove. /** @hide */ public static final int VALID_NETWORK = 1; @@ -202,7 +248,7 @@ public abstract class NetworkAgent { * Sent by ConnectivityService to the NetworkAgent to request that the specified packet be sent * periodically on the given interval. * - * arg1 = the slot number of the keepalive to start + * arg1 = the hardware slot number of the keepalive to start * arg2 = interval in seconds * obj = KeepalivePacketData object describing the data to be sent * @@ -214,7 +260,7 @@ public abstract class NetworkAgent { /** * Requests that the specified keepalive packet be stopped. * - * arg1 = slot number of the keepalive to stop. + * arg1 = hardware slot number of the keepalive to stop. * * Also used internally by ConnectivityService / KeepaliveTracker, with different semantics. * @hide @@ -229,7 +275,7 @@ public abstract class NetworkAgent { * This is also sent by KeepaliveTracker to the app's {@link SocketKeepalive}, * so that the app's {@link SocketKeepalive.Callback} methods can be called. * - * arg1 = slot number of the keepalive + * arg1 = hardware slot number of the keepalive * arg2 = error code * @hide */ @@ -259,7 +305,7 @@ public abstract class NetworkAgent { * remote site will send ACK packets in response to the keepalive packets, the firmware also * needs to be configured to properly filter the ACKs to prevent the system from waking up. * This does not happen with UDP, so this message is TCP-specific. - * arg1 = slot number of the keepalive to filter for. + * arg1 = hardware slot number of the keepalive to filter for. * obj = the keepalive packet to send repeatedly. * @hide */ @@ -268,7 +314,7 @@ public abstract class NetworkAgent { /** * Sent by the KeepaliveTracker to NetworkAgent to remove a packet filter. See * {@link #CMD_ADD_KEEPALIVE_PACKET_FILTER}. - * arg1 = slot number of the keepalive packet filter to remove. + * arg1 = hardware slot number of the keepalive packet filter to remove. * @hide */ public static final int CMD_REMOVE_KEEPALIVE_PACKET_FILTER = BASE + 17; @@ -441,7 +487,15 @@ public abstract class NetworkAgent { + (msg.arg1 == VALID_NETWORK ? "VALID, " : "INVALID, ") + redirectUrl); } - onValidationStatus(msg.arg1 /* status */, redirectUrl); + Uri uri = null; + try { + if (null != redirectUrl) { + uri = Uri.parse(redirectUrl); + } + } catch (Exception e) { + Log.wtf(LOG_TAG, "Surprising URI : " + redirectUrl, e); + } + onValidationStatus(msg.arg1 /* status */, uri); break; } case CMD_SAVE_ACCEPT_UNVALIDATED: { @@ -489,19 +543,29 @@ public abstract class NetworkAgent { /** * Register this network agent with ConnectivityService. + * + * This method can only be called once per network agent. + * * @return the Network associated with this network agent (which can also be obtained later * by calling getNetwork() on this agent). + * @throws IllegalStateException thrown by the system server if this network agent is + * already registered. */ @NonNull public Network register() { if (VDBG) log("Registering NetworkAgent"); final ConnectivityManager cm = (ConnectivityManager) mInitialConfiguration.context .getSystemService(Context.CONNECTIVITY_SERVICE); - mNetwork = cm.registerNetworkAgent(new Messenger(mHandler), - new NetworkInfo(mInitialConfiguration.info), - mInitialConfiguration.properties, mInitialConfiguration.capabilities, - mInitialConfiguration.score, mInitialConfiguration.config, providerId); - mInitialConfiguration = null; // All this memory can now be GC'd + synchronized (mRegisterLock) { + if (mNetwork != null) { + throw new IllegalStateException("Agent already registered"); + } + mNetwork = cm.registerNetworkAgent(new Messenger(mHandler), + new NetworkInfo(mInitialConfiguration.info), + mInitialConfiguration.properties, mInitialConfiguration.capabilities, + mInitialConfiguration.score, mInitialConfiguration.config, providerId); + mInitialConfiguration = null; // All this memory can now be GC'd + } return mNetwork; } @@ -544,13 +608,14 @@ public abstract class NetworkAgent { * Must be called by the agent when the network's {@link LinkProperties} change. * @param linkProperties the new LinkProperties. */ - public void sendLinkProperties(@NonNull LinkProperties linkProperties) { + public final void sendLinkProperties(@NonNull LinkProperties linkProperties) { Objects.requireNonNull(linkProperties); queueOrSendMessage(EVENT_NETWORK_PROPERTIES_CHANGED, new LinkProperties(linkProperties)); } /** * Inform ConnectivityService that this agent has now connected. + * Call {@link #unregister} to disconnect. */ public void setConnected() { if (mIsLegacy) { @@ -569,8 +634,7 @@ public abstract class NetworkAgent { */ public void unregister() { if (mIsLegacy) { - throw new UnsupportedOperationException( - "Legacy agents can't call unregister."); + throw new UnsupportedOperationException("Legacy agents can't call unregister."); } mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, null); queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, mNetworkInfo); @@ -626,7 +690,7 @@ public abstract class NetworkAgent { * @hide TODO: expose something better. */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) - public void sendNetworkInfo(NetworkInfo networkInfo) { + public final void sendNetworkInfo(NetworkInfo networkInfo) { if (!mIsLegacy) { throw new UnsupportedOperationException("Only legacy agents can call sendNetworkInfo."); } @@ -637,7 +701,7 @@ public abstract class NetworkAgent { * Must be called by the agent when the network's {@link NetworkCapabilities} change. * @param networkCapabilities the new NetworkCapabilities. */ - public void sendNetworkCapabilities(@NonNull NetworkCapabilities networkCapabilities) { + public final void sendNetworkCapabilities(@NonNull NetworkCapabilities networkCapabilities) { Objects.requireNonNull(networkCapabilities); mBandwidthUpdatePending.set(false); mLastBwRefreshTime = System.currentTimeMillis(); @@ -647,9 +711,10 @@ public abstract class NetworkAgent { /** * Must be called by the agent to update the score of this network. - * @param score the new score. + * + * @param score the new score, between 0 and 99. */ - public void sendNetworkScore(int score) { + public final void sendNetworkScore(@IntRange(from = 0, to = 99) int score) { if (score < 0) { throw new IllegalArgumentException("Score must be >= 0"); } @@ -737,11 +802,11 @@ public abstract class NetworkAgent { * subsequent attempts to validate connectivity that fail. * * @param status one of {@code VALIDATION_STATUS_VALID} or {@code VALIDATION_STATUS_NOT_VALID}. - * @param redirectUrl If Internet connectivity is being redirected (e.g., on a captive portal), + * @param redirectUri If Internet connectivity is being redirected (e.g., on a captive portal), * this is the destination the probes are being redirected to, otherwise {@code null}. */ - public void onValidationStatus(int status, @Nullable String redirectUrl) { - networkStatus(status, redirectUrl); + public void onValidationStatus(@ValidationStatus int status, @Nullable Uri redirectUri) { + networkStatus(status, redirectUri.toString()); } /** @hide TODO delete once subclasses have moved to onValidationStatus */ protected void networkStatus(int status, String redirectUrl) { @@ -770,7 +835,12 @@ public abstract class NetworkAgent { * @param intervalSeconds the interval between packets * @param packet the packet to send. */ - public void onStartSocketKeepalive(int slot, int intervalSeconds, + // seconds is from SocketKeepalive.MIN_INTERVAL_SEC to MAX_INTERVAL_SEC, but these should + // not be exposed as constants because they may change in the future (API guideline 4.8) + // and should have getters if exposed at all. Getters can't be used in the annotation, + // so the values unfortunately need to be copied. + public void onStartSocketKeepalive(int slot, + @IntRange(from = 10, to = 3600) int intervalSeconds, @NonNull KeepalivePacketData packet) { Message msg = mHandler.obtainMessage(CMD_START_SOCKET_KEEPALIVE, slot, intervalSeconds, packet); @@ -801,9 +871,11 @@ public abstract class NetworkAgent { * Must be called by the agent when a socket keepalive event occurs. * * @param slot the hardware slot on which the event occurred. - * @param event the event that occurred. + * @param event the event that occurred, as one of the SocketKeepalive.ERROR_* + * or SocketKeepalive.SUCCESS constants. */ - public void sendSocketKeepaliveEvent(int slot, int event) { + public final void sendSocketKeepaliveEvent(int slot, + @SocketKeepalive.KeepaliveEvent int event) { queueOrSendMessage(EVENT_SOCKET_KEEPALIVE, slot, event); } /** @hide TODO delete once callers have moved to sendSocketKeepaliveEvent */ @@ -845,9 +917,18 @@ public abstract class NetworkAgent { } /** - * Called by ConnectivityService to inform this network transport of signal strength thresholds + * Called by ConnectivityService to inform this network agent of signal strength thresholds * that when crossed should trigger a system wakeup and a NetworkCapabilities update. * + * When the system updates the list of thresholds that should wake up the CPU for a + * given agent it will call this method on the agent. The agent that implement this + * should implement it in hardware so as to ensure the CPU will be woken up on breach. + * Agents are expected to react to a breach by sending an updated NetworkCapabilities + * object with the appropriate signal strength to sendNetworkCapabilities. + * + * The specific units are bearer-dependent. See details on the units and requests in + * {@link NetworkCapabilities.Builder#setSignalStrength}. + * * @param thresholds the array of thresholds that should trigger wakeups. */ public void onSignalStrengthThresholdsUpdated(@NonNull int[] thresholds) { diff --git a/core/java/android/net/NetworkAgentConfig.java b/core/java/android/net/NetworkAgentConfig.java index ca9328a713f0..fee868a93be4 100644 --- a/core/java/android/net/NetworkAgentConfig.java +++ b/core/java/android/net/NetworkAgentConfig.java @@ -155,6 +155,7 @@ public final class NetworkAgentConfig implements Parcelable { /** * @return the legacy type */ + @ConnectivityManager.LegacyNetworkType public int getLegacyType() { return legacyType; } @@ -206,7 +207,7 @@ public final class NetworkAgentConfig implements Parcelable { /** * Builder class to facilitate constructing {@link NetworkAgentConfig} objects. */ - public static class Builder { + public static final class Builder { private final NetworkAgentConfig mConfig = new NetworkAgentConfig(); /** diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java index 964f13f39ec6..798856d13b1d 100644 --- a/core/java/android/net/NetworkRequest.java +++ b/core/java/android/net/NetworkRequest.java @@ -473,9 +473,7 @@ public class NetworkRequest implements Parcelable { * * @param nc Capabilities that should satisfy this NetworkRequest. null capabilities do not * satisfy any request. - * @hide */ - @SystemApi public boolean satisfiedBy(@Nullable NetworkCapabilities nc) { return networkCapabilities.satisfiedByNetworkCapabilities(nc); } diff --git a/core/java/android/net/SocketKeepalive.java b/core/java/android/net/SocketKeepalive.java index fc9a8f63c131..8ff8f4c48c32 100644 --- a/core/java/android/net/SocketKeepalive.java +++ b/core/java/android/net/SocketKeepalive.java @@ -109,6 +109,16 @@ public abstract class SocketKeepalive implements AutoCloseable { }) public @interface ErrorCode {} + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = { + SUCCESS, + ERROR_INVALID_LENGTH, + ERROR_UNSUPPORTED, + ERROR_INSUFFICIENT_RESOURCES + }) + public @interface KeepaliveEvent {} + /** * The minimum interval in seconds between keepalive packet transmissions. * diff --git a/core/java/android/os/IVibratorService.aidl b/core/java/android/os/IVibratorService.aidl index 84013e7ebc88..615ae6593330 100644 --- a/core/java/android/os/IVibratorService.aidl +++ b/core/java/android/os/IVibratorService.aidl @@ -28,7 +28,7 @@ interface IVibratorService boolean registerVibratorStateListener(in IVibratorStateListener listener); boolean unregisterVibratorStateListener(in IVibratorStateListener listener); boolean hasAmplitudeControl(); - boolean[] areEffectsSupported(in int[] effectIds); + int[] areEffectsSupported(in int[] effectIds); boolean[] arePrimitivesSupported(in int[] primitiveIds); boolean setAlwaysOnEffect(int uid, String opPkg, int alwaysOnId, in VibrationEffect effect, in VibrationAttributes attributes); diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java index d60820ef0f57..8cdcd49cb2cc 100644 --- a/core/java/android/os/RecoverySystem.java +++ b/core/java/android/os/RecoverySystem.java @@ -665,15 +665,17 @@ public class RecoverySystem { * the preparation for unattended update is reset. * * @param context the Context to use. - * @throws IOException if there were any errors setting up unattended update + * @throws IOException if there were any errors clearing the unattended update state * @hide */ @SystemApi @RequiresPermission(android.Manifest.permission.RECOVERY) - public static boolean clearPrepareForUnattendedUpdate(@NonNull Context context) + public static void clearPrepareForUnattendedUpdate(@NonNull Context context) throws IOException { RecoverySystem rs = (RecoverySystem) context.getSystemService(Context.RECOVERY_SERVICE); - return rs.clearLskf(); + if (!rs.clearLskf()) { + throw new IOException("could not reset unattended update state"); + } } /** @@ -684,21 +686,22 @@ public class RecoverySystem { * @param context the Context to use. * @param updateToken the token used to call {@link #prepareForUnattendedUpdate} before * @param reason the reboot reason to give to the {@link PowerManager} - * @throws IOException if there were any errors setting up unattended update - * @return false if the reboot couldn't proceed because the device wasn't ready for an + * @throws IOException if the reboot couldn't proceed because the device wasn't ready for an * unattended reboot or if the {@code updateToken} did not match the previously * given token * @hide */ @SystemApi @RequiresPermission(android.Manifest.permission.RECOVERY) - public static boolean rebootAndApply(@NonNull Context context, @NonNull String updateToken, + public static void rebootAndApply(@NonNull Context context, @NonNull String updateToken, @NonNull String reason) throws IOException { if (updateToken == null) { throw new NullPointerException("updateToken == null"); } RecoverySystem rs = (RecoverySystem) context.getSystemService(Context.RECOVERY_SERVICE); - return rs.rebootWithLskf(updateToken, reason); + if (!rs.rebootWithLskf(updateToken, reason)) { + throw new IOException("system not prepared to apply update"); + } } /** diff --git a/core/java/android/os/SystemVibrator.java b/core/java/android/os/SystemVibrator.java index da20c7f2ae70..2dba8dce62da 100644 --- a/core/java/android/os/SystemVibrator.java +++ b/core/java/android/os/SystemVibrator.java @@ -21,12 +21,13 @@ import android.annotation.NonNull; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.media.AudioAttributes; -import android.os.IVibratorStateListener; import android.util.ArrayMap; import android.util.Log; + import com.android.internal.annotations.GuardedBy; -import java.util.concurrent.Executor; + import java.util.Objects; +import java.util.concurrent.Executor; /** * Vibrator implementation that controls the main system vibrator. @@ -238,13 +239,13 @@ public class SystemVibrator extends Vibrator { } @Override - public boolean[] areEffectsSupported(@VibrationEffect.EffectType int... effectIds) { + public int[] areEffectsSupported(@VibrationEffect.EffectType int... effectIds) { try { return mService.areEffectsSupported(effectIds); } catch (RemoteException e) { Log.w(TAG, "Failed to query effect support"); + throw e.rethrowAsRuntimeException(); } - return new boolean[effectIds.length]; } @Override @@ -254,8 +255,8 @@ public class SystemVibrator extends Vibrator { return mService.arePrimitivesSupported(primitiveIds); } catch (RemoteException e) { Log.w(TAG, "Failed to query effect support"); + throw e.rethrowAsRuntimeException(); } - return new boolean[primitiveIds.length]; } diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java index aa89b515adc6..ca861577ab37 100644 --- a/core/java/android/os/VibrationEffect.java +++ b/core/java/android/os/VibrationEffect.java @@ -961,7 +961,7 @@ public abstract class VibrationEffect implements Parcelable { * * @see VibrationEffect#startComposition() */ - public static class Composition { + public static final class Composition { /** @hide */ @IntDef(prefix = { "PRIMITIVE_" }, value = { PRIMITIVE_CLICK, @@ -1020,6 +1020,8 @@ public abstract class VibrationEffect implements Parcelable { private ArrayList<PrimitiveEffect> mEffects = new ArrayList<>(); + Composition() { } + /** * Add a haptic primitive to the end of the current composition. * @@ -1030,7 +1032,7 @@ public abstract class VibrationEffect implements Parcelable { * * @return The {@link Composition} object to enable adding multiple primitives in one chain. */ - @Nullable + @NonNull public Composition addPrimitive(@Primitive int primitiveId) { addPrimitive(primitiveId, /*scale*/ 1.0f, /*delay*/ 0); return this; @@ -1046,7 +1048,7 @@ public abstract class VibrationEffect implements Parcelable { * * @return The {@link Composition} object to enable adding multiple primitives in one chain. */ - @Nullable + @NonNull public Composition addPrimitive(@Primitive int primitiveId, @FloatRange(from = 0f, to = 1f) float scale) { addPrimitive(primitiveId, scale, /*delay*/ 0); @@ -1058,11 +1060,11 @@ public abstract class VibrationEffect implements Parcelable { * * @param primitiveId The primitive to add * @param scale The scale to apply to the intensity of the primitive. - * @param delay The amount of time, in milliseconds, to wait before playing the prior + * @param delay The amount of time, in milliseconds, to wait between playing the prior * primitive and this one * @return The {@link Composition} object to enable adding multiple primitives in one chain. */ - @Nullable + @NonNull public Composition addPrimitive(@Primitive int primitiveId, @FloatRange(from = 0f, to = 1f) float scale, @IntRange(from = 0) int delay) { mEffects.add(new PrimitiveEffect(checkPrimitive(primitiveId), scale, delay)); diff --git a/core/java/android/os/Vibrator.java b/core/java/android/os/Vibrator.java index d4da7a84d2a1..86d009e8607e 100644 --- a/core/java/android/os/Vibrator.java +++ b/core/java/android/os/Vibrator.java @@ -32,6 +32,7 @@ import android.util.Log; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.Arrays; import java.util.concurrent.Executor; /** @@ -72,6 +73,37 @@ public abstract class Vibrator { */ public static final int VIBRATION_INTENSITY_HIGH = 3; + /** + * Vibration effect support: unknown + * + * The hardware doesn't report it's supported effects, so we can't determine whether the + * effect is supported or not. + */ + public static final int VIBRATION_EFFECT_SUPPORT_UNKNOWN = 0; + + /** + * Vibration effect support: supported + * + * This effect is supported by the underlying hardware. + */ + public static final int VIBRATION_EFFECT_SUPPORT_YES = 1; + + /** + * Vibration effect support: unsupported + * + * This effect is <b>not</b> supported by the underlying hardware. + */ + public static final int VIBRATION_EFFECT_SUPPORT_NO = 2; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = {"VIBRATION_EFFECT_SUPPORT_"}, value = { + VIBRATION_EFFECT_SUPPORT_UNKNOWN, + VIBRATION_EFFECT_SUPPORT_YES, + VIBRATION_EFFECT_SUPPORT_NO, + }) + public @interface VibrationEffectSupport {} + /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(prefix = {"VIBRATION_INTENSITY_"}, value = { @@ -318,47 +350,61 @@ public abstract class Vibrator { /** * Query whether the vibrator supports the given effects. * - * If the returned array is {@code null}, the hardware doesn't support querying its supported - * effects. It may support any or all effects, but there's no way to programmatically know - * whether a {@link #vibrate} call will be successful. + * Not all hardware reports its effect capabilities, so the system may not necessarily know + * whether an effect is supported or not. * - * If the returned array is non-null, then it will be the same length as the query array and - * the value at a given index will contain whether the effect at that same index in the - * querying array is supported or not. + * The returned array will be the same length as the query array and the value at a given index + * will contain {@link #VIBRATION_EFFECT_SUPPORT_YES} if the effect at that same index in the + * querying array is supported, {@link #VIBRATION_EFFECT_SUPPORT_NO} if it isn't supported, or + * {@link #VIBRATION_EFFECT_SUPPORT_UNKNOWN} if the system can't determine whether it's + * supported or not. * * @param effectIds Which effects to query for. - * @return Whether the effects are supported. Null when the hardware doesn't tell us what it - * supports. + * @return An array containing the systems current knowledge about whether the given effects + * are supported or not. */ - @Nullable - public boolean[] areEffectsSupported( + @NonNull + @VibrationEffectSupport + public int[] areEffectsSupported( @NonNull @VibrationEffect.EffectType int... effectIds) { - return new boolean[effectIds.length]; + final int[] support = new int[effectIds.length]; + Arrays.fill(support, VIBRATION_EFFECT_SUPPORT_NO); + return support; } /** * Query whether the vibrator supports all of the given effects. * - * If the result is {@code null}, the hardware doesn't support querying its supported - * effects. It may support any or all effects, but there's no way to programmatically know - * whether a {@link #vibrate} call will be successful. + * Not all hardware reports its effect capabilities, so the system may not necessarily know + * whether an effect is supported or not. * - * If the returned array is non-null, then it will return whether all of the effects are + * If the result is {@link #VIBRATION_EFFECT_SUPPORT_YES}, all effects in the query are * supported by the hardware. * + * If the result is {@link #VIBRATION_EFFECT_SUPPORT_NO}, at least one of the effects in the + * query is not supported. + * + * If the result is {@link #VIBRATION_EFFECT_SUPPORT_UNKNOWN}, the system doesn't know whether + * all of the effects are supported. It may support any or all of the queried effects, + * but there's no way to programmatically know whether a {@link #vibrate} call will successfully + * cause a vibration. It's guaranteed, however, that none of the queried effects are + * definitively unsupported by the hardware. + * * @param effectIds Which effects to query for. - * @return Whether the effects are supported. {@code null} when the hardware doesn't tell us - * what it supports. + * @return Whether all of the effects are supported. */ - @Nullable - public Boolean areAllEffectsSupported( + @VibrationEffectSupport + public final int areAllEffectsSupported( @NonNull @VibrationEffect.EffectType int... effectIds) { - for (boolean supported : areEffectsSupported(effectIds)) { - if (!supported) { - return false; + int support = VIBRATION_EFFECT_SUPPORT_YES; + for (int supported : areEffectsSupported(effectIds)) { + if (supported == VIBRATION_EFFECT_SUPPORT_NO) { + return VIBRATION_EFFECT_SUPPORT_NO; + } else if (supported == VIBRATION_EFFECT_SUPPORT_UNKNOWN) { + support = VIBRATION_EFFECT_SUPPORT_UNKNOWN; } } - return true; + return support; } @@ -384,7 +430,7 @@ public abstract class Vibrator { * @param primitiveIds Which primitives to query for. * @return Whether primitives effects are supported. */ - public boolean areAllPrimitivesSupported( + public final boolean areAllPrimitivesSupported( @NonNull @VibrationEffect.Composition.Primitive int... primitiveIds) { for (boolean supported : arePrimitivesSupported(primitiveIds)) { if (!supported) { diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index bbcb9d9249af..530585d86465 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -6589,11 +6589,9 @@ public final class Settings { "accessibility_shortcut_target_service"; /** - * Setting specifying the accessibility services, accessibility shortcut targets, - * or features to be toggled via the accessibility button in the navigation bar. - * - * <p> This is a colon-separated string list which contains the flattened - * {@link ComponentName} and the class name of a system class implementing a supported + * Setting specifying the accessibility service or feature to be toggled via the + * accessibility button in the navigation bar. This is either a flattened + * {@link ComponentName} or the class name of a system class implementing a supported * accessibility feature. * @hide */ @@ -6602,15 +6600,14 @@ public final class Settings { /** * Setting specifying the accessibility services, accessibility shortcut targets, - * or features to be toggled via the long press accessibility button in the navigation bar. + * or features to be toggled via the accessibility button in the navigation bar. * * <p> This is a colon-separated string list which contains the flattened * {@link ComponentName} and the class name of a system class implementing a supported * accessibility feature. * @hide */ - public static final String ACCESSIBILITY_BUTTON_LONG_PRESS_TARGETS = - "accessibility_button_long_press_targets"; + public static final String ACCESSIBILITY_BUTTON_TARGETS = "accessibility_button_targets"; /** * The system class name of magnification controller which is a target to be toggled via @@ -6775,8 +6772,8 @@ public final class Settings { * zoom in the display content and is targeted to low vision users. The current * magnification scale is controlled by {@link #ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE}. * - * @deprecated Use {@link #ACCESSIBILITY_BUTTON_TARGET_COMPONENT} instead. - * {@link #ACCESSIBILITY_BUTTON_TARGET_COMPONENT} holds the magnification system class name + * @deprecated Use {@link #ACCESSIBILITY_BUTTON_TARGETS} instead. + * {@link #ACCESSIBILITY_BUTTON_TARGETS} holds the magnification system class name * when navigation bar magnification is enabled. * @hide */ @@ -8574,6 +8571,16 @@ public final class Settings { public static final String QS_TILES = "sysui_qs_tiles"; /** + * Whether this user has enabled Quick controls. + * + * 0 indicates disabled and 1 indicates enabled. A non existent value should be treated as + * enabled. + * + * @hide + */ + public static final String CONTROLS_ENABLED = "controls_enabled"; + + /** * Specifies whether the web action API is enabled. * * @hide diff --git a/core/java/android/service/contentcapture/ContentCaptureService.java b/core/java/android/service/contentcapture/ContentCaptureService.java index cecfe24613a4..61744e423b5b 100644 --- a/core/java/android/service/contentcapture/ContentCaptureService.java +++ b/core/java/android/service/contentcapture/ContentCaptureService.java @@ -18,7 +18,7 @@ package android.service.contentcapture; import static android.view.contentcapture.ContentCaptureHelper.sDebug; import static android.view.contentcapture.ContentCaptureHelper.sVerbose; import static android.view.contentcapture.ContentCaptureHelper.toList; -import static android.view.contentcapture.ContentCaptureSession.NO_SESSION_ID; +import static android.view.contentcapture.ContentCaptureManager.NO_SESSION_ID; import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage; diff --git a/core/java/android/service/controls/ControlsProviderService.java b/core/java/android/service/controls/ControlsProviderService.java index 9accf5b0abf5..4262c4022131 100644 --- a/core/java/android/service/controls/ControlsProviderService.java +++ b/core/java/android/service/controls/ControlsProviderService.java @@ -304,12 +304,11 @@ public abstract class ControlsProviderService extends Service { Preconditions.checkNotNull(context); Preconditions.checkNotNull(componentName); Preconditions.checkNotNull(control); - final ComponentName sysuiComponent = ComponentName.unflattenFromString( - context.getResources().getString( - com.android.internal.R.string.config_systemUIServiceComponent)); + final String controlsPackage = context.getString( + com.android.internal.R.string.config_controlsPackage); Intent intent = new Intent(ACTION_ADD_CONTROL); intent.putExtra(Intent.EXTRA_COMPONENT_NAME, componentName); - intent.setPackage(sysuiComponent.getPackageName()); + intent.setPackage(controlsPackage); if (isStatelessControl(control)) { intent.putExtra(EXTRA_CONTROL, control); } else { diff --git a/core/java/android/service/dataloader/DataLoaderService.java b/core/java/android/service/dataloader/DataLoaderService.java index 0170726b31d6..c047dc0d07c7 100644 --- a/core/java/android/service/dataloader/DataLoaderService.java +++ b/core/java/android/service/dataloader/DataLoaderService.java @@ -29,7 +29,6 @@ import android.content.pm.IDataLoader; import android.content.pm.IDataLoaderStatusListener; import android.content.pm.InstallationFile; import android.content.pm.InstallationFileParcel; -import android.content.pm.NamedParcelFileDescriptor; import android.os.IBinder; import android.os.ParcelFileDescriptor; import android.util.ExceptionUtils; @@ -133,16 +132,6 @@ public abstract class DataLoaderService extends Service { } } } - if (params.dynamicArgs != null) { - NamedParcelFileDescriptor[] fds = params.dynamicArgs; - for (NamedParcelFileDescriptor nfd : fds) { - try { - nfd.fd.close(); - } catch (IOException e) { - Slog.e(TAG, "Failed to close DynamicArgs parcel file descriptor " + e); - } - } - } } } diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java index e70311fb9429..c9be1c1fabb2 100644 --- a/core/java/android/service/dreams/DreamService.java +++ b/core/java/android/service/dreams/DreamService.java @@ -15,8 +15,6 @@ */ package android.service.dreams; -import static android.view.WindowManager.LayoutParams.TYPE_DREAM; - import android.annotation.IdRes; import android.annotation.LayoutRes; import android.annotation.NonNull; @@ -1071,7 +1069,6 @@ public class DreamService extends Service implements Window.Callback { private void onWindowCreated(Window w) { mWindow = w; mWindow.setCallback(this); - mWindow.setType(TYPE_DREAM); mWindow.requestFeature(Window.FEATURE_NO_TITLE); WindowManager.LayoutParams lp = mWindow.getAttributes(); diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java index e6bd84391fef..40a460dfece0 100644 --- a/core/java/android/view/InsetsController.java +++ b/core/java/android/view/InsetsController.java @@ -16,6 +16,7 @@ package android.view; +import static android.view.InsetsState.ITYPE_CAPTION_BAR; import static android.view.InsetsState.ITYPE_IME; import static android.view.InsetsState.toInternalType; import static android.view.InsetsState.toPublicType; @@ -367,6 +368,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation private int mLastLegacySystemUiFlags; private DisplayCutout mLastDisplayCutout; private boolean mStartingAnimation; + private int mCaptionInsetsHeight = 0; private SyncRtSurfaceTransactionApplier mApplier; @@ -460,7 +462,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation @VisibleForTesting public boolean onStateChanged(InsetsState state) { - boolean localStateChanged = !mState.equals(state); + boolean localStateChanged = !mState.equals(state, true /* excludingCaptionInsets */) + || !captionInsetsUnchanged(); if (!localStateChanged && mLastDispachedState.equals(state)) { return false; } @@ -470,7 +473,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation if (localStateChanged) { mViewRoot.notifyInsetsChanged(); } - if (!mState.equals(mLastDispachedState)) { + if (!mState.equals(mLastDispachedState, true /* excludingCaptionInsets */)) { sendStateToWindowManager(); } return true; @@ -488,6 +491,23 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation mState.removeSource(source.getType()); } } + if (mCaptionInsetsHeight != 0) { + mState.getSource(ITYPE_CAPTION_BAR).setFrame(new Rect(mFrame.left, mFrame.top, + mFrame.right, mFrame.top + mCaptionInsetsHeight)); + } + } + + private boolean captionInsetsUnchanged() { + if (mState.peekSource(ITYPE_CAPTION_BAR) == null + && mCaptionInsetsHeight == 0) { + return true; + } + if (mState.peekSource(ITYPE_CAPTION_BAR) != null + && mCaptionInsetsHeight + == mState.peekSource(ITYPE_CAPTION_BAR).getFrame().height()) { + return true; + } + return false; } /** @@ -964,6 +984,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation InsetsState tmpState = new InsetsState(); for (int i = mSourceConsumers.size() - 1; i >= 0; i--) { final InsetsSourceConsumer consumer = mSourceConsumers.valueAt(i); + if (consumer.getType() == ITYPE_CAPTION_BAR) continue; if (consumer.getControl() != null) { tmpState.addSource(mState.getSource(consumer.getType())); } @@ -1105,6 +1126,11 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation } @Override + public void setCaptionInsetsHeight(int height) { + mCaptionInsetsHeight = height; + } + + @Override public void setSystemBarsBehavior(@Behavior int behavior) { mViewRoot.mWindowAttributes.privateFlags |= PRIVATE_FLAG_BEHAVIOR_CONTROLLED; if (mViewRoot.mWindowAttributes.insetsFlags.behavior != behavior) { diff --git a/core/java/android/view/InsetsSource.java b/core/java/android/view/InsetsSource.java index 294faaf0b5c8..033ccef3666d 100644 --- a/core/java/android/view/InsetsSource.java +++ b/core/java/android/view/InsetsSource.java @@ -16,6 +16,7 @@ package android.view; +import static android.view.InsetsState.ITYPE_CAPTION_BAR; import static android.view.InsetsState.ITYPE_IME; import android.annotation.NonNull; @@ -118,6 +119,12 @@ public class InsetsSource implements Parcelable { if (!getIntersection(frame, relativeFrame, mTmpFrame)) { return Insets.NONE; } + // During drag-move and drag-resizing, the caption insets position may not get updated + // before the app frame get updated. To layout the app content correctly during drag events, + // we always return the insets with the corresponding height covering the top. + if (getType() == ITYPE_CAPTION_BAR) { + return Insets.of(0, frame.height(), 0, 0); + } // TODO: Currently, non-floating IME always intersects at bottom due to issues with cutout. // However, we should let the policy decide from the server. diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java index 40e6f57f2286..c5154662928e 100644 --- a/core/java/android/view/InsetsState.java +++ b/core/java/android/view/InsetsState.java @@ -45,6 +45,8 @@ import android.view.WindowInsets.Type; import android.view.WindowInsets.Type.InsetsType; import android.view.WindowManager.LayoutParams.SoftInputModeFlags; +import com.android.internal.annotations.VisibleForTesting; + import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -498,6 +500,19 @@ public class InsetsState implements Parcelable { @Override public boolean equals(Object o) { + return equals(o, false); + } + + /** + * An equals method can exclude the caption insets. This is useful because we assemble the + * caption insets information on the client side, and when we communicate with server, it's + * excluded. + * @param excludingCaptionInsets {@code true} if we want to compare two InsetsState objects but + * ignore the caption insets source value. + * @return {@code true} if the two InsetsState objects are equal, {@code false} otherwise. + */ + @VisibleForTesting + public boolean equals(Object o, boolean excludingCaptionInsets) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } @@ -506,11 +521,24 @@ public class InsetsState implements Parcelable { if (!mDisplayFrame.equals(state.mDisplayFrame)) { return false; } - if (mSources.size() != state.mSources.size()) { + int size = mSources.size(); + int otherSize = state.mSources.size(); + if (excludingCaptionInsets) { + if (mSources.get(ITYPE_CAPTION_BAR) != null) { + size--; + } + if (state.mSources.get(ITYPE_CAPTION_BAR) != null) { + otherSize--; + } + } + if (size != otherSize) { return false; } for (int i = mSources.size() - 1; i >= 0; i--) { InsetsSource source = mSources.valueAt(i); + if (excludingCaptionInsets) { + if (source.getType() == ITYPE_CAPTION_BAR) continue; + } InsetsSource otherSource = state.mSources.get(source.getType()); if (otherSource == null) { return false; diff --git a/core/java/android/view/PendingInsetsController.java b/core/java/android/view/PendingInsetsController.java index 229ee03521bc..a106b2c4726d 100644 --- a/core/java/android/view/PendingInsetsController.java +++ b/core/java/android/view/PendingInsetsController.java @@ -42,6 +42,7 @@ public class PendingInsetsController implements WindowInsetsController { private InsetsController mReplayedInsetsController; private ArrayList<OnControllableInsetsChangedListener> mControllableInsetsChangedListeners = new ArrayList<>(); + private int mCaptionInsetsHeight = 0; @Override public void show(int types) { @@ -80,6 +81,11 @@ public class PendingInsetsController implements WindowInsetsController { } @Override + public void setCaptionInsetsHeight(int height) { + mCaptionInsetsHeight = height; + } + + @Override public void setSystemBarsBehavior(int behavior) { if (mReplayedInsetsController != null) { mReplayedInsetsController.setSystemBarsBehavior(behavior); @@ -134,6 +140,9 @@ public class PendingInsetsController implements WindowInsetsController { if (mAppearanceMask != 0) { controller.setSystemBarsAppearance(mAppearance, mAppearanceMask); } + if (mCaptionInsetsHeight != 0) { + controller.setCaptionInsetsHeight(mCaptionInsetsHeight); + } int size = mRequests.size(); for (int i = 0; i < size; i++) { mRequests.get(i).replay(controller); diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 4922917c911c..da186087a34a 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -28768,6 +28768,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, publicAlternatives = "Use {@link WindowInsets#getInsets(int)}") final Rect mStableInsets = new Rect(); + /** + * Current caption insets to the display coordinate. + */ + final Rect mCaptionInsets = new Rect(); + final DisplayCutout.ParcelableWrapper mDisplayCutout = new DisplayCutout.ParcelableWrapper(DisplayCutout.NO_CUTOUT); diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 50202aed36d2..51304dcfe8cb 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -158,6 +158,7 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.os.IResultReceiver; import com.android.internal.os.SomeArgs; +import com.android.internal.policy.DecorView; import com.android.internal.policy.PhoneFallbackEventHandler; import com.android.internal.util.Preconditions; import com.android.internal.view.BaseSurfaceHolder; @@ -2221,6 +2222,19 @@ public final class ViewRootImpl implements ViewParent, Trace.traceEnd(Trace.TRACE_TAG_VIEW); } + private boolean updateCaptionInsets() { + if (!(mView instanceof DecorView)) return false; + final int captionInsetsHeight = ((DecorView) mView).getCaptionInsetsHeight(); + final Rect captionFrame = new Rect(); + if (captionInsetsHeight != 0) { + captionFrame.set(mWinFrame.left, mWinFrame.top, mWinFrame.right, + mWinFrame.top + captionInsetsHeight); + } + if (mAttachInfo.mCaptionInsets.equals(captionFrame)) return false; + mAttachInfo.mCaptionInsets.set(captionFrame); + return true; + } + private boolean shouldDispatchCutout() { return mWindowAttributes.layoutInDisplayCutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS @@ -2592,6 +2606,9 @@ public final class ViewRootImpl implements ViewParent, mAttachInfo.mAlwaysConsumeSystemBars = mPendingAlwaysConsumeSystemBars; dispatchApplyInsets = true; } + if (updateCaptionInsets()) { + dispatchApplyInsets = true; + } if (dispatchApplyInsets || mLastSystemUiVisibility != mAttachInfo.mSystemUiVisibility || mApplyInsetsRequested) { mLastSystemUiVisibility = mAttachInfo.mSystemUiVisibility; diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java index 0c5c18316e61..ae9afabad533 100644 --- a/core/java/android/view/Window.java +++ b/core/java/android/view/Window.java @@ -49,9 +49,6 @@ import android.transition.Transition; import android.transition.TransitionManager; import android.util.Pair; import android.view.View.OnApplyWindowInsetsListener; -import android.view.ViewGroup.LayoutParams; -import android.view.WindowInsets.Side.InsetsSide; -import android.view.WindowInsets.Type.InsetsType; import android.view.accessibility.AccessibilityEvent; import java.util.Collections; @@ -323,7 +320,7 @@ public abstract class Window { @UnsupportedAppUsage private boolean mDestroyed; - private boolean mOverlayWithDecorCaptionEnabled = false; + private boolean mOverlayWithDecorCaptionEnabled = true; private boolean mCloseOnSwipeEnabled = false; // The current window attributes. diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java index fde184ccfb0e..9b2a6cbce48f 100644 --- a/core/java/android/view/WindowInsets.java +++ b/core/java/android/view/WindowInsets.java @@ -17,6 +17,7 @@ package android.view; +import static android.view.WindowInsets.Type.CAPTION_BAR; import static android.view.WindowInsets.Type.DISPLAY_CUTOUT; import static android.view.WindowInsets.Type.FIRST; import static android.view.WindowInsets.Type.IME; diff --git a/core/java/android/view/WindowInsetsController.java b/core/java/android/view/WindowInsetsController.java index 0282ecac8920..439223cf568b 100644 --- a/core/java/android/view/WindowInsetsController.java +++ b/core/java/android/view/WindowInsetsController.java @@ -196,6 +196,15 @@ public interface WindowInsetsController { @Appearance int getSystemBarsAppearance(); /** + * Notify the caption insets height change. The information will be used on the client side to, + * make sure the InsetsState has the correct caption insets. + * + * @param height the height of caption bar insets. + * @hide + */ + void setCaptionInsetsHeight(int height); + + /** * Controls the behavior of system bars. * * @param behavior Determines how the bars behave when being hidden by the application. diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index 77ce5c1b1ddc..cc380f32297e 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -781,8 +781,6 @@ public interface WindowManager extends ViewManager { to = "BOOT_PROGRESS"), @ViewDebug.IntToString(from = TYPE_INPUT_CONSUMER, to = "INPUT_CONSUMER"), - @ViewDebug.IntToString(from = TYPE_DREAM, - to = "DREAM"), @ViewDebug.IntToString(from = TYPE_NAVIGATION_BAR_PANEL, to = "NAVIGATION_BAR_PANEL"), @ViewDebug.IntToString(from = TYPE_DISPLAY_OVERLAY, @@ -1105,13 +1103,6 @@ public interface WindowManager extends ViewManager { public static final int TYPE_INPUT_CONSUMER = FIRST_SYSTEM_WINDOW+22; /** - * Window type: Dreams (screen saver) window, just above keyguard. - * In multiuser systems shows only on the owning user's window. - * @hide - */ - public static final int TYPE_DREAM = FIRST_SYSTEM_WINDOW+23; - - /** * Window type: Navigation bar panel (when navigation bar is distinct from status bar) * In multiuser systems shows on all users' windows. * @hide @@ -1180,8 +1171,9 @@ public interface WindowManager extends ViewManager { public static final int TYPE_QS_DIALOG = FIRST_SYSTEM_WINDOW+35; /** - * Window type: shares similar characteristics with {@link #TYPE_DREAM}. The layer is + * Window type: shows directly above the keyguard. The layer is * reserved for screenshot region selection. These windows must not take input focus. + * In multiuser systems shows only on the owning user's window. * @hide */ public static final int TYPE_SCREENSHOT = FIRST_SYSTEM_WINDOW + 36; diff --git a/core/java/android/view/contentcapture/ContentCaptureContext.java b/core/java/android/view/contentcapture/ContentCaptureContext.java index 1692051924f4..b84cb88ccd84 100644 --- a/core/java/android/view/contentcapture/ContentCaptureContext.java +++ b/core/java/android/view/contentcapture/ContentCaptureContext.java @@ -15,7 +15,7 @@ */ package android.view.contentcapture; -import static android.view.contentcapture.ContentCaptureSession.NO_SESSION_ID; +import static android.view.contentcapture.ContentCaptureManager.NO_SESSION_ID; import android.annotation.IntDef; import android.annotation.NonNull; diff --git a/core/java/android/view/contentcapture/ContentCaptureEvent.java b/core/java/android/view/contentcapture/ContentCaptureEvent.java index ea34d948c91a..f49b1beee8ad 100644 --- a/core/java/android/view/contentcapture/ContentCaptureEvent.java +++ b/core/java/android/view/contentcapture/ContentCaptureEvent.java @@ -16,7 +16,7 @@ package android.view.contentcapture; import static android.view.contentcapture.ContentCaptureHelper.getSanitizedString; -import static android.view.contentcapture.ContentCaptureSession.NO_SESSION_ID; +import static android.view.contentcapture.ContentCaptureManager.NO_SESSION_ID; import android.annotation.IntDef; import android.annotation.NonNull; diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java index b9889276ae0b..954b83b6f9ee 100644 --- a/core/java/android/view/contentcapture/ContentCaptureManager.java +++ b/core/java/android/view/contentcapture/ContentCaptureManager.java @@ -235,6 +235,13 @@ public final class ContentCaptureManager { public static final int RESULT_CODE_SECURITY_EXCEPTION = -1; /** + * ID used to indicate that a session does not exist + * @hide + */ + @SystemApi + public static final int NO_SESSION_ID = 0; + + /** * Timeout for calls to system_server. */ private static final int SYNC_CALLS_TIMEOUT_MS = 5000; diff --git a/core/java/android/view/contentcapture/ContentCaptureSession.java b/core/java/android/view/contentcapture/ContentCaptureSession.java index 012f5e6d3507..39c7210d8dac 100644 --- a/core/java/android/view/contentcapture/ContentCaptureSession.java +++ b/core/java/android/view/contentcapture/ContentCaptureSession.java @@ -17,12 +17,12 @@ package android.view.contentcapture; import static android.view.contentcapture.ContentCaptureHelper.sDebug; import static android.view.contentcapture.ContentCaptureHelper.sVerbose; +import static android.view.contentcapture.ContentCaptureManager.NO_SESSION_ID; import android.annotation.CallSuper; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; -import android.annotation.SystemApi; import android.graphics.Insets; import android.util.DebugUtils; import android.util.Log; @@ -53,13 +53,6 @@ public abstract class ContentCaptureSession implements AutoCloseable { private static final Random sIdGenerator = new Random(); /** - * ID used to indicate that a session does not exist - * @hide - */ - @SystemApi - public static final int NO_SESSION_ID = 0; - - /** * Initial state, when there is no session. * * @hide diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java index 51b73fc674e7..d2508f3616e4 100644 --- a/core/java/com/android/internal/policy/DecorView.java +++ b/core/java/com/android/internal/policy/DecorView.java @@ -78,7 +78,6 @@ import android.view.ContextThemeWrapper; import android.view.Gravity; import android.view.InputQueue; import android.view.InsetsState; -import android.view.InsetsController; import android.view.InsetsState.InternalInsetsType; import android.view.KeyEvent; import android.view.KeyboardShortcutGroup; @@ -1174,6 +1173,12 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind false /* matchVertical */, statusBarNeedsLeftInset, statusBarSideInset, animate && !disallowAnimate, mForceWindowDrawsBarBackgrounds, state); + + if (mHasCaption) { + final int captionColor = calculateStatusBarColor(); + mDecorCaptionView.getCaption().setBackgroundColor(captionColor); + updateDecorCaptionShade(); + } } // When we expand the window with FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS or @@ -1355,7 +1360,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind : state.attributes.isPresent(insetsState, mWindow.getAttributes().flags, force); boolean show = state.attributes.isVisible(state.present, color, mWindow.getAttributes().flags, force); - boolean showView = show && !isResizing() && size > 0; + boolean showView = show && !isResizing() && !mHasCaption && size > 0; boolean visibilityChanged = false; View view = state.view; @@ -2021,6 +2026,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind if (getForeground() != null) { drawableChanged(); } + getWindowInsetsController().setCaptionInsetsHeight(getCaptionInsetsHeight()); } } @@ -2094,6 +2100,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind mDecorCaptionView.onConfigurationChanged(displayWindowDecor); enableCaption(displayWindowDecor); } + getWindowInsetsController().setCaptionInsetsHeight(getCaptionInsetsHeight()); } void onResourcesLoaded(LayoutInflater inflater, int layoutResource) { @@ -2182,11 +2189,11 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind inflater = inflater.from(context); final DecorCaptionView view = (DecorCaptionView) inflater.inflate(R.layout.decor_caption, null); - setDecorCaptionShade(context, view); + setDecorCaptionShade(view); return view; } - private void setDecorCaptionShade(Context context, DecorCaptionView view) { + private void setDecorCaptionShade(DecorCaptionView view) { final int shade = mWindow.getDecorCaptionShade(); switch (shade) { case DECOR_CAPTION_SHADE_LIGHT: @@ -2196,15 +2203,10 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind setDarkDecorCaptionShade(view); break; default: { - TypedValue value = new TypedValue(); - context.getTheme().resolveAttribute(R.attr.colorPrimary, value, true); - // We invert the shade depending on brightness of the theme. Dark shade for light - // theme and vice versa. Thanks to this the buttons should be visible on the - // background. - if (Color.luminance(value.data) < 0.5) { - setLightDecorCaptionShade(view); - } else { + if ((getWindowSystemUiVisibility() & SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) != 0) { setDarkDecorCaptionShade(view); + } else { + setLightDecorCaptionShade(view); } break; } @@ -2213,7 +2215,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind void updateDecorCaptionShade() { if (mDecorCaptionView != null) { - setDecorCaptionShade(getContext(), mDecorCaptionView); + setDecorCaptionShade(mDecorCaptionView); } } @@ -2484,6 +2486,15 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind } /** + * @hide + * @return the height of insets covering the top of window content area. + */ + public int getCaptionInsetsHeight() { + if (!mWindow.isOverlayWithDecorCaptionEnabled()) return 0; + return getCaptionHeight(); + } + + /** * Converts a DIP measure into physical pixels. * @param dip The dip value. * @return Returns the number of pixels. diff --git a/core/java/com/android/internal/widget/DecorCaptionView.java b/core/java/com/android/internal/widget/DecorCaptionView.java index b5d787c24fbd..7a01024ffc36 100644 --- a/core/java/com/android/internal/widget/DecorCaptionView.java +++ b/core/java/com/android/internal/widget/DecorCaptionView.java @@ -17,7 +17,6 @@ package com.android.internal.widget; import android.content.Context; -import android.graphics.Color; import android.graphics.Rect; import android.os.RemoteException; import android.util.AttributeSet; @@ -53,8 +52,7 @@ import java.util.ArrayList; * <li>..</li> * </ul> * - * Although this ViewGroup has only two direct sub-Views, its behavior is more complex due to - * overlaying caption on the content and drawing. + * Here describe the behavior of overlaying caption on the content and drawing. * * First, no matter where the content View gets added, it will always be the first child and the * caption will be the second. This way the caption will always be drawn on top of the content when @@ -66,11 +64,9 @@ import java.util.ArrayList; * <li>DecorCaptionView.onInterceptTouchEvent() will try intercepting the touch events if the * down action is performed on top close or maximize buttons; the reason for that is we want these * buttons to always work.</li> - * <li>The content View will receive the touch event. Mind that content is actually underneath the - * caption, so we need to introduce our own dispatch ordering. We achieve this by overriding - * {@link #buildTouchDispatchChildList()}.</li> - * <li>If the touch event is not consumed by the content View, it will go to the caption View - * and the dragging logic will be executed.</li> + * <li>The caption view will try to consume the event to apply the dragging logic.</li> + * <li>If the touch event is not consumed by the caption, the content View will receive the touch + * event</li> * </ul> */ public class DecorCaptionView extends ViewGroup implements View.OnTouchListener, @@ -137,11 +133,6 @@ public class DecorCaptionView extends ViewGroup implements View.OnTouchListener, mOwner = owner; mShow = show; mOverlayWithAppContent = owner.isOverlayWithDecorCaptionEnabled(); - if (mOverlayWithAppContent) { - // The caption is covering the content, so we make its background transparent to make - // the content visible. - mCaption.setBackgroundColor(Color.TRANSPARENT); - } updateCaptionVisibility(); // By changing the outline provider to BOUNDS, the window can remove its // background without removing the shadow. @@ -236,18 +227,6 @@ public class DecorCaptionView extends ViewGroup implements View.OnTouchListener, } @Override - public ArrayList<View> buildTouchDispatchChildList() { - mTouchDispatchList.ensureCapacity(3); - if (mCaption != null) { - mTouchDispatchList.add(mCaption); - } - if (mContent != null) { - mTouchDispatchList.add(mContent); - } - return mTouchDispatchList; - } - - @Override public boolean shouldDelayChildPressedState() { return false; } diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp index cb5a332c6e85..bf3fc5704739 100644 --- a/core/jni/android_util_AssetManager.cpp +++ b/core/jni/android_util_AssetManager.cpp @@ -214,12 +214,8 @@ static jint CopyValue(JNIEnv* env, ApkAssetsCookie cookie, const Res_value& valu // ---------------------------------------------------------------------------- -static std::unique_ptr<DynamicLibManager> sDynamicLibManager = - std::make_unique<DynamicLibManager>(); - // Let the opaque type AAssetManager refer to a guarded AssetManager2 instance. struct GuardedAssetManager : public ::AAssetManager { - GuardedAssetManager() : guarded_assetmanager(sDynamicLibManager.get()) {} Guarded<AssetManager2> guarded_assetmanager; }; diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto index a3313b21131d..075aa97edb58 100644 --- a/core/proto/android/providers/settings/secure.proto +++ b/core/proto/android/providers/settings/secure.proto @@ -77,7 +77,7 @@ message SecureSettingsProto { optional SettingProto interactive_ui_timeout_ms = 33 [ (android.privacy).dest = DEST_AUTOMATIC ]; // Settings for magnification mode optional SettingProto accessibility_magnification_mode = 34 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto button_long_press_targets = 35 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto button_targets = 35 [ (android.privacy).dest = DEST_AUTOMATIC ]; } optional Accessibility accessibility = 2; @@ -180,6 +180,14 @@ message SecureSettingsProto { optional SettingProto cmas_additional_broadcast_pkg = 14 [ (android.privacy).dest = DEST_AUTOMATIC ]; repeated SettingProto completed_categories = 15; optional SettingProto connectivity_release_pending_intent_delay_ms = 16 [ (android.privacy).dest = DEST_AUTOMATIC ]; + + message Controls { + option (android.msg_privacy).dest = DEST_EXPLICIT; + + optional SettingProto enabled = 1 [ (android.privacy).dest = DEST_AUTOMATIC ]; + } + optional Controls controls = 79; + optional SettingProto device_paired = 17 [ (android.privacy).dest = DEST_AUTOMATIC ]; optional SettingProto dialer_default_application = 18 [ (android.privacy).dest = DEST_AUTOMATIC ]; optional SettingProto display_density_forced = 19 [ (android.privacy).dest = DEST_AUTOMATIC ]; @@ -580,5 +588,5 @@ message SecureSettingsProto { // Please insert fields in alphabetical order and group them into messages // if possible (to avoid reaching the method limit). - // Next tag = 79; + // Next tag = 80; } diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index e3a73377e365..acda77f185fd 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -2779,6 +2779,10 @@ <string name="config_systemUIServiceComponent" translatable="false" >com.android.systemui/com.android.systemui.SystemUIService</string> + <!-- Package handling Quick controls --> + <string name="config_controlsPackage" translatable="false" + >com.android.systemui</string> + <!-- Keyguard component --> <string name="config_keyguardComponent" translatable="false" >com.android.systemui/com.android.systemui.keyguard.KeyguardService</string> @@ -4424,4 +4428,7 @@ <!-- Set to true to enable the user switcher on the keyguard. --> <bool name="config_keyguardUserSwitcher">false</bool> + <!-- Set to true to make assistant show in front of the dream/screensaver. --> + <bool name="config_assistantOnTopOfDream">false</bool> + </resources> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 5b880365657c..e2e65dd465ae 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -1138,17 +1138,17 @@ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permlab_accessFineLocation">access precise location only in the foreground</string> <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> - <string name="permdesc_accessFineLocation">This app can get your exact location only when it is in the foreground. Location services must be turned on and available on your device for the app to be able to use them. This may increase battery consumption.</string> + <string name="permdesc_accessFineLocation">This app can get your precise location from location services while the app is in use. Location services for your device must be turned on for the app to get location. This may increase battery usage.</string> <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permlab_accessCoarseLocation">access approximate location only in the foreground</string> <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> - <string name="permdesc_accessCoarseLocation">This app can get your approximate location only when it is in the foreground. Location services must be turned on and available on your device for the app to be able to use them.</string> + <string name="permdesc_accessCoarseLocation">This app can get your approximate location from location services while the app is in use. Location services for your device must be turned on for the app to get location.</string> <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permlab_accessBackgroundLocation">access location in the background</string> <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> - <string name="permdesc_accessBackgroundLocation">This app can access location while running in the background, in addition to foreground location access.</string> + <string name="permdesc_accessBackgroundLocation">This app can access location at any time, even while the app is not in use.</string> <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permlab_modifyAudioSettings">change your audio settings</string> @@ -3597,6 +3597,8 @@ <string name="ext_media_new_notification_title">New <xliff:g id="name" example="SD card">%s</xliff:g></string> <!-- Notification body when new external media is detected [CHAR LIMIT=NONE] --> <string name="ext_media_new_notification_message">Tap to set up</string> + <!-- Automotive specific notification body when new external media is detected. Empty because there is no fix action (b/151671685) [CHAR LIMIT=NONE] --> + <string name="ext_media_new_notification_message" product="automotive"></string> <!-- Notification body when external media is ready for use [CHAR LIMIT=NONE] --> <string name="ext_media_ready_notification_message">For transferring photos and media</string> @@ -3605,8 +3607,10 @@ <string name="ext_media_unmountable_notification_title">Issue with <xliff:g id="name" example="SD card">%s</xliff:g></string> <!-- Notification body when external media is unmountable (corrupt) [CHAR LIMIT=NONE] --> <string name="ext_media_unmountable_notification_message">Tap to fix</string> - <!-- TV-specifiv notification body when external media is unmountable (corrupt) [CHAR LIMIT=NONE] --> + <!-- TV-specific notification body when external media is unmountable (corrupt) [CHAR LIMIT=NONE] --> <string name="ext_media_unmountable_notification_message" product="tv"><xliff:g id="name" example="SD card">%s</xliff:g> is corrupt. Select to fix.</string> + <!-- Automotive specific notification body when external media is unmountable (corrupt). Empty because there is no fix action (b/151671685) [CHAR LIMIT=NONE] --> + <string name="ext_media_unmountable_notification_message" product="automotive"></string> <!-- Notification title when external media is unsupported [CHAR LIMIT=30] --> <string name="ext_media_unsupported_notification_title">Unsupported <xliff:g id="name" example="SD card">%s</xliff:g></string> @@ -3614,6 +3618,8 @@ <string name="ext_media_unsupported_notification_message">This device doesn\u2019t support this <xliff:g id="name" example="SD card">%s</xliff:g>. Tap to set up in a supported format.</string> <!-- TV-specific notification body when external media is unsupported [CHAR LIMIT=NONE] --> <string name="ext_media_unsupported_notification_message" product="tv">This device doesn\u2019t support this <xliff:g id="name" example="SD card">%s</xliff:g>. Select to set up in a supported format.</string> + <!-- Automotive specific notification body when external media is unsupported. No action is specified to fix (b/151671685) [CHAR LIMIT=NONE] --> + <string name="ext_media_unsupported_notification_message" product="automotive">This device doesn\u2019t support this <xliff:g id="name" example="SD card">%s</xliff:g>.</string> <!-- Notification title when external media is unsafely removed [CHAR LIMIT=30] --> <string name="ext_media_badremoval_notification_title"><xliff:g id="name" example="SD card">%s</xliff:g> unexpectedly removed</string> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 22caf4c2a37d..04c6a41833df 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -365,6 +365,7 @@ <java-symbol type="bool" name="config_hasRecents" /> <java-symbol type="string" name="config_recentsComponentName" /> <java-symbol type="string" name="config_systemUIServiceComponent" /> + <java-symbol type="string" name="config_controlsPackage" /> <java-symbol type="string" name="config_screenRecorderComponent" /> <java-symbol type="string" name="config_somnambulatorComponent" /> <java-symbol type="string" name="config_screenshotServiceComponent" /> @@ -3953,4 +3954,7 @@ <!-- Set to true to enable the user switcher on the keyguard. --> <java-symbol type="bool" name="config_keyguardUserSwitcher" /> + + <!-- Set to true to make assistant show in front of the dream/screensaver. --> + <java-symbol type="bool" name="config_assistantOnTopOfDream"/> </resources> diff --git a/core/tests/coretests/src/android/service/controls/ControlProviderServiceTest.java b/core/tests/coretests/src/android/service/controls/ControlProviderServiceTest.java index 13000e943141..f4ebe2f9a755 100644 --- a/core/tests/coretests/src/android/service/controls/ControlProviderServiceTest.java +++ b/core/tests/coretests/src/android/service/controls/ControlProviderServiceTest.java @@ -64,8 +64,7 @@ import java.util.function.Consumer; @RunWith(AndroidJUnit4.class) public class ControlProviderServiceTest { - private static final ComponentName TEST_SYSUI_COMPONENT = - ComponentName.unflattenFromString("sysui/.test.cls"); + private static final String TEST_CONTROLS_PACKAGE = "sysui"; private static final ComponentName TEST_COMPONENT = ComponentName.unflattenFromString("test.pkg/.test.cls"); @@ -97,8 +96,8 @@ public class ControlProviderServiceTest { when(mSubscriber.asBinder()).thenCallRealMethod(); when(mSubscriber.queryLocalInterface(any())).thenReturn(mSubscriber); - when(mResources.getString(com.android.internal.R.string.config_systemUIServiceComponent)) - .thenReturn(TEST_SYSUI_COMPONENT.flattenToString()); + when(mResources.getString(com.android.internal.R.string.config_controlsPackage)) + .thenReturn(TEST_CONTROLS_PACKAGE); when(mContext.getResources()).thenReturn(mResources); Bundle b = new Bundle(); @@ -252,7 +251,7 @@ public class ControlProviderServiceTest { eq(Manifest.permission.BIND_CONTROLS)); Intent intent = mIntentArgumentCaptor.getValue(); assertEquals(ControlsProviderService.ACTION_ADD_CONTROL, intent.getAction()); - assertEquals(TEST_SYSUI_COMPONENT.getPackageName(), intent.getPackage()); + assertEquals(TEST_CONTROLS_PACKAGE, intent.getPackage()); assertEquals(TEST_COMPONENT, intent.getParcelableExtra(Intent.EXTRA_COMPONENT_NAME)); assertTrue(equals(control, intent.getParcelableExtra(ControlsProviderService.EXTRA_CONTROL))); diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java index efdb51dcdfa9..cbb379bf8207 100644 --- a/core/tests/coretests/src/android/view/InsetsControllerTest.java +++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java @@ -21,6 +21,7 @@ import static android.view.InsetsController.ANIMATION_TYPE_NONE; import static android.view.InsetsController.ANIMATION_TYPE_SHOW; import static android.view.InsetsSourceConsumer.ShowResult.IME_SHOW_DELAYED; import static android.view.InsetsSourceConsumer.ShowResult.SHOW_IMMEDIATELY; +import static android.view.InsetsState.ITYPE_CAPTION_BAR; import static android.view.InsetsState.ITYPE_IME; import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; import static android.view.InsetsState.ITYPE_STATUS_BAR; @@ -88,7 +89,6 @@ import java.util.concurrent.CountDownLatch; @Presubmit @RunWith(AndroidJUnit4.class) public class InsetsControllerTest { - private InsetsController mController; private SurfaceSession mSession = new SurfaceSession(); private SurfaceControl mLeash; @@ -665,6 +665,26 @@ public class InsetsControllerTest { InstrumentationRegistry.getInstrumentation().waitForIdleSync(); } + @Test + public void testCaptionInsetsStateAssemble() { + InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { + mController.onFrameChanged(new Rect(0, 0, 100, 300)); + final InsetsState state = new InsetsState(mController.getState(), true); + final Rect captionFrame = new Rect(0, 0, 100, 100); + mController.setCaptionInsetsHeight(100); + mController.onStateChanged(state); + final InsetsState currentState = new InsetsState(mController.getState()); + // The caption bar source should be synced with the info in mAttachInfo. + assertEquals(captionFrame, currentState.peekSource(ITYPE_CAPTION_BAR).getFrame()); + assertTrue(currentState.equals(state, true /* excludingCaptionInsets*/)); + mController.setCaptionInsetsHeight(0); + mController.onStateChanged(state); + // The caption bar source should not be there at all, because we don't add empty + // caption to the state from the server. + assertNull(mController.getState().peekSource(ITYPE_CAPTION_BAR)); + }); + } + private void waitUntilNextFrame() throws Exception { final CountDownLatch latch = new CountDownLatch(1); Choreographer.getMainThreadInstance().postCallback(Choreographer.CALLBACK_COMMIT, diff --git a/core/tests/coretests/src/android/view/InsetsStateTest.java b/core/tests/coretests/src/android/view/InsetsStateTest.java index 721dc98ff4d1..2884777fc997 100644 --- a/core/tests/coretests/src/android/view/InsetsStateTest.java +++ b/core/tests/coretests/src/android/view/InsetsStateTest.java @@ -153,6 +153,35 @@ public class InsetsStateTest { } } + + @Test + public void testCalculateInsets_captionStatusBarOverlap() throws Exception { + try (InsetsModeSession session = + new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_FULL)) { + mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100)); + mState.getSource(ITYPE_STATUS_BAR).setVisible(true); + mState.getSource(ITYPE_CAPTION_BAR).setFrame(new Rect(0, 0, 100, 300)); + mState.getSource(ITYPE_CAPTION_BAR).setVisible(true); + + Rect visibleInsets = mState.calculateVisibleInsets( + new Rect(0, 0, 100, 400), SOFT_INPUT_ADJUST_NOTHING); + assertEquals(new Rect(0, 300, 0, 0), visibleInsets); + } + } + + @Test + public void testCalculateInsets_captionBarOffset() throws Exception { + try (InsetsModeSession session = + new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_FULL)) { + mState.getSource(ITYPE_CAPTION_BAR).setFrame(new Rect(0, 0, 100, 300)); + mState.getSource(ITYPE_CAPTION_BAR).setVisible(true); + + Rect visibleInsets = mState.calculateVisibleInsets( + new Rect(0, 0, 150, 400), SOFT_INPUT_ADJUST_NOTHING); + assertEquals(new Rect(0, 300, 0, 0), visibleInsets); + } + } + @Test public void testStripForDispatch() { mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100)); diff --git a/core/tests/coretests/src/android/widget/EditorCursorDragTest.java b/core/tests/coretests/src/android/widget/EditorCursorDragTest.java index 9a93dbf67d33..4bfffd72d835 100644 --- a/core/tests/coretests/src/android/widget/EditorCursorDragTest.java +++ b/core/tests/coretests/src/android/widget/EditorCursorDragTest.java @@ -494,6 +494,7 @@ public class EditorCursorDragTest { simulateDrag(tv, events, true); } + @Suppress // b/152574363 @Test public void testLineChangeSlop() throws Throwable { TextView tv = mActivity.findViewById(R.id.textview); diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml index 1efde8681352..59bdf3dad43e 100644 --- a/data/etc/privapp-permissions-platform.xml +++ b/data/etc/privapp-permissions-platform.xml @@ -27,6 +27,10 @@ applications that come with the platform <permission name="android.permission.INTERACT_ACROSS_USERS" /> </privapp-permissions> + <privapp-permissions package="com.android.angle"> + <permission name="android.permission.WRITE_SECURE_SETTINGS"/> + </privapp-permissions> + <privapp-permissions package="com.android.apps.tag"> <permission name="android.permission.WRITE_SECURE_SETTINGS"/> </privapp-permissions> diff --git a/libs/androidfw/Android.bp b/libs/androidfw/Android.bp index f87f98a59a12..02c85aa34f4b 100644 --- a/libs/androidfw/Android.bp +++ b/libs/androidfw/Android.bp @@ -44,7 +44,6 @@ cc_library { "AttributeResolution.cpp", "ChunkIterator.cpp", "ConfigDescription.cpp", - "DynamicLibManager.cpp", "Idmap.cpp", "LoadedArsc.cpp", "Locale.cpp", diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp index f20e18453f8b..eaf452b5fa71 100644 --- a/libs/androidfw/AssetManager2.cpp +++ b/libs/androidfw/AssetManager2.cpp @@ -25,7 +25,6 @@ #include "android-base/logging.h" #include "android-base/stringprintf.h" -#include "androidfw/DynamicLibManager.h" #include "androidfw/ResourceUtils.h" #include "androidfw/Util.h" #include "utils/ByteOrder.h" @@ -67,12 +66,7 @@ struct FindEntryResult { StringPoolRef entry_string_ref; }; -AssetManager2::AssetManager2() : dynamic_lib_manager_(std::make_unique<DynamicLibManager>()) { - memset(&configuration_, 0, sizeof(configuration_)); -} - -AssetManager2::AssetManager2(DynamicLibManager* dynamic_lib_manager) - : dynamic_lib_manager_(dynamic_lib_manager) { +AssetManager2::AssetManager2() { memset(&configuration_, 0, sizeof(configuration_)); } @@ -91,6 +85,9 @@ void AssetManager2::BuildDynamicRefTable() { package_groups_.clear(); package_ids_.fill(0xff); + // A mapping from apk assets path to the runtime package id of its first loaded package. + std::unordered_map<std::string, uint8_t> apk_assets_package_ids; + // Overlay resources are not directly referenced by an application so their resource ids // can change throughout the application's lifetime. Assign overlay package ids last. std::vector<const ApkAssets*> sorted_apk_assets(apk_assets_); @@ -98,37 +95,25 @@ void AssetManager2::BuildDynamicRefTable() { return !a->IsOverlay(); }); - std::unordered_map<std::string, uint8_t> apk_assets_package_ids; - std::unordered_map<std::string, uint8_t> package_name_package_ids; - - // Assign stable package ids to application packages. - uint8_t next_available_package_id = 0U; - for (const auto& apk_assets : sorted_apk_assets) { - for (const auto& package : apk_assets->GetLoadedArsc()->GetPackages()) { - uint8_t package_id = package->GetPackageId(); - if (package->IsOverlay()) { - package_id = GetDynamicLibManager()->FindUnassignedId(next_available_package_id); - next_available_package_id = package_id + 1; - } else if (package->IsDynamic()) { - package_id = GetDynamicLibManager()->GetAssignedId(package->GetPackageName()); - } - - // Map the path of the apk assets to the package id of its first loaded package. - apk_assets_package_ids[apk_assets->GetPath()] = package_id; - - // Map the package name of the package to the first loaded package with that package id. - package_name_package_ids[package->GetPackageName()] = package_id; - } + // The assets cookie must map to the position of the apk assets in the unsorted apk assets list. + std::unordered_map<const ApkAssets*, ApkAssetsCookie> apk_assets_cookies; + apk_assets_cookies.reserve(apk_assets_.size()); + for (size_t i = 0, n = apk_assets_.size(); i < n; i++) { + apk_assets_cookies[apk_assets_[i]] = static_cast<ApkAssetsCookie>(i); } - const int apk_assets_count = apk_assets_.size(); - for (int i = 0; i < apk_assets_count; i++) { - const auto& apk_assets = apk_assets_[i]; - for (const auto& package : apk_assets->GetLoadedArsc()->GetPackages()) { - const auto package_id_entry = package_name_package_ids.find(package->GetPackageName()); - CHECK(package_id_entry != package_name_package_ids.end()) - << "no package id assgined to package " << package->GetPackageName(); - const uint8_t package_id = package_id_entry->second; + // 0x01 is reserved for the android package. + int next_package_id = 0x02; + for (const ApkAssets* apk_assets : sorted_apk_assets) { + const LoadedArsc* loaded_arsc = apk_assets->GetLoadedArsc(); + for (const std::unique_ptr<const LoadedPackage>& package : loaded_arsc->GetPackages()) { + // Get the package ID or assign one if a shared library. + int package_id; + if (package->IsDynamic()) { + package_id = next_package_id++; + } else { + package_id = package->GetPackageId(); + } // Add the mapping for package ID to index if not present. uint8_t idx = package_ids_[package_id]; @@ -162,7 +147,7 @@ void AssetManager2::BuildDynamicRefTable() { target_package_group.overlays_.push_back( ConfiguredOverlay{loaded_idmap->GetTargetResourcesMap(target_package_id, overlay_table.get()), - static_cast<ApkAssetsCookie>(i)}); + apk_assets_cookies[apk_assets]}); } } @@ -174,7 +159,7 @@ void AssetManager2::BuildDynamicRefTable() { // Add the package and to the set of packages with the same ID. package_group->packages_.push_back(ConfiguredPackage{package.get(), {}}); - package_group->cookies_.push_back(static_cast<ApkAssetsCookie>(i)); + package_group->cookies_.push_back(apk_assets_cookies[apk_assets]); // Add the package name -> build time ID mappings. for (const DynamicPackageEntry& entry : package->GetDynamicPackageMap()) { @@ -182,6 +167,8 @@ void AssetManager2::BuildDynamicRefTable() { package_group->dynamic_ref_table->mEntries.replaceValueFor( package_name, static_cast<uint8_t>(entry.package_id)); } + + apk_assets_package_ids.insert(std::make_pair(apk_assets->GetPath(), package_id)); } } @@ -1329,16 +1316,6 @@ uint8_t AssetManager2::GetAssignedPackageId(const LoadedPackage* package) const return 0; } -DynamicLibManager* AssetManager2::GetDynamicLibManager() const { - auto dynamic_lib_manager = - std::get_if<std::unique_ptr<DynamicLibManager>>(&dynamic_lib_manager_); - if (dynamic_lib_manager) { - return (*dynamic_lib_manager).get(); - } else { - return *std::get_if<DynamicLibManager*>(&dynamic_lib_manager_); - } -} - std::unique_ptr<Theme> AssetManager2::NewTheme() { return std::unique_ptr<Theme>(new Theme(this)); } diff --git a/libs/androidfw/DynamicLibManager.cpp b/libs/androidfw/DynamicLibManager.cpp deleted file mode 100644 index 895b7695bf26..000000000000 --- a/libs/androidfw/DynamicLibManager.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "androidfw/DynamicLibManager.h" - -namespace android { - -uint8_t DynamicLibManager::GetAssignedId(const std::string& library_package_name) { - auto lib_entry = shared_lib_package_ids_.find(library_package_name); - if (lib_entry != shared_lib_package_ids_.end()) { - return lib_entry->second; - } - - return shared_lib_package_ids_[library_package_name] = next_package_id_++; -} - -uint8_t DynamicLibManager::FindUnassignedId(uint8_t start_package_id) { - return (start_package_id < next_package_id_) ? next_package_id_ : start_package_id; -} - -} // namespace android diff --git a/libs/androidfw/include/androidfw/AssetManager2.h b/libs/androidfw/include/androidfw/AssetManager2.h index b2cec2a42994..e21abade99a4 100644 --- a/libs/androidfw/include/androidfw/AssetManager2.h +++ b/libs/androidfw/include/androidfw/AssetManager2.h @@ -27,7 +27,6 @@ #include "androidfw/ApkAssets.h" #include "androidfw/Asset.h" #include "androidfw/AssetManager.h" -#include "androidfw/DynamicLibManager.h" #include "androidfw/ResourceTypes.h" #include "androidfw/Util.h" @@ -95,7 +94,6 @@ class AssetManager2 { }; AssetManager2(); - explicit AssetManager2(DynamicLibManager* dynamic_lib_manager); // Sets/resets the underlying ApkAssets for this AssetManager. The ApkAssets // are not owned by the AssetManager, and must have a longer lifetime. @@ -126,6 +124,9 @@ class AssetManager2 { // This may be nullptr if the APK represented by `cookie` has no resource table. std::shared_ptr<const DynamicRefTable> GetDynamicRefTableForCookie(ApkAssetsCookie cookie) const; + // Retrieve the assigned package id of the package if loaded into this AssetManager + uint8_t GetAssignedPackageId(const LoadedPackage* package) const; + // Returns a string representation of the overlayable API of a package. bool GetOverlayablesToString(const android::StringPiece& package_name, std::string* out) const; @@ -370,11 +371,6 @@ class AssetManager2 { // been seen while traversing bag parents. const ResolvedBag* GetBag(uint32_t resid, std::vector<uint32_t>& child_resids); - // Retrieve the assigned package id of the package if loaded into this AssetManager - uint8_t GetAssignedPackageId(const LoadedPackage* package) const; - - DynamicLibManager* GetDynamicLibManager() const; - // The ordered list of ApkAssets to search. These are not owned by the AssetManager, and must // have a longer lifetime. std::vector<const ApkAssets*> apk_assets_; @@ -393,9 +389,6 @@ class AssetManager2 { // may need to be purged. ResTable_config configuration_; - // Component responsible for assigning package ids to shared libraries. - std::variant<std::unique_ptr<DynamicLibManager>, DynamicLibManager*> dynamic_lib_manager_; - // Cached set of bags. These are cached because they can inherit keys from parent bags, // which involves some calculation. std::unordered_map<uint32_t, util::unique_cptr<ResolvedBag>> cached_bags_; diff --git a/libs/androidfw/include/androidfw/DynamicLibManager.h b/libs/androidfw/include/androidfw/DynamicLibManager.h deleted file mode 100644 index 1ff7079573d2..000000000000 --- a/libs/androidfw/include/androidfw/DynamicLibManager.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROIDFW_DYNAMICLIBMANAGER_H -#define ANDROIDFW_DYNAMICLIBMANAGER_H - -#include <string> -#include <unordered_map> - -#include "android-base/macros.h" - -namespace android { - -// Manages assigning resource ids for dynamic resources. -class DynamicLibManager { - public: - DynamicLibManager() = default; - - // Retrieves the assigned package id for the library. - uint8_t GetAssignedId(const std::string& library_package_name); - - // Queries in ascending order for the first available package id that is not currently assigned to - // a library. - uint8_t FindUnassignedId(uint8_t start_package_id); - - private: - DISALLOW_COPY_AND_ASSIGN(DynamicLibManager); - - uint8_t next_package_id_ = 0x02; - std::unordered_map<std::string, uint8_t> shared_lib_package_ids_; -}; - -} // namespace android - -#endif //ANDROIDFW_DYNAMICLIBMANAGER_H diff --git a/libs/androidfw/include/androidfw/MutexGuard.h b/libs/androidfw/include/androidfw/MutexGuard.h index 8891512958f0..64924f433245 100644 --- a/libs/androidfw/include/androidfw/MutexGuard.h +++ b/libs/androidfw/include/androidfw/MutexGuard.h @@ -47,8 +47,7 @@ class Guarded { static_assert(!std::is_pointer<T>::value, "T must not be a raw pointer"); public: - template <typename ...Args> - explicit Guarded(Args&& ...args) : guarded_(std::forward<Args>(args)...) { + explicit Guarded() : guarded_() { } template <typename U = T> diff --git a/libs/androidfw/tests/AssetManager2_test.cpp b/libs/androidfw/tests/AssetManager2_test.cpp index ac32699c6dfd..8c255d16fe1f 100644 --- a/libs/androidfw/tests/AssetManager2_test.cpp +++ b/libs/androidfw/tests/AssetManager2_test.cpp @@ -17,9 +17,9 @@ #include "androidfw/AssetManager2.h" #include "androidfw/AssetManager.h" -#include "android-base/logging.h" - #include "TestHelpers.h" +#include "android-base/file.h" +#include "android-base/logging.h" #include "androidfw/ResourceUtils.h" #include "data/appaslib/R.h" #include "data/basic/R.h" @@ -45,37 +45,43 @@ namespace android { class AssetManager2Test : public ::testing::Test { public: void SetUp() override { - basic_assets_ = ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk"); + // Move to the test data directory so the idmap can locate the overlay APK. + std::string original_path = base::GetExecutableDirectory(); + chdir(GetTestDataPath().c_str()); + + basic_assets_ = ApkAssets::Load("basic/basic.apk"); ASSERT_NE(nullptr, basic_assets_); - basic_de_fr_assets_ = ApkAssets::Load(GetTestDataPath() + "/basic/basic_de_fr.apk"); + basic_de_fr_assets_ = ApkAssets::Load("basic/basic_de_fr.apk"); ASSERT_NE(nullptr, basic_de_fr_assets_); - style_assets_ = ApkAssets::Load(GetTestDataPath() + "/styles/styles.apk"); + style_assets_ = ApkAssets::Load("styles/styles.apk"); ASSERT_NE(nullptr, style_assets_); - lib_one_assets_ = ApkAssets::Load(GetTestDataPath() + "/lib_one/lib_one.apk"); + lib_one_assets_ = ApkAssets::Load("lib_one/lib_one.apk"); ASSERT_NE(nullptr, lib_one_assets_); - lib_two_assets_ = ApkAssets::Load(GetTestDataPath() + "/lib_two/lib_two.apk"); + lib_two_assets_ = ApkAssets::Load("lib_two/lib_two.apk"); ASSERT_NE(nullptr, lib_two_assets_); - libclient_assets_ = ApkAssets::Load(GetTestDataPath() + "/libclient/libclient.apk"); + libclient_assets_ = ApkAssets::Load("libclient/libclient.apk"); ASSERT_NE(nullptr, libclient_assets_); - appaslib_assets_ = ApkAssets::Load(GetTestDataPath() + "/appaslib/appaslib.apk", - PROPERTY_DYNAMIC); + appaslib_assets_ = ApkAssets::Load("appaslib/appaslib.apk", PROPERTY_DYNAMIC); ASSERT_NE(nullptr, appaslib_assets_); - system_assets_ = ApkAssets::Load(GetTestDataPath() + "/system/system.apk", - PROPERTY_SYSTEM); + system_assets_ = ApkAssets::Load("system/system.apk", PROPERTY_SYSTEM); ASSERT_NE(nullptr, system_assets_); - app_assets_ = ApkAssets::Load(GetTestDataPath() + "/app/app.apk"); + app_assets_ = ApkAssets::Load("app/app.apk"); ASSERT_THAT(app_assets_, NotNull()); - overlayable_assets_ = ApkAssets::Load(GetTestDataPath() + "/overlayable/overlayable.apk"); + overlay_assets_ = ApkAssets::LoadOverlay("overlay/overlay.idmap"); + ASSERT_NE(nullptr, overlay_assets_); + + overlayable_assets_ = ApkAssets::Load("overlayable/overlayable.apk"); ASSERT_THAT(overlayable_assets_, NotNull()); + chdir(original_path.c_str()); } protected: @@ -88,6 +94,7 @@ class AssetManager2Test : public ::testing::Test { std::unique_ptr<const ApkAssets> appaslib_assets_; std::unique_ptr<const ApkAssets> system_assets_; std::unique_ptr<const ApkAssets> app_assets_; + std::unique_ptr<const ApkAssets> overlay_assets_; std::unique_ptr<const ApkAssets> overlayable_assets_; }; @@ -216,23 +223,24 @@ TEST_F(AssetManager2Test, FindsResourceFromAppLoadedAsSharedLibrary) { EXPECT_EQ(fix_package_id(appaslib::R::array::integerArray1, 0x02), value.data); } -TEST_F(AssetManager2Test, AssignsUnchangingPackageIdToSharedLibrary) { - DynamicLibManager lib_manager; - AssetManager2 assetmanager(&lib_manager); +TEST_F(AssetManager2Test, AssignsOverlayPackageIdLast) { + AssetManager2 assetmanager; assetmanager.SetApkAssets( - {lib_one_assets_.get(), lib_two_assets_.get(), libclient_assets_.get()}); - - AssetManager2 assetmanager2(&lib_manager); - assetmanager2.SetApkAssets( - {lib_two_assets_.get(), lib_one_assets_.get(), libclient_assets_.get()}); + {overlayable_assets_.get(), overlay_assets_.get(), lib_one_assets_.get()}); - uint32_t res_id = assetmanager.GetResourceId("com.android.lib_one:string/foo"); - ASSERT_NE(0U, res_id); + auto apk_assets = assetmanager.GetApkAssets(); + ASSERT_EQ(3, apk_assets.size()); + ASSERT_EQ(overlayable_assets_.get(), apk_assets[0]); + ASSERT_EQ(overlay_assets_.get(), apk_assets[1]); + ASSERT_EQ(lib_one_assets_.get(), apk_assets[2]); - uint32_t res_id_2 = assetmanager2.GetResourceId("com.android.lib_one:string/foo"); - ASSERT_NE(0U, res_id_2); + auto get_first_package_id = [&assetmanager](const ApkAssets* apkAssets) -> uint8_t { + return assetmanager.GetAssignedPackageId(apkAssets->GetLoadedArsc()->GetPackages()[0].get()); + }; - ASSERT_EQ(res_id, res_id_2); + ASSERT_EQ(get_first_package_id(overlayable_assets_.get()), 0x7f); + ASSERT_EQ(get_first_package_id(overlay_assets_.get()), 0x03); + ASSERT_EQ(get_first_package_id(lib_one_assets_.get()), 0x02); } TEST_F(AssetManager2Test, GetSharedLibraryResourceName) { @@ -770,7 +778,6 @@ TEST_F(AssetManager2Test, GetOverlayablesToString) { ASSERT_EQ(api.find("not_overlayable"), std::string::npos); ASSERT_NE(api.find("resource='com.android.overlayable:string/overlayable2' overlayable='OverlayableResources1' actor='overlay://theme' policy='0x0000000a'\n"), std::string::npos); - } } // namespace android diff --git a/media/java/android/media/AudioDeviceInfo.java b/media/java/android/media/AudioDeviceInfo.java index 9950f05560d7..db2a1e8b6e7c 100644 --- a/media/java/android/media/AudioDeviceInfo.java +++ b/media/java/android/media/AudioDeviceInfo.java @@ -432,7 +432,7 @@ public final class AudioDeviceInfo { * @return An array of supported encapsulation modes for the device. This * may be an empty array if no encapsulation modes are supported. */ - public @NonNull int[] getEncapsulationModes() { + public @NonNull @AudioTrack.EncapsulationMode int[] getEncapsulationModes() { // Implement a getter in r-dev or r-tv-dev as needed. return new int[0]; // be careful of returning a copy of any internal data. } @@ -451,7 +451,7 @@ public final class AudioDeviceInfo { * @return An array of supported encapsulation metadata types for the device. This * may be an empty array if no metadata types are supported. */ - public @NonNull int[] getEncapsulationMetadataTypes() { + public @NonNull @AudioTrack.EncapsulationMetadataType int[] getEncapsulationMetadataTypes() { // Implement a getter in r-dev or r-tv-dev as needed. return new int[0]; // be careful of returning a copy of any internal data. } diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index fffdd683f22c..ba8f7e60e268 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -4769,7 +4769,7 @@ public class AudioManager { * opened on that device. * * @param device an instance of {@link AudioDeviceInfo} returned from {@link getDevices()}. - * @param delayMs delay in milliseconds desired. This should be in range of {@code 0} + * @param delayMillis delay in milliseconds desired. This should be in range of {@code 0} * to the value returned by {@link #getMaxAdditionalOutputDeviceDelay()}. * @return true if successful, false if the device does not support output device delay * or the delay is not in range of {@link #getMaxAdditionalOutputDeviceDelay()}. @@ -4777,7 +4777,7 @@ public class AudioManager { @SystemApi @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public boolean setAdditionalOutputDeviceDelay( - @NonNull AudioDeviceInfo device, @IntRange(from = 0) int delayMs) { + @NonNull AudioDeviceInfo device, @IntRange(from = 0) long delayMillis) { Objects.requireNonNull(device); // Implement the setter in r-dev or r-tv-dev as needed. return false; @@ -4793,7 +4793,7 @@ public class AudioManager { */ @SystemApi @IntRange(from = 0) - public int getAdditionalOutputDeviceDelay(@NonNull AudioDeviceInfo device) { + public long getAdditionalOutputDeviceDelay(@NonNull AudioDeviceInfo device) { Objects.requireNonNull(device); // Implement the getter in r-dev or r-tv-dev as needed. return 0; @@ -4811,7 +4811,7 @@ public class AudioManager { */ @SystemApi @IntRange(from = 0) - public int getMaxAdditionalOutputDeviceDelay(@NonNull AudioDeviceInfo device) { + public long getMaxAdditionalOutputDeviceDelay(@NonNull AudioDeviceInfo device) { Objects.requireNonNull(device); // Implement the getter in r-dev or r-tv-dev as needed. return 0; diff --git a/media/java/android/media/AudioMetadata.java b/media/java/android/media/AudioMetadata.java index 1a9517cafdde..c91ff0d099cf 100644 --- a/media/java/android/media/AudioMetadata.java +++ b/media/java/android/media/AudioMetadata.java @@ -79,96 +79,11 @@ public final class AudioMetadata { } /** - * A read only {@code Map} interface of {@link Key} value pairs. - * - * <p>Using a {@link Key} interface, the map looks up the corresponding value.</p> - */ - public interface ReadMap { - /** - * Returns true if the key exists in the map. - * - * @param key interface for requesting the value. - * @param <T> type of value. - * @return true if key exists in the Map. - */ - <T> boolean containsKey(@NonNull Key<T> key); - - /** - * Returns a copy of the map. - * - * This is intended for safe conversion between a {@link ReadMap} - * interface and a {@link Map} interface. - * Currently only simple objects are used for key values which - * means a shallow copy is sufficient. - * - * @return a Map copied from the existing map. - */ - @NonNull - Map dup(); // lint checker doesn't like clone(). - - /** - * Returns the value associated with the key. - * - * @param key interface for requesting the value. - * @param <T> type of value. - * @return returns the value of associated with key or null if it doesn't exist. - */ - @Nullable - <T> T get(@NonNull Key<T> key); - - /** - * Returns a {@code Set} of keys associated with the map. - * @hide - */ - @NonNull - Set<Key<?>> keySet(); - - /** - * Returns the number of elements in the map. - */ - int size(); - } - - /** - * A writeable {@link Map} interface of {@link Key} value pairs. - * This interface is not guaranteed to be thread-safe - * unless the supplier for the {@code Map} states it as thread safe. - */ - // TODO: Create a wrapper like java.util.Collections.synchronizedMap? - public interface Map extends ReadMap { - /** - * Removes the value associated with the key. - * @param key interface for storing the value. - * @param <T> type of value. - * @return the value of the key, null if it doesn't exist. - */ - @Nullable - <T> T remove(@NonNull Key<T> key); - - /** - * Sets a value for the key. - * - * @param key interface for storing the value. - * @param <T> type of value. - * @param value a non-null value of type T. - * @return the previous value associated with key or null if it doesn't exist. - */ - // See automatic Kotlin overloading for Java interoperability. - // https://kotlinlang.org/docs/reference/java-interop.html#operators - // See also Kotlin set for overloaded operator indexing. - // https://kotlinlang.org/docs/reference/operator-overloading.html#indexed - // Also the Kotlin mutable-list set. - // https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-mutable-list/set.html - @Nullable - <T> T set(@NonNull Key<T> key, @NonNull T value); - } - - /** - * Creates a {@link Map} suitable for adding keys. - * @return an empty {@link Map} instance. + * Creates a {@link AudioMetadataMap} suitable for adding keys. + * @return an empty {@link AudioMetadataMap} instance. */ @NonNull - public static Map createMap() { + public static AudioMetadataMap createMap() { return new BaseMap(); } @@ -339,7 +254,7 @@ public final class AudioMetadata { * It is possible to require the keys to be of a certain class * before allowing a set or get operation. */ - public static class BaseMap implements Map { + public static class BaseMap implements AudioMetadataMap { @Override public <T> boolean containsKey(@NonNull Key<T> key) { Pair<Key<?>, Object> valuePair = mHashMap.get(pairFromKey(key)); @@ -348,7 +263,7 @@ public final class AudioMetadata { @Override @NonNull - public Map dup() { + public AudioMetadataMap dup() { BaseMap map = new BaseMap(); map.mHashMap.putAll(this.mHashMap); return map; diff --git a/media/java/android/media/AudioMetadataMap.java b/media/java/android/media/AudioMetadataMap.java new file mode 100644 index 000000000000..196193174754 --- /dev/null +++ b/media/java/android/media/AudioMetadataMap.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media; + +import android.annotation.NonNull; +import android.annotation.Nullable; + +/** + * AudioMetadataMap is a writeable {@code Map}-style + * interface of {@link AudioMetadata.Key} value pairs. + * This interface is not guaranteed to be thread-safe + * unless the underlying implementation for the {@code AudioMetadataMap} + * states it as thread safe. + * + * {@see AudioMetadataReadMap} + */ +// TODO: Create a wrapper like java.util.Collections.synchronizedMap? + +public interface AudioMetadataMap extends AudioMetadataReadMap { + /** + * Removes the value associated with the key. + * @param key interface for storing the value. + * @param <T> type of value. + * @return the value of the key, null if it doesn't exist. + */ + @Nullable + <T> T remove(@NonNull AudioMetadata.Key<T> key); + + /** + * Sets a value for the key. + * + * @param key interface for storing the value. + * @param <T> type of value. + * @param value a non-null value of type T. + * @return the previous value associated with key or null if it doesn't exist. + */ + // See automatic Kotlin overloading for Java interoperability. + // https://kotlinlang.org/docs/reference/java-interop.html#operators + // See also Kotlin set for overloaded operator indexing. + // https://kotlinlang.org/docs/reference/operator-overloading.html#indexed + // Also the Kotlin mutable-list set. + // https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-mutable-list/set.html + @Nullable + <T> T set(@NonNull AudioMetadata.Key<T> key, @NonNull T value); +} diff --git a/media/java/android/media/AudioMetadataReadMap.java b/media/java/android/media/AudioMetadataReadMap.java new file mode 100644 index 000000000000..e74242a292d4 --- /dev/null +++ b/media/java/android/media/AudioMetadataReadMap.java @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media; + +import android.annotation.IntRange; +import android.annotation.NonNull; +import android.annotation.Nullable; + +import java.util.Set; + +/** + * A read only {@code Map}-style interface of {@link AudioMetadata.Key} value pairs used + * for {@link AudioMetadata}. + * + * <p>Using a {@link AudioMetadata.Key} interface, + * this map looks up the corresponding value. + * Read-only maps are thread-safe for lookup, but the underlying object + * values may need their own thread protection if mutable.</p> + * + * {@see AudioMetadataMap} + */ +public interface AudioMetadataReadMap { + /** + * Returns true if the key exists in the map. + * + * @param key interface for requesting the value. + * @param <T> type of value. + * @return true if key exists in the Map. + */ + <T> boolean containsKey(@NonNull AudioMetadata.Key<T> key); + + /** + * Returns a copy of the map. + * + * This is intended for safe conversion between a {@link AudioMetadataReadMap} + * interface and a {@link AudioMetadataMap} interface. + * Currently only simple objects are used for key values which + * means a shallow copy is sufficient. + * + * @return a Map copied from the existing map. + */ + @NonNull + AudioMetadataMap dup(); // lint checker doesn't like clone(). + + /** + * Returns the value associated with the key. + * + * @param key interface for requesting the value. + * @param <T> type of value. + * @return returns the value of associated with key or null if it doesn't exist. + */ + @Nullable + <T> T get(@NonNull AudioMetadata.Key<T> key); + + /** + * Returns a {@code Set} of keys associated with the map. + * @hide + */ + @NonNull + Set<AudioMetadata.Key<?>> keySet(); + + /** + * Returns the number of elements in the map. + */ + @IntRange(from = 0) + int size(); +} diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java index d17e42996726..1d229b80cb2c 100644 --- a/media/java/android/media/AudioTrack.java +++ b/media/java/android/media/AudioTrack.java @@ -918,7 +918,29 @@ public class AudioTrack extends PlayerBase private final int mContentId; private final int mSyncId; - private TunerConfiguration(int contentId, int syncId) { + /** + * Constructs a TunerConfiguration instance for use in {@link AudioTrack.Builder} + * + * @param contentId selects the audio stream to use. + * The contentId may be obtained from + * {@link android.media.tv.tuner.filter.Filter#getId()}. + * This is always a positive number. + * @param syncId selects the clock to use for synchronization + * of audio with other streams such as video. + * The syncId may be obtained from + * {@link android.media.tv.tuner.Tuner#getAvSyncHwId()}. + * This is always a positive number. + */ + @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) + public TunerConfiguration( + @IntRange(from = 1) int contentId, @IntRange(from = 1)int syncId) { + if (contentId < 1) { + throw new IllegalArgumentException( + "contentId " + contentId + " must be positive"); + } + if (syncId < 1) { + throw new IllegalArgumentException("syncId " + syncId + " must be positive"); + } mContentId = contentId; mSyncId = syncId; } @@ -938,73 +960,6 @@ public class AudioTrack extends PlayerBase public @IntRange(from = 1) int getSyncId() { return mSyncId; // The Builder ensures this is > 0. } - - /** - * Builder class for {@link AudioTrack.TunerConfiguration} objects. - */ - public static class Builder { - private int mContentId; - private int mSyncId; - - /** - * Sets the contentId from the Tuner filter. - * - * @param contentId selects the audio stream to use. - * The contentId may be obtained from - * {@link android.media.tv.tuner.filter.Filter#getId()}. - * This is always a positive number. - * - * @return the same Builder instance. - */ - @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) - public @NonNull Builder setContentId(@IntRange(from = 1) int contentId) { - if (contentId < 1) { - throw new IllegalArgumentException( - "contentId " + contentId + " must be positive"); - } - mContentId = contentId; - return this; - } - - /** - * Sets the syncId from the Tuner filter. - * - * @param syncId selects the clock to use for synchronization - * of audio with other streams such as video. - * The syncId may be obtained from - * {@link android.media.tv.tuner.Tuner#getAvSyncHwId()}. - * This is always a positive number. - * - * @return the same Builder instance. - */ - @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) - public @NonNull Builder setSyncId(@IntRange(from = 1) int syncId) { - if (syncId < 1) { - throw new IllegalArgumentException("syncId " + syncId + " must be positive"); - } - mSyncId = syncId; - return this; - } - - /** - * Builds a {@link AudioTrack.TunerConfiguration} instance initialized with - * the parameters set on this {@code Builder}. - * - * @return a new successfully initialized {@link AudioTrack.TunerConfiguration}. - * @throws UnsupportedOperationException if the parameters set on the - * {@code Builder} are incompatible. - */ - @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) - public @NonNull TunerConfiguration build() { - if (mContentId < 1 || mSyncId < 1) { - throw new UnsupportedOperationException( - "mContentId " + mContentId - + " mSyncId " + mSyncId - + " must be set"); - } - return new TunerConfiguration(mContentId, mSyncId); - } - } } /** @@ -3673,7 +3628,7 @@ public class AudioTrack extends PlayerBase // OnCodecFormatChangedListener notifications uses an instance // of ListenerList to manage its listeners. - private final Utils.ListenerList<AudioMetadata.ReadMap> mCodecFormatChangedListeners = + private final Utils.ListenerList<AudioMetadataReadMap> mCodecFormatChangedListeners = new Utils.ListenerList(); /** @@ -3684,13 +3639,13 @@ public class AudioTrack extends PlayerBase * Called when the compressed codec format changes. * * @param audioTrack is the {@code AudioTrack} instance associated with the codec. - * @param info is a {@link AudioMetadata.ReadMap} of values which contains decoded format + * @param info is a {@link AudioMetadataReadMap} of values which contains decoded format * changes reported by the codec. Not all hardware * codecs indicate codec format changes. Acceptable keys are taken from * {@code AudioMetadata.Format.KEY_*} range, with the associated value type. */ void onCodecFormatChanged( - @NonNull AudioTrack audioTrack, @Nullable AudioMetadata.ReadMap info); + @NonNull AudioTrack audioTrack, @Nullable AudioMetadataReadMap info); } /** @@ -3708,7 +3663,7 @@ public class AudioTrack extends PlayerBase mCodecFormatChangedListeners.add( listener, /* key for removal */ executor, - (int eventCode, AudioMetadata.ReadMap readMap) -> { + (int eventCode, AudioMetadataReadMap readMap) -> { // eventCode is unused by this implementation. listener.onCodecFormatChanged(this, readMap); } @@ -4067,7 +4022,7 @@ public class AudioTrack extends PlayerBase ByteBuffer buffer = (ByteBuffer) obj; buffer.order(ByteOrder.nativeOrder()); buffer.rewind(); - AudioMetadata.ReadMap audioMetaData = AudioMetadata.fromByteBuffer(buffer); + AudioMetadataReadMap audioMetaData = AudioMetadata.fromByteBuffer(buffer); if (audioMetaData == null) { Log.e(TAG, "Unable to get audio metadata from byte buffer"); return; diff --git a/media/java/android/media/MediaRoute2Info.java b/media/java/android/media/MediaRoute2Info.java index 998561316dd4..e5ad569bb24f 100644 --- a/media/java/android/media/MediaRoute2Info.java +++ b/media/java/android/media/MediaRoute2Info.java @@ -663,8 +663,8 @@ public final class MediaRoute2Info implements Parcelable { } /** - * Constructor for builder to create {@link MediaRoute2Info} with - * existing {@link MediaRoute2Info} instance. + * Constructor for builder to create {@link MediaRoute2Info} with existing + * {@link MediaRoute2Info} instance. * * @param routeInfo the existing instance to copy data from. */ @@ -690,6 +690,38 @@ public final class MediaRoute2Info implements Parcelable { } /** + * Constructor for builder to create {@link MediaRoute2Info} with existing + * {@link MediaRoute2Info} instance and replace ID with the given {@code id}. + * + * @param id The ID of the new route. Must not be empty. + * @param routeInfo the existing instance to copy data from. + * @hide + */ + public Builder(@NonNull String id, @NonNull MediaRoute2Info routeInfo) { + if (TextUtils.isEmpty(id)) { + throw new IllegalArgumentException("id must not be empty"); + } + Objects.requireNonNull(routeInfo, "routeInfo must not be null"); + + mId = id; + mName = routeInfo.mName; + mFeatures = new ArrayList<>(routeInfo.mFeatures); + mType = routeInfo.mType; + mIsSystem = routeInfo.mIsSystem; + mIconUri = routeInfo.mIconUri; + mDescription = routeInfo.mDescription; + mConnectionState = routeInfo.mConnectionState; + mClientPackageName = routeInfo.mClientPackageName; + mVolumeHandling = routeInfo.mVolumeHandling; + mVolumeMax = routeInfo.mVolumeMax; + mVolume = routeInfo.mVolume; + if (routeInfo.mExtras != null) { + mExtras = new Bundle(routeInfo.mExtras); + } + mProviderId = routeInfo.mProviderId; + } + + /** * Adds a feature for the route. * @param feature a feature that the route has. May be one of predefined features * such as {@link #FEATURE_LIVE_AUDIO}, {@link #FEATURE_LIVE_VIDEO} or diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java index d320df9c24ba..736e995451cd 100644 --- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java +++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java @@ -96,6 +96,7 @@ public class SecureSettings { Settings.Secure.CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, Settings.Secure.QS_TILES, + Settings.Secure.CONTROLS_ENABLED, Settings.Secure.DOZE_ENABLED, Settings.Secure.DOZE_ALWAYS_ON, Settings.Secure.DOZE_PICK_UP_GESTURE, @@ -163,6 +164,6 @@ public class SecureSettings { Settings.Secure.AWARE_TAP_PAUSE_TOUCH_COUNT, Settings.Secure.PEOPLE_STRIP, Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE, - Settings.Secure.ACCESSIBILITY_BUTTON_LONG_PRESS_TARGETS, + Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, }; } diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java index 8801a9c32a36..b413e8e9dda2 100644 --- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java +++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java @@ -78,9 +78,7 @@ public class SecureSettingsValidators { ACCESSIBILITY_SHORTCUT_TARGET_LIST_VALIDATOR); // technically either ComponentName or class name, but there's proper value // validation at callsites, so allow any non-null string - VALIDATORS.put( - Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT, - ACCESSIBILITY_SHORTCUT_TARGET_LIST_VALIDATOR); + VALIDATORS.put(Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT, value -> value != null); VALIDATORS.put(Secure.ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED, BOOLEAN_VALIDATOR); @@ -143,6 +141,7 @@ public class SecureSettingsValidators { VALIDATORS.put(Secure.CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.QS_TILES, TILE_LIST_VALIDATOR); + VALIDATORS.put(Secure.CONTROLS_ENABLED, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.DOZE_ENABLED, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.DOZE_ALWAYS_ON, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.DOZE_PICK_UP_GESTURE, BOOLEAN_VALIDATOR); @@ -248,7 +247,7 @@ public class SecureSettingsValidators { Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN, Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW)); VALIDATORS.put( - Secure.ACCESSIBILITY_BUTTON_LONG_PRESS_TARGETS, + Secure.ACCESSIBILITY_BUTTON_TARGETS, ACCESSIBILITY_SHORTCUT_TARGET_LIST_VALIDATOR); } } diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java index b22caf0edc66..8a7b9134a5d9 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java @@ -1811,8 +1811,8 @@ class SettingsProtoDumpUtil { Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE, SecureSettingsProto.Accessibility.ACCESSIBILITY_MAGNIFICATION_MODE); dumpSetting(s, p, - Settings.Secure.ACCESSIBILITY_BUTTON_LONG_PRESS_TARGETS, - SecureSettingsProto.Accessibility.BUTTON_LONG_PRESS_TARGETS); + Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, + SecureSettingsProto.Accessibility.BUTTON_TARGETS); p.end(accessibilityToken); final long adaptiveSleepToken = p.start(SecureSettingsProto.ADAPTIVE_SLEEP); @@ -1972,6 +1972,13 @@ class SettingsProtoDumpUtil { dumpSetting(s, p, Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS, SecureSettingsProto.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS); + + final long controlsToken = p.start(SecureSettingsProto.CONTROLS); + dumpSetting(s, p, + Settings.Secure.CONTROLS_ENABLED, + SecureSettingsProto.Controls.ENABLED); + p.end(controlsToken); + dumpSetting(s, p, Settings.Secure.DEVICE_PAIRED, SecureSettingsProto.DEVICE_PAIRED); diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java index 0ae00e1ac8b5..a1376c3203f5 100644 --- a/packages/Shell/src/com/android/shell/BugreportProgressService.java +++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java @@ -1808,13 +1808,13 @@ public class BugreportProgressService extends Service { * Current value of progress (in percentage) of the bugreport generation as * displayed by the UI. */ - AtomicInteger progress; + AtomicInteger progress = new AtomicInteger(0); /** * Last value of progress (in percentage) of the bugreport generation for which * system notification was updated. */ - AtomicInteger lastProgress; + AtomicInteger lastProgress = new AtomicInteger(0); /** * Time of the last progress update. diff --git a/packages/SystemUI/res/drawable/control_background_ripple.xml b/packages/SystemUI/res/drawable/control_background_ripple.xml new file mode 100644 index 000000000000..37914e272811 --- /dev/null +++ b/packages/SystemUI/res/drawable/control_background_ripple.xml @@ -0,0 +1,23 @@ +<!-- + ~ Copyright (C) 2020 The Android Open 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. + --> + +<ripple xmlns:android="http://schemas.android.com/apk/res/android" + android:color="?android:attr/colorControlHighlight"> + <item android:id="@android:id/mask"> + <color android:color="@android:color/white" /> + </item> + <item android:drawable="@drawable/control_background" /> +</ripple>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/controls_base_item.xml b/packages/SystemUI/res/layout/controls_base_item.xml index 6e1fd2072b32..b83e500fbaeb 100644 --- a/packages/SystemUI/res/layout/controls_base_item.xml +++ b/packages/SystemUI/res/layout/controls_base_item.xml @@ -50,6 +50,7 @@ app:layout_constraintBottom_toBottomOf="@+id/icon" app:layout_constraintStart_toEndOf="@+id/icon" /> + <TextView android:id="@+id/status_extra" android:layout_width="wrap_content" @@ -64,7 +65,7 @@ <TextView android:id="@+id/title" - android:layout_width="wrap_content" + android:layout_width="match_parent" android:layout_height="wrap_content" android:textAppearance="@style/TextAppearance.Control.Title" android:paddingLeft="@dimen/control_padding_adjustment" @@ -73,12 +74,20 @@ android:focusable="false" android:maxLines="1" android:ellipsize="end" - app:layout_constraintBottom_toTopOf="@+id/subtitle" - app:layout_constraintStart_toStartOf="parent" /> + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintBottom_toTopOf="@id/barrier"/> + + <androidx.constraintlayout.widget.Barrier + android:id="@+id/barrier" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + app:barrierDirection="top" + app:constraint_referenced_ids="subtitle,favorite" /> <TextView android:id="@+id/subtitle" - android:layout_width="wrap_content" + android:layout_width="0dp" android:layout_height="wrap_content" android:textAppearance="@style/TextAppearance.Control.Subtitle" android:paddingLeft="@dimen/control_padding_adjustment" @@ -88,24 +97,22 @@ android:focusable="false" android:maxLines="1" android:ellipsize="end" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toStartOf="@id/favorite" app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintStart_toStartOf="parent"/> + /> - <FrameLayout - android:id="@+id/favorite_container" + <CheckBox + android:id="@+id/favorite" android:visibility="gone" - android:layout_width="48dp" - android:layout_height="48dp" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="bottom|end" + android:button="@drawable/controls_btn_star" + android:layout_marginTop="4dp" + android:layout_marginStart="4dp" + app:layout_constraintStart_toEndOf="@id/subtitle" app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintBottom_toBottomOf="parent"> - - <CheckBox - android:id="@+id/favorite" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="bottom|end" - android:button="@drawable/controls_btn_star"/> - </FrameLayout> - + app:layout_constraintBottom_toBottomOf="parent"/> </androidx.constraintlayout.widget.ConstraintLayout> diff --git a/packages/SystemUI/res/values-television/dimens.xml b/packages/SystemUI/res/values-television/dimens.xml new file mode 100644 index 000000000000..6da0c693f389 --- /dev/null +++ b/packages/SystemUI/res/values-television/dimens.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2020 The Android Open 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 + --> +<resources> + <!-- Opacity at which the background for the shutdown UI will be drawn. --> + <item name="shutdown_scrim_behind_alpha" format="float" type="dimen">1.0</item> +</resources>
\ No newline at end of file diff --git a/packages/SystemUI/res/values-television/styles.xml b/packages/SystemUI/res/values-television/styles.xml index b59f0072b8c3..b01c5d88e3b3 100644 --- a/packages/SystemUI/res/values-television/styles.xml +++ b/packages/SystemUI/res/values-television/styles.xml @@ -17,4 +17,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android"> <style name="Theme.SystemUI.Dialog" parent="@android:style/Theme.DeviceDefault.Dialog" /> <style name="Theme.SystemUI.Dialog.Alert" parent="@*android:style/Theme.DeviceDefault.Dialog.Alert" /> + + <style name="Animation.ShutdownUi"> + <item name="android:windowEnterAnimation">@null</item> + <item name="android:windowExitAnimation">@null</item> + </style> </resources> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index ee7f5230145e..864442ecd0c5 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -1266,4 +1266,7 @@ <dimen name="screenrecord_status_icon_radius">5dp</dimen> <dimen name="kg_user_switcher_text_size">16sp</dimen> + + <!-- Opacity at which the background for the shutdown UI will be drawn. --> + <item name="shutdown_scrim_behind_alpha" format="float" type="dimen">0.95</item> </resources> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 8a3a16e9a6cf..b779130afc93 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -2687,9 +2687,9 @@ <!-- Controls management controls screen header for Other zone [CHAR LIMIT=60] --> <string name="controls_favorite_other_zone_header">Other</string> - <!-- Controls dialog title [CHAR LIMIT=30] --> + <!-- Controls dialog title [CHAR LIMIT=40] --> <string name="controls_dialog_title">Add to quick controls</string> - <!-- Controls dialog add to favorites [CHAR LIMIT=30] --> + <!-- Controls dialog add to favorites [CHAR LIMIT=40] --> <string name="controls_dialog_ok">Add to favorites</string> <!-- Controls dialog message [CHAR LIMIT=NONE] --> <string name="controls_dialog_message"><xliff:g id="app" example="System UI">%s</xliff:g> suggested this control to add to your favorites.</string> diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml index 1233d4dc73e7..9f1e63e0aa27 100644 --- a/packages/SystemUI/res/values/styles.xml +++ b/packages/SystemUI/res/values/styles.xml @@ -305,6 +305,9 @@ <item name="android:windowExitAnimation">@null</item> </style> + <style name="Animation.ShutdownUi" parent="@android:style/Animation.Toast"> + </style> + <!-- Standard animations for hiding and showing the status bar. --> <style name="Animation.StatusBar"> </style> diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index 3afe19f926ec..7cbc840afed4 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -127,6 +127,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab private static final boolean DEBUG = KeyguardConstants.DEBUG; private static final boolean DEBUG_SIM_STATES = KeyguardConstants.DEBUG_SIM_STATES; private static final boolean DEBUG_FACE = true; + private static final boolean DEBUG_SPEW = false; private static final int LOW_BATTERY_THRESHOLD = 20; private static final String ACTION_FACE_UNLOCK_STARTED @@ -324,7 +325,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } }; - private class BiometricAuthenticated { + @VisibleForTesting + static class BiometricAuthenticated { private final boolean mAuthenticated; private final boolean mIsStrongBiometric; @@ -338,11 +340,14 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab private SparseBooleanArray mUserHasTrust = new SparseBooleanArray(); private SparseBooleanArray mUserTrustIsManaged = new SparseBooleanArray(); private SparseBooleanArray mUserTrustIsUsuallyManaged = new SparseBooleanArray(); - private SparseArray<BiometricAuthenticated> mUserFingerprintAuthenticated = new SparseArray<>(); - private SparseArray<BiometricAuthenticated> mUserFaceAuthenticated = new SparseArray<>(); private SparseBooleanArray mUserFaceUnlockRunning = new SparseBooleanArray(); private Map<Integer, Intent> mSecondaryLockscreenRequirement = new HashMap<Integer, Intent>(); + @VisibleForTesting + SparseArray<BiometricAuthenticated> mUserFingerprintAuthenticated = new SparseArray<>(); + @VisibleForTesting + SparseArray<BiometricAuthenticated> mUserFaceAuthenticated = new SparseArray<>(); + private static int sCurrentUser; private Runnable mUpdateBiometricListeningState = this::updateBiometricListeningState; @@ -1850,11 +1855,33 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab // Only listen if this KeyguardUpdateMonitor belongs to the primary user. There is an // instance of KeyguardUpdateMonitor for each user but KeyguardUpdateMonitor is user-aware. - return (mBouncer || mAuthInterruptActive || awakeKeyguard || shouldListenForFaceAssistant()) + final boolean shouldListen = + (mBouncer || mAuthInterruptActive || awakeKeyguard + || shouldListenForFaceAssistant()) && !mSwitchingUser && !isFaceDisabled(user) && becauseCannotSkipBouncer && !mKeyguardGoingAway && mFaceSettingEnabledForUser.get(user) && !mLockIconPressed && strongAuthAllowsScanning && mIsPrimaryUser && !mSecureCameraLaunched; + + // Too chatty, but very useful when debugging issues. + if (DEBUG_SPEW) { + Log.v(TAG, "shouldListenForFace(" + user + ")=" + shouldListen + "... " + + ", mBouncer: " + mBouncer + + ", mAuthInterruptActive: " + mAuthInterruptActive + + ", awakeKeyguard: " + awakeKeyguard + + ", shouldListenForFaceAssistant: " + shouldListenForFaceAssistant() + + ", mSwitchingUser: " + mSwitchingUser + + ", isFaceDisabled(" + user + "): " + isFaceDisabled(user) + + ", becauseCannotSkipBouncer: " + becauseCannotSkipBouncer + + ", mKeyguardGoingAway: " + mKeyguardGoingAway + + ", mFaceSettingEnabledForUser(" + user + "): " + + mFaceSettingEnabledForUser.get(user) + + ", mLockIconPressed: " + mLockIconPressed + + ", strongAuthAllowsScanning: " + strongAuthAllowsScanning + + ", isPrimaryUser: " + mIsPrimaryUser + + ", mSecureCameraLaunched: " + mSecureCameraLaunched); + } + return shouldListen; } /** @@ -2049,8 +2076,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab /** * Handle {@link #MSG_USER_SWITCHING} */ - private void handleUserSwitching(int userId, IRemoteCallback reply) { + @VisibleForTesting + void handleUserSwitching(int userId, IRemoteCallback reply) { Assert.isMainThread(); + clearBiometricRecognized(); mUserTrustIsUsuallyManaged.put(userId, mTrustManager.isTrustUsuallyManaged(userId)); for (int i = 0; i < mCallbacks.size(); i++) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BadgedImageView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BadgedImageView.java index a1cb7f61ad04..55be77ca3be5 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BadgedImageView.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BadgedImageView.java @@ -28,6 +28,8 @@ import com.android.launcher3.icons.DotRenderer; import com.android.systemui.Interpolators; import com.android.systemui.R; +import java.util.EnumSet; + /** * View that displays an adaptive icon with an app-badge and a dot. * @@ -42,12 +44,27 @@ public class BadgedImageView extends ImageView { /** Same as value in Launcher3 IconShape */ public static final int DEFAULT_PATH_SIZE = 100; - static final int DOT_STATE_DEFAULT = 0; - static final int DOT_STATE_SUPPRESSED_FOR_FLYOUT = 1; - static final int DOT_STATE_ANIMATING = 2; + /** + * Flags that suppress the visibility of the 'new' dot, for one reason or another. If any of + * these flags are set, the dot will not be shown even if {@link Bubble#showDot()} returns true. + */ + enum SuppressionFlag { + // Suppressed because the flyout is visible - it will morph into the dot via animation. + FLYOUT_VISIBLE, + // Suppressed because this bubble is behind others in the collapsed stack. + BEHIND_STACK, + } + + /** + * Start by suppressing the dot because the flyout is visible - most bubbles are added with a + * flyout, so this is a reasonable default. + */ + private final EnumSet<SuppressionFlag> mDotSuppressionFlags = + EnumSet.of(SuppressionFlag.FLYOUT_VISIBLE); - // Flyout gets shown before the dot - private int mCurrentDotState = DOT_STATE_SUPPRESSED_FOR_FLYOUT; + private float mDotScale = 0f; + private float mAnimatingToDotScale = 0f; + private boolean mDotIsAnimating = false; private BubbleViewProvider mBubble; @@ -57,8 +74,6 @@ public class BadgedImageView extends ImageView { private boolean mOnLeft; private int mDotColor; - private float mDotScale = 0f; - private boolean mDotDrawn; private Rect mTempBounds = new Rect(); @@ -83,28 +98,28 @@ public class BadgedImageView extends ImageView { Path iconPath = PathParser.createPathFromPathData( getResources().getString(com.android.internal.R.string.config_icon_mask)); mDotRenderer = new DotRenderer(mBubbleBitmapSize, iconPath, DEFAULT_PATH_SIZE); + + setFocusable(true); } /** * Updates the view with provided info. */ - public void update(BubbleViewProvider bubble) { + public void setRenderedBubble(BubbleViewProvider bubble) { mBubble = bubble; setImageBitmap(bubble.getBadgedImage()); - setDotState(DOT_STATE_SUPPRESSED_FOR_FLYOUT); mDotColor = bubble.getDotColor(); drawDot(bubble.getDotPath()); - animateDot(); } @Override public void onDraw(Canvas canvas) { super.onDraw(canvas); - if (isDotHidden()) { - mDotDrawn = false; + + if (!shouldDrawDot()) { return; } - mDotDrawn = mDotScale > 0.1f; + getDrawingRect(mTempBounds); mDrawParams.color = mDotColor; @@ -115,23 +130,33 @@ public class BadgedImageView extends ImageView { mDotRenderer.draw(canvas, mDrawParams); } - /** - * Sets the dot state, does not animate changes. - */ - void setDotState(int state) { - mCurrentDotState = state; - if (state == DOT_STATE_SUPPRESSED_FOR_FLYOUT || state == DOT_STATE_DEFAULT) { - mDotScale = mBubble.showDot() ? 1f : 0f; - invalidate(); + /** Adds a dot suppression flag, updating dot visibility if needed. */ + void addDotSuppressionFlag(SuppressionFlag flag) { + if (mDotSuppressionFlags.add(flag)) { + // Update dot visibility, and animate out if we're now behind the stack. + updateDotVisibility(flag == SuppressionFlag.BEHIND_STACK /* animate */); } } - /** - * Whether the dot should be hidden based on current dot state. - */ - private boolean isDotHidden() { - return (mCurrentDotState == DOT_STATE_DEFAULT && !mBubble.showDot()) - || mCurrentDotState == DOT_STATE_SUPPRESSED_FOR_FLYOUT; + /** Removes a dot suppression flag, updating dot visibility if needed. */ + void removeDotSuppressionFlag(SuppressionFlag flag) { + if (mDotSuppressionFlags.remove(flag)) { + // Update dot visibility, animating if we're no longer behind the stack. + updateDotVisibility(flag == SuppressionFlag.BEHIND_STACK); + } + } + + /** Updates the visibility of the dot, animating if requested. */ + void updateDotVisibility(boolean animate) { + final float targetScale = shouldDrawDot() ? 1f : 0f; + + if (animate) { + animateDotScale(targetScale, null /* after */); + } else { + mDotScale = targetScale; + mAnimatingToDotScale = targetScale; + invalidate(); + } } /** @@ -194,11 +219,11 @@ public class BadgedImageView extends ImageView { } /** Sets the position of the 'new' dot, animating it out and back in if requested. */ - void setDotPosition(boolean onLeft, boolean animate) { - if (animate && onLeft != getDotOnLeft() && !isDotHidden()) { - animateDot(false /* showDot */, () -> { + void setDotPositionOnLeft(boolean onLeft, boolean animate) { + if (animate && onLeft != getDotOnLeft() && shouldDrawDot()) { + animateDotScale(0f /* showDot */, () -> { setDotOnLeft(onLeft); - animateDot(true /* showDot */, null); + animateDotScale(1.0f, null /* after */); }); } else { setDotOnLeft(onLeft); @@ -209,28 +234,34 @@ public class BadgedImageView extends ImageView { return getDotOnLeft(); } - /** Changes the dot's visibility to match the bubble view's state. */ - void animateDot() { - if (mCurrentDotState == DOT_STATE_DEFAULT) { - animateDot(mBubble.showDot(), null); - } + /** Whether to draw the dot in onDraw(). */ + private boolean shouldDrawDot() { + // Always render the dot if it's animating, since it could be animating out. Otherwise, show + // it if the bubble wants to show it, and we aren't suppressing it. + return mDotIsAnimating || (mBubble.showDot() && mDotSuppressionFlags.isEmpty()); } /** - * Animates the dot to show or hide. + * Animates the dot to the given scale, running the optional callback when the animation ends. */ - private void animateDot(boolean showDot, Runnable after) { - if (mDotDrawn == showDot) { - // State is consistent, do nothing. + private void animateDotScale(float toScale, @Nullable Runnable after) { + mDotIsAnimating = true; + + // Don't restart the animation if we're already animating to the given value. + if (mAnimatingToDotScale == toScale || !shouldDrawDot()) { + mDotIsAnimating = false; return; } - setDotState(DOT_STATE_ANIMATING); + mAnimatingToDotScale = toScale; + + final boolean showDot = toScale > 0f; // Do NOT wait until after animation ends to setShowDot // to avoid overriding more recent showDot states. clearAnimation(); - animate().setDuration(200) + animate() + .setDuration(200) .setInterpolator(Interpolators.FAST_OUT_SLOW_IN) .setUpdateListener((valueAnimator) -> { float fraction = valueAnimator.getAnimatedFraction(); @@ -238,7 +269,7 @@ public class BadgedImageView extends ImageView { setDotScale(fraction); }).withEndAction(() -> { setDotScale(showDot ? 1f : 0f); - setDotState(DOT_STATE_DEFAULT); + mDotIsAnimating = false; if (after != null) { after.run(); } diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java index 726a7dd111d7..afa3164cbd38 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java @@ -247,7 +247,7 @@ class Bubble implements BubbleViewProvider { mExpandedView.update(/* bubble */ this); } if (mIconView != null) { - mIconView.update(/* bubble */ this); + mIconView.setRenderedBubble(/* bubble */ this); } } @@ -306,7 +306,7 @@ class Bubble implements BubbleViewProvider { void markAsAccessedAt(long lastAccessedMillis) { mLastAccessed = lastAccessedMillis; setSuppressNotification(true); - setShowDot(false /* show */, true /* animate */); + setShowDot(false /* show */); } /** @@ -346,12 +346,11 @@ class Bubble implements BubbleViewProvider { /** * Sets whether the bubble for this notification should show a dot indicating updated content. */ - void setShowDot(boolean showDot, boolean animate) { + void setShowDot(boolean showDot) { mShowBubbleUpdateDot = showDot; - if (animate && mIconView != null) { - mIconView.animateDot(); - } else if (mIconView != null) { - mIconView.invalidate(); + + if (mIconView != null) { + mIconView.updateDotVisibility(true /* animate */); } } diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java index 01c2faa62403..9d885fd3c207 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java @@ -331,14 +331,14 @@ public class BubbleController implements ConfigurationController.ConfigurationLi @Override public void onZenChanged(int zen) { for (Bubble b : mBubbleData.getBubbles()) { - b.setShowDot(b.showInShade(), true /* animate */); + b.setShowDot(b.showInShade()); } } @Override public void onConfigChanged(ZenModeConfig config) { for (Bubble b : mBubbleData.getBubbles()) { - b.setShowDot(b.showInShade(), true /* animate */); + b.setShowDot(b.showInShade()); } } }); @@ -1101,7 +1101,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi } else if (interceptBubbleDismissal) { Bubble bubble = mBubbleData.getBubbleWithKey(entry.getKey()); bubble.setSuppressNotification(true); - bubble.setShowDot(false /* show */, true /* animate */); + bubble.setShowDot(false /* show */); } else { return false; } @@ -1141,7 +1141,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi Bubble bubbleChild = mBubbleData.getBubbleWithKey(child.getKey()); mNotificationGroupManager.onEntryRemoved(bubbleChild.getEntry()); bubbleChild.setSuppressNotification(true); - bubbleChild.setShowDot(false /* show */, true /* animate */); + bubbleChild.setShowDot(false /* show */); } else { // non-bubbled children can be removed for (NotifCallback cb : mCallbacks) { diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java index 2bd15188b7d3..1c69594469c1 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java @@ -288,7 +288,7 @@ public class BubbleData { boolean isBubbleExpandedAndSelected = mExpanded && mSelectedBubble == bubble; boolean suppress = isBubbleExpandedAndSelected || !showInShade || !bubble.showInShade(); bubble.setSuppressNotification(suppress); - bubble.setShowDot(!isBubbleExpandedAndSelected /* show */, true /* animate */); + bubble.setShowDot(!isBubbleExpandedAndSelected /* show */); dispatchPendingChanges(); } diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflow.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflow.java index 4fb2d0881ede..13669a68defa 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflow.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflow.java @@ -112,7 +112,7 @@ public class BubbleOverflow implements BubbleViewProvider { mPath.transform(matrix); mOverflowBtn.setVisibility(GONE); - mOverflowBtn.update(this); + mOverflowBtn.setRenderedBubble(this); } ImageView getBtn() { diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java index b65198595095..2231d11b7bc2 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java @@ -183,7 +183,7 @@ class BubbleOverflowAdapter extends RecyclerView.Adapter<BubbleOverflowAdapter.V public void onBindViewHolder(ViewHolder vh, int index) { Bubble b = mBubbles.get(index); - vh.iconView.update(b); + vh.iconView.setRenderedBubble(b); vh.iconView.setOnClickListener(view -> { mBubbles.remove(b); notifyDataSetChanged(); diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java index 7191a203ea8c..4b036812dbed 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java @@ -22,8 +22,6 @@ import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; import static com.android.systemui.Interpolators.FAST_OUT_SLOW_IN; import static com.android.systemui.Prefs.Key.HAS_SEEN_BUBBLES_EDUCATION; import static com.android.systemui.Prefs.Key.HAS_SEEN_BUBBLES_MANAGE_EDUCATION; -import static com.android.systemui.bubbles.BadgedImageView.DOT_STATE_DEFAULT; -import static com.android.systemui.bubbles.BadgedImageView.DOT_STATE_SUPPRESSED_FOR_FLYOUT; import static com.android.systemui.bubbles.BubbleDebugConfig.DEBUG_BUBBLE_STACK_VIEW; import static com.android.systemui.bubbles.BubbleDebugConfig.DEBUG_USER_EDUCATION; import static com.android.systemui.bubbles.BubbleDebugConfig.TAG_BUBBLES; @@ -226,7 +224,7 @@ public class BubbleStackView extends FrameLayout { private boolean mIsExpanded; /** Whether the stack is currently on the left side of the screen, or animating there. */ - private boolean mStackOnLeftOrWillBe = false; + private boolean mStackOnLeftOrWillBe = true; /** Whether a touch gesture, such as a stack/bubble drag or flyout drag, is in progress. */ private boolean mIsGestureInProgress = false; @@ -936,9 +934,13 @@ public class BubbleStackView extends FrameLayout { mStackOnLeftOrWillBe = mStackAnimationController.isStackOnLeftSide(); } + if (bubble.getIconView() == null) { + return; + } + // Set the dot position to the opposite of the side the stack is resting on, since the stack // resting slightly off-screen would result in the dot also being off-screen. - bubble.getIconView().setDotPosition( + bubble.getIconView().setDotPositionOnLeft( !mStackOnLeftOrWillBe /* onLeft */, false /* animate */); mBubbleContainer.addView(bubble.getIconView(), 0, @@ -1698,7 +1700,7 @@ public class BubbleStackView extends FrameLayout { || mBubbleToExpandAfterFlyoutCollapse != null || bubbleView == null) { if (bubbleView != null) { - bubbleView.setDotState(DOT_STATE_DEFAULT); + bubbleView.removeDotSuppressionFlag(BadgedImageView.SuppressionFlag.FLYOUT_VISIBLE); } // Skip the message if none exists, we're expanded or animating expansion, or we're // about to expand a bubble from the previous tapped flyout, or if bubble view is null. @@ -1717,12 +1719,16 @@ public class BubbleStackView extends FrameLayout { mBubbleData.setExpanded(true); mBubbleToExpandAfterFlyoutCollapse = null; } - bubbleView.setDotState(DOT_STATE_DEFAULT); + + // Stop suppressing the dot now that the flyout has morphed into the dot. + bubbleView.removeDotSuppressionFlag( + BadgedImageView.SuppressionFlag.FLYOUT_VISIBLE); }; mFlyout.setVisibility(INVISIBLE); - // Don't show the dot when we're animating the flyout - bubbleView.setDotState(DOT_STATE_SUPPRESSED_FOR_FLYOUT); + // Suppress the dot when we are animating the flyout. + bubbleView.addDotSuppressionFlag( + BadgedImageView.SuppressionFlag.FLYOUT_VISIBLE); // Start flyout expansion. Post in case layout isn't complete and getWidth returns 0. post(() -> { @@ -1743,6 +1749,11 @@ public class BubbleStackView extends FrameLayout { }; mFlyout.postDelayed(mAnimateInFlyout, 200); }; + + if (bubble.getIconView() == null) { + return; + } + mFlyout.setupFlyoutStartingAsDot(flyoutMessage, mStackAnimationController.getStackPosition(), getWidth(), mStackAnimationController.isStackOnLeftSide(), @@ -1877,9 +1888,19 @@ public class BubbleStackView extends FrameLayout { for (int i = 0; i < bubbleCount; i++) { BadgedImageView bv = (BadgedImageView) mBubbleContainer.getChildAt(i); bv.setZ((mMaxBubbles * mBubbleElevation) - i); + // If the dot is on the left, and so is the stack, we need to change the dot position. if (bv.getDotPositionOnLeft() == mStackOnLeftOrWillBe) { - bv.setDotPosition(!mStackOnLeftOrWillBe, animate); + bv.setDotPositionOnLeft(!mStackOnLeftOrWillBe, animate); + } + + if (!mIsExpanded && i > 0) { + // If we're collapsed and this bubble is behind other bubbles, suppress its dot. + bv.addDotSuppressionFlag( + BadgedImageView.SuppressionFlag.BEHIND_STACK); + } else { + bv.removeDotSuppressionFlag( + BadgedImageView.SuppressionFlag.BEHIND_STACK); } } } diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java index 7ee162e03dbc..00de8b4a51b8 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java @@ -287,7 +287,7 @@ public class StackAnimationController extends /** Whether the stack is on the left side of the screen. */ public boolean isStackOnLeftSide() { if (mLayout == null || !isStackPositionSet()) { - return false; + return true; // Default to left, which is where it starts by default. } float stackCenter = mStackPosition.x + mBubbleBitmapSize / 2; diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt index 118fcbb20f26..fdb0e4c95bed 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt @@ -65,7 +65,7 @@ class ControlsControllerImpl @Inject constructor ( companion object { private const val TAG = "ControlsControllerImpl" - internal const val CONTROLS_AVAILABLE = "systemui.controls_available" + internal const val CONTROLS_AVAILABLE = Settings.Secure.CONTROLS_ENABLED internal val URI = Settings.Secure.getUriFor(CONTROLS_AVAILABLE) private const val USER_CHANGE_RETRY_DELAY = 500L // ms private const val DEFAULT_ENABLED = 1 @@ -439,13 +439,14 @@ class ControlsControllerImpl @Inject constructor ( Log.d(TAG, "Controls not available") return } - executor.execute { - val changed = Favorites.updateControls( - componentName, - listOf(control) - ) - if (changed) { - persistenceWrapper.storeFavorites(Favorites.getAllStructures()) + + // Assume that non STATUS_OK responses may contain incomplete or invalid information about + // the control, and do not attempt to update it + if (control.getStatus() == Control.STATUS_OK) { + executor.execute { + if (Favorites.updateControls(componentName, listOf(control))) { + persistenceWrapper.storeFavorites(Favorites.getAllStructures()) + } } } uiController.onRefreshState(componentName, listOf(control)) diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt index 563c2f677801..764fda05354c 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt @@ -68,6 +68,8 @@ class ControlAdapter( width = ViewGroup.LayoutParams.MATCH_PARENT } elevation = this@ControlAdapter.elevation + background = parent.context.getDrawable( + R.drawable.control_background_ripple) } ) { id, favorite -> model?.changeFavoriteStatus(id, favorite) @@ -137,10 +139,7 @@ private class ControlHolder(view: View, val favoriteCallback: ModelFavoriteChang private val title: TextView = itemView.requireViewById(R.id.title) private val subtitle: TextView = itemView.requireViewById(R.id.subtitle) private val removed: TextView = itemView.requireViewById(R.id.status) - private val favorite: CheckBox = itemView.requireViewById<CheckBox>(R.id.favorite) - private val favoriteFrame: ViewGroup = itemView - .requireViewById<ViewGroup>(R.id.favorite_container) - .apply { + private val favorite: CheckBox = itemView.requireViewById<CheckBox>(R.id.favorite).apply { visibility = View.VISIBLE } @@ -155,7 +154,7 @@ private class ControlHolder(view: View, val favoriteCallback: ModelFavoriteChang favorite.setOnClickListener { favoriteCallback(data.control.controlId, favorite.isChecked) } - favoriteFrame.setOnClickListener { favorite.performClick() } + itemView.setOnClickListener { favorite.performClick() } applyRenderInfo(renderInfo) } diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java index 12955a153360..ce29859f12ca 100644 --- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java +++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java @@ -49,8 +49,6 @@ import dagger.Lazy; public class GlobalActionsImpl implements GlobalActions, CommandQueue.Callbacks { - private static final float SHUTDOWN_SCRIM_ALPHA = 0.95f; - private final Context mContext; private final Lazy<GlobalActionsDialog> mGlobalActionsDialogLazy; private final KeyguardStateController mKeyguardStateController; @@ -124,7 +122,7 @@ public class GlobalActionsImpl implements GlobalActions, CommandQueue.Callbacks | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED); window.setBackgroundDrawable(background); - window.setWindowAnimations(R.style.Animation_Toast); + window.setWindowAnimations(com.android.systemui.R.style.Animation_ShutdownUi); d.setContentView(R.layout.shutdown_dialog); d.setCancelable(false); @@ -153,7 +151,9 @@ public class GlobalActionsImpl implements GlobalActions, CommandQueue.Callbacks mBlurUtils.applyBlur(d.getWindow().getDecorView().getViewRootImpl(), mBlurUtils.blurRadiusOfRatio(1)); } else { - background.setAlpha((int) (SHUTDOWN_SCRIM_ALPHA * 255)); + float backgroundAlpha = mContext.getResources().getFloat( + com.android.systemui.R.dimen.shutdown_scrim_behind_alpha); + background.setAlpha((int) (backgroundAlpha * 255)); } d.show(); diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java index 6ce5e7cf506c..af8b18482ea8 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java +++ b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java @@ -16,6 +16,9 @@ package com.android.systemui.pip; +import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; +import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; + import static com.android.systemui.pip.PipAnimationController.ANIM_TYPE_ALPHA; import static com.android.systemui.pip.PipAnimationController.ANIM_TYPE_BOUNDS; import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_NONE; @@ -26,8 +29,6 @@ import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTI import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; -import android.app.ActivityTaskManager; -import android.window.ITaskOrganizerController; import android.app.PictureInPictureParams; import android.content.Context; import android.content.pm.ActivityInfo; @@ -38,9 +39,9 @@ import android.os.Looper; import android.os.RemoteException; import android.util.Log; import android.util.Size; +import android.view.SurfaceControl; import android.window.ITaskOrganizer; import android.window.IWindowContainer; -import android.view.SurfaceControl; import android.window.WindowContainerTransaction; import android.window.WindowOrganizer; @@ -216,6 +217,29 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub { mOneShotAnimationType = animationType; } + /** + * Dismiss PiP, this is done in two phases using {@link WindowContainerTransaction} + * - setActivityWindowingMode to fullscreen at beginning of the transaction. without changing + * the windowing mode of the Task itself. This makes sure the activity render it's fullscreen + * configuration while the Task is still in PiP. + * - setWindowingMode to fullscreen at the end of transition + * @param animationDurationMs duration in millisecond for the exiting PiP transition + */ + public void dismissPip(int animationDurationMs) { + try { + final WindowContainerTransaction wct = new WindowContainerTransaction(); + wct.setActivityWindowingMode(mToken, WINDOWING_MODE_FULLSCREEN); + WindowOrganizer.applyTransaction(wct); + } catch (RemoteException e) { + Log.e(TAG, "Failed to apply container transaction", e); + } + final Rect destinationBounds = mBoundsToRestore.remove(mToken.asBinder()); + scheduleAnimateResizePip(mLastReportedBounds, destinationBounds, + TRANSITION_DIRECTION_TO_FULLSCREEN, animationDurationMs, + null /* updateBoundsCallback */); + mInPip = false; + } + @Override public void onTaskAppeared(ActivityManager.RunningTaskInfo info) { Objects.requireNonNull(info, "Requires RunningTaskInfo"); @@ -235,7 +259,8 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub { mBoundsToRestore.put(mToken.asBinder(), currentBounds); if (mOneShotAnimationType == ANIM_TYPE_BOUNDS) { scheduleAnimateResizePip(currentBounds, destinationBounds, - TRANSITION_DIRECTION_TO_PIP, mEnterExitAnimationDuration, null); + TRANSITION_DIRECTION_TO_PIP, mEnterExitAnimationDuration, + null /* updateBoundsCallback */); } else if (mOneShotAnimationType == ANIM_TYPE_ALPHA) { mUpdateHandler.post(() -> mPipAnimationController .getAnimator(mLeash, destinationBounds, 0f, 1f) @@ -249,6 +274,12 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub { } } + /** + * Note that dismissing PiP is now originated from SystemUI, see {@link #dismissPip(int)}. + * Meanwhile this callback is invoked whenever the task is removed. For instance: + * - as a result of removeStacksInWindowingModes from WM + * - activity itself is died + */ @Override public void onTaskVanished(ActivityManager.RunningTaskInfo info) { IWindowContainer token = info.token; @@ -259,7 +290,8 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub { } final Rect boundsToRestore = mBoundsToRestore.remove(token.asBinder()); scheduleAnimateResizePip(mLastReportedBounds, boundsToRestore, - TRANSITION_DIRECTION_TO_FULLSCREEN, mEnterExitAnimationDuration, null); + TRANSITION_DIRECTION_TO_FULLSCREEN, mEnterExitAnimationDuration, + null /* updateBoundsCallback */); mInPip = false; } @@ -274,7 +306,8 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub { getAspectRatioOrDefault(newParams), null /* bounds */, getMinimalSize(info.topActivityInfo)); Objects.requireNonNull(destinationBounds, "Missing destination bounds"); - scheduleAnimateResizePip(destinationBounds, mEnterExitAnimationDuration, null); + scheduleAnimateResizePip(destinationBounds, mEnterExitAnimationDuration, + null /* updateBoundsCallback */); } /** @@ -434,12 +467,19 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub { } mLastReportedBounds.set(destinationBounds); try { - // If we are animating to fullscreen, then we need to reset the override bounds on the - // task to ensure that the task "matches" the parent's bounds - Rect taskBounds = direction == TRANSITION_DIRECTION_TO_FULLSCREEN - ? null - : destinationBounds; final WindowContainerTransaction wct = new WindowContainerTransaction(); + final Rect taskBounds; + if (direction == TRANSITION_DIRECTION_TO_FULLSCREEN) { + // If we are animating to fullscreen, then we need to reset the override bounds + // on the task to ensure that the task "matches" the parent's bounds, this applies + // also to the final windowing mode, which should be reset to undefined rather than + // fullscreen. + taskBounds = null; + wct.setWindowingMode(mToken, WINDOWING_MODE_UNDEFINED) + .setActivityWindowingMode(mToken, WINDOWING_MODE_UNDEFINED); + } else { + taskBounds = destinationBounds; + } if (direction == TRANSITION_DIRECTION_TO_PIP) { wct.scheduleFinishEnterPip(mToken, taskBounds); } else { diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java index 449a2bca6abb..7974281b956f 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java @@ -219,11 +219,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, cancelAnimations(); mMenuController.hideMenuWithoutResize(); mPipTaskOrganizer.getUpdateHandler().post(() -> { - try { - mActivityTaskManager.dismissPip(!skipAnimation, EXPAND_STACK_TO_FULLSCREEN_DURATION); - } catch (RemoteException e) { - Log.e(TAG, "Error expanding PiP activity", e); - } + mPipTaskOrganizer.dismissPip(skipAnimation ? 0 : EXPAND_STACK_TO_FULLSCREEN_DURATION); }); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java index 0403a0505b00..cd737217b84a 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java +++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java @@ -142,6 +142,9 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout { @Override public void computeScroll() { if (!mScroller.isFinished() && mScroller.computeScrollOffset()) { + if (!isFakeDragging()) { + beginFakeDrag(); + } fakeDragBy(getScrollX() - mScroller.getCurrX()); // Keep on drawing until the animation has finished. postInvalidateOnAnimation(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java index 3074e33c46a8..ceefff1d14e3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java @@ -203,6 +203,7 @@ public class KeyguardBouncer { Log.wtf(TAG, "onFullyShown when view was null"); } else { mKeyguardView.onResume(); + mRoot.announceForAccessibility(mKeyguardView.getAccessibilityTitleForCurrentMode()); } } @@ -438,7 +439,6 @@ public class KeyguardBouncer { mStatusBarHeight = mRoot.getResources().getDimensionPixelOffset( com.android.systemui.R.dimen.status_bar_height); mRoot.setVisibility(View.INVISIBLE); - mRoot.setAccessibilityPaneTitle(mKeyguardView.getAccessibilityTitleForCurrentMode()); final WindowInsets rootInsets = mRoot.getRootWindowInsets(); if (rootInsets != null) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java index 496bf68e67a5..bf5900ff24bb 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java @@ -67,9 +67,9 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC private final Handler mBgHandler; protected final Context mContext; - private int mLevel; - private boolean mPluggedIn; - private boolean mCharging; + protected int mLevel; + protected boolean mPluggedIn; + protected boolean mCharging; private boolean mCharged; private boolean mPowerSave; private boolean mAodPowerSave; diff --git a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java index 11885c55b51d..442c7eaae729 100644 --- a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java +++ b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java @@ -187,8 +187,9 @@ public class StorageNotification extends SystemUI { } private void updateMissingPrivateVolumes() { - if (isTv()) { + if (isTv() || isAutomotive()) { // On TV, TvSettings displays a modal full-screen activity in this case. + // Not applicable for automotive. return; } @@ -595,6 +596,9 @@ public class StorageNotification extends SystemUI { if (isTv()) { intent.setPackage("com.android.tv.settings"); intent.setAction("com.android.tv.settings.action.NEW_STORAGE"); + } else if (isAutomotive()) { + // TODO(b/151671685): add intent to handle unsupported usb + return null; } else { intent.setClassName("com.android.settings", "com.android.settings.deviceinfo.StorageWizardInit"); @@ -611,6 +615,9 @@ public class StorageNotification extends SystemUI { if (isTv()) { intent.setPackage("com.android.tv.settings"); intent.setAction("com.android.tv.settings.action.NEW_STORAGE"); + } else if (isAutomotive()) { + // TODO(b/151671685): add intent to handle unmountable usb + return null; } else { intent.setClassName("com.android.settings", "com.android.settings.deviceinfo.StorageWizardInit"); @@ -669,6 +676,9 @@ public class StorageNotification extends SystemUI { if (isTv()) { intent.setPackage("com.android.tv.settings"); intent.setAction(Settings.ACTION_INTERNAL_STORAGE_SETTINGS); + } else if (isAutomotive()) { + // TODO(b/151671685): add volume settings intent for automotive + return null; } else { switch (vol.getType()) { case VolumeInfo.TYPE_PRIVATE: @@ -700,7 +710,7 @@ public class StorageNotification extends SystemUI { } private PendingIntent buildForgetPendingIntent(VolumeRecord rec) { - // Not used on TV + // Not used on TV and Automotive final Intent intent = new Intent(); intent.setClassName("com.android.settings", "com.android.settings.Settings$PrivateVolumeForgetActivity"); @@ -716,6 +726,9 @@ public class StorageNotification extends SystemUI { if (isTv()) { intent.setPackage("com.android.tv.settings"); intent.setAction("com.android.tv.settings.action.MIGRATE_STORAGE"); + } else if (isAutomotive()) { + // TODO(b/151671685): add storage migrate intent for automotive + return null; } else { intent.setClassName("com.android.settings", "com.android.settings.deviceinfo.StorageWizardMigrateProgress"); @@ -735,6 +748,9 @@ public class StorageNotification extends SystemUI { if (isTv()) { intent.setPackage("com.android.tv.settings"); intent.setAction("com.android.tv.settings.action.MOVE_APP"); + } else if (isAutomotive()) { + // TODO(b/151671685): add storage move intent for automotive + return null; } else { intent.setClassName("com.android.settings", "com.android.settings.deviceinfo.StorageWizardMoveProgress"); @@ -750,6 +766,9 @@ public class StorageNotification extends SystemUI { if (isTv()) { intent.setPackage("com.android.tv.settings"); intent.setAction(Settings.ACTION_INTERNAL_STORAGE_SETTINGS); + } else if (isAutomotive()) { + // TODO(b/151671685): add storage ready intent for automotive + return null; } else { intent.setClassName("com.android.settings", "com.android.settings.deviceinfo.StorageWizardReady"); diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java index 9d9ba1bc91b9..eecde7218d28 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java @@ -52,6 +52,7 @@ import android.hardware.face.FaceManager; import android.hardware.fingerprint.FingerprintManager; import android.os.Bundle; import android.os.Handler; +import android.os.IRemoteCallback; import android.os.UserHandle; import android.os.UserManager; import android.telephony.ServiceState; @@ -63,6 +64,7 @@ import android.testing.TestableContext; import android.testing.TestableLooper; import com.android.internal.telephony.TelephonyIntents; +import com.android.keyguard.KeyguardUpdateMonitor.BiometricAuthenticated; import com.android.systemui.SysuiTestCase; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dump.DumpManager; @@ -506,6 +508,24 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { } @Test + public void testBiometricsCleared_whenUserSwitches() throws Exception { + final IRemoteCallback reply = new IRemoteCallback.Stub() { + @Override + public void sendResult(Bundle data) {} // do nothing + }; + final BiometricAuthenticated dummyAuthentication = + new BiometricAuthenticated(true /* authenticated */, true /* strong */); + mKeyguardUpdateMonitor.mUserFaceAuthenticated.put(0 /* user */, dummyAuthentication); + mKeyguardUpdateMonitor.mUserFingerprintAuthenticated.put(0 /* user */, dummyAuthentication); + assertThat(mKeyguardUpdateMonitor.mUserFingerprintAuthenticated.size()).isEqualTo(1); + assertThat(mKeyguardUpdateMonitor.mUserFaceAuthenticated.size()).isEqualTo(1); + + mKeyguardUpdateMonitor.handleUserSwitching(10 /* user */, reply); + assertThat(mKeyguardUpdateMonitor.mUserFingerprintAuthenticated.size()).isEqualTo(0); + assertThat(mKeyguardUpdateMonitor.mUserFaceAuthenticated.size()).isEqualTo(0); + } + + @Test public void testGetUserCanSkipBouncer_whenTrust() { int user = KeyguardUpdateMonitor.getCurrentUser(); mKeyguardUpdateMonitor.onTrustChanged(true /* enabled */, user, 0 /* flags */); diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt index eb4d438600d8..93aee33cc1c8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt @@ -161,7 +161,7 @@ class ControlsControllerImplTest : SysuiTestCase() { verify(listingController).addCallback(capture(listingCallbackCaptor)) } - private fun builderFromInfo( + private fun statelessBuilderFromInfo( controlInfo: ControlInfo, structure: CharSequence = "" ): Control.StatelessBuilder { @@ -170,6 +170,15 @@ class ControlsControllerImplTest : SysuiTestCase() { .setSubtitle(controlInfo.controlSubtitle).setStructure(structure) } + private fun statefulBuilderFromInfo( + controlInfo: ControlInfo, + structure: CharSequence = "" + ): Control.StatefulBuilder { + return Control.StatefulBuilder(controlInfo.controlId, pendingIntent) + .setDeviceType(controlInfo.deviceType).setTitle(controlInfo.controlTitle) + .setSubtitle(controlInfo.controlSubtitle).setStructure(structure) + } + @Test fun testStartOnUser() { assertEquals(user, controller.currentUserId) @@ -236,7 +245,7 @@ class ControlsControllerImplTest : SysuiTestCase() { @Test fun testLoadForComponent_noFavorites() { var loaded = false - val control = builderFromInfo(TEST_CONTROL_INFO).build() + val control = statelessBuilderFromInfo(TEST_CONTROL_INFO).build() controller.loadForComponent(TEST_COMPONENT, Consumer { data -> val controls = data.allControls @@ -263,8 +272,8 @@ class ControlsControllerImplTest : SysuiTestCase() { @Test fun testLoadForComponent_favorites() { var loaded = false - val control = builderFromInfo(TEST_CONTROL_INFO).build() - val control2 = builderFromInfo(TEST_CONTROL_INFO_2).build() + val control = statelessBuilderFromInfo(TEST_CONTROL_INFO).build() + val control2 = statelessBuilderFromInfo(TEST_CONTROL_INFO_2).build() controller.replaceFavoritesForStructure(TEST_STRUCTURE_INFO) controller.replaceFavoritesForStructure(TEST_STRUCTURE_INFO_2) delayableExecutor.runAllReady() @@ -445,7 +454,7 @@ class ControlsControllerImplTest : SysuiTestCase() { delayableExecutor.runAllReady() val newControlInfo = TEST_CONTROL_INFO.copy(controlTitle = TEST_CONTROL_TITLE_2) - val control = builderFromInfo(newControlInfo).build() + val control = statelessBuilderFromInfo(newControlInfo).build() controller.loadForComponent(TEST_COMPONENT, Consumer {}) @@ -461,11 +470,11 @@ class ControlsControllerImplTest : SysuiTestCase() { } @Test - fun testFavoriteInformationModifiedOnRefresh() { + fun testFavoriteInformationModifiedOnRefreshWithOkStatus() { controller.replaceFavoritesForStructure(TEST_STRUCTURE_INFO) val newControlInfo = TEST_CONTROL_INFO.copy(controlTitle = TEST_CONTROL_TITLE_2) - val control = builderFromInfo(newControlInfo).build() + val control = statefulBuilderFromInfo(newControlInfo).setStatus(Control.STATUS_OK).build() controller.refreshStatus(TEST_COMPONENT, control) @@ -477,6 +486,23 @@ class ControlsControllerImplTest : SysuiTestCase() { } @Test + fun testFavoriteInformationNotModifiedOnRefreshWithNonOkStatus() { + controller.replaceFavoritesForStructure(TEST_STRUCTURE_INFO) + + val newControlInfo = TEST_CONTROL_INFO.copy(controlTitle = TEST_CONTROL_TITLE_2) + val control = statefulBuilderFromInfo(newControlInfo).setStatus(Control.STATUS_ERROR) + .build() + + controller.refreshStatus(TEST_COMPONENT, control) + + delayableExecutor.runAllReady() + + val favorites = controller.getFavorites().flatMap { it.controls } + assertEquals(1, favorites.size) + assertEquals(TEST_CONTROL_INFO, favorites[0]) + } + + @Test fun testSwitchUsers() { controller.replaceFavoritesForStructure(TEST_STRUCTURE_INFO) delayableExecutor.runAllReady() @@ -762,7 +788,8 @@ class ControlsControllerImplTest : SysuiTestCase() { @Test fun testSeedFavoritesForComponent() { var succeeded = false - val control = builderFromInfo(TEST_CONTROL_INFO, TEST_STRUCTURE_INFO.structure).build() + val control = statelessBuilderFromInfo(TEST_CONTROL_INFO, TEST_STRUCTURE_INFO.structure) + .build() controller.seedFavoritesForComponent(TEST_COMPONENT, Consumer { accepted -> succeeded = accepted @@ -803,7 +830,8 @@ class ControlsControllerImplTest : SysuiTestCase() { fun testSeedFavoritesForComponent_inProgressCallback() { var succeeded = false var seeded = false - val control = builderFromInfo(TEST_CONTROL_INFO, TEST_STRUCTURE_INFO.structure).build() + val control = statelessBuilderFromInfo(TEST_CONTROL_INFO, TEST_STRUCTURE_INFO.structure) + .build() controller.seedFavoritesForComponent(TEST_COMPONENT, Consumer { accepted -> succeeded = accepted diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java index 35971bd4037c..e052ae2653f0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java @@ -26,6 +26,7 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyZeroInteractions; @@ -56,11 +57,13 @@ import com.android.systemui.statusbar.policy.KeyguardStateController; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @SmallTest @RunWith(AndroidTestingRunner.class) @@ -91,13 +94,14 @@ public class KeyguardBouncerTest extends SysuiTestCase { private Handler mHandler; @Mock private KeyguardSecurityModel mKeyguardSecurityModel; - + @Rule + public MockitoRule mRule = MockitoJUnit.rule(); + private ViewGroup mRootView; private KeyguardBouncer mBouncer; @Before public void setup() { allowTestableLooperAsMainThread(); - MockitoAnnotations.initMocks(this); mDependency.injectTestDependency(KeyguardUpdateMonitor.class, mKeyguardUpdateMonitor); mDependency.injectTestDependency(KeyguardSecurityModel.class, mKeyguardSecurityModel); mDependency.injectMockDependency(KeyguardStateController.class); @@ -115,6 +119,8 @@ public class KeyguardBouncerTest extends SysuiTestCase { protected void inflateView() { super.inflateView(); mKeyguardView = mKeyguardHostView; + mRoot = spy(mRoot); + mRootView = mRoot; } }; } @@ -217,6 +223,7 @@ public class KeyguardBouncerTest extends SysuiTestCase { mBouncer.setExpansion(0); verify(mKeyguardHostView).onResume(); + verify(mRootView).announceForAccessibility(any()); } @Test diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java b/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java index c84892d675f9..4b2c9215f7b7 100644 --- a/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java +++ b/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java @@ -307,28 +307,22 @@ public class Tethering { userManager, this, mNotificationUpdater); mExecutor = new TetheringThreadExecutor(mHandler); mActiveDataSubIdListener = new ActiveDataSubIdListener(mExecutor); + mNetdCallback = new NetdCallback(); // Load tethering configuration. updateConfiguration(); - // NetdCallback should be registered after updateConfiguration() to ensure - // TetheringConfiguration is created. - mNetdCallback = new NetdCallback(); + } + + /** + * Start to register callbacks. + * Call this function when tethering is ready to handle callback events. + */ + public void startStateMachineUpdaters() { try { mNetd.registerUnsolicitedEventListener(mNetdCallback); } catch (RemoteException e) { mLog.e("Unable to register netd UnsolicitedEventListener"); } - - startStateMachineUpdaters(mHandler); - startTrackDefaultNetwork(); - - final WifiManager wifiManager = getWifiManager(); - if (wifiManager != null) { - wifiManager.registerSoftApCallback(mExecutor, new TetheringSoftApCallback()); - } - } - - private void startStateMachineUpdaters(Handler handler) { mCarrierConfigChange.startListening(); mContext.getSystemService(TelephonyManager.class).listen(mActiveDataSubIdListener, PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE); @@ -341,7 +335,14 @@ public class Tethering { filter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION); filter.addAction(UserManager.ACTION_USER_RESTRICTIONS_CHANGED); filter.addAction(ACTION_RESTRICT_BACKGROUND_CHANGED); - mContext.registerReceiver(mStateReceiver, filter, null, handler); + mContext.registerReceiver(mStateReceiver, filter, null, mHandler); + + final WifiManager wifiManager = getWifiManager(); + if (wifiManager != null) { + wifiManager.registerSoftApCallback(mExecutor, new TetheringSoftApCallback()); + } + + startTrackDefaultNetwork(); } private class TetheringThreadExecutor implements Executor { diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java index c5329d8d3316..c30be25dbd22 100644 --- a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java +++ b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java @@ -80,6 +80,7 @@ public class TetheringService extends Service { mContext = mDeps.getContext(); mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); mTethering = makeTethering(mDeps); + mTethering.startStateMachineUpdaters(); } /** diff --git a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java index 5ead1106d75a..a59c6fd9e193 100644 --- a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java +++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java @@ -484,6 +484,7 @@ public class TetheringTest { mServiceContext.registerReceiver(mBroadcastReceiver, new IntentFilter(ACTION_TETHER_STATE_CHANGED)); mTethering = makeTethering(); + mTethering.startStateMachineUpdaters(); verify(mStatsManager, times(1)).registerNetworkStatsProvider(anyString(), any()); verify(mNetd).registerUnsolicitedEventListener(any()); final ArgumentCaptor<PhoneStateListener> phoneListenerCaptor = diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java index 32bca35009a8..9486b0d39bc2 100644 --- a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java +++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java @@ -17,7 +17,7 @@ package com.android.server.contentcapture; import static android.service.contentcapture.ContentCaptureService.setClientState; -import static android.view.contentcapture.ContentCaptureSession.NO_SESSION_ID; +import static android.view.contentcapture.ContentCaptureManager.NO_SESSION_ID; import static android.view.contentcapture.ContentCaptureSession.STATE_DISABLED; import static android.view.contentcapture.ContentCaptureSession.STATE_DUPLICATED_ID; import static android.view.contentcapture.ContentCaptureSession.STATE_INTERNAL_ERROR; diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java index aa63e40747ee..06ab426c6698 100644 --- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java +++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java @@ -16,9 +16,9 @@ package com.android.server.contentcapture; import static android.service.contentcapture.ContentCaptureService.setClientState; +import static android.view.contentcapture.ContentCaptureManager.NO_SESSION_ID; import static android.view.contentcapture.ContentCaptureManager.RESULT_CODE_FALSE; import static android.view.contentcapture.ContentCaptureManager.RESULT_CODE_TRUE; -import static android.view.contentcapture.ContentCaptureSession.NO_SESSION_ID; import static android.view.contentcapture.ContentCaptureSession.STATE_ACTIVE; import static android.view.contentcapture.ContentCaptureSession.STATE_DISABLED; import static android.view.contentcapture.ContentCaptureSession.STATE_SERVICE_RESURRECTED; diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 76a8e1474a95..237a961fd338 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -7967,10 +7967,13 @@ public class ConnectivityService extends IConnectivityManager.Stub return false; } + final Network[] underlyingNetworks; synchronized (mVpns) { - if (getVpnIfOwner(callbackUid) != null) { - return true; - } + final Vpn vpn = getVpnIfOwner(callbackUid); + underlyingNetworks = (vpn == null) ? null : vpn.getUnderlyingNetworks(); + } + if (underlyingNetworks != null) { + if (Arrays.asList(underlyingNetworks).contains(nai.network)) return true; } // Administrator UIDs also contains the Owner UID diff --git a/services/core/java/com/android/server/PackageWatchdog.java b/services/core/java/com/android/server/PackageWatchdog.java index 41a104c5d4dc..d9e7c3851906 100644 --- a/services/core/java/com/android/server/PackageWatchdog.java +++ b/services/core/java/com/android/server/PackageWatchdog.java @@ -1062,7 +1062,12 @@ public class PackageWatchdog { public void updatePackagesLocked(List<MonitoredPackage> packages) { for (int pIndex = 0; pIndex < packages.size(); pIndex++) { MonitoredPackage p = packages.get(pIndex); - this.packages.put(p.getName(), p); + MonitoredPackage existingPackage = this.packages.get(p.getName()); + if (existingPackage != null) { + existingPackage.updateHealthCheckDuration(p.mDurationMs); + } else { + this.packages.put(p.getName(), p); + } } } @@ -1331,6 +1336,12 @@ public class PackageWatchdog { return updateHealthCheckStateLocked(); } + /** Explicitly update the monitoring duration of the package. */ + @GuardedBy("mLock") + public void updateHealthCheckDuration(long newDurationMs) { + mDurationMs = newDurationMs; + } + /** * Marks the health check as passed and transitions to {@link HealthCheckState.PASSED} * if not yet {@link HealthCheckState.FAILED}. diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java index dd9cc641f2dd..ac4a42ca7024 100644 --- a/services/core/java/com/android/server/VibratorService.java +++ b/services/core/java/com/android/server/VibratorService.java @@ -605,15 +605,16 @@ public class VibratorService extends IVibratorService.Stub } @Override // Binder call - public boolean[] areEffectsSupported(int[] effectIds) { - // Return null to indicate that the HAL doesn't actually tell us what effects are - // supported. + public int[] areEffectsSupported(int[] effectIds) { + int[] supported = new int[effectIds.length]; if (mSupportedEffects == null) { - return null; - } - boolean[] supported = new boolean[effectIds.length]; - for (int i = 0; i < effectIds.length; i++) { - supported[i] = mSupportedEffects.contains(effectIds[i]); + Arrays.fill(supported, Vibrator.VIBRATION_EFFECT_SUPPORT_UNKNOWN); + } else { + for (int i = 0; i < effectIds.length; i++) { + supported[i] = mSupportedEffects.contains(effectIds[i]) + ? Vibrator.VIBRATION_EFFECT_SUPPORT_YES + : Vibrator.VIBRATION_EFFECT_SUPPORT_NO; + } } return supported; } diff --git a/services/core/java/com/android/server/incident/PendingReports.java b/services/core/java/com/android/server/incident/PendingReports.java index 9fcbab71519d..f39bebf060f7 100644 --- a/services/core/java/com/android/server/incident/PendingReports.java +++ b/services/core/java/com/android/server/incident/PendingReports.java @@ -359,6 +359,8 @@ class PendingReports { private void sendBroadcast(ComponentName receiver, int primaryUser) { final Intent intent = new Intent(Intent.ACTION_PENDING_INCIDENT_REPORTS_CHANGED); intent.setComponent(receiver); + intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); + intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); final BroadcastOptions options = BroadcastOptions.makeBasic(); options.setBackgroundActivityStartsAllowed(true); diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java index e6129b9b1f32..0b22586bb373 100644 --- a/services/core/java/com/android/server/input/InputManagerService.java +++ b/services/core/java/com/android/server/input/InputManagerService.java @@ -76,6 +76,7 @@ import android.view.InputChannel; import android.view.InputDevice; import android.view.InputEvent; import android.view.InputMonitor; +import android.view.InputWindowHandle; import android.view.KeyEvent; import android.view.PointerIcon; import android.view.Surface; @@ -220,7 +221,8 @@ public class InputManagerService extends IInputManager.Stub int policyFlags); private static native VerifiedInputEvent nativeVerifyInputEvent(long ptr, InputEvent event); private static native void nativeToggleCapsLock(long ptr, int deviceId); - private static native void nativeDisplayRemoved(long ptr, int displayId); + private static native void nativeSetInputWindows(long ptr, InputWindowHandle[] windowHandles, + int displayId); private static native void nativeSetInputDispatchMode(long ptr, boolean enabled, boolean frozen); private static native void nativeSetSystemUiVisibility(long ptr, int visibility); private static native void nativeSetFocusedApplication(long ptr, @@ -1534,7 +1536,7 @@ public class InputManagerService extends IInputManager.Stub /** Clean up input window handles of the given display. */ public void onDisplayRemoved(int displayId) { - nativeDisplayRemoved(mPtr, displayId); + nativeSetInputWindows(mPtr, null /* windowHandles */, displayId); } @Override diff --git a/services/core/java/com/android/server/location/RemoteListenerHelper.java b/services/core/java/com/android/server/location/RemoteListenerHelper.java index 11f068533a6d..f6652892c3de 100644 --- a/services/core/java/com/android/server/location/RemoteListenerHelper.java +++ b/services/core/java/com/android/server/location/RemoteListenerHelper.java @@ -273,7 +273,7 @@ public abstract class RemoteListenerHelper<TRequest, TListener extends IInterfac } @Nullable - protected TRequest getRequest() { + public TRequest getRequest() { return mRequest; } } diff --git a/services/core/java/com/android/server/location/ExponentialBackOff.java b/services/core/java/com/android/server/location/gnss/ExponentialBackOff.java index 8c77b2176b74..05a534fa36e9 100644 --- a/services/core/java/com/android/server/location/ExponentialBackOff.java +++ b/services/core/java/com/android/server/location/gnss/ExponentialBackOff.java @@ -1,4 +1,20 @@ -package com.android.server.location; +/* + * Copyright (C) 2020 The Android Open 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.location.gnss; /** * A simple implementation of exponential backoff. diff --git a/services/core/java/com/android/server/location/GnssAntennaInfoProvider.java b/services/core/java/com/android/server/location/gnss/GnssAntennaInfoProvider.java index bc50ebc2c5c3..d839095542c7 100644 --- a/services/core/java/com/android/server/location/GnssAntennaInfoProvider.java +++ b/services/core/java/com/android/server/location/gnss/GnssAntennaInfoProvider.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server.location; +package com.android.server.location.gnss; import android.content.Context; import android.location.GnssAntennaInfo; @@ -23,6 +23,8 @@ import android.os.Handler; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; +import com.android.server.location.CallerIdentity; +import com.android.server.location.RemoteListenerHelper; import java.util.List; diff --git a/services/core/java/com/android/server/location/GnssBatchingProvider.java b/services/core/java/com/android/server/location/gnss/GnssBatchingProvider.java index f3918ee9e8ff..f583a3ed3136 100644 --- a/services/core/java/com/android/server/location/GnssBatchingProvider.java +++ b/services/core/java/com/android/server/location/gnss/GnssBatchingProvider.java @@ -1,4 +1,20 @@ -package com.android.server.location; +/* + * Copyright (C) 2020 The Android Open 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.location.gnss; import android.util.Log; diff --git a/services/core/java/com/android/server/location/GnssCapabilitiesProvider.java b/services/core/java/com/android/server/location/gnss/GnssCapabilitiesProvider.java index 5c8507f7fde0..71b5b33c242b 100644 --- a/services/core/java/com/android/server/location/GnssCapabilitiesProvider.java +++ b/services/core/java/com/android/server/location/gnss/GnssCapabilitiesProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 The Android Open Source Project + * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server.location; +package com.android.server.location.gnss; import android.location.GnssCapabilities; import android.util.Log; diff --git a/services/core/java/com/android/server/location/GnssConfiguration.java b/services/core/java/com/android/server/location/gnss/GnssConfiguration.java index a3523f23ddcf..14ab79e7ecde 100644 --- a/services/core/java/com/android/server/location/GnssConfiguration.java +++ b/services/core/java/com/android/server/location/gnss/GnssConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 The Android Open Source Project + * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server.location; +package com.android.server.location.gnss; import android.content.Context; import android.os.PersistableBundle; diff --git a/services/core/java/com/android/server/location/GnssGeofenceProvider.java b/services/core/java/com/android/server/location/gnss/GnssGeofenceProvider.java index a84b0b1c4335..53883b91c36d 100644 --- a/services/core/java/com/android/server/location/GnssGeofenceProvider.java +++ b/services/core/java/com/android/server/location/gnss/GnssGeofenceProvider.java @@ -1,4 +1,20 @@ -package com.android.server.location; +/* + * Copyright (C) 2020 The Android Open 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.location.gnss; import android.location.IGpsGeofenceHardware; import android.util.Log; diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java index c1fbcfba864a..ad3c8a61182f 100644 --- a/services/core/java/com/android/server/location/GnssLocationProvider.java +++ b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 The Android Open Source Project + * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server.location; +package com.android.server.location.gnss; import android.app.AlarmManager; import android.app.AppOpsManager; @@ -78,8 +78,9 @@ import com.android.internal.util.FrameworkStatsLog; import com.android.server.DeviceIdleInternal; import com.android.server.FgThread; import com.android.server.LocalServices; -import com.android.server.location.GnssSatelliteBlacklistHelper.GnssSatelliteBlacklistCallback; -import com.android.server.location.NtpTimeHelper.InjectNtpTimeCallback; +import com.android.server.location.AbstractLocationProvider; +import com.android.server.location.gnss.NtpTimeHelper.InjectNtpTimeCallback; +import com.android.server.location.gnss.GnssSatelliteBlacklistHelper.GnssSatelliteBlacklistCallback; import java.io.FileDescriptor; import java.io.PrintWriter; diff --git a/services/core/java/com/android/server/location/gnss/GnssManagerService.java b/services/core/java/com/android/server/location/gnss/GnssManagerService.java index b57c261931f8..9e64e3aeae59 100644 --- a/services/core/java/com/android/server/location/gnss/GnssManagerService.java +++ b/services/core/java/com/android/server/location/gnss/GnssManagerService.java @@ -55,14 +55,6 @@ import com.android.server.LocationManagerServiceUtils.LinkedListener; import com.android.server.LocationManagerServiceUtils.LinkedListenerBase; import com.android.server.location.AppForegroundHelper; import com.android.server.location.CallerIdentity; -import com.android.server.location.GnssAntennaInfoProvider; -import com.android.server.location.GnssBatchingProvider; -import com.android.server.location.GnssCapabilitiesProvider; -import com.android.server.location.GnssLocationProvider; -import com.android.server.location.GnssMeasurementCorrectionsProvider; -import com.android.server.location.GnssMeasurementsProvider; -import com.android.server.location.GnssNavigationMessageProvider; -import com.android.server.location.GnssStatusListenerHelper; import com.android.server.location.LocationUsageLogger; import com.android.server.location.RemoteListenerHelper; import com.android.server.location.SettingsHelper; diff --git a/services/core/java/com/android/server/location/GnssMeasurementCorrectionsProvider.java b/services/core/java/com/android/server/location/gnss/GnssMeasurementCorrectionsProvider.java index 82528caa0b4e..ac165d1a206b 100644 --- a/services/core/java/com/android/server/location/GnssMeasurementCorrectionsProvider.java +++ b/services/core/java/com/android/server/location/gnss/GnssMeasurementCorrectionsProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 The Android Open Source Project + * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server.location; +package com.android.server.location.gnss; import android.location.GnssMeasurementCorrections; import android.os.Handler; diff --git a/services/core/java/com/android/server/location/GnssMeasurementsProvider.java b/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java index 6ba5f079264c..76c3ad02e7e9 100644 --- a/services/core/java/com/android/server/location/GnssMeasurementsProvider.java +++ b/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 The Android Open Source Project + * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server.location; +package com.android.server.location.gnss; import android.content.Context; import android.location.GnssMeasurementsEvent; @@ -26,6 +26,8 @@ import android.provider.Settings; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; +import com.android.server.location.CallerIdentity; +import com.android.server.location.RemoteListenerHelper; /** * An base implementation for GPS measurements provider. It abstracts out the responsibility of diff --git a/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java b/services/core/java/com/android/server/location/gnss/GnssNavigationMessageProvider.java index fb901e86f494..722be3df2691 100644 --- a/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java +++ b/services/core/java/com/android/server/location/gnss/GnssNavigationMessageProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 The Android Open Source Project + * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server.location; +package com.android.server.location.gnss; import android.content.Context; import android.location.GnssNavigationMessage; @@ -24,6 +24,8 @@ import android.os.RemoteException; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; +import com.android.server.location.CallerIdentity; +import com.android.server.location.RemoteListenerHelper; /** * An base implementation for GPS navigation messages provider. diff --git a/services/core/java/com/android/server/location/GnssNetworkConnectivityHandler.java b/services/core/java/com/android/server/location/gnss/GnssNetworkConnectivityHandler.java index 5d6474bdbccc..3fb713bc01a5 100644 --- a/services/core/java/com/android/server/location/GnssNetworkConnectivityHandler.java +++ b/services/core/java/com/android/server/location/gnss/GnssNetworkConnectivityHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 The Android Open Source Project + * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server.location; +package com.android.server.location.gnss; import android.content.Context; import android.database.Cursor; diff --git a/services/core/java/com/android/server/location/GnssPositionMode.java b/services/core/java/com/android/server/location/gnss/GnssPositionMode.java index 36838fc3647f..045118afbda0 100644 --- a/services/core/java/com/android/server/location/GnssPositionMode.java +++ b/services/core/java/com/android/server/location/gnss/GnssPositionMode.java @@ -1,4 +1,20 @@ -package com.android.server.location; +/* + * Copyright (C) 2020 The Android Open 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.location.gnss; import java.util.Arrays; diff --git a/services/core/java/com/android/server/location/GnssSatelliteBlacklistHelper.java b/services/core/java/com/android/server/location/gnss/GnssSatelliteBlacklistHelper.java index eb99a851115f..dccef9b9a9c4 100644 --- a/services/core/java/com/android/server/location/GnssSatelliteBlacklistHelper.java +++ b/services/core/java/com/android/server/location/gnss/GnssSatelliteBlacklistHelper.java @@ -1,4 +1,20 @@ -package com.android.server.location; +/* + * Copyright (C) 2020 The Android Open 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.location.gnss; import android.content.ContentResolver; import android.content.Context; diff --git a/services/core/java/com/android/server/location/GnssStatusListenerHelper.java b/services/core/java/com/android/server/location/gnss/GnssStatusListenerHelper.java index 1d16c03fd6f7..d2ecdeebd9d0 100644 --- a/services/core/java/com/android/server/location/GnssStatusListenerHelper.java +++ b/services/core/java/com/android/server/location/gnss/GnssStatusListenerHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 The Android Open Source Project + * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -11,16 +11,19 @@ * 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 + * limitations under the License. */ -package com.android.server.location; +package com.android.server.location.gnss; import android.content.Context; import android.location.IGnssStatusListener; import android.os.Handler; import android.util.Log; +import com.android.server.location.CallerIdentity; +import com.android.server.location.RemoteListenerHelper; + /** * Implementation of a handler for {@link IGnssStatusListener}. */ diff --git a/services/core/java/com/android/server/location/GnssVisibilityControl.java b/services/core/java/com/android/server/location/gnss/GnssVisibilityControl.java index 2b5fc7989d8b..06fa0ea7791d 100644 --- a/services/core/java/com/android/server/location/GnssVisibilityControl.java +++ b/services/core/java/com/android/server/location/gnss/GnssVisibilityControl.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 The Android Open Source Project + * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server.location; +package com.android.server.location.gnss; import android.annotation.Nullable; import android.annotation.SuppressLint; diff --git a/services/core/java/com/android/server/location/GpsPsdsDownloader.java b/services/core/java/com/android/server/location/gnss/GpsPsdsDownloader.java index 6fcb7d1af2ce..273f9cb13a1b 100644 --- a/services/core/java/com/android/server/location/GpsPsdsDownloader.java +++ b/services/core/java/com/android/server/location/gnss/GpsPsdsDownloader.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 The Android Open Source Project + * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server.location; +package com.android.server.location.gnss; import android.net.TrafficStats; import android.text.TextUtils; diff --git a/services/core/java/com/android/server/location/NtpTimeHelper.java b/services/core/java/com/android/server/location/gnss/NtpTimeHelper.java index d2296ea27913..2bbb61fbe018 100644 --- a/services/core/java/com/android/server/location/NtpTimeHelper.java +++ b/services/core/java/com/android/server/location/gnss/NtpTimeHelper.java @@ -1,4 +1,20 @@ -package com.android.server.location; +/* + * Copyright (C) 2020 The Android Open 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.location.gnss; import android.content.Context; import android.net.ConnectivityManager; @@ -12,6 +28,7 @@ import android.util.NtpTrustedTime; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; +import com.android.server.location.gnss.ExponentialBackOff; import java.util.Date; diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java index 9bbbc3b93fd7..6aae62ea3f18 100644 --- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java +++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java @@ -708,7 +708,7 @@ class MediaRouter2ServiceImpl { } List<RoutingSessionInfo> sessionInfos = new ArrayList<>(); - for (MediaRoute2Provider provider : managerRecord.mUserRecord.mHandler.mMediaProviders) { + for (MediaRoute2Provider provider : managerRecord.mUserRecord.mHandler.mRouteProviders) { sessionInfos.addAll(provider.getSessionInfos()); } return sessionInfos; @@ -1059,7 +1059,7 @@ class MediaRouter2ServiceImpl { //TODO: Make this thread-safe. private final SystemMediaRoute2Provider mSystemProvider; - private final ArrayList<MediaRoute2Provider> mMediaProviders = + private final ArrayList<MediaRoute2Provider> mRouteProviders = new ArrayList<>(); private final List<MediaRoute2ProviderInfo> mLastProviderInfos = new ArrayList<>(); @@ -1074,7 +1074,7 @@ class MediaRouter2ServiceImpl { mServiceRef = new WeakReference<>(service); mUserRecord = userRecord; mSystemProvider = new SystemMediaRoute2Provider(service.mContext, this); - mMediaProviders.add(mSystemProvider); + mRouteProviders.add(mSystemProvider); mWatcher = new MediaRoute2ProviderWatcher(service.mContext, this, this, mUserRecord.mUserId); } @@ -1097,13 +1097,13 @@ class MediaRouter2ServiceImpl { @Override public void onAddProviderService(@NonNull MediaRoute2ProviderServiceProxy proxy) { proxy.setCallback(this); - mMediaProviders.add(proxy); + mRouteProviders.add(proxy); proxy.updateDiscoveryPreference(mUserRecord.mCompositeDiscoveryPreference); } @Override public void onRemoveProviderService(@NonNull MediaRoute2ProviderServiceProxy proxy) { - mMediaProviders.remove(proxy); + mRouteProviders.remove(proxy); } @Override @@ -1148,10 +1148,10 @@ class MediaRouter2ServiceImpl { //TODO: notify session info updates private void onProviderStateChangedOnHandler(@NonNull MediaRoute2Provider provider) { - int providerIndex = getProviderInfoIndex(provider.getUniqueId()); + int providerInfoIndex = getLastProviderInfoIndex(provider.getUniqueId()); MediaRoute2ProviderInfo providerInfo = provider.getProviderInfo(); MediaRoute2ProviderInfo prevInfo = - (providerIndex < 0) ? null : mLastProviderInfos.get(providerIndex); + (providerInfoIndex < 0) ? null : mLastProviderInfos.get(providerInfoIndex); if (Objects.equals(prevInfo, providerInfo)) return; @@ -1171,7 +1171,7 @@ class MediaRouter2ServiceImpl { this, getRouters(), new ArrayList<>(removedRoutes))); } } else { - mLastProviderInfos.set(providerIndex, providerInfo); + mLastProviderInfos.set(providerInfoIndex, providerInfo); List<MediaRoute2Info> addedRoutes = new ArrayList<>(); List<MediaRoute2Info> removedRoutes = new ArrayList<>(); List<MediaRoute2Info> changedRoutes = new ArrayList<>(); @@ -1219,7 +1219,7 @@ class MediaRouter2ServiceImpl { } } - private int getProviderInfoIndex(@NonNull String providerId) { + private int getLastProviderInfoIndex(@NonNull String providerId) { for (int i = 0; i < mLastProviderInfos.size(); i++) { MediaRoute2ProviderInfo providerInfo = mLastProviderInfos.get(i); if (TextUtils.equals(providerInfo.getUniqueId(), providerId)) { @@ -1795,13 +1795,13 @@ class MediaRouter2ServiceImpl { new RouteDiscoveryPreference.Builder(discoveryPreferences) .build(); } - for (MediaRoute2Provider provider : mMediaProviders) { + for (MediaRoute2Provider provider : mRouteProviders) { provider.updateDiscoveryPreference(mUserRecord.mCompositeDiscoveryPreference); } } private MediaRoute2Provider findProvider(@Nullable String providerId) { - for (MediaRoute2Provider provider : mMediaProviders) { + for (MediaRoute2Provider provider : mRouteProviders) { if (TextUtils.equals(provider.getUniqueId(), providerId)) { return provider; } diff --git a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java index c7d14e0afe7b..c69787d602e2 100644 --- a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java +++ b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java @@ -54,6 +54,7 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); static final String DEFAULT_ROUTE_ID = "DEFAULT_ROUTE"; + static final String DEVICE_ROUTE_ID = "DEVICE_ROUTE"; static final String SYSTEM_SESSION_ID = "SYSTEM_SESSION"; private final AudioManager mAudioManager; @@ -67,14 +68,17 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { SystemMediaRoute2Provider.class.getName()); private String mSelectedRouteId; + // For apps without MODIFYING_AUDIO_ROUTING permission. + // This should be the currently selected route. MediaRoute2Info mDefaultRoute; + MediaRoute2Info mDeviceRoute; final AudioRoutesInfo mCurAudioRoutesInfo = new AudioRoutesInfo(); final IAudioRoutesObserver.Stub mAudioRoutesObserver = new IAudioRoutesObserver.Stub() { @Override public void dispatchAudioRoutesChanged(final AudioRoutesInfo newRoutes) { mHandler.post(() -> { - updateDefaultRoute(newRoutes); + updateDeviceRoute(newRoutes); notifyProviderState(); }); } @@ -97,7 +101,7 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { newAudioRoutes = mAudioService.startWatchingRoutes(mAudioRoutesObserver); } catch (RemoteException e) { } - updateDefaultRoute(newAudioRoutes); + updateDeviceRoute(newAudioRoutes); mBtRouteProvider = BluetoothRouteProvider.getInstance(context, (routes) -> { publishProviderState(); @@ -109,7 +113,6 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { } }); updateSessionInfosIfNeeded(); - mContext.registerReceiver(new VolumeChangeReceiver(), new IntentFilter(AudioManager.VOLUME_CHANGED_ACTION)); @@ -150,7 +153,7 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { @Override public void transferToRoute(long requestId, String sessionId, String routeId) { - if (TextUtils.equals(routeId, mDefaultRoute.getId())) { + if (TextUtils.equals(routeId, mDeviceRoute.getId())) { mBtRouteProvider.transferTo(null); } else { mBtRouteProvider.transferTo(routeId); @@ -170,7 +173,11 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { // Do nothing since we don't support grouping volume yet. } - private void updateDefaultRoute(AudioRoutesInfo newRoutes) { + public MediaRoute2Info getDefaultRoute() { + return mDefaultRoute; + } + + private void updateDeviceRoute(AudioRoutesInfo newRoutes) { int name = R.string.default_audio_route_name; if (newRoutes != null) { mCurAudioRoutesInfo.mainType = newRoutes.mainType; @@ -185,8 +192,8 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { name = com.android.internal.R.string.default_audio_route_name_usb; } } - mDefaultRoute = new MediaRoute2Info.Builder( - DEFAULT_ROUTE_ID, mContext.getResources().getText(name).toString()) + mDeviceRoute = new MediaRoute2Info.Builder( + DEVICE_ROUTE_ID, mContext.getResources().getText(name).toString()) .setVolumeHandling(mAudioManager.isVolumeFixed() ? MediaRoute2Info.PLAYBACK_VOLUME_FIXED : MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE) @@ -203,7 +210,7 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { private void updateProviderState() { MediaRoute2ProviderInfo.Builder builder = new MediaRoute2ProviderInfo.Builder(); - builder.addRoute(mDefaultRoute); + builder.addRoute(mDeviceRoute); if (mBtRouteProvider != null) { for (MediaRoute2Info route : mBtRouteProvider.getAllBluetoothRoutes()) { builder.addRoute(route); @@ -228,11 +235,12 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { MediaRoute2Info selectedRoute = mBtRouteProvider.getSelectedRoute(); if (selectedRoute == null) { - selectedRoute = mDefaultRoute; + selectedRoute = mDeviceRoute; } else { - builder.addTransferableRoute(mDefaultRoute.getId()); + builder.addTransferableRoute(mDeviceRoute.getId()); } mSelectedRouteId = selectedRoute.getId(); + mDefaultRoute = new MediaRoute2Info.Builder(DEFAULT_ROUTE_ID, selectedRoute).build(); builder.addSelectedRoute(mSelectedRouteId); for (MediaRoute2Info route : mBtRouteProvider.getTransferableRoutes()) { @@ -282,8 +290,8 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, 0); if (newVolume != oldVolume) { - if (TextUtils.equals(mDefaultRoute.getId(), mSelectedRouteId)) { - mDefaultRoute = new MediaRoute2Info.Builder(mDefaultRoute) + if (TextUtils.equals(mDeviceRoute.getId(), mSelectedRouteId)) { + mDeviceRoute = new MediaRoute2Info.Builder(mDeviceRoute) .setVolume(newVolume) .build(); } else { diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 31dc09416ac8..87061e1d488c 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -107,6 +107,7 @@ import android.annotation.CallbackExecutor; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; +import android.annotation.UserIdInt; import android.annotation.WorkerThread; import android.app.ActivityManager; import android.app.ActivityManagerInternal; @@ -2842,20 +2843,18 @@ public class NotificationManagerService extends SystemService { record = mToastQueue.get(index); record.update(duration); } else { - // Limit the number of toasts that any given package except the android - // package can enqueue. Prevents DOS attacks and deals with leaks. - if (!isSystemToast) { - int count = 0; - final int N = mToastQueue.size(); - for (int i = 0; i < N; i++) { - final ToastRecord r = mToastQueue.get(i); - if (r.pkg.equals(pkg)) { - count++; - if (count >= MAX_PACKAGE_NOTIFICATIONS) { - Slog.e(TAG, "Package has already posted " + count - + " toasts. Not showing more. Package=" + pkg); - return; - } + // Limit the number of toasts that any given package can enqueue. + // Prevents DOS attacks and deals with leaks. + int count = 0; + final int N = mToastQueue.size(); + for (int i = 0; i < N; i++) { + final ToastRecord r = mToastQueue.get(i); + if (r.pkg.equals(pkg)) { + count++; + if (count >= MAX_PACKAGE_NOTIFICATIONS) { + Slog.e(TAG, "Package has already posted " + count + + " toasts. Not showing more. Package=" + pkg); + return; } } } diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index 42ed20654a2c..1248ec01e020 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -3245,8 +3245,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { new ComponentName( readStringAttribute(in, ATTR_DATALOADER_PACKAGE_NAME), readStringAttribute(in, ATTR_DATALOADER_CLASS_NAME)), - readStringAttribute(in, ATTR_DATALOADER_ARGUMENTS), - null); + readStringAttribute(in, ATTR_DATALOADER_ARGUMENTS)); } final File appIconFile = buildAppIconFile(sessionId, sessionsDir); diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 1e1256547f2c..c9736401f680 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -49,7 +49,6 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR; import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER; -import static android.view.WindowManager.LayoutParams.TYPE_DREAM; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; @@ -2091,7 +2090,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { // Window manager does the checking for this. outAppOp[0] = OP_TOAST_WINDOW; return ADD_OKAY; - case TYPE_DREAM: case TYPE_INPUT_METHOD: case TYPE_WALLPAPER: case TYPE_PRESENTATION: @@ -2230,7 +2228,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { case TYPE_STATUS_BAR: case TYPE_NAVIGATION_BAR: case TYPE_WALLPAPER: - case TYPE_DREAM: return false; default: // Hide only windows below the keyguard host window. diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java index efe2af3352c2..7eb3f01798c5 100644 --- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java +++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java @@ -31,7 +31,6 @@ import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS; import static android.view.WindowManager.LayoutParams.TYPE_DISPLAY_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER; import static android.view.WindowManager.LayoutParams.TYPE_DRAG; -import static android.view.WindowManager.LayoutParams.TYPE_DREAM; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_CONSUMER; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG; @@ -806,9 +805,6 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants { return canAddInternalSystemWindow ? 13 : 10; case TYPE_APPLICATION_OVERLAY: return 12; - case TYPE_DREAM: - // used for Dreams (screensavers with TYPE_DREAM windows) - return 14; case TYPE_INPUT_METHOD: // on-screen keyboards and other such input method user interfaces go here. return 15; diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 2f814f598a05..29f7d523e9a0 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -5201,7 +5201,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } finishLaunchTickingLocked(); if (task != null) { - task.hasBeenVisible = true; + task.setHasBeenVisible(true); } } diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index bf92542cdd63..ce885ab543bc 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -3986,35 +3986,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } } - /** - * Dismisses Pip - * @param animate True if the dismissal should be animated. - * @param animationDuration The duration of the resize animation in milliseconds or -1 if the - * default animation duration should be used. - */ - @Override - public void dismissPip(boolean animate, int animationDuration) { - enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "dismissPip()"); - final long ident = Binder.clearCallingIdentity(); - try { - synchronized (mGlobalLock) { - final ActivityStack stack = - mRootWindowContainer.getDefaultDisplay().getRootPinnedTask(); - if (stack == null) { - Slog.w(TAG, "dismissPip: pinned stack not found."); - return; - } - if (stack.getWindowingMode() != WINDOWING_MODE_PINNED) { - throw new IllegalArgumentException("Stack: " + stack - + " doesn't support animated resize."); - } - stack.dismissPip(); - } - } finally { - Binder.restoreCallingIdentity(ident); - } - } - @Override public void suppressResizeConfigChanges(boolean suppress) throws RemoteException { mAmInternal.enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "suppressResizeConfigChanges()"); diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index a90016afcc49..9fc90daaccfc 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -17,6 +17,7 @@ package com.android.server.wm; import static android.app.ActivityTaskManager.INVALID_TASK_ID; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM; import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; @@ -67,7 +68,6 @@ import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_MAGNIFI import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS; -import static android.view.WindowManager.LayoutParams.TYPE_DREAM; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; @@ -766,11 +766,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo if (mTmpInitial) { w.resetContentChanged(); } - if (w.mAttrs.type == TYPE_DREAM) { - // Don't layout windows behind a dream, so that if it does stuff like hide - // the status bar we won't get a bad transition when it goes away. - mTmpWindow = w; - } w.mLayoutNeeded = false; w.prelayout(); final boolean firstLayout = !w.isLaidOut(); @@ -824,10 +819,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo + " mContainingFrame=" + w.getContainingFrame() + " mDisplayFrame=" + w.getDisplayFrameLw()); } - } else if (w.mAttrs.type == TYPE_DREAM) { - // Don't layout windows behind a dream, so that if it does stuff like hide the - // status bar we won't get a bad transition when it goes away. - mTmpWindow = mTmpWindow2; } }; @@ -911,17 +902,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo // Take care of the window being ready to display. final boolean committed = winAnimator.commitFinishDrawingLocked(); if (isDefaultDisplay && committed) { - if (w.mAttrs.type == TYPE_DREAM) { - // HACK: When a dream is shown, it may at that point hide the lock screen. - // So we need to redo the layout to let the phone window manager make this - // happen. - pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT; - if (DEBUG_LAYOUT_REPEATS) { - surfacePlacer.debugLayoutRepeats( - "dream and commitFinishDrawingLocked true", - pendingLayoutChanges); - } - } if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) { if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "First draw done in potential wallpaper target " + w); @@ -3021,6 +3001,11 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo if (recentsStack != null) { pw.println(prefix + "recentsStack=" + recentsStack.getName()); } + final ActivityStack dreamStack = + getStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_DREAM); + if (dreamStack != null) { + pw.println(prefix + "dreamStack=" + dreamStack.getName()); + } pw.println(); mPinnedStackControllerLocked.dump(prefix, pw); @@ -3209,7 +3194,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo if (mode == UPDATE_FOCUS_PLACING_SURFACES) { performLayout(true /*initial*/, updateInputWindows); } else if (mode == UPDATE_FOCUS_REMOVING_FOCUS) { - mWmService.mRoot.performSurfacePlacement(false); + mWmService.mRoot.performSurfacePlacement(); } } @@ -3846,7 +3831,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo } // TODO: Super crazy long method that should be broken down... - void applySurfaceChangesTransaction(boolean recoveringMemory) { + void applySurfaceChangesTransaction() { final WindowSurfacePlacer surfacePlacer = mWmService.mWindowPlacerLocked; mTmpUpdateAllDrawn.clear(); @@ -5628,6 +5613,10 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo } void onDisplayChanged() { + mDisplay.getRealSize(mTmpDisplaySize); + setBounds(0, 0, mTmpDisplaySize.x, mTmpDisplaySize.y); + updateDisplayInfo(); + // The window policy is responsible for stopping activities on the default display. final int displayId = mDisplay.getDisplayId(); if (displayId != DEFAULT_DISPLAY) { @@ -5639,10 +5628,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo mOffToken = null; } } - - mDisplay.getRealSize(mTmpDisplaySize); - setBounds(0, 0, mTmpDisplaySize.x, mTmpDisplaySize.y); - updateDisplayInfo(); mWmService.requestTraversal(); } diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index f593393eecfb..367151cf0f79 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -78,7 +78,6 @@ import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST; import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS; import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER; -import static android.view.WindowManager.LayoutParams.TYPE_DREAM; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_CONSUMER; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG; @@ -850,7 +849,6 @@ public class DisplayPolicy { | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; attrs.flags &= ~WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH; break; - case TYPE_DREAM: case TYPE_WALLPAPER: // Dreams and wallpapers don't have an app window token and can thus not be // letterboxed. Hence always let them extend under the cutout. @@ -1225,13 +1223,6 @@ public class DisplayPolicy { if (DEBUG_ANIM) Slog.i(TAG, "**** STARTING EXIT"); return R.anim.app_starting_exit; } - } else if (win.getAttrs().type == TYPE_DREAM && mDreamingLockscreen - && transit == TRANSIT_ENTER) { - // Special case: we are animating in a dream, while the keyguard - // is shown. We don't want an animation on the dream, because - // we need it shown immediately with the keyguard animating away - // to reveal it. - return ANIMATION_NONE; } return ANIMATION_STYLEABLE; @@ -2528,7 +2519,7 @@ public class DisplayPolicy { if ((fl & FLAG_FORCE_NOT_FULLSCREEN) != 0) { mForceStatusBar = true; } - if (attrs.type == TYPE_DREAM) { + if (win.isDreamWindow()) { // If the lockscreen was showing when the dream started then wait // for the dream to draw before hiding the lockscreen. if (!mDreamingLockscreen diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java index 18332b9484c0..88cdd1781aee 100644 --- a/services/core/java/com/android/server/wm/InputMonitor.java +++ b/services/core/java/com/android/server/wm/InputMonitor.java @@ -62,7 +62,7 @@ final class InputMonitor { // When true, need to call updateInputWindowsLw(). private boolean mUpdateInputWindowsNeeded = true; private boolean mUpdateInputWindowsPending; - private boolean mUpdateInputWindowsImmediately; + private boolean mApplyImmediately; // Currently focused input window handle. private InputWindowHandle mFocusedInputWindowHandle; @@ -347,20 +347,14 @@ final class InputMonitor { } } - /** - * Immediately update the input transaction and merge into the passing Transaction that could be - * collected and applied later. - */ - void updateInputWindowsImmediately(SurfaceControl.Transaction t) { + void updateInputWindowsImmediately() { mHandler.removeCallbacks(mUpdateInputWindows); - mUpdateInputWindowsImmediately = true; + mApplyImmediately = true; mUpdateInputWindows.run(); - mUpdateInputWindowsImmediately = false; - t.merge(mInputTransaction); + mApplyImmediately = false; } - /** - * Called when the current input focus changes. + /* Called when the current input focus changes. * Layer assignment is assumed to be complete by the time this is called. */ public void setInputFocusLw(WindowState newWindow, boolean updateInputWindows) { @@ -471,7 +465,10 @@ final class InputMonitor { if (mAddWallpaperInputConsumerHandle) { mWallpaperInputConsumer.show(mInputTransaction, 0); } - if (!mUpdateInputWindowsImmediately) { + + if (mApplyImmediately) { + mInputTransaction.apply(); + } else { mDisplayContent.getPendingTransaction().merge(mInputTransaction); mDisplayContent.scheduleAnimation(); } diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java index 9089240fe9d1..057592c0c2fc 100644 --- a/services/core/java/com/android/server/wm/RecentsAnimation.java +++ b/services/core/java/com/android/server/wm/RecentsAnimation.java @@ -400,6 +400,12 @@ class RecentsAnimation implements RecentsAnimationCallbacks, throw e; } finally { mService.continueWindowLayout(); + // Make sure the surfaces are updated with the latest state. Sometimes the + // surface placement may be skipped if display configuration is changed (i.e. + // {@link DisplayContent#mWaitingForConfig} is true). + if (mWindowManager.mRoot.isLayoutNeeded()) { + mWindowManager.mRoot.performSurfacePlacement(); + } Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); } }); diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index 6eb988bf39b9..76c16d40bf2c 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -36,7 +36,6 @@ import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.INVALID_DISPLAY; import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE; -import static android.view.WindowManager.LayoutParams.TYPE_DREAM; import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG; import static android.view.WindowManager.TRANSIT_CRASHING_ACTIVITY_CLOSE; import static android.view.WindowManager.TRANSIT_SHOW_SINGLE_TASK_DISPLAY; @@ -796,10 +795,10 @@ class RootWindowContainer extends WindowContainer<DisplayContent> return leakedSurface || killedApps; } - void performSurfacePlacement(boolean recoveringMemory) { + void performSurfacePlacement() { Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "performSurfacePlacement"); try { - performSurfacePlacementNoTrace(recoveringMemory); + performSurfacePlacementNoTrace(); } finally { Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); } @@ -807,7 +806,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> // "Something has changed! Let's make it correct now." // TODO: Super crazy long method that should be broken down... - void performSurfacePlacementNoTrace(boolean recoveringMemory) { + void performSurfacePlacementNoTrace() { if (DEBUG_WINDOW_TRACE) Slog.v(TAG, "performSurfacePlacementInner: entry. Called by " + Debug.getCallers(3)); @@ -842,7 +841,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "applySurfaceChanges"); mWmService.openSurfaceTransaction(); try { - applySurfaceChangesTransaction(recoveringMemory); + applySurfaceChangesTransaction(); } catch (RuntimeException e) { Slog.wtf(TAG, "Unhandled exception in Window Manager", e); } finally { @@ -1042,7 +1041,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> } } - private void applySurfaceChangesTransaction(boolean recoveringMemory) { + private void applySurfaceChangesTransaction() { mHoldScreenWindow = null; mObscuringWindow = null; @@ -1065,7 +1064,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> final int count = mChildren.size(); for (int j = 0; j < count; ++j) { final DisplayContent dc = mChildren.get(j); - dc.applySurfaceChangesTransaction(recoveringMemory); + dc.applySurfaceChangesTransaction(); } // Give the display manager a chance to adjust properties like display rotation if it needs @@ -1138,7 +1137,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> // While a dream or keyguard is showing, obscure ordinary application content on // secondary displays (by forcibly enabling mirroring unless there is other content // we want to show) but still allow opaque keyguard dialogs to be shown. - if (type == TYPE_DREAM || mWmService.mPolicy.isKeyguardShowing()) { + if (w.isDreamWindow() || mWmService.mPolicy.isKeyguardShowing()) { mObscureApplicationContentOnSecondaryDisplays = true; } displayHasContent = true; @@ -2289,6 +2288,9 @@ class RootWindowContainer extends WindowContainer<DisplayContent> TRANSIT_SHOW_SINGLE_TASK_DISPLAY, false); } stack.awakeFromSleepingLocked(); + if (display.isSingleTaskInstance()) { + display.executeAppTransition(); + } if (stack.isFocusedStackOnDisplay() && !mStackSupervisor.getKeyguardController() .isKeyguardOrAodShowing(display.mDisplayId)) { diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 7a41ea57610d..91b4ec95f8fd 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -258,7 +258,7 @@ class Task extends WindowContainer<WindowContainer> { boolean autoRemoveRecents; // If true, we should automatically remove the task from // recents when activity finishes boolean askedCompatMode;// Have asked the user about compat mode for this task. - boolean hasBeenVisible; // Set if any activities in the task have been visible to the user. + private boolean mHasBeenVisible; // Set if any activities in the task have been visible String stringName; // caching of toString() result. boolean mUserSetupComplete; // The user set-up is complete as of the last time the task activity @@ -483,6 +483,10 @@ class Task extends WindowContainer<WindowContainer> { */ ITaskOrganizer mTaskOrganizer; private int mLastTaskOrganizerWindowingMode = -1; + /** + * Prevent duplicate calls to onTaskAppeared. + */ + boolean mTaskAppearedSent; /** * Last Picture-in-Picture params applicable to the task. Updated when the app @@ -1517,7 +1521,7 @@ class Task extends WindowContainer<WindowContainer> { // We will automatically remove the task either if it has explicitly asked for // this, or it is empty and has never contained an activity that got shown to // the user. - return autoRemoveRecents || (!hasChild() && !hasBeenVisible); + return autoRemoveRecents || (!hasChild() && !getHasBeenVisible()); } /** @@ -2030,7 +2034,7 @@ class Task extends WindowContainer<WindowContainer> { } private void saveLaunchingStateIfNeeded(DisplayContent display) { - if (!hasBeenVisible) { + if (!getHasBeenVisible()) { // Not ever visible to user. return; } @@ -3558,7 +3562,7 @@ class Task extends WindowContainer<WindowContainer> { pw.print(prefix); pw.print("mRootProcess="); pw.println(mRootProcess); } pw.print(prefix); pw.print("taskId=" + mTaskId); pw.println(" stackId=" + getRootTaskId()); - pw.print(prefix + "hasBeenVisible=" + hasBeenVisible); + pw.print(prefix + "mHasBeenVisible=" + getHasBeenVisible()); pw.print(" mResizeMode=" + ActivityInfo.resizeModeToString(mResizeMode)); pw.print(" mSupportsPictureInPicture=" + mSupportsPictureInPicture); pw.print(" isResizeable=" + isResizeable()); @@ -4087,14 +4091,42 @@ class Task extends WindowContainer<WindowContainer> { super.reparentSurfaceControl(t, newParent); } + void setHasBeenVisible(boolean hasBeenVisible) { + mHasBeenVisible = hasBeenVisible; + if (hasBeenVisible) { + sendTaskAppeared(); + if (!isRootTask()) { + getRootTask().setHasBeenVisible(true); + } + } + } + + boolean getHasBeenVisible() { + return mHasBeenVisible; + } + + /** In the case that these three conditions are true, we want to send the Task to + * the organizer: + * 1. We have a SurfaceControl + * 2. An organizer has been set + * 3. We have finished drawing + * Any time any of these conditions are updated, the updating code should call + * sendTaskAppeared. + */ + private boolean taskAppearedReady() { + return mSurfaceControl != null && mTaskOrganizer != null && getHasBeenVisible(); + } + private void sendTaskAppeared() { - if (mSurfaceControl != null && mTaskOrganizer != null) { + if (taskAppearedReady() && !mTaskAppearedSent) { + mTaskAppearedSent = true; mAtmService.mTaskOrganizerController.onTaskAppeared(mTaskOrganizer, this); } } private void sendTaskVanished() { - if (mTaskOrganizer != null) { + if (mTaskOrganizer != null && mTaskAppearedSent) { + mTaskAppearedSent = false; mAtmService.mTaskOrganizerController.onTaskVanished(mTaskOrganizer, this); } } @@ -4113,6 +4145,7 @@ class Task extends WindowContainer<WindowContainer> { void taskOrganizerUnregistered() { mTaskOrganizer = null; + mTaskAppearedSent = false; mLastTaskOrganizerWindowingMode = -1; onTaskOrganizerChanged(); if (mCreatedByOrganizer) { diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java index be0d6f8a0b9f..f046e8adc478 100644 --- a/services/core/java/com/android/server/wm/TaskPositioner.java +++ b/services/core/java/com/android/server/wm/TaskPositioner.java @@ -268,9 +268,8 @@ class TaskPositioner implements IBinder.DeathRecipient { mDisplayContent.getDisplayRotation().pause(); // Notify InputMonitor to take mDragWindowHandle. - final SurfaceControl.Transaction t = mService.mTransactionFactory.get(); - mDisplayContent.getInputMonitor().updateInputWindowsImmediately(t); - t.syncInputWindows().apply(); + mDisplayContent.getInputMonitor().updateInputWindowsImmediately(); + new SurfaceControl.Transaction().syncInputWindows().apply(true); final DisplayMetrics displayMetrics = displayContent.getDisplayMetrics(); mMinVisibleWidth = dipToPixel(MINIMUM_VISIBLE_WIDTH_IN_DP, displayMetrics); diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 075772566d56..b1f22f8623d6 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -58,7 +58,6 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CO import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; -import static android.view.WindowManager.LayoutParams.TYPE_DREAM; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; @@ -1482,12 +1481,6 @@ public class WindowManagerService extends IWindowManager.Stub + "%s. Aborting.", attrs.token); return WindowManagerGlobal.ADD_BAD_APP_TOKEN; } - } else if (rootType == TYPE_DREAM) { - if (token.windowType != TYPE_DREAM) { - ProtoLog.w(WM_ERROR, "Attempted to add Dream window with bad token " - + "%s. Aborting.", attrs.token); - return WindowManagerGlobal.ADD_BAD_APP_TOKEN; - } } else if (rootType == TYPE_ACCESSIBILITY_OVERLAY) { if (token.windowType != TYPE_ACCESSIBILITY_OVERLAY) { ProtoLog.w(WM_ERROR, @@ -1723,11 +1716,6 @@ public class WindowManagerService extends IWindowManager.Stub + "%s. Aborting.", tokenForLog); return false; } - if (rootType == TYPE_DREAM) { - ProtoLog.w(WM_ERROR, "Attempted to add Dream window with unknown token " - + "%s. Aborting.", tokenForLog); - return false; - } if (rootType == TYPE_QS_DIALOG) { ProtoLog.w(WM_ERROR, "Attempted to add QS dialog window with unknown token " + "%s. Aborting.", tokenForLog); @@ -7746,23 +7734,19 @@ public class WindowManagerService extends IWindowManager.Stub public void syncInputTransactions() { waitForAnimationsToComplete(); - // Collect all input transactions from all displays to make sure we could sync all input - // windows at same time. - final SurfaceControl.Transaction t = mTransactionFactory.get(); synchronized (mGlobalLock) { mWindowPlacerLocked.performSurfacePlacementIfScheduled(); mRoot.forAllDisplays(displayContent -> - displayContent.getInputMonitor().updateInputWindowsImmediately(t)); + displayContent.getInputMonitor().updateInputWindowsImmediately()); } - t.syncInputWindows().apply(); + mTransactionFactory.get().syncInputWindows().apply(true); } private void waitForAnimationsToComplete() { synchronized (mGlobalLock) { long timeoutRemaining = ANIMATION_COMPLETED_TIMEOUT_MS; - while ((mAnimator.isAnimationScheduled() - || mRoot.isAnimating(TRANSITION | CHILDREN)) && timeoutRemaining > 0) { + while (mRoot.isAnimating(TRANSITION | CHILDREN) && timeoutRemaining > 0) { long startTime = System.currentTimeMillis(); try { mGlobalLock.wait(timeoutRemaining); diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index c4d700c9aca3..b4487409c74e 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -20,6 +20,7 @@ import static android.app.ActivityTaskManager.INVALID_TASK_ID; import static android.app.AppOpsManager.MODE_ALLOWED; import static android.app.AppOpsManager.MODE_DEFAULT; import static android.app.AppOpsManager.OP_NONE; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM; import static android.app.WindowConfiguration.isSplitScreenWindowingMode; import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; import static android.os.PowerManager.DRAW_WAKE_LOCK; @@ -1694,6 +1695,11 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP return !isParentWindowHidden() || isAnimating(TRANSITION | PARENTS); } + boolean isDreamWindow() { + return mActivityRecord != null + && mActivityRecord.getActivityType() == ACTIVITY_TYPE_DREAM; + } + /** * Whether this window's drawn state might affect the drawn states of the app token. * diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java index 0cfdebc6792d..6b9fbcbf459f 100644 --- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java +++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java @@ -157,9 +157,7 @@ class WindowSurfacePlacer { mInLayout = true; - boolean recoveringMemory = false; if (!mService.mForceRemoves.isEmpty()) { - recoveringMemory = true; // Wait a little bit for things to settle down, and off we go. while (!mService.mForceRemoves.isEmpty()) { final WindowState ws = mService.mForceRemoves.remove(0); @@ -177,7 +175,7 @@ class WindowSurfacePlacer { } try { - mService.mRoot.performSurfacePlacement(recoveringMemory); + mService.mRoot.performSurfacePlacement(); mInLayout = false; diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp index 9bc5d34c11af..e3f9ae8969b3 100644 --- a/services/core/jni/com_android_server_input_InputManagerService.cpp +++ b/services/core/jni/com_android_server_input_InputManagerService.cpp @@ -206,7 +206,7 @@ public: status_t unregisterInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel); status_t pilferPointers(const sp<IBinder>& token); - void displayRemoved(JNIEnv* env, int32_t displayId); + void setInputWindows(JNIEnv* env, jobjectArray windowHandleObjArray, int32_t displayId); void setFocusedApplication(JNIEnv* env, int32_t displayId, jobject applicationHandleObj); void setFocusedDisplay(JNIEnv* env, int32_t displayId); void setInputDispatchMode(bool enabled, bool frozen); @@ -771,10 +771,55 @@ void NativeInputManager::getDispatcherConfiguration(InputDispatcherConfiguration } } -void NativeInputManager::displayRemoved(JNIEnv* env, int32_t displayId) { - // Set an empty list to remove all handles from the specific display. - std::vector<sp<InputWindowHandle>> windowHandles; - mInputManager->getDispatcher()->setInputWindows({{displayId, windowHandles}}); +void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowHandleObjArray, + int32_t displayId) { + std::vector<sp<InputWindowHandle> > windowHandles; + + if (windowHandleObjArray) { + jsize length = env->GetArrayLength(windowHandleObjArray); + for (jsize i = 0; i < length; i++) { + jobject windowHandleObj = env->GetObjectArrayElement(windowHandleObjArray, i); + if (! windowHandleObj) { + break; // found null element indicating end of used portion of the array + } + + sp<InputWindowHandle> windowHandle = + android_view_InputWindowHandle_getHandle(env, windowHandleObj); + if (windowHandle != nullptr) { + windowHandles.push_back(windowHandle); + } + env->DeleteLocalRef(windowHandleObj); + } + } + + mInputManager->getDispatcher()->setInputWindows(windowHandles, displayId); + + // Do this after the dispatcher has updated the window handle state. + bool newPointerGesturesEnabled = true; + size_t numWindows = windowHandles.size(); + for (size_t i = 0; i < numWindows; i++) { + const sp<InputWindowHandle>& windowHandle = windowHandles[i]; + const InputWindowInfo* windowInfo = windowHandle->getInfo(); + if (windowInfo && windowInfo->hasFocus && (windowInfo->inputFeatures + & InputWindowInfo::INPUT_FEATURE_DISABLE_TOUCH_PAD_GESTURES)) { + newPointerGesturesEnabled = false; + } + } + + bool pointerGesturesEnabledChanged = false; + { // acquire lock + AutoMutex _l(mLock); + + if (mLocked.pointerGesturesEnabled != newPointerGesturesEnabled) { + mLocked.pointerGesturesEnabled = newPointerGesturesEnabled; + pointerGesturesEnabledChanged = true; + } + } // release lock + + if (pointerGesturesEnabledChanged) { + mInputManager->getReader()->requestRefreshConfiguration( + InputReaderConfiguration::CHANGE_POINTER_GESTURE_ENABLEMENT); + } } void NativeInputManager::setFocusedApplication(JNIEnv* env, int32_t displayId, @@ -1522,10 +1567,11 @@ static void nativeToggleCapsLock(JNIEnv* env, jclass /* clazz */, im->getInputManager()->getReader()->toggleCapsLockState(deviceId); } -static void nativeDisplayRemoved(JNIEnv* env, jclass /* clazz */, jlong ptr, jint displayId) { +static void nativeSetInputWindows(JNIEnv* env, jclass /* clazz */, + jlong ptr, jobjectArray windowHandleObjArray, jint displayId) { NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); - im->displayRemoved(env, displayId); + im->setInputWindows(env, windowHandleObjArray, displayId); } static void nativeSetFocusedApplication(JNIEnv* env, jclass /* clazz */, @@ -1769,7 +1815,8 @@ static const JNINativeMethod gInputManagerMethods[] = { {"nativeVerifyInputEvent", "(JLandroid/view/InputEvent;)Landroid/view/VerifiedInputEvent;", (void*)nativeVerifyInputEvent}, {"nativeToggleCapsLock", "(JI)V", (void*)nativeToggleCapsLock}, - {"nativeDisplayRemoved", "(JI)V", (void*)nativeDisplayRemoved}, + {"nativeSetInputWindows", "(J[Landroid/view/InputWindowHandle;I)V", + (void*)nativeSetInputWindows}, {"nativeSetFocusedApplication", "(JILandroid/view/InputApplicationHandle;)V", (void*)nativeSetFocusedApplication}, {"nativeSetFocusedDisplay", "(JI)V", (void*)nativeSetFocusedDisplay}, diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp index 822f3835cc07..e4061b4fc34c 100644 --- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp +++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp @@ -2068,8 +2068,8 @@ static void android_location_GnssLocationProvider_class_init_native(JNIEnv* env, class_gnssClock = (jclass) env->NewGlobalRef(gnssClockClass); method_gnssClockCtor = env->GetMethodID(class_gnssClock, "<init>", "()V"); - jclass gnssConfiguration_halInterfaceVersionClass = - env->FindClass("com/android/server/location/GnssConfiguration$HalInterfaceVersion"); + jclass gnssConfiguration_halInterfaceVersionClass = env->FindClass( + "com/android/server/location/gnss/GnssConfiguration$HalInterfaceVersion"); class_gnssConfiguration_halInterfaceVersion = (jclass) env->NewGlobalRef(gnssConfiguration_halInterfaceVersionClass); method_halInterfaceVersionCtor = @@ -3738,39 +3738,29 @@ static const JNINativeMethod sNetworkConnectivityMethods[] = { }; static const JNINativeMethod sConfigurationMethods[] = { - /* name, signature, funcPtr */ - {"native_get_gnss_configuration_version", - "()Lcom/android/server/location/GnssConfiguration$HalInterfaceVersion;", - reinterpret_cast<void *>( - android_location_GnssConfiguration_get_gnss_configuration_version)}, - {"native_set_supl_es", - "(I)Z", - reinterpret_cast<void *>(android_location_GnssConfiguration_set_supl_es)}, - {"native_set_supl_version", - "(I)Z", - reinterpret_cast<void *>(android_location_GnssConfiguration_set_supl_version)}, - {"native_set_supl_mode", - "(I)Z", - reinterpret_cast<void *>(android_location_GnssConfiguration_set_supl_mode)}, - {"native_set_lpp_profile", - "(I)Z", - reinterpret_cast<void *>(android_location_GnssConfiguration_set_lpp_profile)}, - {"native_set_gnss_pos_protocol_select", - "(I)Z", - reinterpret_cast<void *>( - android_location_GnssConfiguration_set_gnss_pos_protocol_select)}, - {"native_set_gps_lock", - "(I)Z", - reinterpret_cast<void *>(android_location_GnssConfiguration_set_gps_lock)}, - {"native_set_emergency_supl_pdn", - "(I)Z", - reinterpret_cast<void *>(android_location_GnssConfiguration_set_emergency_supl_pdn)}, - {"native_set_satellite_blacklist", - "([I[I)Z", - reinterpret_cast<void *>(android_location_GnssConfiguration_set_satellite_blacklist)}, - {"native_set_es_extension_sec", - "(I)Z", - reinterpret_cast<void *>(android_location_GnssConfiguration_set_es_extension_sec)}, + /* name, signature, funcPtr */ + {"native_get_gnss_configuration_version", + "()Lcom/android/server/location/gnss/GnssConfiguration$HalInterfaceVersion;", + reinterpret_cast<void*>( + android_location_GnssConfiguration_get_gnss_configuration_version)}, + {"native_set_supl_es", "(I)Z", + reinterpret_cast<void*>(android_location_GnssConfiguration_set_supl_es)}, + {"native_set_supl_version", "(I)Z", + reinterpret_cast<void*>(android_location_GnssConfiguration_set_supl_version)}, + {"native_set_supl_mode", "(I)Z", + reinterpret_cast<void*>(android_location_GnssConfiguration_set_supl_mode)}, + {"native_set_lpp_profile", "(I)Z", + reinterpret_cast<void*>(android_location_GnssConfiguration_set_lpp_profile)}, + {"native_set_gnss_pos_protocol_select", "(I)Z", + reinterpret_cast<void*>(android_location_GnssConfiguration_set_gnss_pos_protocol_select)}, + {"native_set_gps_lock", "(I)Z", + reinterpret_cast<void*>(android_location_GnssConfiguration_set_gps_lock)}, + {"native_set_emergency_supl_pdn", "(I)Z", + reinterpret_cast<void*>(android_location_GnssConfiguration_set_emergency_supl_pdn)}, + {"native_set_satellite_blacklist", "([I[I)Z", + reinterpret_cast<void*>(android_location_GnssConfiguration_set_satellite_blacklist)}, + {"native_set_es_extension_sec", "(I)Z", + reinterpret_cast<void*>(android_location_GnssConfiguration_set_es_extension_sec)}, }; static const JNINativeMethod sVisibilityControlMethods[] = { @@ -3782,53 +3772,27 @@ static const JNINativeMethod sVisibilityControlMethods[] = { }; int register_android_server_location_GnssLocationProvider(JNIEnv* env) { - jniRegisterNativeMethods(env, "com/android/server/location/GnssAntennaInfoProvider", + jniRegisterNativeMethods(env, "com/android/server/location/gnss/GnssAntennaInfoProvider", sAntennaInfoMethods, NELEM(sAntennaInfoMethods)); - jniRegisterNativeMethods( - env, - "com/android/server/location/GnssBatchingProvider", - sMethodsBatching, - NELEM(sMethodsBatching)); - jniRegisterNativeMethods( - env, - "com/android/server/location/GnssGeofenceProvider", - sGeofenceMethods, - NELEM(sGeofenceMethods)); - jniRegisterNativeMethods( - env, - "com/android/server/location/GnssMeasurementsProvider", - sMeasurementMethods, - NELEM(sMeasurementMethods)); - jniRegisterNativeMethods( - env, - "com/android/server/location/GnssMeasurementCorrectionsProvider", - sMeasurementCorrectionsMethods, - NELEM(sMeasurementCorrectionsMethods)); - jniRegisterNativeMethods( - env, - "com/android/server/location/GnssNavigationMessageProvider", - sNavigationMessageMethods, - NELEM(sNavigationMessageMethods)); - jniRegisterNativeMethods( - env, - "com/android/server/location/GnssNetworkConnectivityHandler", - sNetworkConnectivityMethods, - NELEM(sNetworkConnectivityMethods)); - jniRegisterNativeMethods( - env, - "com/android/server/location/GnssConfiguration", - sConfigurationMethods, - NELEM(sConfigurationMethods)); - jniRegisterNativeMethods( - env, - "com/android/server/location/GnssVisibilityControl", - sVisibilityControlMethods, - NELEM(sVisibilityControlMethods)); - return jniRegisterNativeMethods( - env, - "com/android/server/location/GnssLocationProvider", - sMethods, - NELEM(sMethods)); + jniRegisterNativeMethods(env, "com/android/server/location/gnss/GnssBatchingProvider", + sMethodsBatching, NELEM(sMethodsBatching)); + jniRegisterNativeMethods(env, "com/android/server/location/gnss/GnssGeofenceProvider", + sGeofenceMethods, NELEM(sGeofenceMethods)); + jniRegisterNativeMethods(env, "com/android/server/location/gnss/GnssMeasurementsProvider", + sMeasurementMethods, NELEM(sMeasurementMethods)); + jniRegisterNativeMethods(env, + "com/android/server/location/gnss/GnssMeasurementCorrectionsProvider", + sMeasurementCorrectionsMethods, NELEM(sMeasurementCorrectionsMethods)); + jniRegisterNativeMethods(env, "com/android/server/location/gnss/GnssNavigationMessageProvider", + sNavigationMessageMethods, NELEM(sNavigationMessageMethods)); + jniRegisterNativeMethods(env, "com/android/server/location/gnss/GnssNetworkConnectivityHandler", + sNetworkConnectivityMethods, NELEM(sNetworkConnectivityMethods)); + jniRegisterNativeMethods(env, "com/android/server/location/gnss/GnssConfiguration", + sConfigurationMethods, NELEM(sConfigurationMethods)); + jniRegisterNativeMethods(env, "com/android/server/location/gnss/GnssVisibilityControl", + sVisibilityControlMethods, NELEM(sVisibilityControlMethods)); + return jniRegisterNativeMethods(env, "com/android/server/location/gnss/GnssLocationProvider", + sMethods, NELEM(sMethods)); } } /* namespace android */ diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index e304bca4553c..b0eb14852251 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -9184,8 +9184,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return true; } - Log.w(LOG_TAG, String.format("Package %s (uid=%d, pid=%d) cannot access Device IDs", - packageName, uid, pid)); return false; } @@ -15742,9 +15740,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } + final int suspendedState = suspended + ? PERSONAL_APPS_SUSPENDED_EXPLICITLY + : PERSONAL_APPS_NOT_SUSPENDED; mInjector.binderWithCleanCallingIdentity( - () -> applyPersonalAppsSuspension( - callingUserId, PERSONAL_APPS_SUSPENDED_EXPLICITLY)); + () -> applyPersonalAppsSuspension(callingUserId, suspendedState)); DevicePolicyEventLogger .createEvent(DevicePolicyEnums.SET_PERSONAL_APPS_SUSPENDED) diff --git a/services/incremental/IncrementalService.cpp b/services/incremental/IncrementalService.cpp index ed85b931c08e..ae27c7aabdda 100644 --- a/services/incremental/IncrementalService.cpp +++ b/services/incremental/IncrementalService.cpp @@ -286,7 +286,6 @@ void IncrementalService::onDump(int fd) { dprintf(fd, "\t\t\tpackageName: %s\n", params.packageName.c_str()); dprintf(fd, "\t\t\tclassName: %s\n", params.className.c_str()); dprintf(fd, "\t\t\targuments: %s\n", params.arguments.c_str()); - dprintf(fd, "\t\t\tdynamicArgs: %d\n", int(params.dynamicArgs.size())); } dprintf(fd, "\t\tstorages (%d):\n", int(mnt.storages.size())); for (auto&& [storageId, storage] : mnt.storages) { diff --git a/services/robotests/src/com/android/server/location/GnssAntennaInfoProviderTest.java b/services/robotests/src/com/android/server/location/gnss/GnssAntennaInfoProviderTest.java index 76f7ad646bb1..d8acd6ea6948 100644 --- a/services/robotests/src/com/android/server/location/GnssAntennaInfoProviderTest.java +++ b/services/robotests/src/com/android/server/location/gnss/GnssAntennaInfoProviderTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server.location; +package com.android.server.location.gnss; import static com.google.common.truth.Truth.assertThat; @@ -41,7 +41,8 @@ import org.robolectric.RuntimeEnvironment; @Presubmit public class GnssAntennaInfoProviderTest { @Mock - private GnssAntennaInfoProvider.GnssAntennaInfoProviderNative mMockNative; + private GnssAntennaInfoProvider.GnssAntennaInfoProviderNative + mMockNative; private GnssAntennaInfoProvider mTestProvider; /** Setup. */ diff --git a/services/robotests/src/com/android/server/location/GnssBatchingProviderTest.java b/services/robotests/src/com/android/server/location/gnss/GnssBatchingProviderTest.java index d58c3f73b8e8..25d6aa4dae29 100644 --- a/services/robotests/src/com/android/server/location/GnssBatchingProviderTest.java +++ b/services/robotests/src/com/android/server/location/gnss/GnssBatchingProviderTest.java @@ -1,4 +1,20 @@ -package com.android.server.location; +/* + * Copyright (C) 2020 The Android Open 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.location.gnss; import static com.google.common.truth.Truth.assertThat; @@ -11,7 +27,7 @@ import static org.mockito.Mockito.when; import android.platform.test.annotations.Presubmit; -import com.android.server.location.GnssBatchingProvider.GnssBatchingProviderNative; +import com.android.server.location.gnss.GnssBatchingProvider.GnssBatchingProviderNative; import org.junit.Before; import org.junit.Test; diff --git a/services/robotests/src/com/android/server/location/GnssGeofenceProviderTest.java b/services/robotests/src/com/android/server/location/gnss/GnssGeofenceProviderTest.java index 30c73368da15..4a533aac01db 100644 --- a/services/robotests/src/com/android/server/location/GnssGeofenceProviderTest.java +++ b/services/robotests/src/com/android/server/location/gnss/GnssGeofenceProviderTest.java @@ -1,4 +1,20 @@ -package com.android.server.location; +/* + * Copyright (C) 2020 The Android Open 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.location.gnss; import static org.mockito.ArgumentMatchers.anyDouble; import static org.mockito.ArgumentMatchers.anyInt; diff --git a/services/robotests/src/com/android/server/location/GnssMeasurementsProviderTest.java b/services/robotests/src/com/android/server/location/gnss/GnssMeasurementsProviderTest.java index b349b67dab0c..e7d9ef810e51 100644 --- a/services/robotests/src/com/android/server/location/GnssMeasurementsProviderTest.java +++ b/services/robotests/src/com/android/server/location/gnss/GnssMeasurementsProviderTest.java @@ -1,4 +1,20 @@ -package com.android.server.location; +/* + * Copyright (C) 2020 The Android Open 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.location.gnss; import static com.google.common.truth.Truth.assertThat; @@ -26,7 +42,8 @@ import org.robolectric.RuntimeEnvironment; @Presubmit public class GnssMeasurementsProviderTest { @Mock - private GnssMeasurementsProvider.GnssMeasurementProviderNative mMockNative; + private GnssMeasurementsProvider.GnssMeasurementProviderNative + mMockNative; private GnssMeasurementsProvider mTestProvider; @Before diff --git a/services/robotests/src/com/android/server/location/GnssNavigationMessageProviderTest.java b/services/robotests/src/com/android/server/location/gnss/GnssNavigationMessageProviderTest.java index aa2a96e6fad4..c21db73fb56c 100644 --- a/services/robotests/src/com/android/server/location/GnssNavigationMessageProviderTest.java +++ b/services/robotests/src/com/android/server/location/gnss/GnssNavigationMessageProviderTest.java @@ -1,4 +1,20 @@ -package com.android.server.location; +/* + * Copyright (C) 2020 The Android Open 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.location.gnss; import static com.google.common.truth.Truth.assertThat; @@ -25,7 +41,8 @@ import org.robolectric.RuntimeEnvironment; @Presubmit public class GnssNavigationMessageProviderTest { @Mock - private GnssNavigationMessageProvider.GnssNavigationMessageProviderNative mMockNative; + private GnssNavigationMessageProvider.GnssNavigationMessageProviderNative + mMockNative; private GnssNavigationMessageProvider mTestProvider; @Before diff --git a/services/robotests/src/com/android/server/location/GnssPositionModeTest.java b/services/robotests/src/com/android/server/location/gnss/GnssPositionModeTest.java index f37f50e76ae5..7117ff95b401 100644 --- a/services/robotests/src/com/android/server/location/GnssPositionModeTest.java +++ b/services/robotests/src/com/android/server/location/gnss/GnssPositionModeTest.java @@ -1,4 +1,20 @@ -package com.android.server.location; +/* + * Copyright (C) 2020 The Android Open 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.location.gnss; import static com.google.common.truth.Truth.assertThat; diff --git a/services/robotests/src/com/android/server/location/GnssSatelliteBlacklistHelperTest.java b/services/robotests/src/com/android/server/location/gnss/GnssSatelliteBlacklistHelperTest.java index ba4a753e4813..7c73a2f92f71 100644 --- a/services/robotests/src/com/android/server/location/GnssSatelliteBlacklistHelperTest.java +++ b/services/robotests/src/com/android/server/location/gnss/GnssSatelliteBlacklistHelperTest.java @@ -1,4 +1,20 @@ -package com.android.server.location; +/* + * Copyright (C) 2020 The Android Open 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.location.gnss; import static com.google.common.truth.Truth.assertThat; @@ -35,7 +51,8 @@ public class GnssSatelliteBlacklistHelperTest { private ContentResolver mContentResolver; @Mock - private GnssSatelliteBlacklistHelper.GnssSatelliteBlacklistCallback mCallback; + private GnssSatelliteBlacklistHelper.GnssSatelliteBlacklistCallback + mCallback; @Before public void setUp() { diff --git a/services/robotests/src/com/android/server/location/NtpTimeHelperTest.java b/services/robotests/src/com/android/server/location/gnss/NtpTimeHelperTest.java index 9c5d4ad6ceeb..9b59aaddc4d4 100644 --- a/services/robotests/src/com/android/server/location/NtpTimeHelperTest.java +++ b/services/robotests/src/com/android/server/location/gnss/NtpTimeHelperTest.java @@ -1,4 +1,20 @@ -package com.android.server.location; +/* + * Copyright (C) 2020 The Android Open 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.location.gnss; import static com.google.common.truth.Truth.assertThat; @@ -10,7 +26,7 @@ import android.os.SystemClock; import android.platform.test.annotations.Presubmit; import android.util.NtpTrustedTime; -import com.android.server.location.NtpTimeHelper.InjectNtpTimeCallback; +import com.android.server.location.gnss.NtpTimeHelper.InjectNtpTimeCallback; import org.junit.Before; import org.junit.Test; diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp index 449e75cd11a0..e58e91179931 100644 --- a/services/tests/servicestests/Android.bp +++ b/services/tests/servicestests/Android.bp @@ -91,7 +91,15 @@ android_test { enabled: false, }, - data: [":JobTestApp"], + data: [ + ":JobTestApp", + ], + + java_resources: [ + ":PackageParserTestApp1", + ":PackageParserTestApp2", + ":PackageParserTestApp3", + ], resource_zips: [":FrameworksServicesTests_apks_as_resources"], } diff --git a/services/tests/servicestests/src/com/android/server/MountServiceTests.java b/services/tests/servicestests/src/com/android/server/MountServiceTests.java deleted file mode 100644 index b1b31744c88b..000000000000 --- a/services/tests/servicestests/src/com/android/server/MountServiceTests.java +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open 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 android.content.Context; -import android.content.res.Resources; -import android.content.res.Resources.NotFoundException; -import android.os.FileUtils; -import android.os.storage.OnObbStateChangeListener; -import android.os.storage.StorageManager; -import android.test.AndroidTestCase; -import android.test.ComparisonFailure; -import android.test.suitebuilder.annotation.LargeTest; -import android.util.Log; - -import com.android.frameworks.servicestests.R; - -import java.io.File; -import java.io.InputStream; - -public class MountServiceTests extends AndroidTestCase { - private static final String TAG = "MountServiceTests"; - - private static final long MAX_WAIT_TIME = 25*1000; - private static final long WAIT_TIME_INCR = 5*1000; - - private static final String OBB_MOUNT_PREFIX = "/mnt/obb/"; - - private static void assertStartsWith(String message, String prefix, String actual) { - if (!actual.startsWith(prefix)) { - throw new ComparisonFailure(message, prefix, actual); - } - } - - private static class ObbObserver extends OnObbStateChangeListener { - private String path; - - public int state = -1; - boolean done = false; - - @Override - public void onObbStateChange(String path, int state) { - Log.d(TAG, "Received message. path=" + path + ", state=" + state); - synchronized (this) { - this.path = path; - this.state = state; - done = true; - notifyAll(); - } - } - - public String getPath() { - assertTrue("Expected ObbObserver to have received a state change.", done); - return path; - } - - public int getState() { - assertTrue("Expected ObbObserver to have received a state change.", done); - return state; - } - - public void reset() { - this.path = null; - this.state = -1; - done = false; - } - - public boolean isDone() { - return done; - } - - public boolean waitForCompletion() { - long waitTime = 0; - synchronized (this) { - while (!isDone() && waitTime < MAX_WAIT_TIME) { - try { - wait(WAIT_TIME_INCR); - waitTime += WAIT_TIME_INCR; - } catch (InterruptedException e) { - Log.i(TAG, "Interrupted during sleep", e); - } - } - } - - return isDone(); - } - } - - private File getFilePath(String name) { - final File filesDir = mContext.getFilesDir(); - final File outFile = new File(filesDir, name); - return outFile; - } - - private void copyRawToFile(int rawResId, File outFile) { - Resources res = mContext.getResources(); - InputStream is = null; - try { - is = res.openRawResource(rawResId); - } catch (NotFoundException e) { - fail("Failed to load resource with id: " + rawResId); - } - FileUtils.setPermissions(outFile.getPath(), FileUtils.S_IRWXU | FileUtils.S_IRWXG - | FileUtils.S_IRWXO, -1, -1); - assertTrue(FileUtils.copyToFile(is, outFile)); - FileUtils.setPermissions(outFile.getPath(), FileUtils.S_IRWXU | FileUtils.S_IRWXG - | FileUtils.S_IRWXO, -1, -1); - } - - private StorageManager getStorageManager() { - return (StorageManager) getContext().getSystemService(Context.STORAGE_SERVICE); - } - - private void mountObb(StorageManager sm, final int resource, final File file, - int expectedState) { - copyRawToFile(resource, file); - - final ObbObserver observer = new ObbObserver(); - assertTrue("mountObb call on " + file.getPath() + " should succeed", - sm.mountObb(file.getPath(), null, observer)); - - assertTrue("Mount should have completed", - observer.waitForCompletion()); - - if (expectedState == OnObbStateChangeListener.MOUNTED) { - assertTrue("OBB should be mounted", sm.isObbMounted(file.getPath())); - } - - assertEquals("Actual file and resolved file should be the same", - file.getPath(), observer.getPath()); - - assertEquals(expectedState, observer.getState()); - } - - private ObbObserver mountObbWithoutWait(final StorageManager sm, final int resource, - final File file) { - copyRawToFile(resource, file); - - final ObbObserver observer = new ObbObserver(); - assertTrue("mountObb call on " + file.getPath() + " should succeed", sm.mountObb(file - .getPath(), null, observer)); - - return observer; - } - - private void waitForObbActionCompletion(final StorageManager sm, final File file, - final ObbObserver observer, int expectedState, boolean checkPath) { - assertTrue("Mount should have completed", observer.waitForCompletion()); - - assertTrue("OBB should be mounted", sm.isObbMounted(file.getPath())); - - if (checkPath) { - assertEquals("Actual file and resolved file should be the same", file.getPath(), - observer.getPath()); - } - - assertEquals(expectedState, observer.getState()); - } - - private String checkMountedPath(final StorageManager sm, final File file) { - final String mountPath = sm.getMountedObbPath(file.getPath()); - assertStartsWith("Path should be in " + OBB_MOUNT_PREFIX, - OBB_MOUNT_PREFIX, - mountPath); - return mountPath; - } - - private void unmountObb(final StorageManager sm, final File file, int expectedState) { - final ObbObserver observer = new ObbObserver(); - - assertTrue("unmountObb call on test1.obb should succeed", - sm.unmountObb(file.getPath(), false, observer)); - - assertTrue("Unmount should have completed", - observer.waitForCompletion()); - - assertEquals(expectedState, observer.getState()); - - if (expectedState == OnObbStateChangeListener.UNMOUNTED) { - assertFalse("OBB should not be mounted", sm.isObbMounted(file.getPath())); - } - } - - @LargeTest - public void testMountAndUnmountObbNormal() { - StorageManager sm = getStorageManager(); - - final File outFile = getFilePath("test1.obb"); - - mountObb(sm, R.raw.test1, outFile, OnObbStateChangeListener.MOUNTED); - - mountObb(sm, R.raw.test1, outFile, OnObbStateChangeListener.ERROR_ALREADY_MOUNTED); - - final String mountPath = checkMountedPath(sm, outFile); - final File mountDir = new File(mountPath); - - assertTrue("OBB mounted path should be a directory", - mountDir.isDirectory()); - - unmountObb(sm, outFile, OnObbStateChangeListener.UNMOUNTED); - } - - @LargeTest - public void testAttemptMountNonObb() { - StorageManager sm = getStorageManager(); - - final File outFile = getFilePath("test1_nosig.obb"); - - try { - mountObb(sm, R.raw.test1_nosig, outFile, OnObbStateChangeListener.ERROR_INTERNAL); - fail("mountObb should've failed with an exception"); - } catch (IllegalArgumentException e) { - // Expected - } - - assertFalse("OBB should not be mounted", - sm.isObbMounted(outFile.getPath())); - - assertNull("OBB's mounted path should be null", - sm.getMountedObbPath(outFile.getPath())); - } - - @LargeTest - public void testAttemptMountObbWrongPackage() { - StorageManager sm = getStorageManager(); - - final File outFile = getFilePath("test1_wrongpackage.obb"); - - mountObb(sm, R.raw.test1_wrongpackage, outFile, - OnObbStateChangeListener.ERROR_PERMISSION_DENIED); - - assertFalse("OBB should not be mounted", - sm.isObbMounted(outFile.getPath())); - - assertNull("OBB's mounted path should be null", - sm.getMountedObbPath(outFile.getPath())); - } - - @LargeTest - public void testMountAndUnmountTwoObbs() { - StorageManager sm = getStorageManager(); - - final File file1 = getFilePath("test1.obb"); - final File file2 = getFilePath("test2.obb"); - - ObbObserver oo1 = mountObbWithoutWait(sm, R.raw.test1, file1); - ObbObserver oo2 = mountObbWithoutWait(sm, R.raw.test1, file2); - - Log.d(TAG, "Waiting for OBB #1 to complete mount"); - waitForObbActionCompletion(sm, file1, oo1, OnObbStateChangeListener.MOUNTED, false); - Log.d(TAG, "Waiting for OBB #2 to complete mount"); - waitForObbActionCompletion(sm, file2, oo2, OnObbStateChangeListener.MOUNTED, false); - - final String mountPath1 = checkMountedPath(sm, file1); - final File mountDir1 = new File(mountPath1); - assertTrue("OBB mounted path should be a directory", mountDir1.isDirectory()); - - final String mountPath2 = checkMountedPath(sm, file2); - final File mountDir2 = new File(mountPath2); - assertTrue("OBB mounted path should be a directory", mountDir2.isDirectory()); - - unmountObb(sm, file1, OnObbStateChangeListener.UNMOUNTED); - unmountObb(sm, file2, OnObbStateChangeListener.UNMOUNTED); - } -} diff --git a/services/tests/servicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java index a99c982753c5..be2a5c529181 100644 --- a/services/tests/servicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java @@ -61,17 +61,9 @@ import android.os.RemoteException; import com.android.server.LocalServices; import com.android.server.location.AppForegroundHelper; -import com.android.server.location.GnssAntennaInfoProvider; -import com.android.server.location.GnssAntennaInfoProvider.GnssAntennaInfoProviderNative; -import com.android.server.location.GnssBatchingProvider; -import com.android.server.location.GnssCapabilitiesProvider; -import com.android.server.location.GnssLocationProvider; -import com.android.server.location.GnssMeasurementCorrectionsProvider; -import com.android.server.location.GnssMeasurementsProvider; -import com.android.server.location.GnssMeasurementsProvider.GnssMeasurementProviderNative; -import com.android.server.location.GnssNavigationMessageProvider; -import com.android.server.location.GnssNavigationMessageProvider.GnssNavigationMessageProviderNative; -import com.android.server.location.GnssStatusListenerHelper; +import com.android.server.location.gnss.GnssAntennaInfoProvider.GnssAntennaInfoProviderNative; +import com.android.server.location.gnss.GnssMeasurementsProvider.GnssMeasurementProviderNative; +import com.android.server.location.gnss.GnssNavigationMessageProvider.GnssNavigationMessageProviderNative; import com.android.server.location.LocationUsageLogger; import com.android.server.location.SettingsHelper; diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java index a19d91976307..d760629552b8 100644 --- a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java @@ -17,11 +17,15 @@ package com.android.server.pm; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; +import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; + import android.annotation.NonNull; +import android.content.Context; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.ConfigurationInfo; @@ -30,7 +34,6 @@ import android.content.pm.FeatureInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageParser; import android.content.pm.PackageUserState; -import android.content.pm.ProviderInfo; import android.content.pm.ServiceInfo; import android.content.pm.Signature; import android.content.pm.parsing.ParsingPackage; @@ -49,6 +52,7 @@ import android.util.ArraySet; import android.util.DisplayMetrics; import androidx.annotation.Nullable; +import androidx.test.InstrumentationRegistry; import androidx.test.filters.MediumTest; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; @@ -69,9 +73,11 @@ import org.junit.runner.RunWith; import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.lang.reflect.Array; import java.lang.reflect.Field; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; @@ -90,6 +96,9 @@ public class PackageParserTest { private File mTmpDir; private static final File FRAMEWORK = new File("/system/framework/framework-res.apk"); + private static final String TEST_APP1_APK = "PackageParserTestApp1.apk"; + private static final String TEST_APP2_APK = "PackageParserTestApp2.apk"; + private static final String TEST_APP3_APK = "PackageParserTestApp3.apk"; @Before public void setUp() throws IOException { @@ -209,6 +218,61 @@ public class PackageParserTest { assertSame(deserialized.getSharedUserId(), deserialized2.getSharedUserId()); } + private static PackageParser2 makeParser() { + return new PackageParser2(null, false, null, null, null); + } + + private File extractFile(String filename) throws Exception { + final Context context = InstrumentationRegistry.getTargetContext(); + final File tmpFile = File.createTempFile(filename, ".apk"); + try (InputStream inputStream = context.getAssets().openNonAsset(filename)) { + Files.copy(inputStream, tmpFile.toPath(), REPLACE_EXISTING); + } + return tmpFile; + } + + /** + * Tests AndroidManifest.xml with no android:isolatedSplits attribute. + */ + @Test + public void testParseIsolatedSplitsDefault() throws Exception { + final File testFile = extractFile(TEST_APP1_APK); + try { + final ParsedPackage pkg = makeParser().parsePackage(testFile, 0, false); + assertFalse("isolatedSplits", pkg.isIsolatedSplitLoading()); + } finally { + testFile.delete(); + } + } + + /** + * Tests AndroidManifest.xml with an android:isolatedSplits attribute set to a constant. + */ + @Test + public void testParseIsolatedSplitsConstant() throws Exception { + final File testFile = extractFile(TEST_APP2_APK); + try { + final ParsedPackage pkg = makeParser().parsePackage(testFile, 0, false); + assertTrue("isolatedSplits", pkg.isIsolatedSplitLoading()); + } finally { + testFile.delete(); + } + } + + /** + * Tests AndroidManifest.xml with an android:isolatedSplits attribute set to a resource. + */ + @Test + public void testParseIsolatedSplitsResource() throws Exception { + final File testFile = extractFile(TEST_APP3_APK); + try { + final ParsedPackage pkg = makeParser().parsePackage(testFile, 0, false); + assertTrue("isolatedSplits", pkg.isIsolatedSplitLoading()); + } finally { + testFile.delete(); + } + } + /** * A trivial subclass of package parser that only caches the package name, and throws away * all other information. diff --git a/services/tests/servicestests/test-apps/PackageParserApp/Android.bp b/services/tests/servicestests/test-apps/PackageParserApp/Android.bp new file mode 100644 index 000000000000..c409438e94ae --- /dev/null +++ b/services/tests/servicestests/test-apps/PackageParserApp/Android.bp @@ -0,0 +1,53 @@ +// Copyright (C) 2020 The Android Open 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. + +android_test_helper_app { + name: "PackageParserTestApp1", + sdk_version: "current", + srcs: ["**/*.java"], + dex_preopt: { + enabled: false, + }, + optimize: { + enabled: false, + }, + manifest: "AndroidManifestApp1.xml", +} + +android_test_helper_app { + name: "PackageParserTestApp2", + sdk_version: "current", + srcs: ["**/*.java"], + dex_preopt: { + enabled: false, + }, + optimize: { + enabled: false, + }, + manifest: "AndroidManifestApp2.xml", +} + +android_test_helper_app { + name: "PackageParserTestApp3", + sdk_version: "current", + srcs: ["**/*.java"], + dex_preopt: { + enabled: false, + }, + optimize: { + enabled: false, + }, + resource_dirs: ["res"], + manifest: "AndroidManifestApp3.xml", +} diff --git a/services/tests/servicestests/test-apps/PackageParserApp/AndroidManifestApp1.xml b/services/tests/servicestests/test-apps/PackageParserApp/AndroidManifestApp1.xml new file mode 100644 index 000000000000..01d335d2cbbd --- /dev/null +++ b/services/tests/servicestests/test-apps/PackageParserApp/AndroidManifestApp1.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2020 The Android Open 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. +--> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.servicestests.apps.packageparserapp" > + + <application> + <activity android:name=".TestActivity" + android:exported="true" /> + </application> + +</manifest>
\ No newline at end of file diff --git a/services/tests/servicestests/test-apps/PackageParserApp/AndroidManifestApp2.xml b/services/tests/servicestests/test-apps/PackageParserApp/AndroidManifestApp2.xml new file mode 100644 index 000000000000..567946cc70d7 --- /dev/null +++ b/services/tests/servicestests/test-apps/PackageParserApp/AndroidManifestApp2.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2020 The Android Open 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. +--> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.servicestests.apps.packageparserapp" + android:isolatedSplits="true" > + + <application> + <activity android:name=".TestActivity" + android:exported="true" /> + </application> + +</manifest>
\ No newline at end of file diff --git a/services/tests/servicestests/test-apps/PackageParserApp/AndroidManifestApp3.xml b/services/tests/servicestests/test-apps/PackageParserApp/AndroidManifestApp3.xml new file mode 100644 index 000000000000..77285a805950 --- /dev/null +++ b/services/tests/servicestests/test-apps/PackageParserApp/AndroidManifestApp3.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2020 The Android Open 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. +--> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.servicestests.apps.packageparserapp" + android:isolatedSplits="@bool/config_isIsolated" > + + <application> + <activity android:name=".TestActivity" + android:exported="true" /> + </application> + +</manifest>
\ No newline at end of file diff --git a/services/tests/servicestests/test-apps/PackageParserApp/res/values/values.xml b/services/tests/servicestests/test-apps/PackageParserApp/res/values/values.xml new file mode 100644 index 000000000000..6a4cc653494f --- /dev/null +++ b/services/tests/servicestests/test-apps/PackageParserApp/res/values/values.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2020 The Android Open 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. +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <bool name="config_isIsolated">true</bool> +</resources>
\ No newline at end of file diff --git a/core/java/android/content/pm/NamedParcelFileDescriptor.aidl b/services/tests/servicestests/test-apps/PackageParserApp/src/com/android/servicestests/apps/packageparserapp/TestActivity.java index 68dd5f54654b..2eacb96fb2aa 100644 --- a/core/java/android/content/pm/NamedParcelFileDescriptor.aidl +++ b/services/tests/servicestests/test-apps/PackageParserApp/src/com/android/servicestests/apps/packageparserapp/TestActivity.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 The Android Open Source Project + * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,15 +14,15 @@ * limitations under the License. */ -package android.content.pm; +package com.android.servicestests.apps.packageparserapp; -import android.os.ParcelFileDescriptor; +import android.app.Activity; +import android.os.Bundle; -/** - * A named ParcelFileDescriptor. - * @hide - */ -parcelable NamedParcelFileDescriptor { - @utf8InCpp String name; - ParcelFileDescriptor fd; +public class TestActivity extends Activity { + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + finish(); + } } diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java index c71d8194f889..08e492a7b0ff 100644 --- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java @@ -28,7 +28,6 @@ import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE; import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; -import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; @@ -38,7 +37,6 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; -import android.graphics.Rect; import android.os.IBinder; import android.os.RemoteException; import android.platform.test.annotations.Presubmit; @@ -70,7 +68,7 @@ public class AppTransitionTests extends WindowTestsBase { @Before public void setUp() throws Exception { - doNothing().when(mWm.mRoot).performSurfacePlacement(anyBoolean()); + doNothing().when(mWm.mRoot).performSurfacePlacement(); mDc = mWm.getDefaultDisplayContentLocked(); } diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java index 6cc57f4dbf8c..cf3cfecbf65e 100644 --- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java @@ -174,7 +174,7 @@ public class AppWindowTokenTests extends WindowTestsBase { null /* freezeThisOneIfNeeded */, false /* forceUpdate */); // In this test, DC will not get config update. Set the waiting flag to false. mDisplayContent.mWaitingForConfig = false; - mWm.mRoot.performSurfacePlacement(false /* recoveringMemory */); + mWm.mRoot.performSurfacePlacement(); assertEquals(SCREEN_ORIENTATION_REVERSE_LANDSCAPE, mDisplayContent.getLastOrientation()); assertTrue(appWindow.mResizeReported); appWindow.removeImmediately(); diff --git a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java index 8f3ff52b8018..ae467c0c811d 100644 --- a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java @@ -120,7 +120,7 @@ public class LaunchParamsPersisterTests extends ActivityTestsBase { .build(); mTestTask.mUserId = TEST_USER_ID; mTestTask.mLastNonFullscreenBounds = TEST_BOUNDS; - mTestTask.hasBeenVisible = true; + mTestTask.setHasBeenVisible(true); mTaskWithDifferentComponent = new TaskBuilder(mSupervisor) .setComponent(ALTERNATIVE_COMPONENT).build(); @@ -346,7 +346,7 @@ public class LaunchParamsPersisterTests extends ActivityTestsBase { .build(); anotherTaskOfTheSameUser.setWindowingMode(WINDOWING_MODE_FREEFORM); anotherTaskOfTheSameUser.setBounds(200, 300, 400, 500); - anotherTaskOfTheSameUser.hasBeenVisible = true; + anotherTaskOfTheSameUser.setHasBeenVisible(true); mTarget.saveTask(anotherTaskOfTheSameUser); stack = mTestDisplay.createStack(TEST_WINDOWING_MODE, @@ -358,7 +358,7 @@ public class LaunchParamsPersisterTests extends ActivityTestsBase { .build(); anotherTaskOfDifferentUser.setWindowingMode(WINDOWING_MODE_FREEFORM); anotherTaskOfDifferentUser.setBounds(300, 400, 500, 600); - anotherTaskOfDifferentUser.hasBeenVisible = true; + anotherTaskOfDifferentUser.setHasBeenVisible(true); mTarget.saveTask(anotherTaskOfDifferentUser); mTarget.onCleanupUser(TEST_USER_ID); diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java index da3ee3990137..8846fb8e0962 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java @@ -1113,7 +1113,6 @@ public class RecentTasksTest extends ActivityTestsBase { () -> mService.moveTaskToStack(0, INVALID_STACK_ID, true)); assertSecurityException(expectCallable, () -> mService.setTaskWindowingModeSplitScreenPrimary(0, true)); - assertSecurityException(expectCallable, () -> mService.dismissPip(true, 0)); assertSecurityException(expectCallable, () -> mService.moveTopActivityToPinnedStack(INVALID_STACK_ID, new Rect())); assertSecurityException(expectCallable, () -> mService.getAllStackInfos()); diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java index f242989ab885..da07baca3ce1 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java @@ -100,7 +100,7 @@ public class RecentsAnimationControllerTest extends WindowTestsBase { @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); - doNothing().when(mWm.mRoot).performSurfacePlacement(anyBoolean()); + doNothing().when(mWm.mRoot).performSurfacePlacement(); when(mMockRunner.asBinder()).thenReturn(new Binder()); mDefaultDisplay = mWm.mRoot.getDefaultDisplay(); mController = spy(new RecentsAnimationController(mWm, mMockRunner, mAnimationCallbacks, diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java index edf81ea32ad3..893a14541c48 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java @@ -481,7 +481,7 @@ public class SizeCompatTests extends ActivityTestsBase { // The letterbox needs a main window to layout. addWindowToActivity(mActivity); // Compute the frames of the window and invoke {@link ActivityRecord#layoutLetterbox}. - mActivity.mRootWindowContainer.performSurfacePlacement(false /* recoveringMemory */); + mActivity.mRootWindowContainer.performSurfacePlacement(); // The letterbox insets should be [350, 0 - 350, 0]. assertEquals(new Rect(mActivity.getBounds().left, 0, dh - mActivity.getBounds().right, 0), mActivity.getLetterboxInsets()); diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java index ed635ce3f69e..4cc84a65fb29 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java @@ -96,10 +96,28 @@ public class TaskOrganizerTests extends WindowTestsBase { return registerMockOrganizer(WINDOWING_MODE_MULTI_WINDOW); } + Task createTask(ActivityStack stack, boolean fakeDraw) { + final Task task = createTaskInStack(stack, 0); + + if (fakeDraw) { + task.setHasBeenVisible(true); + } + return task; + } + + Task createTask(ActivityStack stack) { + // Fake draw notifications for most of our tests. + return createTask(stack, true); + } + + ActivityStack createStack() { + return createTaskStackOnDisplay(mDisplayContent); + } + @Test public void testAppearVanish() throws RemoteException { - final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent); - final Task task = createTaskInStack(stack, 0 /* userId */); + final ActivityStack stack = createStack(); + final Task task = createTask(stack); final ITaskOrganizer organizer = registerMockOrganizer(); task.setTaskOrganizer(organizer); @@ -110,9 +128,42 @@ public class TaskOrganizerTests extends WindowTestsBase { } @Test + public void testAppearWaitsForVisibility() throws RemoteException { + final ActivityStack stack = createStack(); + final Task task = createTask(stack, false); + final ITaskOrganizer organizer = registerMockOrganizer(); + + task.setTaskOrganizer(organizer); + + verify(organizer, never()).onTaskAppeared(any()); + task.setHasBeenVisible(true); + assertTrue(stack.getHasBeenVisible()); + + verify(organizer).onTaskAppeared(any()); + + task.removeImmediately(); + verify(organizer).onTaskVanished(any()); + } + + @Test + public void testNoVanishedIfNoAppear() throws RemoteException { + final ActivityStack stack = createStack(); + final Task task = createTask(stack, false /* hasBeenVisible */); + final ITaskOrganizer organizer = registerMockOrganizer(); + + // In this test we skip making the Task visible, and verify + // that even though a TaskOrganizer is set remove doesn't emit + // a vanish callback, because we never emitted appear. + task.setTaskOrganizer(organizer); + verify(organizer, never()).onTaskAppeared(any()); + task.removeImmediately(); + verify(organizer, never()).onTaskVanished(any()); + } + + @Test public void testSwapOrganizer() throws RemoteException { - final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent); - final Task task = createTaskInStack(stack, 0 /* userId */); + final ActivityStack stack = createStack(); + final Task task = createTask(stack); final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_MULTI_WINDOW); final ITaskOrganizer organizer2 = registerMockOrganizer(WINDOWING_MODE_PINNED); @@ -125,8 +176,8 @@ public class TaskOrganizerTests extends WindowTestsBase { @Test public void testSwapWindowingModes() throws RemoteException { - final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent); - final Task task = createTaskInStack(stack, 0 /* userId */); + final ActivityStack stack = createStack(); + final Task task = createTask(stack); final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_MULTI_WINDOW); final ITaskOrganizer organizer2 = registerMockOrganizer(WINDOWING_MODE_PINNED); @@ -139,8 +190,8 @@ public class TaskOrganizerTests extends WindowTestsBase { @Test public void testClearOrganizer() throws RemoteException { - final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent); - final Task task = createTaskInStack(stack, 0 /* userId */); + final ActivityStack stack = createStack(); + final Task task = createTask(stack); final ITaskOrganizer organizer = registerMockOrganizer(); stack.setTaskOrganizer(organizer); @@ -154,8 +205,8 @@ public class TaskOrganizerTests extends WindowTestsBase { @Test public void testUnregisterOrganizer() throws RemoteException { - final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent); - final Task task = createTaskInStack(stack, 0 /* userId */); + final ActivityStack stack = createStack(); + final Task task = createTask(stack); final ITaskOrganizer organizer = registerMockOrganizer(); stack.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW); @@ -169,12 +220,12 @@ public class TaskOrganizerTests extends WindowTestsBase { @Test public void testUnregisterOrganizerReturnsRegistrationToPrevious() throws RemoteException { - final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent); - final Task task = createTaskInStack(stack, 0 /* userId */); - final ActivityStack stack2 = createTaskStackOnDisplay(mDisplayContent); - final Task task2 = createTaskInStack(stack2, 0 /* userId */); - final ActivityStack stack3 = createTaskStackOnDisplay(mDisplayContent); - final Task task3 = createTaskInStack(stack3, 0 /* userId */); + final ActivityStack stack = createStack(); + final Task task = createTask(stack); + final ActivityStack stack2 = createStack(); + final Task task2 = createTask(stack2); + final ActivityStack stack3 = createStack(); + final Task task3 = createTask(stack3); final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_MULTI_WINDOW); // First organizer is registered, verify a task appears when changing windowing mode @@ -202,9 +253,9 @@ public class TaskOrganizerTests extends WindowTestsBase { public void testRegisterTaskOrganizerStackWindowingModeChanges() throws RemoteException { final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_PINNED); - final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent); - final Task task = createTaskInStack(stack, 0 /* userId */); - final Task task2 = createTaskInStack(stack, 0 /* userId */); + final ActivityStack stack = createStack(); + final Task task = createTask(stack); + final Task task2 = createTask(stack); stack.setWindowingMode(WINDOWING_MODE_PINNED); verify(organizer, times(1)).onTaskAppeared(any()); @@ -214,8 +265,8 @@ public class TaskOrganizerTests extends WindowTestsBase { @Test public void testRegisterTaskOrganizerWithExistingTasks() throws RemoteException { - final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent); - final Task task = createTaskInStack(stack, 0 /* userId */); + final ActivityStack stack = createStack(); + final Task task = createTask(stack); stack.setWindowingMode(WINDOWING_MODE_PINNED); final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_PINNED); @@ -560,8 +611,8 @@ public class TaskOrganizerTests extends WindowTestsBase { @Test public void testTrivialBLASTCallback() throws RemoteException { - final ActivityStack stackController1 = createTaskStackOnDisplay(mDisplayContent); - final Task task = createTaskInStack(stackController1, 0 /* userId */); + final ActivityStack stackController1 = createStack(); + final Task task = createTask(stackController1); final ITaskOrganizer organizer = registerMockOrganizer(); spyOn(task); @@ -582,8 +633,8 @@ public class TaskOrganizerTests extends WindowTestsBase { @Test public void testOverlappingBLASTCallback() throws RemoteException { - final ActivityStack stackController1 = createTaskStackOnDisplay(mDisplayContent); - final Task task = createTaskInStack(stackController1, 0 /* userId */); + final ActivityStack stackController1 = createStack(); + final Task task = createTask(stackController1); final ITaskOrganizer organizer = registerMockOrganizer(); spyOn(task); @@ -611,8 +662,8 @@ public class TaskOrganizerTests extends WindowTestsBase { @Test public void testBLASTCallbackWithWindow() { - final ActivityStack stackController1 = createTaskStackOnDisplay(mDisplayContent); - final Task task = createTaskInStack(stackController1, 0 /* userId */); + final ActivityStack stackController1 = createStack(); + final Task task = createTask(stackController1); final ITaskOrganizer organizer = registerMockOrganizer(); final WindowState w = createAppWindow(task, TYPE_APPLICATION, "Enlightened Window"); makeWindowVisible(w); @@ -635,8 +686,8 @@ public class TaskOrganizerTests extends WindowTestsBase { @Test public void testBLASTCallbackWithInvisibleWindow() { - final ActivityStack stackController1 = createTaskStackOnDisplay(mDisplayContent); - final Task task = createTaskInStack(stackController1, 0 /* userId */); + final ActivityStack stackController1 = createStack(); + final Task task = createTask(stackController1); final ITaskOrganizer organizer = registerMockOrganizer(); final WindowState w = createAppWindow(task, TYPE_APPLICATION, "Enlightened Window"); @@ -657,8 +708,8 @@ public class TaskOrganizerTests extends WindowTestsBase { @Test public void testBLASTCallbackWithChildWindow() { - final ActivityStack stackController1 = createTaskStackOnDisplay(mDisplayContent); - final Task task = createTaskInStack(stackController1, 0 /* userId */); + final ActivityStack stackController1 = createStack(); + final Task task = createTask(stackController1); final ITaskOrganizer organizer = registerMockOrganizer(); final WindowState w = createAppWindow(task, TYPE_APPLICATION, "Enlightened Window"); final WindowState child = createWindow(w, TYPE_APPLICATION, "Other Window"); @@ -708,6 +759,8 @@ public class TaskOrganizerTests extends WindowTestsBase { record.info.flags |= ActivityInfo.FLAG_SUPPORTS_PICTURE_IN_PICTURE; spyOn(record); doReturn(true).when(record).checkEnterPictureInPictureState(any(), anyBoolean()); + + record.getRootTask().setHasBeenVisible(true); return record; } @@ -755,4 +808,23 @@ public class TaskOrganizerTests extends WindowTestsBase { assertEquals(3, ratio.getNumerator()); assertEquals(4, ratio.getDenominator()); } + + @Test + public void testPreventDuplicateAppear() throws RemoteException { + final ActivityStack stack = createStack(); + final Task task = createTask(stack); + final ITaskOrganizer organizer = registerMockOrganizer(); + + task.setTaskOrganizer(organizer); + // setHasBeenVisible was already called once by the set-up code. + task.setHasBeenVisible(true); + verify(organizer, times(1)).onTaskAppeared(any()); + + task.taskOrganizerUnregistered(); + task.setTaskOrganizer(organizer); + verify(organizer, times(2)).onTaskAppeared(any()); + + task.removeImmediately(); + verify(organizer).onTaskVanished(any()); + } } diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java index 56c19a47b68a..1ad4079c5193 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java @@ -874,11 +874,11 @@ public class TaskRecordTests extends ActivityTestsBase { spyOn(persister); final Task task = getTestTask(); - task.hasBeenVisible = false; + task.setHasBeenVisible(false); task.getDisplayContent().setDisplayWindowingMode(WINDOWING_MODE_FREEFORM); task.getStack().setWindowingMode(WINDOWING_MODE_FULLSCREEN); - task.hasBeenVisible = true; + task.setHasBeenVisible(true); task.onConfigurationChanged(task.getParent().getConfiguration()); verify(persister).saveTask(task, task.getDisplayContent()); @@ -890,7 +890,7 @@ public class TaskRecordTests extends ActivityTestsBase { spyOn(persister); final Task task = getTestTask(); - task.hasBeenVisible = false; + task.setHasBeenVisible(false); task.getDisplayContent().setWindowingMode(WindowConfiguration.WINDOWING_MODE_FREEFORM); task.getStack().setWindowingMode(WINDOWING_MODE_FULLSCREEN); final DisplayContent oldDisplay = task.getDisplayContent(); @@ -900,7 +900,7 @@ public class TaskRecordTests extends ActivityTestsBase { persister.getLaunchParams(task, null, params); assertEquals(WINDOWING_MODE_UNDEFINED, params.mWindowingMode); - task.hasBeenVisible = true; + task.setHasBeenVisible(true); task.removeImmediately(); verify(persister).saveTask(task, oldDisplay); @@ -915,10 +915,10 @@ public class TaskRecordTests extends ActivityTestsBase { spyOn(persister); final Task task = getTestTask(); - task.hasBeenVisible = false; + task.setHasBeenVisible(false); task.getStack().setWindowingMode(WINDOWING_MODE_FULLSCREEN); - task.hasBeenVisible = true; + task.setHasBeenVisible(true); task.onConfigurationChanged(task.getParent().getConfiguration()); verify(persister, never()).saveTask(same(task), any()); @@ -930,11 +930,11 @@ public class TaskRecordTests extends ActivityTestsBase { spyOn(persister); final Task task = getTestTask(); - task.hasBeenVisible = false; + task.setHasBeenVisible(false); task.getDisplayContent().setDisplayWindowingMode(WINDOWING_MODE_FREEFORM); task.getStack().setWindowingMode(WINDOWING_MODE_PINNED); - task.hasBeenVisible = true; + task.setHasBeenVisible(true); task.onConfigurationChanged(task.getParent().getConfiguration()); verify(persister, never()).saveTask(same(task), any()); diff --git a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java index 7e02966779a2..1a38a42873b7 100644 --- a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java +++ b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java @@ -361,7 +361,8 @@ public final class TelephonyPermissions { TelephonyCommonStatsLog.write(TelephonyCommonStatsLog.DEVICE_IDENTIFIER_ACCESS_DENIED, callingPackage, message, /* isPreinstalled= */ false, false); } - Log.w(LOG_TAG, "reportAccessDeniedToReadIdentifiers:" + callingPackage + ":" + message); + Log.w(LOG_TAG, "reportAccessDeniedToReadIdentifiers:" + callingPackage + ":" + message + ":" + + subId); // if the target SDK is pre-Q then check if the calling package would have previously // had access to device identifiers. if (callingPackageInfo != null && ( diff --git a/telephony/java/com/android/internal/telephony/DctConstants.java b/telephony/java/com/android/internal/telephony/DctConstants.java index 3e1d72c7eeb8..2b1d9e58c4d5 100644 --- a/telephony/java/com/android/internal/telephony/DctConstants.java +++ b/telephony/java/com/android/internal/telephony/DctConstants.java @@ -74,7 +74,6 @@ public class DctConstants { public static final int BASE = Protocol.BASE_DATA_CONNECTION_TRACKER; public static final int EVENT_DATA_SETUP_COMPLETE = BASE + 0; public static final int EVENT_RADIO_AVAILABLE = BASE + 1; - public static final int EVENT_RECORDS_LOADED = BASE + 2; public static final int EVENT_TRY_SETUP_DATA = BASE + 3; public static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE = BASE + 6; public static final int EVENT_VOICE_CALL_STARTED = BASE + 7; @@ -94,7 +93,6 @@ public class DctConstants { public static final int EVENT_CLEAN_UP_CONNECTION = BASE + 24; public static final int EVENT_RESTART_RADIO = BASE + 26; public static final int EVENT_CLEAN_UP_ALL_CONNECTIONS = BASE + 29; - public static final int EVENT_ICC_CHANGED = BASE + 33; public static final int EVENT_DATA_SETUP_COMPLETE_ERROR = BASE + 35; public static final int CMD_SET_ENABLE_FAIL_FAST_MOBILE_DATA = BASE + 36; public static final int CMD_ENABLE_MOBILE_PROVISIONING = BASE + 37; @@ -114,7 +112,7 @@ public class DctConstants { public static final int EVENT_SERVICE_STATE_CHANGED = BASE + 52; public static final int EVENT_5G_TIMER_HYSTERESIS = BASE + 53; public static final int EVENT_5G_TIMER_WATCHDOG = BASE + 54; - public static final int EVENT_UPDATE_CARRIER_CONFIGS = BASE + 55; + public static final int EVENT_CARRIER_CONFIG_CHANGED = BASE + 55; /***** Constants *****/ diff --git a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java index 2957192ecf0f..d011dbbbe5db 100644 --- a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java +++ b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java @@ -1123,6 +1123,28 @@ public class PackageWatchdogTest { assertThat(testController.getSyncRequests()).isEqualTo(expectedSyncRequests); } + /** + * Ensure that the failure history of a package is preserved when making duplicate calls to + * observe the package. + */ + @Test + public void testFailureHistoryIsPreserved() { + PackageWatchdog watchdog = createWatchdog(); + TestObserver observer = new TestObserver(OBSERVER_NAME_1); + watchdog.startObservingHealth(observer, List.of(APP_A), SHORT_DURATION); + for (int i = 0; i < PackageWatchdog.DEFAULT_TRIGGER_FAILURE_COUNT - 1; i++) { + watchdog.onPackageFailure(List.of(new VersionedPackage(APP_A, VERSION_CODE)), + PackageWatchdog.FAILURE_REASON_UNKNOWN); + } + mTestLooper.dispatchAll(); + assertThat(observer.mMitigatedPackages).isEmpty(); + watchdog.startObservingHealth(observer, List.of(APP_A), LONG_DURATION); + watchdog.onPackageFailure(List.of(new VersionedPackage(APP_A, VERSION_CODE)), + PackageWatchdog.FAILURE_REASON_UNKNOWN); + mTestLooper.dispatchAll(); + assertThat(observer.mMitigatedPackages).isEqualTo(List.of(APP_A)); + } + private void adoptShellPermissions(String... permissions) { InstrumentationRegistry .getInstrumentation() diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 4bfb51bca20e..83399b8076af 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -307,6 +307,8 @@ public class ConnectivityServiceTest { private static final long TIMESTAMP = 1234L; + private static final int NET_ID = 110; + private static final String CLAT_PREFIX = "v4-"; private static final String MOBILE_IFNAME = "test_rmnet_data0"; private static final String WIFI_IFNAME = "test_wlan0"; @@ -1015,6 +1017,7 @@ public class ConnectivityServiceTest { private int mVpnType = VpnManager.TYPE_VPN_SERVICE; private VpnInfo mVpnInfo; + private Network[] mUnderlyingNetworks; public MockVpn(int userId) { super(startHandlerThreadAndReturnLooper(), mServiceContext, mNetworkManagementService, @@ -1104,9 +1107,21 @@ public class ConnectivityServiceTest { return super.getVpnInfo(); } - private void setVpnInfo(VpnInfo vpnInfo) { + private synchronized void setVpnInfo(VpnInfo vpnInfo) { mVpnInfo = vpnInfo; } + + @Override + public synchronized Network[] getUnderlyingNetworks() { + if (mUnderlyingNetworks != null) return mUnderlyingNetworks; + + return super.getUnderlyingNetworks(); + } + + /** Don't override behavior for {@link Vpn#setUnderlyingNetworks}. */ + private synchronized void overrideUnderlyingNetworks(Network[] underlyingNetworks) { + mUnderlyingNetworks = underlyingNetworks; + } } private void mockVpn(int uid) { @@ -6795,15 +6810,11 @@ public class ConnectivityServiceTest { mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED); - try { - assertFalse( - "Mismatched uid/package name should not pass the location permission check", - mService.checkConnectivityDiagnosticsPermissions( - Process.myPid() + 1, Process.myUid() + 1, naiWithoutUid, - mContext.getOpPackageName())); - } catch (SecurityException e) { - fail("checkConnectivityDiagnosticsPermissions shouldn't surface a SecurityException"); - } + assertFalse( + "Mismatched uid/package name should not pass the location permission check", + mService.checkConnectivityDiagnosticsPermissions( + Process.myPid() + 1, Process.myUid() + 1, naiWithoutUid, + mContext.getOpPackageName())); } @Test @@ -6824,9 +6835,10 @@ public class ConnectivityServiceTest { @Test public void testCheckConnectivityDiagnosticsPermissionsActiveVpn() throws Exception { + final Network network = new Network(NET_ID); final NetworkAgentInfo naiWithoutUid = new NetworkAgentInfo( - null, null, null, null, null, new NetworkCapabilities(), 0, + null, null, network, null, null, new NetworkCapabilities(), 0, mServiceContext, null, null, mService, null, null, null, 0); setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION, @@ -6839,11 +6851,19 @@ public class ConnectivityServiceTest { info.ownerUid = Process.myUid(); info.vpnIface = "interface"; mMockVpn.setVpnInfo(info); + mMockVpn.overrideUnderlyingNetworks(new Network[] {network}); assertTrue( "Active VPN permission not applied", mService.checkConnectivityDiagnosticsPermissions( Process.myPid(), Process.myUid(), naiWithoutUid, mContext.getOpPackageName())); + + mMockVpn.overrideUnderlyingNetworks(null); + assertFalse( + "VPN shouldn't receive callback on non-underlying network", + mService.checkConnectivityDiagnosticsPermissions( + Process.myPid(), Process.myUid(), naiWithoutUid, + mContext.getOpPackageName())); } @Test diff --git a/wifi/Android.bp b/wifi/Android.bp index d0f1a26f7dbf..614786193a18 100644 --- a/wifi/Android.bp +++ b/wifi/Android.bp @@ -81,7 +81,6 @@ java_library { libs: [ "framework-annotations-lib", "unsupportedappusage", // for android.compat.annotation.UnsupportedAppUsage - "unsupportedappusage-annotation", // for dalvik.annotation.compat.UnsupportedAppUsage "framework-telephony-stubs", ], srcs: [ |