diff options
57 files changed, 697 insertions, 758 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/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 aca06fe4d3a6..07dba53884dd 100644 --- a/api/current.txt +++ b/api/current.txt @@ -24357,7 +24357,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 { @@ -24375,16 +24375,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 { @@ -24699,7 +24699,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 { @@ -26400,7 +26400,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); @@ -26436,6 +26436,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"; } @@ -30347,6 +30348,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; } @@ -37145,11 +37147,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 @@ -37159,9 +37160,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(); @@ -37172,6 +37173,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 { diff --git a/api/system-current.txt b/api/system-current.txt index e5fd4d39e758..38c265bd50b3 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 { 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/NamedParcelFileDescriptor.aidl b/core/java/android/content/pm/NamedParcelFileDescriptor.aidl deleted file mode 100644 index 68dd5f54654b..000000000000 --- a/core/java/android/content/pm/NamedParcelFileDescriptor.aidl +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.content.pm; - -import android.os.ParcelFileDescriptor; - -/** - * A named ParcelFileDescriptor. - * @hide - */ -parcelable NamedParcelFileDescriptor { - @utf8InCpp String name; - ParcelFileDescriptor fd; -} 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/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..d2a03f0ff166 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 */ 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/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto index a3313b21131d..d09273cdd369 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; diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index e3a73377e365..28dcc2fdb573 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -4424,4 +4424,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/symbols.xml b/core/res/res/values/symbols.xml index 22caf4c2a37d..646ffabedb8d 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -3953,4 +3953,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/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/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/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java index d320df9c24ba..3c0ddc4b65c5 100644 --- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java +++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java @@ -163,6 +163,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..3e64a378bc6a 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); @@ -248,7 +246,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..6fba15f5381f 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); 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/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/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/systemui/bubbles/BadgedImageView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BadgedImageView.java index a1cb7f61ad04..0b59ebcd57e9 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, + } - // Flyout gets shown before the dot - private int mCurrentDotState = DOT_STATE_SUPPRESSED_FOR_FLYOUT; + /** + * 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); + + 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(); @@ -88,23 +103,21 @@ public class BadgedImageView extends ImageView { /** * 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 +128,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 +217,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 +232,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 +267,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/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/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/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/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/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index e304bca4553c..3ddee29366c7 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -15742,9 +15742,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/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/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/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: [ |