diff options
529 files changed, 10607 insertions, 8775 deletions
diff --git a/Android.bp b/Android.bp index c571fa0e5cfc..4c07fcf2c17f 100644 --- a/Android.bp +++ b/Android.bp @@ -248,7 +248,6 @@ java_defaults { "core/java/android/os/ICancellationSignal.aidl", "core/java/android/os/IDeviceIdentifiersPolicyService.aidl", "core/java/android/os/IDeviceIdleController.aidl", - "core/java/android/os/IDynamicAndroidService.aidl", "core/java/android/os/IHardwarePropertiesManager.aidl", ":libincident_aidl", "core/java/android/os/IMaintenanceActivityListener.aidl", @@ -272,6 +271,7 @@ java_defaults { "core/java/android/os/IUserManager.aidl", ":libvibrator_aidl", "core/java/android/os/IVibratorService.aidl", + "core/java/android/os/image/IDynamicSystemService.aidl", "core/java/android/os/storage/IStorageManager.aidl", "core/java/android/os/storage/IStorageEventListener.aidl", "core/java/android/os/storage/IStorageShutdownObserver.aidl", @@ -886,66 +886,6 @@ gensrcs { output_extension: "srcjar", } -// AIDL interfaces between the core system and the networking mainline module. -aidl_interface { - name: "networkstack-aidl-interfaces", - local_include_dir: "core/java", - srcs: [ - "core/java/android/net/ApfCapabilitiesParcelable.aidl", - "core/java/android/net/DhcpResultsParcelable.aidl", - "core/java/android/net/INetworkMonitor.aidl", - "core/java/android/net/INetworkMonitorCallbacks.aidl", - "core/java/android/net/INetworkStackConnector.aidl", - "core/java/android/net/INetworkStackStatusCallback.aidl", - "core/java/android/net/InitialConfigurationParcelable.aidl", - "core/java/android/net/PrivateDnsConfigParcel.aidl", - "core/java/android/net/ProvisioningConfigurationParcelable.aidl", - "core/java/android/net/StaticIpConfigurationParcelable.aidl", - "core/java/android/net/TcpKeepalivePacketDataParcelable.aidl", - "core/java/android/net/dhcp/DhcpServingParamsParcel.aidl", - "core/java/android/net/dhcp/IDhcpServer.aidl", - "core/java/android/net/dhcp/IDhcpServerCallbacks.aidl", - "core/java/android/net/ip/IIpClient.aidl", - "core/java/android/net/ip/IIpClientCallbacks.aidl", - "core/java/android/net/IIpMemoryStore.aidl", - "core/java/android/net/IIpMemoryStoreCallbacks.aidl", - "core/java/android/net/ipmemorystore/**/*.aidl", - ], - backend: { - ndk: { - enabled: false, - }, - cpp: { - enabled: false, - }, - }, - api_dir: "aidl/networkstack", -} - -aidl_interface { - name: "ipmemorystore-aidl-interfaces", - local_include_dir: "core/java", - srcs: [ - "core/java/android/net/IIpMemoryStore.aidl", - "core/java/android/net/IIpMemoryStoreCallbacks.aidl", - "core/java/android/net/ipmemorystore/**/*.aidl", - ], -} - -aidl_interface { - name: "networkstack-aidl-framework", - local_include_dir: "core/java", - srcs: [ - "core/java/android/net/TcpKeepalivePacketDataParcelable.aidl", - ], - api_dir: "aidl/networkstack", - backend: { - java: { - sdk_version: "28", - }, - }, -} - filegroup { name: "framework-annotations", srcs: [ @@ -1685,6 +1625,7 @@ droidstubs { srcs: [ ":openjdk_java_files", ":non_openjdk_java_files", + ":opt-telephony-common-srcs", ], arg_files: [ "core/res/AndroidManifest.xml", diff --git a/api/current.txt b/api/current.txt index af17508c2bf6..87a0125eb49a 100644 --- a/api/current.txt +++ b/api/current.txt @@ -5485,7 +5485,6 @@ package android.app { method @NonNull public android.graphics.drawable.Icon getIcon(); method @NonNull public android.app.PendingIntent getIntent(); method public boolean getSuppressInitialNotification(); - method @Deprecated public CharSequence getTitle(); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.app.Notification.BubbleMetadata> CREATOR; } @@ -5500,7 +5499,6 @@ package android.app { method @NonNull public android.app.Notification.BubbleMetadata.Builder setIcon(@NonNull android.graphics.drawable.Icon); method @NonNull public android.app.Notification.BubbleMetadata.Builder setIntent(@NonNull android.app.PendingIntent); method @NonNull public android.app.Notification.BubbleMetadata.Builder setSuppressInitialNotification(boolean); - method @Deprecated public android.app.Notification.BubbleMetadata.Builder setTitle(CharSequence); } public static class Notification.Builder { @@ -5850,8 +5848,8 @@ package android.app { field public static final int INTERRUPTION_FILTER_NONE = 3; // 0x3 field public static final int INTERRUPTION_FILTER_PRIORITY = 2; // 0x2 field public static final int INTERRUPTION_FILTER_UNKNOWN = 0; // 0x0 - field public static final String META_DATA_AUTOMATIC_RULE_TYPE = "android.app.automatic.ruleType"; - field public static final String META_DATA_RULE_INSTANCE_LIMIT = "android.app.zen.automatic.ruleInstanceLimit"; + field public static final String META_DATA_AUTOMATIC_RULE_TYPE = "android.service.zen.automatic.ruleType"; + field public static final String META_DATA_RULE_INSTANCE_LIMIT = "android.service.zen.automatic.ruleInstanceLimit"; } public static class NotificationManager.Policy implements android.os.Parcelable { @@ -9796,6 +9794,7 @@ package android.content { field public static final int BIND_DEBUG_UNBIND = 2; // 0x2 field public static final int BIND_EXTERNAL_SERVICE = -2147483648; // 0x80000000 field public static final int BIND_IMPORTANT = 64; // 0x40 + field public static final int BIND_INCLUDE_CAPABILITIES = 4096; // 0x1000 field public static final int BIND_NOT_FOREGROUND = 4; // 0x4 field public static final int BIND_WAIVE_PRIORITY = 32; // 0x20 field public static final String BIOMETRIC_SERVICE = "biometric"; @@ -11600,6 +11599,7 @@ package android.content.pm { method public abstract android.content.pm.ServiceInfo getServiceInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException; method @NonNull public abstract java.util.List<android.content.pm.SharedLibraryInfo> getSharedLibraries(int); method @Nullable public android.os.Bundle getSuspendedPackageAppExtras(); + method public boolean getSyntheticAppDetailsActivityEnabled(@NonNull String); method public abstract android.content.pm.FeatureInfo[] getSystemAvailableFeatures(); method public abstract String[] getSystemSharedLibraryNames(); method public abstract CharSequence getText(String, @StringRes int, android.content.pm.ApplicationInfo); @@ -23250,7 +23250,7 @@ package android.media { method public static boolean isHapticPlaybackSupported(); method public boolean isMicrophoneMute(); method public boolean isMusicActive(); - method public static boolean isOffloadedPlaybackSupported(@NonNull android.media.AudioFormat); + method public static boolean isOffloadedPlaybackSupported(@NonNull android.media.AudioFormat, @NonNull android.media.AudioAttributes); method public boolean isSpeakerphoneOn(); method public boolean isStreamMute(int); method public boolean isVolumeFixed(); @@ -23403,15 +23403,16 @@ package android.media { } public final class AudioPlaybackCaptureConfiguration { + method @NonNull public android.media.projection.MediaProjection getMediaProjection(); } public static final class AudioPlaybackCaptureConfiguration.Builder { ctor public AudioPlaybackCaptureConfiguration.Builder(@NonNull android.media.projection.MediaProjection); method @NonNull public android.media.AudioPlaybackCaptureConfiguration.Builder addMatchingUid(int); - method @NonNull public android.media.AudioPlaybackCaptureConfiguration.Builder addMatchingUsage(@NonNull android.media.AudioAttributes); + method @NonNull public android.media.AudioPlaybackCaptureConfiguration.Builder addMatchingUsage(int); method @NonNull public android.media.AudioPlaybackCaptureConfiguration build(); method @NonNull public android.media.AudioPlaybackCaptureConfiguration.Builder excludeUid(int); - method @NonNull public android.media.AudioPlaybackCaptureConfiguration.Builder excludeUsage(@NonNull android.media.AudioAttributes); + method @NonNull public android.media.AudioPlaybackCaptureConfiguration.Builder excludeUsage(int); } public final class AudioPlaybackConfiguration implements android.os.Parcelable { @@ -23484,11 +23485,11 @@ package android.media { method public void release(); method public void removeOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener); method @Deprecated public void removeOnRoutingChangedListener(android.media.AudioRecord.OnRoutingChangedListener); - method public boolean setMicrophoneDirection(int); - method public boolean setMicrophoneFieldDimension(@FloatRange(from=-1.0, to=1.0) float); method public int setNotificationMarkerPosition(int); method public int setPositionNotificationPeriod(int); method public boolean setPreferredDevice(android.media.AudioDeviceInfo); + method public boolean setPreferredMicrophoneDirection(int); + method public boolean setPreferredMicrophoneFieldDimension(@FloatRange(from=-1.0, to=1.0) float); method public void setRecordPositionUpdateListener(android.media.AudioRecord.OnRecordPositionUpdateListener); method public void setRecordPositionUpdateListener(android.media.AudioRecord.OnRecordPositionUpdateListener, android.os.Handler); method public void startRecording() throws java.lang.IllegalStateException; @@ -23708,17 +23709,6 @@ package android.media { method public void onTearDown(@NonNull android.media.AudioTrack); } - public class CallbackDataSourceDesc extends android.media.DataSourceDesc { - method @NonNull public android.media.DataSourceCallback getDataSourceCallback(); - } - - public static class CallbackDataSourceDesc.Builder extends android.media.DataSourceDesc.BuilderBase<android.media.CallbackDataSourceDesc.Builder> { - ctor public CallbackDataSourceDesc.Builder(); - ctor public CallbackDataSourceDesc.Builder(@Nullable android.media.CallbackDataSourceDesc); - method @NonNull public android.media.CallbackDataSourceDesc build(); - method @NonNull public android.media.CallbackDataSourceDesc.Builder setDataSource(@NonNull android.media.DataSourceCallback); - } - public class CamcorderProfile { method public static android.media.CamcorderProfile get(int); method public static android.media.CamcorderProfile get(int, int); @@ -23771,12 +23761,6 @@ package android.media { field public static final int QUALITY_MEDIUM = 1; // 0x1 } - public abstract class DataSourceCallback implements java.io.Closeable { - ctor public DataSourceCallback(); - method public abstract long getSize() throws java.io.IOException; - method public abstract int readAt(long, @NonNull byte[], int, int) throws java.io.IOException; - } - public class DataSourceDesc { method public long getEndPosition(); method @Nullable public String getMediaId(); @@ -23785,10 +23769,17 @@ package android.media { field public static final long POSITION_UNKNOWN = 576460752303423L; // 0x20c49ba5e353fL } - protected static class DataSourceDesc.BuilderBase<T extends android.media.DataSourceDesc.BuilderBase> { - method @NonNull public T setEndPosition(long); - method @NonNull public T setMediaId(@Nullable String); - method @NonNull public T setStartPosition(long); + public static final class DataSourceDesc.Builder { + ctor public DataSourceDesc.Builder(); + ctor public DataSourceDesc.Builder(@Nullable android.media.DataSourceDesc); + method @NonNull public android.media.DataSourceDesc build(); + method @NonNull public android.media.DataSourceDesc.Builder setDataSource(@NonNull android.net.Uri); + method @NonNull public android.media.DataSourceDesc.Builder setDataSource(@NonNull android.net.Uri, @Nullable java.util.Map<java.lang.String,java.lang.String>, @Nullable java.util.List<java.net.HttpCookie>); + method @NonNull public android.media.DataSourceDesc.Builder setDataSource(@NonNull android.os.ParcelFileDescriptor); + method @NonNull public android.media.DataSourceDesc.Builder setDataSource(@NonNull android.os.ParcelFileDescriptor, long, long); + method @NonNull public android.media.DataSourceDesc.Builder setEndPosition(long); + method @NonNull public android.media.DataSourceDesc.Builder setMediaId(@Nullable String); + method @NonNull public android.media.DataSourceDesc.Builder setStartPosition(long); } public final class DeniedByServerException extends android.media.MediaDrmException { @@ -23993,21 +23984,6 @@ package android.media { field public static final int EULER_Z = 2; // 0x2 } - public class FileDataSourceDesc extends android.media.DataSourceDesc { - method public long getLength(); - method public long getOffset(); - method @NonNull public android.os.ParcelFileDescriptor getParcelFileDescriptor(); - field public static final long FD_LENGTH_UNKNOWN = 576460752303423487L; // 0x7ffffffffffffffL - } - - public static class FileDataSourceDesc.Builder extends android.media.DataSourceDesc.BuilderBase<android.media.FileDataSourceDesc.Builder> { - ctor public FileDataSourceDesc.Builder(); - ctor public FileDataSourceDesc.Builder(@Nullable android.media.FileDataSourceDesc); - method @NonNull public android.media.FileDataSourceDesc build(); - method @NonNull public android.media.FileDataSourceDesc.Builder setDataSource(@NonNull android.os.ParcelFileDescriptor); - method @NonNull public android.media.FileDataSourceDesc.Builder setDataSource(@NonNull android.os.ParcelFileDescriptor, long, long); - } - public abstract class Image implements java.lang.AutoCloseable { method public abstract void close(); method public android.graphics.Rect getCropRect(); @@ -24943,6 +24919,7 @@ package android.media { ctor public MediaDrm.SessionException(int, @Nullable String); method public int getErrorCode(); field public static final int ERROR_RESOURCE_CONTENTION = 1; // 0x1 + field public static final int ERROR_UNKNOWN = 0; // 0x0 } public class MediaDrmException extends java.lang.Exception { @@ -25072,6 +25049,7 @@ package android.media { field public static final String KEY_FRAME_RATE = "frame-rate"; field public static final String KEY_GRID_COLUMNS = "grid-cols"; field public static final String KEY_GRID_ROWS = "grid-rows"; + field public static final String KEY_HAPTIC_CHANNEL_COUNT = "haptic-channel-count"; field public static final String KEY_HDR10_PLUS_INFO = "hdr10-plus-info"; field public static final String KEY_HDR_STATIC_INFO = "hdr-static-info"; field public static final String KEY_HEIGHT = "height"; @@ -25094,6 +25072,7 @@ package android.media { field public static final String KEY_OPERATING_RATE = "operating-rate"; field public static final String KEY_OUTPUT_REORDER_DEPTH = "output-reorder-depth"; field public static final String KEY_PCM_ENCODING = "pcm-encoding"; + field public static final String KEY_PREPEND_HEADER_TO_SYNC_FRAMES = "prepend-sps-pps-to-idr-frames"; field public static final String KEY_PRIORITY = "priority"; field public static final String KEY_PROFILE = "profile"; field public static final String KEY_PUSH_BLANK_BUFFERS_ON_STOP = "push-blank-buffers-on-shutdown"; @@ -25569,8 +25548,8 @@ package android.media { method @NonNull public Object clearNextDataSources(); method public void clearPendingCommands(); method public void close(); - method @NonNull public Object deselectTrack(int); - method @NonNull public Object deselectTrack(@NonNull android.media.DataSourceDesc, int); + method @NonNull public Object deselectTrack(@NonNull android.media.MediaPlayer2.TrackInfo); + method @NonNull public Object deselectTrack(@NonNull android.media.DataSourceDesc, @NonNull android.media.MediaPlayer2.TrackInfo); method @NonNull public android.media.AudioAttributes getAudioAttributes(); method public int getAudioSessionId(); method public long getBufferedPosition(); @@ -25585,8 +25564,8 @@ package android.media { method public float getPlayerVolume(); method @Nullable public android.media.AudioDeviceInfo getPreferredDevice(); method @Nullable public android.media.AudioDeviceInfo getRoutedDevice(); - method public int getSelectedTrack(int); - method public int getSelectedTrack(@NonNull android.media.DataSourceDesc, int); + method @Nullable public android.media.MediaPlayer2.TrackInfo getSelectedTrack(int); + method @Nullable public android.media.MediaPlayer2.TrackInfo getSelectedTrack(@NonNull android.media.DataSourceDesc, int); method public int getState(); method @NonNull public android.media.SyncParams getSyncParams(); method @Nullable public android.media.MediaTimestamp getTimestamp(); @@ -25604,8 +25583,8 @@ package android.media { method public void reset(); method @NonNull public Object seekTo(long); method @NonNull public Object seekTo(long, int); - method @NonNull public Object selectTrack(int); - method @NonNull public Object selectTrack(@NonNull android.media.DataSourceDesc, int); + method @NonNull public Object selectTrack(@NonNull android.media.MediaPlayer2.TrackInfo); + method @NonNull public Object selectTrack(@NonNull android.media.DataSourceDesc, @NonNull android.media.MediaPlayer2.TrackInfo); method @NonNull public Object setAudioAttributes(@NonNull android.media.AudioAttributes); method @NonNull public Object setAudioSessionId(int); method @NonNull public Object setAuxEffectSendLevel(float); @@ -25698,11 +25677,11 @@ package android.media { field public static final int SEEK_PREVIOUS_SYNC = 0; // 0x0 } - public static class MediaPlayer2.DrmEventCallback { + public abstract static class MediaPlayer2.DrmEventCallback { ctor public MediaPlayer2.DrmEventCallback(); method public void onDrmConfig(@NonNull android.media.MediaPlayer2, @NonNull android.media.DataSourceDesc, @NonNull android.media.MediaDrm); - method @Nullable public android.media.MediaPlayer2.DrmPreparationInfo onDrmInfo(@NonNull android.media.MediaPlayer2, @NonNull android.media.DataSourceDesc, @NonNull android.media.MediaPlayer2.DrmInfo); - method @NonNull public byte[] onDrmKeyRequest(@NonNull android.media.MediaPlayer2, @NonNull android.media.DataSourceDesc, @NonNull android.media.MediaDrm.KeyRequest); + method @Nullable public abstract android.media.MediaPlayer2.DrmPreparationInfo onDrmInfo(@NonNull android.media.MediaPlayer2, @NonNull android.media.DataSourceDesc, @NonNull android.media.MediaPlayer2.DrmInfo); + method @NonNull public abstract byte[] onDrmKeyRequest(@NonNull android.media.MediaPlayer2, @NonNull android.media.DataSourceDesc, @NonNull android.media.MediaDrm.KeyRequest); method public void onDrmPrepared(@NonNull android.media.MediaPlayer2, @NonNull android.media.DataSourceDesc, int, @Nullable byte[]); } @@ -25712,17 +25691,22 @@ package android.media { } public static final class MediaPlayer2.DrmPreparationInfo { + method @Nullable public byte[] getInitData(); + method @Nullable public byte[] getKeySetId(); + method public int getKeyType(); + method @Nullable public String getMimeType(); + method @Nullable public java.util.Map<java.lang.String,java.lang.String> getOptionalParameters(); + method @NonNull public java.util.UUID getUuid(); } public static final class MediaPlayer2.DrmPreparationInfo.Builder { - ctor public MediaPlayer2.DrmPreparationInfo.Builder(); + ctor public MediaPlayer2.DrmPreparationInfo.Builder(@NonNull java.util.UUID); method @NonNull public android.media.MediaPlayer2.DrmPreparationInfo build(); method @NonNull public android.media.MediaPlayer2.DrmPreparationInfo.Builder setInitData(@Nullable byte[]); method @NonNull public android.media.MediaPlayer2.DrmPreparationInfo.Builder setKeySetId(@Nullable byte[]); method @NonNull public android.media.MediaPlayer2.DrmPreparationInfo.Builder setKeyType(int); method @NonNull public android.media.MediaPlayer2.DrmPreparationInfo.Builder setMimeType(@Nullable String); method @NonNull public android.media.MediaPlayer2.DrmPreparationInfo.Builder setOptionalParameters(@Nullable java.util.Map<java.lang.String,java.lang.String>); - method @NonNull public android.media.MediaPlayer2.DrmPreparationInfo.Builder setUuid(@NonNull java.util.UUID); } public static class MediaPlayer2.EventCallback { @@ -25732,7 +25716,7 @@ package android.media { method public void onError(@NonNull android.media.MediaPlayer2, @NonNull android.media.DataSourceDesc, int, int); method public void onInfo(@NonNull android.media.MediaPlayer2, @NonNull android.media.DataSourceDesc, int, int); method public void onMediaTimeDiscontinuity(@NonNull android.media.MediaPlayer2, @NonNull android.media.DataSourceDesc, @NonNull android.media.MediaTimestamp); - method public void onSubtitleData(@NonNull android.media.MediaPlayer2, @NonNull android.media.DataSourceDesc, @NonNull android.media.SubtitleData); + method public void onSubtitleData(@NonNull android.media.MediaPlayer2, @NonNull android.media.DataSourceDesc, @NonNull android.media.MediaPlayer2.SubtitleData); method public void onTimedMetaDataAvailable(@NonNull android.media.MediaPlayer2, @NonNull android.media.DataSourceDesc, @NonNull android.media.TimedMetaData); method public void onVideoSizeChanged(@NonNull android.media.MediaPlayer2, @NonNull android.media.DataSourceDesc, @NonNull android.util.Size); } @@ -25756,6 +25740,13 @@ package android.media { ctor public MediaPlayer2.NoDrmSchemeException(@Nullable String); } + public static final class MediaPlayer2.SubtitleData { + method @NonNull public byte[] getData(); + method public long getDurationUs(); + method public long getStartTimeUs(); + method @NonNull public android.media.MediaPlayer2.TrackInfo getTrackInfo(); + } + public static class MediaPlayer2.TrackInfo { method @Nullable public android.media.MediaFormat getFormat(); method @NonNull public String getLanguage(); @@ -25797,8 +25788,6 @@ package android.media { method public void setLocation(float, float); method public void setMaxDuration(int) throws java.lang.IllegalArgumentException; method public void setMaxFileSize(long) throws java.lang.IllegalArgumentException; - method public boolean setMicrophoneDirection(int); - method public boolean setMicrophoneFieldDimension(@FloatRange(from=-1.0, to=1.0) float); method public void setNextOutputFile(java.io.FileDescriptor) throws java.io.IOException; method public void setNextOutputFile(java.io.File) throws java.io.IOException; method public void setOnErrorListener(android.media.MediaRecorder.OnErrorListener); @@ -25809,6 +25798,8 @@ package android.media { method public void setOutputFile(String) throws java.lang.IllegalStateException; method public void setOutputFormat(int) throws java.lang.IllegalStateException; method public boolean setPreferredDevice(android.media.AudioDeviceInfo); + method public boolean setPreferredMicrophoneDirection(int); + method public boolean setPreferredMicrophoneFieldDimension(@FloatRange(from=-1.0, to=1.0) float); method public void setPreviewDisplay(android.view.Surface); method public void setProfile(android.media.CamcorderProfile); method public void setVideoEncoder(int) throws java.lang.IllegalStateException; @@ -26143,19 +26134,20 @@ package android.media { } public final class MediaTimestamp { + ctor public MediaTimestamp(long, long, @FloatRange(from=0.0f, to=java.lang.Float.MAX_VALUE) float); method public long getAnchorMediaTimeUs(); method public long getAnchorSystemNanoTime(); method @Deprecated public long getAnchorSytemNanoTime(); - method public float getMediaClockRate(); + method @FloatRange(from=0.0f, to=java.lang.Float.MAX_VALUE) public float getMediaClockRate(); field public static final android.media.MediaTimestamp TIMESTAMP_UNKNOWN; } public interface MicrophoneDirection { - method public boolean setMicrophoneDirection(int); - method public boolean setMicrophoneFieldDimension(@FloatRange(from=-1.0, to=1.0) float); - field public static final int MIC_DIRECTION_BACK = 2; // 0x2 + method public boolean setPreferredMicrophoneDirection(int); + method public boolean setPreferredMicrophoneFieldDimension(@FloatRange(from=-1.0, to=1.0) float); + field public static final int MIC_DIRECTION_AWAY_FROM_USER = 2; // 0x2 field public static final int MIC_DIRECTION_EXTERNAL = 3; // 0x3 - field public static final int MIC_DIRECTION_FRONT = 1; // 0x1 + field public static final int MIC_DIRECTION_TOWARDS_USER = 1; // 0x1 field public static final int MIC_DIRECTION_UNSPECIFIED = 0; // 0x0 } @@ -26360,6 +26352,8 @@ package android.media { method public android.net.Uri getRingtoneUri(int); method public boolean getStopPreviousRingtone(); method public static android.net.Uri getValidRingtoneUri(android.content.Context); + method public boolean hasHapticChannels(int); + method public static boolean hasHapticChannels(@NonNull android.net.Uri); method public int inferStreamType(); method public static boolean isDefault(android.net.Uri); method @Nullable public static android.content.res.AssetFileDescriptor openDefaultRingtoneUri(@NonNull android.content.Context, @NonNull android.net.Uri) throws java.io.FileNotFoundException; @@ -26420,10 +26414,8 @@ package android.media { ctor public Session2CommandGroup.Builder(); ctor public Session2CommandGroup.Builder(@NonNull android.media.Session2CommandGroup); method @NonNull public android.media.Session2CommandGroup.Builder addCommand(@NonNull android.media.Session2Command); - method @NonNull public android.media.Session2CommandGroup.Builder addCommand(int); method @NonNull public android.media.Session2CommandGroup build(); method @NonNull public android.media.Session2CommandGroup.Builder removeCommand(@NonNull android.media.Session2Command); - method @NonNull public android.media.Session2CommandGroup.Builder removeCommand(int); } public final class Session2Token implements android.os.Parcelable { @@ -26474,6 +26466,7 @@ package android.media { } public final class SubtitleData { + ctor public SubtitleData(int, long, long, @NonNull byte[]); method @NonNull public byte[] getData(); method public long getDurationUs(); method public long getStartTimeUs(); @@ -26514,6 +26507,7 @@ package android.media { } public final class TimedMetaData { + ctor public TimedMetaData(long, @NonNull byte[]); method public byte[] getMetaData(); method public long getTimestamp(); } @@ -26638,21 +26632,6 @@ package android.media { ctor public UnsupportedSchemeException(String); } - public class UriDataSourceDesc extends android.media.DataSourceDesc { - method @NonNull public android.content.Context getContext(); - method @Nullable public java.util.List<java.net.HttpCookie> getCookies(); - method @Nullable public java.util.Map<java.lang.String,java.lang.String> getHeaders(); - method @NonNull public android.net.Uri getUri(); - } - - public static class UriDataSourceDesc.Builder extends android.media.DataSourceDesc.BuilderBase<android.media.UriDataSourceDesc.Builder> { - ctor public UriDataSourceDesc.Builder(); - ctor public UriDataSourceDesc.Builder(@Nullable android.media.UriDataSourceDesc); - method @NonNull public android.media.UriDataSourceDesc build(); - method @NonNull public android.media.UriDataSourceDesc.Builder setDataSource(@NonNull android.content.Context, @NonNull android.net.Uri); - method @NonNull public android.media.UriDataSourceDesc.Builder setDataSource(@NonNull android.content.Context, @NonNull android.net.Uri, @Nullable java.util.Map<java.lang.String,java.lang.String>, @Nullable java.util.List<java.net.HttpCookie>); - } - public interface VolumeAutomation { method @NonNull public android.media.VolumeShaper createVolumeShaper(@NonNull android.media.VolumeShaper.Configuration); } @@ -28761,8 +28740,8 @@ package android.net { public final class DnsResolver { method @NonNull public static android.net.DnsResolver getInstance(); - method public <T> void query(@Nullable android.net.Network, @NonNull byte[], int, @NonNull java.util.concurrent.Executor, @NonNull android.net.DnsResolver.AnswerCallback<T>); - method public <T> void query(@Nullable android.net.Network, @NonNull String, int, int, int, @NonNull java.util.concurrent.Executor, @NonNull android.net.DnsResolver.AnswerCallback<T>); + method public <T> void query(@Nullable android.net.Network, @NonNull byte[], int, @NonNull java.util.concurrent.Executor, @Nullable android.os.CancellationSignal, @NonNull android.net.DnsResolver.AnswerCallback<T>); + method public <T> void query(@Nullable android.net.Network, @NonNull String, int, int, int, @NonNull java.util.concurrent.Executor, @Nullable android.os.CancellationSignal, @NonNull android.net.DnsResolver.AnswerCallback<T>); field public static final int CLASS_IN = 1; // 0x1 field public static final int FLAG_EMPTY = 0; // 0x0 field public static final int FLAG_NO_CACHE_LOOKUP = 4; // 0x4 @@ -28881,16 +28860,25 @@ package android.net { } public final class LinkProperties implements android.os.Parcelable { + ctor public LinkProperties(); + method public boolean addRoute(@NonNull android.net.RouteInfo); + method public void clear(); method public int describeContents(); - method public java.util.List<java.net.InetAddress> getDnsServers(); - method public String getDomains(); - method public android.net.ProxyInfo getHttpProxy(); + method @NonNull public java.util.List<java.net.InetAddress> getDnsServers(); + method @Nullable public String getDomains(); + method @Nullable public android.net.ProxyInfo getHttpProxy(); method @Nullable public String getInterfaceName(); - method public java.util.List<android.net.LinkAddress> getLinkAddresses(); + method @NonNull public java.util.List<android.net.LinkAddress> getLinkAddresses(); method public int getMtu(); method @Nullable public String getPrivateDnsServerName(); - method public java.util.List<android.net.RouteInfo> getRoutes(); + method @NonNull public java.util.List<android.net.RouteInfo> getRoutes(); method public boolean isPrivateDnsActive(); + method public void setDnsServers(@NonNull java.util.Collection<java.net.InetAddress>); + method public void setDomains(@Nullable String); + method public void setHttpProxy(@Nullable android.net.ProxyInfo); + method public void setInterfaceName(@Nullable String); + method public void setLinkAddresses(@NonNull java.util.Collection<android.net.LinkAddress>); + method public void setMtu(int); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.net.LinkProperties> CREATOR; } @@ -28998,6 +28986,7 @@ package android.net { method public int describeContents(); method public int getLinkDownstreamBandwidthKbps(); method public int getLinkUpstreamBandwidthKbps(); + method public int getSignalStrength(); method @Nullable public android.net.TransportInfo getTransportInfo(); method public boolean hasCapability(int); method public boolean hasTransport(int); @@ -29026,6 +29015,7 @@ package android.net { field public static final int NET_CAPABILITY_VALIDATED = 16; // 0x10 field public static final int NET_CAPABILITY_WIFI_P2P = 6; // 0x6 field public static final int NET_CAPABILITY_XCAP = 9; // 0x9 + field public static final int SIGNAL_STRENGTH_UNSPECIFIED = -2147483648; // 0x80000000 field public static final int TRANSPORT_BLUETOOTH = 2; // 0x2 field public static final int TRANSPORT_CELLULAR = 0; // 0x0 field public static final int TRANSPORT_ETHERNET = 3; // 0x3 @@ -29037,7 +29027,7 @@ package android.net { @Deprecated public class NetworkInfo implements android.os.Parcelable { method @Deprecated public int describeContents(); - method @Deprecated public android.net.NetworkInfo.DetailedState getDetailedState(); + method @Deprecated @NonNull public android.net.NetworkInfo.DetailedState getDetailedState(); method @Deprecated public String getExtraInfo(); method @Deprecated public String getReason(); method @Deprecated public android.net.NetworkInfo.State getState(); @@ -30319,13 +30309,11 @@ package android.net.wifi.aware { } public static final class WifiAwareNetworkSpecifier.Builder { - ctor public WifiAwareNetworkSpecifier.Builder(); + ctor public WifiAwareNetworkSpecifier.Builder(@NonNull android.net.wifi.aware.DiscoverySession, @NonNull android.net.wifi.aware.PeerHandle); method @NonNull public android.net.wifi.aware.WifiAwareNetworkSpecifier build(); - method @NonNull public android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder setDiscoverySession(@NonNull android.net.wifi.aware.DiscoverySession); - method @NonNull public android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder setPeerHandle(@NonNull android.net.wifi.aware.PeerHandle); - method @NonNull public android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder setPort(int); + method @NonNull public android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder setPort(@IntRange(from=0, to=65535) int); method @NonNull public android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder setPskPassphrase(@NonNull String); - method @NonNull public android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder setTransportProtocol(int); + method @NonNull public android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder setTransportProtocol(@IntRange(from=0, to=255) int); } public class WifiAwareSession implements java.lang.AutoCloseable { @@ -34622,6 +34610,7 @@ package android.os { method @RequiresPermission(allOf={android.Manifest.permission.READ_LOGS, android.Manifest.permission.PACKAGE_USAGE_STATS}) @Nullable public android.os.DropBoxManager.Entry getNextEntry(String, long); method public boolean isTagEnabled(String); field public static final String ACTION_DROPBOX_ENTRY_ADDED = "android.intent.action.DROPBOX_ENTRY_ADDED"; + field public static final String EXTRA_DROPPED_COUNT = "android.os.extra.DROPPED_COUNT"; field public static final String EXTRA_TAG = "tag"; field public static final String EXTRA_TIME = "time"; field public static final int IS_EMPTY = 1; // 0x1 @@ -35435,6 +35424,7 @@ package android.os { } public final class SystemClock { + method @NonNull public static java.time.Clock currentGnssTimeClock(); method public static long currentThreadTimeMillis(); method public static long elapsedRealtime(); method public static long elapsedRealtimeNanos(); @@ -38767,8 +38757,7 @@ package android.provider { field public static final String MIME_TYPE = "mime_type"; field public static final String ORIGINAL_DOCUMENT_ID = "original_document_id"; field public static final String OWNER_PACKAGE_NAME = "owner_package_name"; - field public static final String PRIMARY_DIRECTORY = "primary_directory"; - field public static final String SECONDARY_DIRECTORY = "secondary_directory"; + field public static final String RELATIVE_PATH = "relative_path"; field public static final String SIZE = "_size"; field public static final String TITLE = "title"; field public static final String WIDTH = "width"; @@ -42501,12 +42490,12 @@ package android.system { method public static java.io.FileDescriptor accept(java.io.FileDescriptor, java.net.InetSocketAddress) throws android.system.ErrnoException, java.net.SocketException; method public static boolean access(String, int) throws android.system.ErrnoException; method public static void bind(java.io.FileDescriptor, java.net.InetAddress, int) throws android.system.ErrnoException, java.net.SocketException; - method public static void bind(java.io.FileDescriptor, java.net.SocketAddress) throws android.system.ErrnoException, java.net.SocketException; + method public static void bind(@NonNull java.io.FileDescriptor, @NonNull java.net.SocketAddress) throws android.system.ErrnoException, java.net.SocketException; method public static void chmod(String, int) throws android.system.ErrnoException; method public static void chown(String, int, int) throws android.system.ErrnoException; method public static void close(java.io.FileDescriptor) throws android.system.ErrnoException; method public static void connect(java.io.FileDescriptor, java.net.InetAddress, int) throws android.system.ErrnoException, java.net.SocketException; - method public static void connect(java.io.FileDescriptor, java.net.SocketAddress) throws android.system.ErrnoException, java.net.SocketException; + method public static void connect(@NonNull java.io.FileDescriptor, @NonNull java.net.SocketAddress) throws android.system.ErrnoException, java.net.SocketException; method public static java.io.FileDescriptor dup(java.io.FileDescriptor) throws android.system.ErrnoException; method public static java.io.FileDescriptor dup2(java.io.FileDescriptor, int) throws android.system.ErrnoException; method public static String[] environ(); @@ -42571,7 +42560,7 @@ package android.system { method public static long sendfile(java.io.FileDescriptor, java.io.FileDescriptor, android.system.Int64Ref, long) throws android.system.ErrnoException; method public static int sendto(java.io.FileDescriptor, java.nio.ByteBuffer, int, java.net.InetAddress, int) throws android.system.ErrnoException, java.net.SocketException; method public static int sendto(java.io.FileDescriptor, byte[], int, int, int, java.net.InetAddress, int) throws android.system.ErrnoException, java.net.SocketException; - method public static int sendto(java.io.FileDescriptor, byte[], int, int, int, java.net.SocketAddress) throws android.system.ErrnoException, java.net.SocketException; + method public static int sendto(@NonNull java.io.FileDescriptor, @NonNull byte[], int, int, int, @Nullable java.net.SocketAddress) throws android.system.ErrnoException, java.net.SocketException; method @Deprecated public static void setegid(int) throws android.system.ErrnoException; method public static void setenv(String, String, boolean) throws android.system.ErrnoException; method @Deprecated public static void seteuid(int) throws android.system.ErrnoException; @@ -44511,6 +44500,13 @@ package android.telephony { field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CellInfoNr> CREATOR; } + public final class CellInfoTdscdma extends android.telephony.CellInfo implements android.os.Parcelable { + method @NonNull public android.telephony.CellIdentityTdscdma getCellIdentity(); + method @NonNull public android.telephony.CellSignalStrengthTdscdma getCellSignalStrength(); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CellInfoTdscdma> CREATOR; + } + public final class CellInfoWcdma extends android.telephony.CellInfo implements android.os.Parcelable { method public android.telephony.CellIdentityWcdma getCellIdentity(); method public android.telephony.CellSignalStrengthWcdma getCellSignalStrength(); @@ -44594,6 +44590,16 @@ package android.telephony { field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CellSignalStrengthNr> CREATOR; } + public final class CellSignalStrengthTdscdma extends android.telephony.CellSignalStrength implements android.os.Parcelable { + method public int describeContents(); + method public int getAsuLevel(); + method public int getDbm(); + method public int getLevel(); + method public int getRscp(); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CellSignalStrengthTdscdma> CREATOR; + } + public final class CellSignalStrengthWcdma extends android.telephony.CellSignalStrength implements android.os.Parcelable { method public int describeContents(); method public int getAsuLevel(); @@ -45020,7 +45026,7 @@ package android.telephony { method public String getCountryIso(); method public int getDataRoaming(); method public CharSequence getDisplayName(); - method @Nullable public String getGroupUuid(); + method @Nullable public android.os.ParcelUuid getGroupUuid(); method public String getIccId(); method public int getIconTint(); method @Deprecated public int getMcc(); @@ -45040,7 +45046,9 @@ package android.telephony { public class SubscriptionManager { method public void addOnOpportunisticSubscriptionsChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.SubscriptionManager.OnOpportunisticSubscriptionsChangedListener); method public void addOnSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnSubscriptionsChangedListener); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void addSubscriptionsIntoGroup(@NonNull java.util.List<java.lang.Integer>, @NonNull android.os.ParcelUuid); method public boolean canManageSubscription(android.telephony.SubscriptionInfo); + method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.os.ParcelUuid createSubscriptionGroup(@NonNull java.util.List<java.lang.Integer>); method @Deprecated public static android.telephony.SubscriptionManager from(android.content.Context); method public java.util.List<android.telephony.SubscriptionInfo> getAccessibleSubscriptionInfoList(); method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public android.telephony.SubscriptionInfo getActiveSubscriptionInfo(int); @@ -45056,16 +45064,15 @@ package android.telephony { method public static int getSlotIndex(int); method @Nullable public int[] getSubscriptionIds(int); method @NonNull public java.util.List<android.telephony.SubscriptionPlan> getSubscriptionPlans(int); - method @Nullable @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public java.util.List<android.telephony.SubscriptionInfo> getSubscriptionsInGroup(int); + method @NonNull @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public java.util.List<android.telephony.SubscriptionInfo> getSubscriptionsInGroup(@NonNull android.os.ParcelUuid); method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public boolean isActiveSubscriptionId(int); method public boolean isNetworkRoaming(int); method public static boolean isUsableSubscriptionId(int); method public static boolean isValidSubscriptionId(int); method public void removeOnOpportunisticSubscriptionsChangedListener(@NonNull android.telephony.SubscriptionManager.OnOpportunisticSubscriptionsChangedListener); method public void removeOnSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnSubscriptionsChangedListener); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean removeSubscriptionsFromGroup(@NonNull int[]); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void removeSubscriptionsFromGroup(@NonNull java.util.List<java.lang.Integer>, @NonNull android.os.ParcelUuid); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setOpportunistic(boolean, int); - method @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String setSubscriptionGroup(@NonNull int[]); method public void setSubscriptionOverrideCongested(int, boolean, long); method public void setSubscriptionOverrideUnmetered(int, boolean, long); method public void setSubscriptionPlans(int, @NonNull java.util.List<android.telephony.SubscriptionPlan>); @@ -45197,7 +45204,7 @@ package android.telephony { method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_NETWORK_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isDataRoamingEnabled(); method public boolean isEmergencyNumber(@NonNull String); method public boolean isHearingAidCompatibilitySupported(); - method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public boolean isMultisimSupported(); + method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public int isMultiSimSupported(); method public boolean isNetworkRoaming(); method public boolean isRttSupported(); method public boolean isSmsCapable(); @@ -45277,6 +45284,9 @@ package android.telephony { field public static final String EXTRA_SUBSCRIPTION_ID = "android.telephony.extra.SUBSCRIPTION_ID"; field public static final String EXTRA_VOICEMAIL_NUMBER = "android.telephony.extra.VOICEMAIL_NUMBER"; field public static final String METADATA_HIDE_VOICEMAIL_SETTINGS_MENU = "android.telephony.HIDE_VOICEMAIL_SETTINGS_MENU"; + field public static final int MULTISIM_ALLOWED = 0; // 0x0 + field public static final int MULTISIM_NOT_SUPPORTED_BY_CARRIER = 2; // 0x2 + field public static final int MULTISIM_NOT_SUPPORTED_BY_HARDWARE = 1; // 0x1 field public static final int NETWORK_TYPE_1xRTT = 7; // 0x7 field public static final int NETWORK_TYPE_CDMA = 4; // 0x4 field public static final int NETWORK_TYPE_EDGE = 2; // 0x2 @@ -53503,7 +53513,6 @@ package android.view.inputmethod { package android.view.inspector { public interface InspectionCompanion<T> { - method @Nullable public default String getNodeName(); method public void mapProperties(@NonNull android.view.inspector.PropertyMapper); method public void readProperties(@NonNull T, @NonNull android.view.inspector.PropertyReader); } diff --git a/api/removed.txt b/api/removed.txt index fa07094e6b84..fe3e866de682 100644 --- a/api/removed.txt +++ b/api/removed.txt @@ -524,6 +524,8 @@ package android.provider { public static interface MediaStore.MediaColumns extends android.provider.BaseColumns { field @Deprecated public static final String HASH = "_hash"; field @Deprecated public static final String IS_TRASHED = "is_trashed"; + field @Deprecated public static final String PRIMARY_DIRECTORY = "primary_directory"; + field @Deprecated public static final String SECONDARY_DIRECTORY = "secondary_directory"; } @Deprecated public static class MediaStore.PendingParams { diff --git a/api/system-current.txt b/api/system-current.txt index 6e89687de37a..10d6d5defdfc 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -12,6 +12,7 @@ package android { field public static final String ACCESS_MTP = "android.permission.ACCESS_MTP"; field public static final String ACCESS_NETWORK_CONDITIONS = "android.permission.ACCESS_NETWORK_CONDITIONS"; field public static final String ACCESS_NOTIFICATIONS = "android.permission.ACCESS_NOTIFICATIONS"; + field public static final String ACCESS_SHARED_LIBRARIES = "android.permission.ACCESS_SHARED_LIBRARIES"; field public static final String ACCESS_SHORTCUTS = "android.permission.ACCESS_SHORTCUTS"; field public static final String ACCESS_SURFACE_FLINGER = "android.permission.ACCESS_SURFACE_FLINGER"; field public static final String ACTIVITY_EMBEDDING = "android.permission.ACTIVITY_EMBEDDING"; @@ -117,6 +118,7 @@ package android { field public static final String MODIFY_QUIET_MODE = "android.permission.MODIFY_QUIET_MODE"; field public static final String MOVE_PACKAGE = "android.permission.MOVE_PACKAGE"; field public static final String NETWORK_MANAGED_PROVISIONING = "android.permission.NETWORK_MANAGED_PROVISIONING"; + field public static final String NETWORK_SCAN = "android.permission.NETWORK_SCAN"; field public static final String NETWORK_SETUP_WIZARD = "android.permission.NETWORK_SETUP_WIZARD"; field public static final String NOTIFICATION_DURING_SETUP = "android.permission.NOTIFICATION_DURING_SETUP"; field public static final String NOTIFY_TV_INPUTS = "android.permission.NOTIFY_TV_INPUTS"; @@ -186,7 +188,6 @@ package android { field public static final String SUBSTITUTE_NOTIFICATION_APP_NAME = "android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME"; field public static final String SUBSTITUTE_SHARE_TARGET_APP_NAME_AND_ICON = "android.permission.SUBSTITUTE_SHARE_TARGET_APP_NAME_AND_ICON"; field public static final String SUSPEND_APPS = "android.permission.SUSPEND_APPS"; - field public static final String TEST_MANAGE_ROLLBACKS = "android.permission.TEST_MANAGE_ROLLBACKS"; field public static final String TETHER_PRIVILEGED = "android.permission.TETHER_PRIVILEGED"; field public static final String TV_INPUT_HARDWARE = "android.permission.TV_INPUT_HARDWARE"; field public static final String TV_VIRTUAL_REMOTE_CONTROLLER = "android.permission.TV_VIRTUAL_REMOTE_CONTROLLER"; @@ -547,6 +548,7 @@ package android.app { } public class NotificationManager { + method @NonNull public java.util.List<java.lang.String> getAllowedAssistantCapabilities(); method @Nullable public android.content.ComponentName getAllowedNotificationAssistant(); method public boolean isNotificationAssistantAccessGranted(@NonNull android.content.ComponentName); method public void setNotificationAssistantAccessGranted(@Nullable android.content.ComponentName, boolean); @@ -744,7 +746,8 @@ package android.app.backup { method @RequiresPermission(android.Manifest.permission.BACKUP) public String getCurrentTransport(); method @Nullable @RequiresPermission(android.Manifest.permission.BACKUP) public android.content.ComponentName getCurrentTransportComponent(); method @RequiresPermission(android.Manifest.permission.BACKUP) public android.content.Intent getDataManagementIntent(String); - method @RequiresPermission(android.Manifest.permission.BACKUP) public String getDataManagementLabel(String); + method @Nullable @RequiresPermission(android.Manifest.permission.BACKUP) public CharSequence getDataManagementIntentLabel(@NonNull String); + method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.BACKUP) public String getDataManagementLabel(@NonNull String); method @RequiresPermission(android.Manifest.permission.BACKUP) public String getDestinationString(String); method @RequiresPermission(android.Manifest.permission.BACKUP) public boolean isAppEligibleForBackup(String); method @RequiresPermission(android.Manifest.permission.BACKUP) public boolean isBackupEnabled(); @@ -758,7 +761,8 @@ package android.app.backup { method @RequiresPermission(android.Manifest.permission.BACKUP) public void setAncestralSerialNumber(long); method @RequiresPermission(android.Manifest.permission.BACKUP) public void setAutoRestore(boolean); method @RequiresPermission(android.Manifest.permission.BACKUP) public void setBackupEnabled(boolean); - method @RequiresPermission(android.Manifest.permission.BACKUP) public void updateTransportAttributes(android.content.ComponentName, String, @Nullable android.content.Intent, String, @Nullable android.content.Intent, @Nullable String); + method @Deprecated @RequiresPermission(android.Manifest.permission.BACKUP) public void updateTransportAttributes(@NonNull android.content.ComponentName, @NonNull String, @Nullable android.content.Intent, @NonNull String, @Nullable android.content.Intent, @Nullable String); + method @RequiresPermission(android.Manifest.permission.BACKUP) public void updateTransportAttributes(@NonNull android.content.ComponentName, @NonNull String, @Nullable android.content.Intent, @NonNull String, @Nullable android.content.Intent, @Nullable CharSequence); field public static final int ERROR_AGENT_FAILURE = -1003; // 0xfffffc15 field public static final int ERROR_BACKUP_CANCELLED = -2003; // 0xfffff82d field public static final int ERROR_BACKUP_NOT_ALLOWED = -2001; // 0xfffff82f @@ -863,7 +867,8 @@ package android.app.backup { method public android.content.Intent configurationIntent(); method public String currentDestinationString(); method public android.content.Intent dataManagementIntent(); - method public String dataManagementLabel(); + method @Nullable public CharSequence dataManagementIntentLabel(); + method @Deprecated @Nullable public String dataManagementLabel(); method public int finishBackup(); method public void finishRestore(); method public android.app.backup.RestoreSet[] getAvailableRestoreSets(); @@ -1059,7 +1064,7 @@ package android.app.prediction { public final class AppPredictor { method public void destroy(); method public void notifyAppTargetEvent(@NonNull android.app.prediction.AppTargetEvent); - method public void notifyLocationShown(@NonNull String, @NonNull java.util.List<android.app.prediction.AppTargetId>); + method public void notifyLaunchLocationShown(@NonNull String, @NonNull java.util.List<android.app.prediction.AppTargetId>); method public void registerPredictionUpdates(@NonNull java.util.concurrent.Executor, @NonNull android.app.prediction.AppPredictor.Callback); method public void requestPredictionUpdate(); method @Nullable public void sortTargets(@NonNull java.util.List<android.app.prediction.AppTarget>, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.util.List<android.app.prediction.AppTarget>>); @@ -1071,8 +1076,6 @@ package android.app.prediction { } public final class AppTarget implements android.os.Parcelable { - ctor public AppTarget(@NonNull android.app.prediction.AppTargetId, @NonNull String, @Nullable String, @NonNull android.os.UserHandle); - ctor public AppTarget(@NonNull android.app.prediction.AppTargetId, @NonNull android.content.pm.ShortcutInfo, @Nullable String); method public int describeContents(); method @Nullable public String getClassName(); method @NonNull public android.app.prediction.AppTargetId getId(); @@ -1084,6 +1087,15 @@ package android.app.prediction { field @NonNull public static final android.os.Parcelable.Creator<android.app.prediction.AppTarget> CREATOR; } + public static final class AppTarget.Builder { + ctor public AppTarget.Builder(@NonNull android.app.prediction.AppTargetId); + method @NonNull public android.app.prediction.AppTarget build(); + method @NonNull public android.app.prediction.AppTarget.Builder setClassName(@NonNull String); + method @NonNull public android.app.prediction.AppTarget.Builder setRank(@IntRange(from=0) int); + method @NonNull public android.app.prediction.AppTarget.Builder setTarget(@NonNull String, @NonNull android.os.UserHandle); + method @NonNull public android.app.prediction.AppTarget.Builder setTarget(@NonNull android.content.pm.ShortcutInfo); + } + public final class AppTargetEvent implements android.os.Parcelable { method public int describeContents(); method public int getAction(); @@ -1349,7 +1361,6 @@ package android.content { field public static final String BACKUP_SERVICE = "backup"; field public static final String CONTENT_SUGGESTIONS_SERVICE = "content_suggestions"; field public static final String CONTEXTHUB_SERVICE = "contexthub"; - field public static final String DYNAMIC_ANDROID_SERVICE = "dynamic_android"; field public static final String EUICC_CARD_SERVICE = "euicc_card"; field public static final String HDMI_CONTROL_SERVICE = "hdmi_control"; field public static final String NETD_SERVICE = "netd"; @@ -1376,32 +1387,6 @@ package android.content { method public void sendOrderedBroadcast(android.content.Intent, String, android.os.Bundle, android.content.BroadcastReceiver, android.os.Handler, int, String, android.os.Bundle); } - public class DynamicAndroidClient { - ctor public DynamicAndroidClient(@NonNull android.content.Context); - method public void bind(); - method public void setOnStatusChangedListener(@NonNull android.content.DynamicAndroidClient.OnStatusChangedListener, @NonNull java.util.concurrent.Executor); - method public void setOnStatusChangedListener(@NonNull android.content.DynamicAndroidClient.OnStatusChangedListener); - method public void start(String, long); - method public void start(String, long, long); - method public void unbind(); - field public static final int CAUSE_ERROR_EXCEPTION = 6; // 0x6 - field public static final int CAUSE_ERROR_INVALID_URL = 4; // 0x4 - field public static final int CAUSE_ERROR_IO = 3; // 0x3 - field public static final int CAUSE_ERROR_IPC = 5; // 0x5 - field public static final int CAUSE_INSTALL_CANCELLED = 2; // 0x2 - field public static final int CAUSE_INSTALL_COMPLETED = 1; // 0x1 - field public static final int CAUSE_NOT_SPECIFIED = 0; // 0x0 - field public static final int STATUS_IN_PROGRESS = 2; // 0x2 - field public static final int STATUS_IN_USE = 4; // 0x4 - field public static final int STATUS_NOT_STARTED = 1; // 0x1 - field public static final int STATUS_READY = 3; // 0x3 - field public static final int STATUS_UNKNOWN = 0; // 0x0 - } - - public static interface DynamicAndroidClient.OnStatusChangedListener { - method public void onStatusChanged(int, int, long); - } - public class Intent implements java.lang.Cloneable android.os.Parcelable { field public static final String ACTION_BATTERY_LEVEL_CHANGED = "android.intent.action.BATTERY_LEVEL_CHANGED"; field public static final String ACTION_CALL_EMERGENCY = "android.intent.action.CALL_EMERGENCY"; @@ -1425,14 +1410,15 @@ package android.content { field public static final String ACTION_QUERY_PACKAGE_RESTART = "android.intent.action.QUERY_PACKAGE_RESTART"; field public static final String ACTION_RESOLVE_INSTANT_APP_PACKAGE = "android.intent.action.RESOLVE_INSTANT_APP_PACKAGE"; field @RequiresPermission(android.Manifest.permission.REVIEW_ACCESSIBILITY_SERVICES) public static final String ACTION_REVIEW_ACCESSIBILITY_SERVICES = "android.intent.action.REVIEW_ACCESSIBILITY_SERVICES"; - field @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS) public static final String ACTION_REVIEW_APP_PERMISSION_USAGE = "android.intent.action.REVIEW_APP_PERMISSION_USAGE"; + field @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS) public static final String ACTION_REVIEW_ONGOING_PERMISSION_USAGE = "android.intent.action.REVIEW_ONGOING_PERMISSION_USAGE"; field public static final String ACTION_REVIEW_PERMISSIONS = "android.intent.action.REVIEW_PERMISSIONS"; - field public static final String ACTION_REVIEW_PERMISSION_USAGE = "android.intent.action.REVIEW_PERMISSION_USAGE"; + field @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS) public static final String ACTION_REVIEW_PERMISSION_USAGE = "android.intent.action.REVIEW_PERMISSION_USAGE"; field public static final String ACTION_ROLLBACK_COMMITTED = "android.intent.action.ROLLBACK_COMMITTED"; field public static final String ACTION_SHOW_SUSPENDED_APP_DETAILS = "android.intent.action.SHOW_SUSPENDED_APP_DETAILS"; field @Deprecated public static final String ACTION_SIM_STATE_CHANGED = "android.intent.action.SIM_STATE_CHANGED"; field public static final String ACTION_SPLIT_CONFIGURATION_CHANGED = "android.intent.action.SPLIT_CONFIGURATION_CHANGED"; field public static final String ACTION_UPGRADE_SETUP = "android.intent.action.UPGRADE_SETUP"; + field public static final String ACTION_USER_ADDED = "android.intent.action.USER_ADDED"; field public static final String ACTION_USER_REMOVED = "android.intent.action.USER_REMOVED"; field public static final String ACTION_VOICE_ASSIST = "android.intent.action.VOICE_ASSIST"; field public static final String CATEGORY_LEANBACK_SETTINGS = "android.intent.category.LEANBACK_SETTINGS"; @@ -1481,9 +1467,9 @@ package android.content.om { public class OverlayManager { method @Nullable public android.content.om.OverlayInfo getOverlayInfo(@NonNull String, @NonNull android.os.UserHandle); - method public java.util.List<android.content.om.OverlayInfo> getOverlayInfosForTarget(@Nullable String, int); - method public boolean setEnabled(@Nullable String, boolean, int); - method public boolean setEnabledExclusiveInCategory(@Nullable String, int); + method @NonNull @RequiresPermission(anyOf={"android.permission.INTERACT_ACROSS_USERS", "android.permission.INTERACT_ACROSS_USERS_FULL"}) public java.util.List<android.content.om.OverlayInfo> getOverlayInfosForTarget(@NonNull String, @NonNull android.os.UserHandle); + method @RequiresPermission(anyOf={"android.permission.INTERACT_ACROSS_USERS", "android.permission.INTERACT_ACROSS_USERS_FULL"}) public void setEnabled(@NonNull String, boolean, @NonNull android.os.UserHandle); + method @RequiresPermission(anyOf={"android.permission.INTERACT_ACROSS_USERS", "android.permission.INTERACT_ACROSS_USERS_FULL"}) public void setEnabledExclusiveInCategory(@NonNull String, @NonNull android.os.UserHandle); } } @@ -1609,6 +1595,7 @@ package android.content.pm { method public abstract java.util.List<android.content.IntentFilter> getAllIntentFilters(String); method @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public android.content.pm.ApplicationInfo getApplicationInfoAsUser(@NonNull String, int, @NonNull android.os.UserHandle) throws android.content.pm.PackageManager.NameNotFoundException; method @NonNull public android.content.pm.dex.ArtManager getArtManager(); + method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_SHARED_LIBRARIES) public java.util.List<android.content.pm.SharedLibraryInfo> getDeclaredSharedLibraries(@NonNull String, int); method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public abstract String getDefaultBrowserPackageNameAsUser(int); method @Nullable @RequiresPermission(android.Manifest.permission.SET_HARMFUL_APP_WARNINGS) public CharSequence getHarmfulAppWarning(@NonNull String); method public String getIncidentReportApproverPackageName(); @@ -1620,7 +1607,6 @@ package android.content.pm { method public abstract java.util.List<android.content.pm.IntentFilterVerificationInfo> getIntentFilterVerifications(String); method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public abstract int getIntentVerificationStatusAsUser(String, int); method @android.content.pm.PackageManager.PermissionFlags @RequiresPermission(anyOf={android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS, android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS, android.Manifest.permission.GET_RUNTIME_PERMISSIONS}) public abstract int getPermissionFlags(String, String, @NonNull android.os.UserHandle); - method public boolean getSyntheticAppDetailsActivityEnabled(@NonNull String); method @NonNull @RequiresPermission(android.Manifest.permission.SUSPEND_APPS) public String[] getUnsuspendablePackages(@NonNull String[]); method @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS) public abstract void grantRuntimePermission(@NonNull String, @NonNull String, @NonNull android.os.UserHandle); method @Deprecated public abstract int installExistingPackage(String) throws android.content.pm.PackageManager.NameNotFoundException; @@ -1840,9 +1826,9 @@ package android.content.rollback { } public final class RollbackManager { - method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, android.Manifest.permission.TEST_MANAGE_ROLLBACKS}) public void commitRollback(int, @NonNull java.util.List<android.content.pm.VersionedPackage>, @NonNull android.content.IntentSender); - method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, android.Manifest.permission.TEST_MANAGE_ROLLBACKS}) @NonNull public java.util.List<android.content.rollback.RollbackInfo> getAvailableRollbacks(); - method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, android.Manifest.permission.TEST_MANAGE_ROLLBACKS}) @NonNull public java.util.List<android.content.rollback.RollbackInfo> getRecentlyCommittedRollbacks(); + method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, "android.permission.TEST_MANAGE_ROLLBACKS"}) public void commitRollback(int, @NonNull java.util.List<android.content.pm.VersionedPackage>, @NonNull android.content.IntentSender); + method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, "android.permission.TEST_MANAGE_ROLLBACKS"}) @NonNull public java.util.List<android.content.rollback.RollbackInfo> getAvailableRollbacks(); + method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, "android.permission.TEST_MANAGE_ROLLBACKS"}) @NonNull public java.util.List<android.content.rollback.RollbackInfo> getRecentlyCommittedRollbacks(); field public static final String EXTRA_STATUS = "android.content.rollback.extra.STATUS"; field public static final String EXTRA_STATUS_MESSAGE = "android.content.rollback.extra.STATUS_MESSAGE"; field public static final int STATUS_FAILURE = 1; // 0x1 @@ -3574,13 +3560,6 @@ package android.media { field public static final int RADIO_TUNER = 1998; // 0x7ce } - public static final class MediaTimestamp.Builder { - ctor public MediaTimestamp.Builder(); - ctor public MediaTimestamp.Builder(@NonNull android.media.MediaTimestamp); - method @NonNull public android.media.MediaTimestamp build(); - method @NonNull public android.media.MediaTimestamp.Builder setMediaTimestamp(long, long, float); - } - public class PlayerProxy { method public void pause(); method public void setPan(float); @@ -3590,20 +3569,6 @@ package android.media { method public void stop(); } - public static final class SubtitleData.Builder { - ctor public SubtitleData.Builder(); - ctor public SubtitleData.Builder(@NonNull android.media.SubtitleData); - method @NonNull public android.media.SubtitleData build(); - method @NonNull public android.media.SubtitleData.Builder setSubtitleData(int, long, long, @NonNull byte[]); - } - - public static final class TimedMetaData.Builder { - ctor public TimedMetaData.Builder(); - ctor public TimedMetaData.Builder(@NonNull android.media.TimedMetaData); - method @NonNull public android.media.TimedMetaData build(); - method @NonNull public android.media.TimedMetaData.Builder setTimedMetaData(long, @NonNull byte[]); - } - } package android.media.audiopolicy { @@ -3680,13 +3645,14 @@ package android.media.audiopolicy { public static class AudioPolicy.Builder { ctor public AudioPolicy.Builder(android.content.Context); - method public android.media.audiopolicy.AudioPolicy.Builder addMix(@NonNull android.media.audiopolicy.AudioMix) throws java.lang.IllegalArgumentException; - method public android.media.audiopolicy.AudioPolicy build(); + method @NonNull public android.media.audiopolicy.AudioPolicy.Builder addMix(@NonNull android.media.audiopolicy.AudioMix) throws java.lang.IllegalArgumentException; + method @NonNull public android.media.audiopolicy.AudioPolicy build(); method public void setAudioPolicyFocusListener(android.media.audiopolicy.AudioPolicy.AudioPolicyFocusListener); method public void setAudioPolicyStatusListener(android.media.audiopolicy.AudioPolicy.AudioPolicyStatusListener); - method public android.media.audiopolicy.AudioPolicy.Builder setAudioPolicyVolumeCallback(@NonNull android.media.audiopolicy.AudioPolicy.AudioPolicyVolumeCallback); - method public android.media.audiopolicy.AudioPolicy.Builder setIsAudioFocusPolicy(boolean); - method public android.media.audiopolicy.AudioPolicy.Builder setLooper(@NonNull android.os.Looper) throws java.lang.IllegalArgumentException; + method @NonNull public android.media.audiopolicy.AudioPolicy.Builder setAudioPolicyVolumeCallback(@NonNull android.media.audiopolicy.AudioPolicy.AudioPolicyVolumeCallback); + method @NonNull public android.media.audiopolicy.AudioPolicy.Builder setIsAudioFocusPolicy(boolean); + method @NonNull public android.media.audiopolicy.AudioPolicy.Builder setIsTestFocusPolicy(boolean); + method @NonNull public android.media.audiopolicy.AudioPolicy.Builder setLooper(@NonNull android.os.Looper) throws java.lang.IllegalArgumentException; } public final class AudioProductStrategies implements java.lang.Iterable<android.media.audiopolicy.AudioProductStrategy> android.os.Parcelable { @@ -4044,8 +4010,7 @@ package android.metrics { package android.net { public class CaptivePortal implements android.os.Parcelable { - ctor public CaptivePortal(android.os.IBinder); - method public void logEvent(int, String); + method public void logEvent(int, @NonNull String); method public void useNetwork(); field public static final int APP_RETURN_DISMISSED = 0; // 0x0 field public static final int APP_RETURN_UNWANTED = 1; // 0x1 @@ -4055,13 +4020,13 @@ package android.net { public class ConnectivityManager { method @RequiresPermission(android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD) public android.net.SocketKeepalive createNattKeepalive(@NonNull android.net.Network, @NonNull java.io.FileDescriptor, @NonNull java.net.InetAddress, @NonNull java.net.InetAddress, @NonNull java.util.concurrent.Executor, @NonNull android.net.SocketKeepalive.Callback); method @RequiresPermission(android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD) public android.net.SocketKeepalive createSocketKeepalive(@NonNull android.net.Network, @NonNull java.net.Socket, @NonNull java.util.concurrent.Executor, @NonNull android.net.SocketKeepalive.Callback); - method public boolean getAvoidBadWifi(); method @RequiresPermission(android.Manifest.permission.LOCAL_MAC_ADDRESS) public String getCaptivePortalServerUrl(); method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void getLatestTetheringEntitlementResult(int, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityManager.OnTetheringEntitlementResultListener); method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public boolean isTetheringSupported(); method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void registerTetheringEventCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityManager.OnTetheringEventCallback); method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void setAirplaneMode(boolean); - method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void startCaptivePortalApp(android.net.Network, android.os.Bundle); + method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, "android.permission.NETWORK_STACK"}) public boolean shouldAvoidBadWifi(); + method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void startCaptivePortalApp(@NonNull android.net.Network, @NonNull android.os.Bundle); method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback); method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback, android.os.Handler); method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void stopTethering(int); @@ -4092,8 +4057,8 @@ package android.net { } public final class IpPrefix implements android.os.Parcelable { - ctor public IpPrefix(java.net.InetAddress, int); - ctor public IpPrefix(String); + ctor public IpPrefix(@NonNull java.net.InetAddress, int); + ctor public IpPrefix(@NonNull String); } public final class IpSecManager { @@ -4116,57 +4081,47 @@ package android.net { ctor public LinkAddress(java.net.InetAddress, int, int, int); ctor public LinkAddress(@NonNull java.net.InetAddress, int); ctor public LinkAddress(@NonNull String); - ctor public LinkAddress(String, int, int); + ctor public LinkAddress(@NonNull String, int, int); method public boolean isGlobalPreferred(); - method public boolean isIPv4(); - method public boolean isIPv6(); - method public boolean isSameAddressAs(android.net.LinkAddress); + method public boolean isIpv4(); + method public boolean isIpv6(); + method public boolean isSameAddressAs(@Nullable android.net.LinkAddress); } public final class LinkProperties implements android.os.Parcelable { - ctor public LinkProperties(); - ctor public LinkProperties(android.net.LinkProperties); - method public boolean addDnsServer(java.net.InetAddress); - method public boolean addLinkAddress(android.net.LinkAddress); - method public boolean addRoute(android.net.RouteInfo); - method public void clear(); + ctor public LinkProperties(@Nullable android.net.LinkProperties); + method public boolean addDnsServer(@NonNull java.net.InetAddress); + method public boolean addLinkAddress(@NonNull android.net.LinkAddress); method @Nullable public android.net.IpPrefix getNat64Prefix(); - method public java.util.List<java.net.InetAddress> getPcscfServers(); - method public String getTcpBufferSizes(); - method public java.util.List<java.net.InetAddress> getValidatedPrivateDnsServers(); - method public boolean hasGlobalIPv6Address(); - method public boolean hasIPv4Address(); - method public boolean hasIPv6DefaultRoute(); - method public boolean isIPv4Provisioned(); - method public boolean isIPv6Provisioned(); + method @NonNull public java.util.List<java.net.InetAddress> getPcscfServers(); + method @Nullable public String getTcpBufferSizes(); + method @NonNull public java.util.List<java.net.InetAddress> getValidatedPrivateDnsServers(); + method public boolean hasGlobalIpv6Address(); + method public boolean hasIpv4Address(); + method public boolean hasIpv6DefaultRoute(); + method public boolean isIpv4Provisioned(); + method public boolean isIpv6Provisioned(); method public boolean isProvisioned(); - method public boolean isReachable(java.net.InetAddress); - method public boolean removeDnsServer(java.net.InetAddress); - method public boolean removeLinkAddress(android.net.LinkAddress); - method public boolean removeRoute(android.net.RouteInfo); - method public void setDnsServers(java.util.Collection<java.net.InetAddress>); - method public void setDomains(String); - method public void setHttpProxy(android.net.ProxyInfo); - method public void setInterfaceName(String); - method public void setLinkAddresses(java.util.Collection<android.net.LinkAddress>); - method public void setMtu(int); - method public void setNat64Prefix(android.net.IpPrefix); - method public void setPcscfServers(java.util.Collection<java.net.InetAddress>); + method public boolean isReachable(@NonNull java.net.InetAddress); + method public boolean removeDnsServer(@NonNull java.net.InetAddress); + method public boolean removeLinkAddress(@NonNull android.net.LinkAddress); + method public boolean removeRoute(@NonNull android.net.RouteInfo); + method public void setNat64Prefix(@Nullable android.net.IpPrefix); + method public void setPcscfServers(@NonNull java.util.Collection<java.net.InetAddress>); method public void setPrivateDnsServerName(@Nullable String); - method public void setTcpBufferSizes(String); + method public void setTcpBufferSizes(@Nullable String); method public void setUsePrivateDns(boolean); - method public void setValidatedPrivateDnsServers(java.util.Collection<java.net.InetAddress>); + method public void setValidatedPrivateDnsServers(@NonNull java.util.Collection<java.net.InetAddress>); } public class Network implements android.os.Parcelable { - ctor public Network(android.net.Network); - method public android.net.Network getPrivateDnsBypassingCopy(); + ctor public Network(@NonNull android.net.Network); + method @NonNull public android.net.Network getPrivateDnsBypassingCopy(); } public final class NetworkCapabilities implements android.os.Parcelable { - method public int getSignalStrength(); - method public int[] getTransportTypes(); - method public boolean satisfiedByNetworkCapabilities(android.net.NetworkCapabilities); + method @NonNull public int[] getTransportTypes(); + method public boolean satisfiedByNetworkCapabilities(@Nullable android.net.NetworkCapabilities); field public static final int NET_CAPABILITY_OEM_PAID = 22; // 0x16 field public static final int NET_CAPABILITY_PARTIAL_CONNECTIVITY = 24; // 0x18 } @@ -4188,7 +4143,7 @@ package android.net { } public static class NetworkRequest.Builder { - method public android.net.NetworkRequest.Builder setSignalStrength(int); + method @NonNull public android.net.NetworkRequest.Builder setSignalStrength(int); } public class NetworkScoreManager { @@ -4212,7 +4167,7 @@ package android.net { } public final class RouteInfo implements android.os.Parcelable { - ctor public RouteInfo(android.net.IpPrefix, java.net.InetAddress, String, int); + ctor public RouteInfo(@Nullable android.net.IpPrefix, @Nullable java.net.InetAddress, @Nullable String, int); method public int getType(); field public static final int RTN_THROW = 9; // 0x9 field public static final int RTN_UNICAST = 1; // 0x1 @@ -4252,18 +4207,18 @@ package android.net { public final class StaticIpConfiguration implements android.os.Parcelable { ctor public StaticIpConfiguration(); - ctor public StaticIpConfiguration(android.net.StaticIpConfiguration); - method public void addDnsServer(java.net.InetAddress); + ctor public StaticIpConfiguration(@Nullable android.net.StaticIpConfiguration); + method public void addDnsServer(@NonNull java.net.InetAddress); method public void clear(); method public int describeContents(); - method public java.util.List<java.net.InetAddress> getDnsServers(); - method public String getDomains(); - method public java.net.InetAddress getGateway(); - method public android.net.LinkAddress getIpAddress(); - method public java.util.List<android.net.RouteInfo> getRoutes(String); - method public void setDomains(String); - method public void setGateway(java.net.InetAddress); - method public void setIpAddress(android.net.LinkAddress); + method @NonNull public java.util.List<java.net.InetAddress> getDnsServers(); + method @Nullable public String getDomains(); + method @Nullable public java.net.InetAddress getGateway(); + method @Nullable public android.net.LinkAddress getIpAddress(); + method @NonNull public java.util.List<android.net.RouteInfo> getRoutes(String); + method public void setDomains(@Nullable String); + method public void setGateway(@Nullable java.net.InetAddress); + method public void setIpAddress(@Nullable android.net.LinkAddress); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.net.StaticIpConfiguration> CREATOR; } @@ -4301,8 +4256,8 @@ package android.net.apf { public final class ApfCapabilities implements android.os.Parcelable { ctor public ApfCapabilities(int, int, int); method public int describeContents(); - method public static boolean getApfDrop8023Frames(android.content.Context); - method public static int[] getApfEthTypeBlackList(android.content.Context); + method public static boolean getApfDrop8023Frames(@NonNull android.content.Context); + method @NonNull public static int[] getApfEthTypeBlackList(@NonNull android.content.Context); method public boolean hasDataAccess(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.net.apf.ApfCapabilities> CREATOR; @@ -4317,28 +4272,28 @@ package android.net.captiveportal { public final class CaptivePortalProbeResult { ctor public CaptivePortalProbeResult(int); - ctor public CaptivePortalProbeResult(int, String, String); - ctor public CaptivePortalProbeResult(int, String, String, android.net.captiveportal.CaptivePortalProbeSpec); + ctor public CaptivePortalProbeResult(int, @Nullable String, @Nullable String); + ctor public CaptivePortalProbeResult(int, @Nullable String, @Nullable String, @Nullable android.net.captiveportal.CaptivePortalProbeSpec); method public boolean isFailed(); method public boolean isPartialConnectivity(); method public boolean isPortal(); method public boolean isSuccessful(); - field public static final android.net.captiveportal.CaptivePortalProbeResult FAILED; + field @NonNull public static final android.net.captiveportal.CaptivePortalProbeResult FAILED; field public static final int FAILED_CODE = 599; // 0x257 field public static final android.net.captiveportal.CaptivePortalProbeResult PARTIAL; field public static final int PORTAL_CODE = 302; // 0x12e - field public static final android.net.captiveportal.CaptivePortalProbeResult SUCCESS; + field @NonNull public static final android.net.captiveportal.CaptivePortalProbeResult SUCCESS; field public static final int SUCCESS_CODE = 204; // 0xcc - field public final String detectUrl; + field @Nullable public final String detectUrl; field @Nullable public final android.net.captiveportal.CaptivePortalProbeSpec probeSpec; - field public final String redirectUrl; + field @Nullable public final String redirectUrl; } public abstract class CaptivePortalProbeSpec { - method public String getEncodedSpec(); - method public abstract android.net.captiveportal.CaptivePortalProbeResult getResult(int, @Nullable String); - method public java.net.URL getUrl(); - method public static java.util.Collection<android.net.captiveportal.CaptivePortalProbeSpec> parseCaptivePortalProbeSpecs(String); + method @NonNull public String getEncodedSpec(); + method @NonNull public abstract android.net.captiveportal.CaptivePortalProbeResult getResult(int, @Nullable String); + method @NonNull public java.net.URL getUrl(); + method @NonNull public static java.util.Collection<android.net.captiveportal.CaptivePortalProbeSpec> parseCaptivePortalProbeSpecs(@NonNull String); method @Nullable public static android.net.captiveportal.CaptivePortalProbeSpec parseSpecOrNull(@Nullable String); } @@ -4349,78 +4304,78 @@ package android.net.metrics { public final class ApfProgramEvent implements android.net.metrics.IpConnectivityLog.Event { } - public static class ApfProgramEvent.Builder { + public static final class ApfProgramEvent.Builder { ctor public ApfProgramEvent.Builder(); - method public android.net.metrics.ApfProgramEvent build(); - method public android.net.metrics.ApfProgramEvent.Builder setActualLifetime(long); - method public android.net.metrics.ApfProgramEvent.Builder setCurrentRas(int); - method public android.net.metrics.ApfProgramEvent.Builder setFilteredRas(int); - method public android.net.metrics.ApfProgramEvent.Builder setFlags(boolean, boolean); - method public android.net.metrics.ApfProgramEvent.Builder setLifetime(long); - method public android.net.metrics.ApfProgramEvent.Builder setProgramLength(int); + method @NonNull public android.net.metrics.ApfProgramEvent build(); + method @NonNull public android.net.metrics.ApfProgramEvent.Builder setActualLifetime(long); + method @NonNull public android.net.metrics.ApfProgramEvent.Builder setCurrentRas(int); + method @NonNull public android.net.metrics.ApfProgramEvent.Builder setFilteredRas(int); + method @NonNull public android.net.metrics.ApfProgramEvent.Builder setFlags(boolean, boolean); + method @NonNull public android.net.metrics.ApfProgramEvent.Builder setLifetime(long); + method @NonNull public android.net.metrics.ApfProgramEvent.Builder setProgramLength(int); } public final class ApfStats implements android.net.metrics.IpConnectivityLog.Event { } - public static class ApfStats.Builder { + public static final class ApfStats.Builder { ctor public ApfStats.Builder(); - method public android.net.metrics.ApfStats build(); - method public android.net.metrics.ApfStats.Builder setDroppedRas(int); - method public android.net.metrics.ApfStats.Builder setDurationMs(long); - method public android.net.metrics.ApfStats.Builder setMatchingRas(int); - method public android.net.metrics.ApfStats.Builder setMaxProgramSize(int); - method public android.net.metrics.ApfStats.Builder setParseErrors(int); - method public android.net.metrics.ApfStats.Builder setProgramUpdates(int); - method public android.net.metrics.ApfStats.Builder setProgramUpdatesAll(int); - method public android.net.metrics.ApfStats.Builder setProgramUpdatesAllowingMulticast(int); - method public android.net.metrics.ApfStats.Builder setReceivedRas(int); - method public android.net.metrics.ApfStats.Builder setZeroLifetimeRas(int); + method @NonNull public android.net.metrics.ApfStats build(); + method @NonNull public android.net.metrics.ApfStats.Builder setDroppedRas(int); + method @NonNull public android.net.metrics.ApfStats.Builder setDurationMs(long); + method @NonNull public android.net.metrics.ApfStats.Builder setMatchingRas(int); + method @NonNull public android.net.metrics.ApfStats.Builder setMaxProgramSize(int); + method @NonNull public android.net.metrics.ApfStats.Builder setParseErrors(int); + method @NonNull public android.net.metrics.ApfStats.Builder setProgramUpdates(int); + method @NonNull public android.net.metrics.ApfStats.Builder setProgramUpdatesAll(int); + method @NonNull public android.net.metrics.ApfStats.Builder setProgramUpdatesAllowingMulticast(int); + method @NonNull public android.net.metrics.ApfStats.Builder setReceivedRas(int); + method @NonNull public android.net.metrics.ApfStats.Builder setZeroLifetimeRas(int); } public final class DhcpClientEvent implements android.net.metrics.IpConnectivityLog.Event { } - public static class DhcpClientEvent.Builder { + public static final class DhcpClientEvent.Builder { ctor public DhcpClientEvent.Builder(); - method public android.net.metrics.DhcpClientEvent build(); - method public android.net.metrics.DhcpClientEvent.Builder setDurationMs(int); - method public android.net.metrics.DhcpClientEvent.Builder setMsg(String); + method @NonNull public android.net.metrics.DhcpClientEvent build(); + method @NonNull public android.net.metrics.DhcpClientEvent.Builder setDurationMs(int); + method @NonNull public android.net.metrics.DhcpClientEvent.Builder setMsg(String); } public final class DhcpErrorEvent implements android.net.metrics.IpConnectivityLog.Event { ctor public DhcpErrorEvent(int); method public static int errorCodeWithOption(int, int); - field public static final int BOOTP_TOO_SHORT; - field public static final int BUFFER_UNDERFLOW; - field public static final int DHCP_BAD_MAGIC_COOKIE; + field public static final int BOOTP_TOO_SHORT = 67174400; // 0x4010000 + field public static final int BUFFER_UNDERFLOW = 83951616; // 0x5010000 + field public static final int DHCP_BAD_MAGIC_COOKIE = 67239936; // 0x4020000 field public static final int DHCP_ERROR = 4; // 0x4 - field public static final int DHCP_INVALID_OPTION_LENGTH; - field public static final int DHCP_NO_COOKIE; - field public static final int DHCP_NO_MSG_TYPE; - field public static final int DHCP_UNKNOWN_MSG_TYPE; + field public static final int DHCP_INVALID_OPTION_LENGTH = 67305472; // 0x4030000 + field public static final int DHCP_NO_COOKIE = 67502080; // 0x4060000 + field public static final int DHCP_NO_MSG_TYPE = 67371008; // 0x4040000 + field public static final int DHCP_UNKNOWN_MSG_TYPE = 67436544; // 0x4050000 field public static final int L2_ERROR = 1; // 0x1 - field public static final int L2_TOO_SHORT; - field public static final int L2_WRONG_ETH_TYPE; + field public static final int L2_TOO_SHORT = 16842752; // 0x1010000 + field public static final int L2_WRONG_ETH_TYPE = 16908288; // 0x1020000 field public static final int L3_ERROR = 2; // 0x2 - field public static final int L3_INVALID_IP; - field public static final int L3_NOT_IPV4; - field public static final int L3_TOO_SHORT; + field public static final int L3_INVALID_IP = 33751040; // 0x2030000 + field public static final int L3_NOT_IPV4 = 33685504; // 0x2020000 + field public static final int L3_TOO_SHORT = 33619968; // 0x2010000 field public static final int L4_ERROR = 3; // 0x3 - field public static final int L4_NOT_UDP; - field public static final int L4_WRONG_PORT; + field public static final int L4_NOT_UDP = 50397184; // 0x3010000 + field public static final int L4_WRONG_PORT = 50462720; // 0x3020000 field public static final int MISC_ERROR = 5; // 0x5 - field public static final int PARSING_ERROR; - field public static final int RECEIVE_ERROR; + field public static final int PARSING_ERROR = 84082688; // 0x5030000 + field public static final int RECEIVE_ERROR = 84017152; // 0x5020000 } public class IpConnectivityLog { ctor public IpConnectivityLog(); - method public boolean log(long, android.net.metrics.IpConnectivityLog.Event); - method public boolean log(String, android.net.metrics.IpConnectivityLog.Event); - method public boolean log(android.net.Network, int[], android.net.metrics.IpConnectivityLog.Event); - method public boolean log(int, int[], android.net.metrics.IpConnectivityLog.Event); - method public boolean log(android.net.metrics.IpConnectivityLog.Event); + method public boolean log(long, @NonNull android.net.metrics.IpConnectivityLog.Event); + method public boolean log(@NonNull String, @NonNull android.net.metrics.IpConnectivityLog.Event); + method public boolean log(@NonNull android.net.Network, @NonNull int[], @NonNull android.net.metrics.IpConnectivityLog.Event); + method public boolean log(int, @NonNull int[], @NonNull android.net.metrics.IpConnectivityLog.Event); + method public boolean log(@NonNull android.net.metrics.IpConnectivityLog.Event); } public static interface IpConnectivityLog.Event extends android.os.Parcelable { @@ -4468,15 +4423,15 @@ package android.net.metrics { public final class RaEvent implements android.net.metrics.IpConnectivityLog.Event { } - public static class RaEvent.Builder { + public static final class RaEvent.Builder { ctor public RaEvent.Builder(); - method public android.net.metrics.RaEvent build(); - method public android.net.metrics.RaEvent.Builder updateDnsslLifetime(long); - method public android.net.metrics.RaEvent.Builder updatePrefixPreferredLifetime(long); - method public android.net.metrics.RaEvent.Builder updatePrefixValidLifetime(long); - method public android.net.metrics.RaEvent.Builder updateRdnssLifetime(long); - method public android.net.metrics.RaEvent.Builder updateRouteInfoLifetime(long); - method public android.net.metrics.RaEvent.Builder updateRouterLifetime(long); + method @NonNull public android.net.metrics.RaEvent build(); + method @NonNull public android.net.metrics.RaEvent.Builder updateDnsslLifetime(long); + method @NonNull public android.net.metrics.RaEvent.Builder updatePrefixPreferredLifetime(long); + method @NonNull public android.net.metrics.RaEvent.Builder updatePrefixValidLifetime(long); + method @NonNull public android.net.metrics.RaEvent.Builder updateRdnssLifetime(long); + method @NonNull public android.net.metrics.RaEvent.Builder updateRouteInfoLifetime(long); + method @NonNull public android.net.metrics.RaEvent.Builder updateRouterLifetime(long); } public final class ValidationProbeEvent implements android.net.metrics.IpConnectivityLog.Event { @@ -4491,12 +4446,12 @@ package android.net.metrics { field public static final int PROBE_PRIVDNS = 5; // 0x5 } - public static class ValidationProbeEvent.Builder { + public static final class ValidationProbeEvent.Builder { ctor public ValidationProbeEvent.Builder(); - method public android.net.metrics.ValidationProbeEvent build(); - method public android.net.metrics.ValidationProbeEvent.Builder setDurationMs(long); - method public android.net.metrics.ValidationProbeEvent.Builder setProbeType(int, boolean); - method public android.net.metrics.ValidationProbeEvent.Builder setReturnCode(int); + method @NonNull public android.net.metrics.ValidationProbeEvent build(); + method @NonNull public android.net.metrics.ValidationProbeEvent.Builder setDurationMs(long); + method @NonNull public android.net.metrics.ValidationProbeEvent.Builder setProbeType(int, boolean); + method @NonNull public android.net.metrics.ValidationProbeEvent.Builder setReturnCode(int); } } @@ -4956,7 +4911,6 @@ package android.net.wifi { method public int getCellularDataNetworkType(); method public int getCellularSignalStrengthDb(); method public int getCellularSignalStrengthDbm(); - method public boolean getIsSameRegisteredCell(); method public int getLinkSpeedMbps(); method public int getProbeElapsedTimeSinceLastUpdateMillis(); method public int getProbeMcsRateSinceLastUpdate(); @@ -4980,6 +4934,7 @@ package android.net.wifi { method public long getTotalTxBad(); method public long getTotalTxRetries(); method public long getTotalTxSuccess(); + method public boolean isSameRegisteredCell(); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.WifiUsabilityStatsEntry> CREATOR; field public static final int PROBE_STATUS_FAILURE = 3; // 0x3 @@ -5509,7 +5464,7 @@ package android.os { } public class ServiceSpecificException extends java.lang.RuntimeException { - ctor public ServiceSpecificException(int, String); + ctor public ServiceSpecificException(int, @Nullable String); ctor public ServiceSpecificException(int); field public final int errorCode; } @@ -5683,6 +5638,36 @@ package android.os { } +package android.os.image { + + public class DynamicSystemClient { + ctor public DynamicSystemClient(@NonNull android.content.Context); + method @RequiresPermission("android.permission.MANAGE_DYNAMIC_SYSTEM") public void bind(); + method public void setOnStatusChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.os.image.DynamicSystemClient.OnStatusChangedListener); + method public void setOnStatusChangedListener(@NonNull android.os.image.DynamicSystemClient.OnStatusChangedListener); + method @RequiresPermission("android.permission.MANAGE_DYNAMIC_SYSTEM") public void start(@NonNull String, long); + method @RequiresPermission("android.permission.MANAGE_DYNAMIC_SYSTEM") public void start(@NonNull String, long, long); + method @RequiresPermission("android.permission.MANAGE_DYNAMIC_SYSTEM") public void unbind(); + field public static final int CAUSE_ERROR_EXCEPTION = 6; // 0x6 + field public static final int CAUSE_ERROR_INVALID_URL = 4; // 0x4 + field public static final int CAUSE_ERROR_IO = 3; // 0x3 + field public static final int CAUSE_ERROR_IPC = 5; // 0x5 + field public static final int CAUSE_INSTALL_CANCELLED = 2; // 0x2 + field public static final int CAUSE_INSTALL_COMPLETED = 1; // 0x1 + field public static final int CAUSE_NOT_SPECIFIED = 0; // 0x0 + field public static final int STATUS_IN_PROGRESS = 2; // 0x2 + field public static final int STATUS_IN_USE = 4; // 0x4 + field public static final int STATUS_NOT_STARTED = 1; // 0x1 + field public static final int STATUS_READY = 3; // 0x3 + field public static final int STATUS_UNKNOWN = 0; // 0x0 + } + + public static interface DynamicSystemClient.OnStatusChangedListener { + method public void onStatusChanged(int, int, long); + } + +} + package android.os.storage { public class StorageManager { @@ -5747,10 +5732,10 @@ package android.permission { } public final class RuntimePermissionUsageInfo implements android.os.Parcelable { - ctor public RuntimePermissionUsageInfo(@NonNull CharSequence, int); + ctor public RuntimePermissionUsageInfo(@NonNull String, int); method public int describeContents(); method public int getAppAccessCount(); - method @NonNull public CharSequence getName(); + method @NonNull public String getName(); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.permission.RuntimePermissionUsageInfo> CREATOR; } @@ -5903,6 +5888,7 @@ package android.provider { field public static final String NAMESPACE_SCHEDULER = "scheduler"; field public static final String NAMESPACE_STORAGE = "storage"; field public static final String NAMESPACE_SYSTEMUI = "systemui"; + field public static final String NAMESPACE_TELEPHONY = "telephony"; field public static final String NAMESPACE_TEXTCLASSIFIER = "textclassifier"; } @@ -5930,13 +5916,6 @@ package android.provider { method @Nullable public String getString(@NonNull String, @Nullable String); } - public static interface DeviceConfig.Telephony { - field public static final String NAMESPACE = "telephony"; - field public static final String RAMPING_RINGER_DURATION = "ramping_ringer_duration"; - field public static final String RAMPING_RINGER_ENABLED = "ramping_ringer_enabled"; - field public static final String RAMPING_RINGER_VIBRATION_DURATION = "ramping_ringer_vibration_duration"; - } - public final class DocumentsContract { method public static boolean isManageMode(@NonNull android.net.Uri); method @NonNull public static android.net.Uri setManageMode(@NonNull android.net.Uri); @@ -6068,6 +6047,7 @@ package android.provider { field public static final String ACTION_ENTERPRISE_PRIVACY_SETTINGS = "android.settings.ENTERPRISE_PRIVACY_SETTINGS"; field public static final String ACTION_LOCATION_CONTROLLER_EXTRA_PACKAGE_SETTINGS = "android.settings.LOCATION_CONTROLLER_EXTRA_PACKAGE_SETTINGS"; field public static final String ACTION_MANAGE_DOMAIN_URLS = "android.settings.MANAGE_DOMAIN_URLS"; + field public static final String ACTION_NOTIFICATION_POLICY_ACCESS_DETAIL_SETTINGS = "android.settings.NOTIFICATION_POLICY_ACCESS_DETAIL_SETTINGS"; field public static final String ACTION_REQUEST_ENABLE_CONTENT_CAPTURE = "android.settings.REQUEST_ENABLE_CONTENT_CAPTURE"; field public static final String ACTION_SHOW_ADMIN_SUPPORT_DETAILS = "android.settings.SHOW_ADMIN_SUPPORT_DETAILS"; } @@ -6132,6 +6112,7 @@ package android.provider { field public static final String LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS = "lock_screen_allow_private_notifications"; field public static final String LOCK_SCREEN_SHOW_NOTIFICATIONS = "lock_screen_show_notifications"; field public static final String ODI_CAPTIONS_ENABLED = "odi_captions_enabled"; + field public static final String ODI_CAPTIONS_OPTED_OUT = "odi_captions_opted_out"; field public static final String THEME_CUSTOMIZATION_OVERLAY_PACKAGES = "theme_customization_overlay_packages"; field public static final String USER_SETUP_COMPLETE = "user_setup_complete"; field public static final int USER_SETUP_PERSONALIZATION_COMPLETE = 10; // 0xa @@ -6324,7 +6305,7 @@ package android.service.appprediction { method @NonNull public final android.os.IBinder onBind(@NonNull android.content.Intent); method public void onCreatePredictionSession(@NonNull android.app.prediction.AppPredictionContext, @NonNull android.app.prediction.AppPredictionSessionId); method @MainThread public void onDestroyPredictionSession(@NonNull android.app.prediction.AppPredictionSessionId); - method @MainThread public abstract void onLocationShown(@NonNull android.app.prediction.AppPredictionSessionId, @NonNull String, @NonNull java.util.List<android.app.prediction.AppTargetId>); + method @MainThread public abstract void onLaunchLocationShown(@NonNull android.app.prediction.AppPredictionSessionId, @NonNull String, @NonNull java.util.List<android.app.prediction.AppTargetId>); method @MainThread public abstract void onRequestPredictionUpdate(@NonNull android.app.prediction.AppPredictionSessionId); method @MainThread public abstract void onSortAppTargets(@NonNull android.app.prediction.AppPredictionSessionId, @NonNull java.util.List<android.app.prediction.AppTarget>, @NonNull android.os.CancellationSignal, @NonNull java.util.function.Consumer<java.util.List<android.app.prediction.AppTarget>>); method @MainThread public void onStartPredictionUpdates(); @@ -6338,12 +6319,15 @@ package android.service.attention { public abstract class AttentionService extends android.app.Service { ctor public AttentionService(); + method public final void disableSelf(); method @Nullable public final android.os.IBinder onBind(@NonNull android.content.Intent); method public abstract void onCancelAttentionCheck(int); method public abstract void onCheckAttention(int, @NonNull android.service.attention.AttentionService.AttentionCallback); - field public static final int ATTENTION_FAILURE_PREEMPTED = 2; // 0x2 - field public static final int ATTENTION_FAILURE_TIMED_OUT = 3; // 0x3 - field public static final int ATTENTION_FAILURE_UNKNOWN = 4; // 0x4 + field public static final int ATTENTION_FAILURE_CAMERA_PERMISSION_ABSENT = 6; // 0x6 + field public static final int ATTENTION_FAILURE_CANCELLED = 3; // 0x3 + field public static final int ATTENTION_FAILURE_PREEMPTED = 4; // 0x4 + field public static final int ATTENTION_FAILURE_TIMED_OUT = 5; // 0x5 + field public static final int ATTENTION_FAILURE_UNKNOWN = 2; // 0x2 field public static final int ATTENTION_SUCCESS_ABSENT = 0; // 0x0 field public static final int ATTENTION_SUCCESS_PRESENT = 1; // 0x1 field public static final String SERVICE_INTERFACE = "android.service.attention.AttentionService"; @@ -6662,6 +6646,7 @@ package android.service.notification { method public final void adjustNotifications(@NonNull java.util.List<android.service.notification.Adjustment>); method public void onActionInvoked(@NonNull String, @NonNull android.app.Notification.Action, int); method @NonNull public final android.os.IBinder onBind(@Nullable android.content.Intent); + method public void onCapabilitiesChanged(); method public void onNotificationDirectReplied(@NonNull String); method @Nullable public abstract android.service.notification.Adjustment onNotificationEnqueued(@NonNull android.service.notification.StatusBarNotification); method @Nullable public android.service.notification.Adjustment onNotificationEnqueued(@NonNull android.service.notification.StatusBarNotification, @NonNull android.app.NotificationChannel); @@ -7589,11 +7574,11 @@ package android.telephony { field public static final int VSNCP_TIMEOUT = 2236; // 0x8bc } - public final class DataSpecificRegistrationStates implements android.os.Parcelable { + public final class DataSpecificRegistrationInfo implements android.os.Parcelable { method public int describeContents(); method @NonNull public android.telephony.LteVopsSupportInfo getLteVopsSupportInfo(); method public void writeToParcel(android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.telephony.DataSpecificRegistrationStates> CREATOR; + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.DataSpecificRegistrationInfo> CREATOR; } public final class DisconnectCause { @@ -7702,7 +7687,7 @@ package android.telephony { method public int getAccessNetworkTechnology(); method @NonNull public java.util.List<java.lang.Integer> getAvailableServices(); method @Nullable public android.telephony.CellIdentity getCellIdentity(); - method @Nullable public android.telephony.DataSpecificRegistrationStates getDataSpecificStates(); + method @Nullable public android.telephony.DataSpecificRegistrationInfo getDataSpecificInfo(); method public int getDomain(); method public int getRegistrationState(); method public int getRejectCause(); @@ -7745,19 +7730,19 @@ package android.telephony { ctor public NetworkService(); method public android.os.IBinder onBind(android.content.Intent); method @Nullable public abstract android.telephony.NetworkService.NetworkServiceProvider onCreateNetworkServiceProvider(int); - field public static final String NETWORK_SERVICE_INTERFACE = "android.telephony.NetworkService"; + field public static final String SERVICE_INTERFACE = "android.telephony.NetworkService"; } public abstract class NetworkService.NetworkServiceProvider implements java.lang.AutoCloseable { ctor public NetworkService.NetworkServiceProvider(int); method public abstract void close(); - method public void getNetworkRegistrationInfo(int, @NonNull android.telephony.NetworkServiceCallback); method public final int getSlotIndex(); method public final void notifyNetworkRegistrationInfoChanged(); + method public void requestNetworkRegistrationInfo(int, @NonNull android.telephony.NetworkServiceCallback); } public class NetworkServiceCallback { - method public void onGetNetworkRegistrationInfoComplete(int, @Nullable android.telephony.NetworkRegistrationInfo); + method public void onRequestNetworkRegistrationInfoComplete(int, @Nullable android.telephony.NetworkRegistrationInfo); field public static final int RESULT_ERROR_BUSY = 3; // 0x3 field public static final int RESULT_ERROR_FAILED = 5; // 0x5 field public static final int RESULT_ERROR_ILLEGAL_STATE = 4; // 0x4 @@ -8059,11 +8044,12 @@ package android.telephony { method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getVoiceActivationState(); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean handlePinMmi(String); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean handlePinMmiForSubscriber(int, String); - method @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean iccCloseLogicalChannelBySlot(int, int); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean iccCloseLogicalChannelBySlot(int, int); method @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannelBySlot(int, @Nullable String, int); method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String iccTransmitApduBasicChannelBySlot(int, int, int, int, int, int, @Nullable String); method @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String iccTransmitApduLogicalChannelBySlot(int, int, int, int, int, int, int, @Nullable String); method public boolean isDataConnectivityPossible(); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isEmergencyAssistanceEnabled(); method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isIdle(); method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isOffhook(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isPotentialEmergencyNumber(@NonNull String); @@ -8083,7 +8069,7 @@ package android.telephony { method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataActivationState(int); method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataEnabled(int, boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataRoamingEnabled(boolean); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setMultisimCarrierRestriction(boolean); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setMultiSimCarrierRestriction(boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setPreferredNetworkTypeBitmask(long); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setRadio(boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setRadioPower(boolean); @@ -8190,39 +8176,55 @@ package android.telephony { package android.telephony.data { public final class DataCallResponse implements android.os.Parcelable { - ctor public DataCallResponse(int, int, int, int, int, @Nullable String, @Nullable java.util.List<android.net.LinkAddress>, @Nullable java.util.List<java.net.InetAddress>, @Nullable java.util.List<java.net.InetAddress>, @Nullable java.util.List<java.lang.String>, int); method public int describeContents(); - method public int getActive(); method @NonNull public java.util.List<android.net.LinkAddress> getAddresses(); - method public int getCallId(); - method @NonNull public java.util.List<java.net.InetAddress> getDnses(); - method @NonNull public java.util.List<java.net.InetAddress> getGateways(); - method @NonNull public String getIfname(); + method public int getCause(); + method @NonNull public java.util.List<java.net.InetAddress> getDnsAddresses(); + method @NonNull public java.util.List<java.net.InetAddress> getGatewayAddresses(); + method public int getId(); + method @NonNull public String getInterfaceName(); + method public int getLinkStatus(); method public int getMtu(); - method @NonNull public java.util.List<java.lang.String> getPcscfs(); + method @NonNull public java.util.List<java.net.InetAddress> getPcscfAddresses(); method public int getProtocolType(); - method public int getStatus(); method public int getSuggestedRetryTime(); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.telephony.data.DataCallResponse> CREATOR; + field public static final int LINK_STATUS_ACTIVE = 2; // 0x2 + field public static final int LINK_STATUS_DORMANT = 1; // 0x1 + field public static final int LINK_STATUS_INACTIVE = 0; // 0x0 + field public static final int LINK_STATUS_UNKNOWN = -1; // 0xffffffff + } + + public static final class DataCallResponse.Builder { + ctor public DataCallResponse.Builder(); + method @NonNull public android.telephony.data.DataCallResponse build(); + method @NonNull public android.telephony.data.DataCallResponse.Builder setAddresses(@NonNull java.util.List<android.net.LinkAddress>); + method @NonNull public android.telephony.data.DataCallResponse.Builder setCause(int); + method @NonNull public android.telephony.data.DataCallResponse.Builder setDnsAddresses(@NonNull java.util.List<java.net.InetAddress>); + method @NonNull public android.telephony.data.DataCallResponse.Builder setGatewayAddresses(@NonNull java.util.List<java.net.InetAddress>); + method @NonNull public android.telephony.data.DataCallResponse.Builder setId(int); + method @NonNull public android.telephony.data.DataCallResponse.Builder setInterfaceName(@NonNull String); + method @NonNull public android.telephony.data.DataCallResponse.Builder setLinkStatus(int); + method @NonNull public android.telephony.data.DataCallResponse.Builder setMtu(int); + method @NonNull public android.telephony.data.DataCallResponse.Builder setPcscfAddresses(@NonNull java.util.List<java.net.InetAddress>); + method @NonNull public android.telephony.data.DataCallResponse.Builder setProtocolType(int); + method @NonNull public android.telephony.data.DataCallResponse.Builder setSuggestedRetryTime(int); } public final class DataProfile implements android.os.Parcelable { method public int describeContents(); method @NonNull public String getApn(); method public int getAuthType(); - method public int getBearerBitmap(); - method public int getMaxConns(); - method public int getMaxConnsTime(); + method public int getBearerBitmask(); method public int getMtu(); method @Nullable public String getPassword(); method public int getProfileId(); - method public int getProtocol(); - method public int getRoamingProtocol(); - method public int getSupportedApnTypesBitmap(); + method public int getProtocolType(); + method public int getRoamingProtocolType(); + method public int getSupportedApnTypesBitmask(); method public int getType(); method @Nullable public String getUserName(); - method public int getWaitTime(); method public boolean isEnabled(); method public boolean isPersistent(); method public boolean isPreferred(); @@ -8233,32 +8235,52 @@ package android.telephony.data { field public static final int TYPE_COMMON = 0; // 0x0 } + public static final class DataProfile.Builder { + ctor public DataProfile.Builder(); + method @NonNull public android.telephony.data.DataProfile build(); + method @NonNull public android.telephony.data.DataProfile.Builder enable(boolean); + method @NonNull public android.telephony.data.DataProfile.Builder setApn(@NonNull String); + method @NonNull public android.telephony.data.DataProfile.Builder setAuthType(int); + method @NonNull public android.telephony.data.DataProfile.Builder setBearerBitmask(int); + method @NonNull public android.telephony.data.DataProfile.Builder setMtu(int); + method @NonNull public android.telephony.data.DataProfile.Builder setPassword(@NonNull String); + method @NonNull public android.telephony.data.DataProfile.Builder setPersistent(boolean); + method @NonNull public android.telephony.data.DataProfile.Builder setPreferred(boolean); + method @NonNull public android.telephony.data.DataProfile.Builder setProfileId(int); + method @NonNull public android.telephony.data.DataProfile.Builder setProtocolType(int); + method @NonNull public android.telephony.data.DataProfile.Builder setRoamingProtocolType(int); + method @NonNull public android.telephony.data.DataProfile.Builder setSupportedApnTypesBitmask(int); + method @NonNull public android.telephony.data.DataProfile.Builder setType(int); + method @NonNull public android.telephony.data.DataProfile.Builder setUserName(@NonNull String); + } + public abstract class DataService extends android.app.Service { ctor public DataService(); method public android.os.IBinder onBind(android.content.Intent); method @Nullable public abstract android.telephony.data.DataService.DataServiceProvider onCreateDataServiceProvider(int); - field public static final String DATA_SERVICE_INTERFACE = "android.telephony.data.DataService"; field public static final int REQUEST_REASON_HANDOVER = 3; // 0x3 field public static final int REQUEST_REASON_NORMAL = 1; // 0x1 field public static final int REQUEST_REASON_SHUTDOWN = 2; // 0x2 + field public static final int REQUEST_REASON_UNKNOWN = 0; // 0x0 + field public static final String SERVICE_INTERFACE = "android.telephony.data.DataService"; } public abstract class DataService.DataServiceProvider implements java.lang.AutoCloseable { ctor public DataService.DataServiceProvider(int); method public abstract void close(); method public void deactivateDataCall(int, int, @Nullable android.telephony.data.DataServiceCallback); - method public void getDataCallList(@NonNull android.telephony.data.DataServiceCallback); method public final int getSlotIndex(); method public final void notifyDataCallListChanged(java.util.List<android.telephony.data.DataCallResponse>); - method public void setDataProfile(@NonNull java.util.List<android.telephony.data.DataProfile>, boolean, @Nullable android.telephony.data.DataServiceCallback); - method public void setInitialAttachApn(@NonNull android.telephony.data.DataProfile, boolean, @Nullable android.telephony.data.DataServiceCallback); - method public void setupDataCall(int, @NonNull android.telephony.data.DataProfile, boolean, boolean, int, @Nullable android.net.LinkProperties, @Nullable android.telephony.data.DataServiceCallback); + method public void requestDataCallList(@NonNull android.telephony.data.DataServiceCallback); + method public void setDataProfile(@NonNull java.util.List<android.telephony.data.DataProfile>, boolean, @NonNull android.telephony.data.DataServiceCallback); + method public void setInitialAttachApn(@NonNull android.telephony.data.DataProfile, boolean, @NonNull android.telephony.data.DataServiceCallback); + method public void setupDataCall(int, @NonNull android.telephony.data.DataProfile, boolean, boolean, int, @Nullable android.net.LinkProperties, @NonNull android.telephony.data.DataServiceCallback); } public class DataServiceCallback { method public void onDataCallListChanged(@NonNull java.util.List<android.telephony.data.DataCallResponse>); method public void onDeactivateDataCallComplete(int); - method public void onGetDataCallListComplete(int, @NonNull java.util.List<android.telephony.data.DataCallResponse>); + method public void onRequestDataCallListComplete(int, @NonNull java.util.List<android.telephony.data.DataCallResponse>); method public void onSetDataProfileComplete(int); method public void onSetInitialAttachApnComplete(int); method public void onSetupDataCallComplete(int, @Nullable android.telephony.data.DataCallResponse); @@ -8271,15 +8293,15 @@ package android.telephony.data { public abstract class QualifiedNetworksService extends android.app.Service { ctor public QualifiedNetworksService(); - method @NonNull public abstract android.telephony.data.QualifiedNetworksService.NetworkAvailabilityUpdater createNetworkAvailabilityUpdater(int); + method @NonNull public abstract android.telephony.data.QualifiedNetworksService.NetworkAvailabilityProvider onCreateNetworkAvailabilityProvider(int); field public static final String QUALIFIED_NETWORKS_SERVICE_INTERFACE = "android.telephony.data.QualifiedNetworksService"; } - public abstract class QualifiedNetworksService.NetworkAvailabilityUpdater implements java.lang.AutoCloseable { - ctor public QualifiedNetworksService.NetworkAvailabilityUpdater(int); + public abstract class QualifiedNetworksService.NetworkAvailabilityProvider implements java.lang.AutoCloseable { + ctor public QualifiedNetworksService.NetworkAvailabilityProvider(int); method public abstract void close(); method public final int getSlotIndex(); - method public final void updateQualifiedNetworkTypes(int, @Nullable int[]); + method public final void updateQualifiedNetworkTypes(int, @NonNull java.util.List<java.lang.Integer>); } } @@ -9122,8 +9144,8 @@ package android.telephony.ims.feature { field public static final int STATE_UNAVAILABLE = 0; // 0x0 } - public static class ImsFeature.Capabilities { - field protected int mCapabilities; + @Deprecated public static class ImsFeature.Capabilities { + field @Deprecated protected int mCapabilities; } protected static class ImsFeature.CapabilityCallbackProxy { diff --git a/api/system-removed.txt b/api/system-removed.txt index 7e044698c72c..9780d43624fa 100644 --- a/api/system-removed.txt +++ b/api/system-removed.txt @@ -141,3 +141,11 @@ package android.telephony { } +package android.telephony.data { + + public final class DataCallResponse implements android.os.Parcelable { + ctor public DataCallResponse(int, int, int, int, int, @Nullable String, @Nullable java.util.List<android.net.LinkAddress>, @Nullable java.util.List<java.net.InetAddress>, @Nullable java.util.List<java.net.InetAddress>, @Nullable java.util.List<java.net.InetAddress>, int); + } + +} + diff --git a/api/test-current.txt b/api/test-current.txt index 583bf62160de..733ca341ab1f 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -420,7 +420,8 @@ package android.app.backup { public class BackupManager { method @RequiresPermission("android.permission.BACKUP") public android.content.Intent getConfigurationIntent(String); method @RequiresPermission("android.permission.BACKUP") public android.content.Intent getDataManagementIntent(String); - method @RequiresPermission("android.permission.BACKUP") public String getDataManagementLabel(String); + method @Nullable @RequiresPermission("android.permission.BACKUP") public CharSequence getDataManagementIntentLabel(@NonNull String); + method @Deprecated @Nullable @RequiresPermission("android.permission.BACKUP") public String getDataManagementLabel(@NonNull String); method @RequiresPermission("android.permission.BACKUP") public String getDestinationString(String); } @@ -460,7 +461,7 @@ package android.app.prediction { method public void destroy(); method public android.app.prediction.AppPredictionSessionId getSessionId(); method public void notifyAppTargetEvent(@NonNull android.app.prediction.AppTargetEvent); - method public void notifyLocationShown(@NonNull String, @NonNull java.util.List<android.app.prediction.AppTargetId>); + method public void notifyLaunchLocationShown(@NonNull String, @NonNull java.util.List<android.app.prediction.AppTargetId>); method public void registerPredictionUpdates(@NonNull java.util.concurrent.Executor, @NonNull android.app.prediction.AppPredictor.Callback); method public void requestPredictionUpdate(); method @Nullable public void sortTargets(@NonNull java.util.List<android.app.prediction.AppTarget>, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.util.List<android.app.prediction.AppTarget>>); @@ -472,7 +473,6 @@ package android.app.prediction { } public final class AppTarget implements android.os.Parcelable { - ctor public AppTarget(@NonNull android.app.prediction.AppTargetId, @NonNull String, @Nullable String, @NonNull android.os.UserHandle); method public int describeContents(); method @Nullable public String getClassName(); method @NonNull public android.app.prediction.AppTargetId getId(); @@ -484,6 +484,15 @@ package android.app.prediction { field @NonNull public static final android.os.Parcelable.Creator<android.app.prediction.AppTarget> CREATOR; } + public static final class AppTarget.Builder { + ctor public AppTarget.Builder(@NonNull android.app.prediction.AppTargetId); + method @NonNull public android.app.prediction.AppTarget build(); + method @NonNull public android.app.prediction.AppTarget.Builder setClassName(@NonNull String); + method @NonNull public android.app.prediction.AppTarget.Builder setRank(@IntRange(from=0) int); + method @NonNull public android.app.prediction.AppTarget.Builder setTarget(@NonNull String, @NonNull android.os.UserHandle); + method @NonNull public android.app.prediction.AppTarget.Builder setTarget(@NonNull android.content.pm.ShortcutInfo); + } + public final class AppTargetEvent implements android.os.Parcelable { method public int describeContents(); method public int getAction(); @@ -1077,6 +1086,13 @@ package android.media { method public android.media.BufferingParams.Builder setResumePlaybackMarkMs(int); } + public class FileDataSourceDesc extends android.media.DataSourceDesc { + method public long getLength(); + method public long getOffset(); + method @NonNull public android.os.ParcelFileDescriptor getParcelFileDescriptor(); + field public static final long FD_LENGTH_UNKNOWN = 576460752303423487L; // 0x7ffffffffffffffL + } + public static final class MediaCodecInfo.VideoCapabilities.PerformancePoint { ctor public MediaCodecInfo.VideoCapabilities.PerformancePoint(int, int, int, int, @NonNull android.util.Size); ctor public MediaCodecInfo.VideoCapabilities.PerformancePoint(@NonNull android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint, @NonNull android.util.Size); @@ -1101,6 +1117,12 @@ package android.media { method public android.media.PlaybackParams setAudioStretchMode(int); } + public class UriDataSourceDesc extends android.media.DataSourceDesc { + method @Nullable public java.util.List<java.net.HttpCookie> getCookies(); + method @Nullable public java.util.Map<java.lang.String,java.lang.String> getHeaders(); + method @NonNull public android.net.Uri getUri(); + } + public static final class VolumeShaper.Configuration.Builder { method @NonNull public android.media.VolumeShaper.Configuration.Builder setOptionFlags(int); } @@ -1189,8 +1211,7 @@ package android.metrics { package android.net { public class CaptivePortal implements android.os.Parcelable { - ctor public CaptivePortal(android.os.IBinder); - method public void logEvent(int, String); + method public void logEvent(int, @NonNull String); method public void useNetwork(); field public static final int APP_RETURN_DISMISSED = 0; // 0x0 field public static final int APP_RETURN_UNWANTED = 1; // 0x1 @@ -1198,14 +1219,14 @@ package android.net { } public class ConnectivityManager { - method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void startCaptivePortalApp(android.net.Network, android.os.Bundle); + method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void startCaptivePortalApp(@NonNull android.net.Network, @NonNull android.os.Bundle); field public static final String EXTRA_CAPTIVE_PORTAL_PROBE_SPEC = "android.net.extra.CAPTIVE_PORTAL_PROBE_SPEC"; field public static final String EXTRA_CAPTIVE_PORTAL_USER_AGENT = "android.net.extra.CAPTIVE_PORTAL_USER_AGENT"; } public final class IpPrefix implements android.os.Parcelable { - ctor public IpPrefix(java.net.InetAddress, int); - ctor public IpPrefix(String); + ctor public IpPrefix(@NonNull java.net.InetAddress, int); + ctor public IpPrefix(@NonNull String); } public final class IpSecManager { @@ -1216,48 +1237,48 @@ package android.net { ctor public LinkAddress(java.net.InetAddress, int, int, int); ctor public LinkAddress(@NonNull java.net.InetAddress, int); ctor public LinkAddress(@NonNull String); - ctor public LinkAddress(String, int, int); + ctor public LinkAddress(@NonNull String, int, int); method public boolean isGlobalPreferred(); - method public boolean isIPv4(); - method public boolean isIPv6(); - method public boolean isSameAddressAs(android.net.LinkAddress); + method public boolean isIpv4(); + method public boolean isIpv6(); + method public boolean isSameAddressAs(@Nullable android.net.LinkAddress); } public final class LinkProperties implements android.os.Parcelable { - ctor public LinkProperties(android.net.LinkProperties); - method public boolean addDnsServer(java.net.InetAddress); - method public boolean addLinkAddress(android.net.LinkAddress); + ctor public LinkProperties(@Nullable android.net.LinkProperties); + method public boolean addDnsServer(@NonNull java.net.InetAddress); + method public boolean addLinkAddress(@NonNull android.net.LinkAddress); method @Nullable public android.net.IpPrefix getNat64Prefix(); - method public java.util.List<java.net.InetAddress> getPcscfServers(); - method public String getTcpBufferSizes(); - method public java.util.List<java.net.InetAddress> getValidatedPrivateDnsServers(); - method public boolean hasGlobalIPv6Address(); - method public boolean hasIPv4Address(); - method public boolean hasIPv6DefaultRoute(); - method public boolean isIPv4Provisioned(); - method public boolean isIPv6Provisioned(); + method @NonNull public java.util.List<java.net.InetAddress> getPcscfServers(); + method @Nullable public String getTcpBufferSizes(); + method @NonNull public java.util.List<java.net.InetAddress> getValidatedPrivateDnsServers(); + method public boolean hasGlobalIpv6Address(); + method public boolean hasIpv4Address(); + method public boolean hasIpv6DefaultRoute(); + method public boolean isIpv4Provisioned(); + method public boolean isIpv6Provisioned(); method public boolean isProvisioned(); - method public boolean isReachable(java.net.InetAddress); - method public boolean removeDnsServer(java.net.InetAddress); - method public boolean removeLinkAddress(android.net.LinkAddress); - method public boolean removeRoute(android.net.RouteInfo); - method public void setNat64Prefix(android.net.IpPrefix); - method public void setPcscfServers(java.util.Collection<java.net.InetAddress>); + method public boolean isReachable(@NonNull java.net.InetAddress); + method public boolean removeDnsServer(@NonNull java.net.InetAddress); + method public boolean removeLinkAddress(@NonNull android.net.LinkAddress); + method public boolean removeRoute(@NonNull android.net.RouteInfo); + method public void setNat64Prefix(@Nullable android.net.IpPrefix); + method public void setPcscfServers(@NonNull java.util.Collection<java.net.InetAddress>); method public void setPrivateDnsServerName(@Nullable String); - method public void setTcpBufferSizes(String); + method public void setTcpBufferSizes(@Nullable String); method public void setUsePrivateDns(boolean); - method public void setValidatedPrivateDnsServers(java.util.Collection<java.net.InetAddress>); + method public void setValidatedPrivateDnsServers(@NonNull java.util.Collection<java.net.InetAddress>); } public class Network implements android.os.Parcelable { - ctor public Network(android.net.Network); - method public android.net.Network getPrivateDnsBypassingCopy(); + ctor public Network(@NonNull android.net.Network); + method @NonNull public android.net.Network getPrivateDnsBypassingCopy(); } public final class NetworkCapabilities implements android.os.Parcelable { method public int[] getCapabilities(); - method public int[] getTransportTypes(); - method public boolean satisfiedByNetworkCapabilities(android.net.NetworkCapabilities); + method @NonNull public int[] getTransportTypes(); + method public boolean satisfiedByNetworkCapabilities(@Nullable android.net.NetworkCapabilities); field public static final int TRANSPORT_TEST = 7; // 0x7 } @@ -1266,7 +1287,7 @@ package android.net { } public final class RouteInfo implements android.os.Parcelable { - ctor public RouteInfo(android.net.IpPrefix, java.net.InetAddress, String, int); + ctor public RouteInfo(@Nullable android.net.IpPrefix, @Nullable java.net.InetAddress, @Nullable String, int); method public int getType(); field public static final int RTN_THROW = 9; // 0x9 field public static final int RTN_UNICAST = 1; // 0x1 @@ -1275,18 +1296,18 @@ package android.net { public final class StaticIpConfiguration implements android.os.Parcelable { ctor public StaticIpConfiguration(); - ctor public StaticIpConfiguration(android.net.StaticIpConfiguration); - method public void addDnsServer(java.net.InetAddress); + ctor public StaticIpConfiguration(@Nullable android.net.StaticIpConfiguration); + method public void addDnsServer(@NonNull java.net.InetAddress); method public void clear(); method public int describeContents(); - method public java.util.List<java.net.InetAddress> getDnsServers(); - method public String getDomains(); - method public java.net.InetAddress getGateway(); - method public android.net.LinkAddress getIpAddress(); - method public java.util.List<android.net.RouteInfo> getRoutes(String); - method public void setDomains(String); - method public void setGateway(java.net.InetAddress); - method public void setIpAddress(android.net.LinkAddress); + method @NonNull public java.util.List<java.net.InetAddress> getDnsServers(); + method @Nullable public String getDomains(); + method @Nullable public java.net.InetAddress getGateway(); + method @Nullable public android.net.LinkAddress getIpAddress(); + method @NonNull public java.util.List<android.net.RouteInfo> getRoutes(String); + method public void setDomains(@Nullable String); + method public void setGateway(@Nullable java.net.InetAddress); + method public void setIpAddress(@Nullable android.net.LinkAddress); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.net.StaticIpConfiguration> CREATOR; } @@ -1323,8 +1344,8 @@ package android.net.apf { public final class ApfCapabilities implements android.os.Parcelable { ctor public ApfCapabilities(int, int, int); method public int describeContents(); - method public static boolean getApfDrop8023Frames(android.content.Context); - method public static int[] getApfEthTypeBlackList(android.content.Context); + method public static boolean getApfDrop8023Frames(@NonNull android.content.Context); + method @NonNull public static int[] getApfEthTypeBlackList(@NonNull android.content.Context); method public boolean hasDataAccess(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.net.apf.ApfCapabilities> CREATOR; @@ -1339,28 +1360,28 @@ package android.net.captiveportal { public final class CaptivePortalProbeResult { ctor public CaptivePortalProbeResult(int); - ctor public CaptivePortalProbeResult(int, String, String); - ctor public CaptivePortalProbeResult(int, String, String, android.net.captiveportal.CaptivePortalProbeSpec); + ctor public CaptivePortalProbeResult(int, @Nullable String, @Nullable String); + ctor public CaptivePortalProbeResult(int, @Nullable String, @Nullable String, @Nullable android.net.captiveportal.CaptivePortalProbeSpec); method public boolean isFailed(); method public boolean isPartialConnectivity(); method public boolean isPortal(); method public boolean isSuccessful(); - field public static final android.net.captiveportal.CaptivePortalProbeResult FAILED; + field @NonNull public static final android.net.captiveportal.CaptivePortalProbeResult FAILED; field public static final int FAILED_CODE = 599; // 0x257 field public static final android.net.captiveportal.CaptivePortalProbeResult PARTIAL; field public static final int PORTAL_CODE = 302; // 0x12e - field public static final android.net.captiveportal.CaptivePortalProbeResult SUCCESS; + field @NonNull public static final android.net.captiveportal.CaptivePortalProbeResult SUCCESS; field public static final int SUCCESS_CODE = 204; // 0xcc - field public final String detectUrl; + field @Nullable public final String detectUrl; field @Nullable public final android.net.captiveportal.CaptivePortalProbeSpec probeSpec; - field public final String redirectUrl; + field @Nullable public final String redirectUrl; } public abstract class CaptivePortalProbeSpec { - method public String getEncodedSpec(); - method public abstract android.net.captiveportal.CaptivePortalProbeResult getResult(int, @Nullable String); - method public java.net.URL getUrl(); - method public static java.util.Collection<android.net.captiveportal.CaptivePortalProbeSpec> parseCaptivePortalProbeSpecs(String); + method @NonNull public String getEncodedSpec(); + method @NonNull public abstract android.net.captiveportal.CaptivePortalProbeResult getResult(int, @Nullable String); + method @NonNull public java.net.URL getUrl(); + method @NonNull public static java.util.Collection<android.net.captiveportal.CaptivePortalProbeSpec> parseCaptivePortalProbeSpecs(@NonNull String); method @Nullable public static android.net.captiveportal.CaptivePortalProbeSpec parseSpecOrNull(@Nullable String); } @@ -1371,78 +1392,78 @@ package android.net.metrics { public final class ApfProgramEvent implements android.net.metrics.IpConnectivityLog.Event { } - public static class ApfProgramEvent.Builder { + public static final class ApfProgramEvent.Builder { ctor public ApfProgramEvent.Builder(); - method public android.net.metrics.ApfProgramEvent build(); - method public android.net.metrics.ApfProgramEvent.Builder setActualLifetime(long); - method public android.net.metrics.ApfProgramEvent.Builder setCurrentRas(int); - method public android.net.metrics.ApfProgramEvent.Builder setFilteredRas(int); - method public android.net.metrics.ApfProgramEvent.Builder setFlags(boolean, boolean); - method public android.net.metrics.ApfProgramEvent.Builder setLifetime(long); - method public android.net.metrics.ApfProgramEvent.Builder setProgramLength(int); + method @NonNull public android.net.metrics.ApfProgramEvent build(); + method @NonNull public android.net.metrics.ApfProgramEvent.Builder setActualLifetime(long); + method @NonNull public android.net.metrics.ApfProgramEvent.Builder setCurrentRas(int); + method @NonNull public android.net.metrics.ApfProgramEvent.Builder setFilteredRas(int); + method @NonNull public android.net.metrics.ApfProgramEvent.Builder setFlags(boolean, boolean); + method @NonNull public android.net.metrics.ApfProgramEvent.Builder setLifetime(long); + method @NonNull public android.net.metrics.ApfProgramEvent.Builder setProgramLength(int); } public final class ApfStats implements android.net.metrics.IpConnectivityLog.Event { } - public static class ApfStats.Builder { + public static final class ApfStats.Builder { ctor public ApfStats.Builder(); - method public android.net.metrics.ApfStats build(); - method public android.net.metrics.ApfStats.Builder setDroppedRas(int); - method public android.net.metrics.ApfStats.Builder setDurationMs(long); - method public android.net.metrics.ApfStats.Builder setMatchingRas(int); - method public android.net.metrics.ApfStats.Builder setMaxProgramSize(int); - method public android.net.metrics.ApfStats.Builder setParseErrors(int); - method public android.net.metrics.ApfStats.Builder setProgramUpdates(int); - method public android.net.metrics.ApfStats.Builder setProgramUpdatesAll(int); - method public android.net.metrics.ApfStats.Builder setProgramUpdatesAllowingMulticast(int); - method public android.net.metrics.ApfStats.Builder setReceivedRas(int); - method public android.net.metrics.ApfStats.Builder setZeroLifetimeRas(int); + method @NonNull public android.net.metrics.ApfStats build(); + method @NonNull public android.net.metrics.ApfStats.Builder setDroppedRas(int); + method @NonNull public android.net.metrics.ApfStats.Builder setDurationMs(long); + method @NonNull public android.net.metrics.ApfStats.Builder setMatchingRas(int); + method @NonNull public android.net.metrics.ApfStats.Builder setMaxProgramSize(int); + method @NonNull public android.net.metrics.ApfStats.Builder setParseErrors(int); + method @NonNull public android.net.metrics.ApfStats.Builder setProgramUpdates(int); + method @NonNull public android.net.metrics.ApfStats.Builder setProgramUpdatesAll(int); + method @NonNull public android.net.metrics.ApfStats.Builder setProgramUpdatesAllowingMulticast(int); + method @NonNull public android.net.metrics.ApfStats.Builder setReceivedRas(int); + method @NonNull public android.net.metrics.ApfStats.Builder setZeroLifetimeRas(int); } public final class DhcpClientEvent implements android.net.metrics.IpConnectivityLog.Event { } - public static class DhcpClientEvent.Builder { + public static final class DhcpClientEvent.Builder { ctor public DhcpClientEvent.Builder(); - method public android.net.metrics.DhcpClientEvent build(); - method public android.net.metrics.DhcpClientEvent.Builder setDurationMs(int); - method public android.net.metrics.DhcpClientEvent.Builder setMsg(String); + method @NonNull public android.net.metrics.DhcpClientEvent build(); + method @NonNull public android.net.metrics.DhcpClientEvent.Builder setDurationMs(int); + method @NonNull public android.net.metrics.DhcpClientEvent.Builder setMsg(String); } public final class DhcpErrorEvent implements android.net.metrics.IpConnectivityLog.Event { ctor public DhcpErrorEvent(int); method public static int errorCodeWithOption(int, int); - field public static final int BOOTP_TOO_SHORT; - field public static final int BUFFER_UNDERFLOW; - field public static final int DHCP_BAD_MAGIC_COOKIE; + field public static final int BOOTP_TOO_SHORT = 67174400; // 0x4010000 + field public static final int BUFFER_UNDERFLOW = 83951616; // 0x5010000 + field public static final int DHCP_BAD_MAGIC_COOKIE = 67239936; // 0x4020000 field public static final int DHCP_ERROR = 4; // 0x4 - field public static final int DHCP_INVALID_OPTION_LENGTH; - field public static final int DHCP_NO_COOKIE; - field public static final int DHCP_NO_MSG_TYPE; - field public static final int DHCP_UNKNOWN_MSG_TYPE; + field public static final int DHCP_INVALID_OPTION_LENGTH = 67305472; // 0x4030000 + field public static final int DHCP_NO_COOKIE = 67502080; // 0x4060000 + field public static final int DHCP_NO_MSG_TYPE = 67371008; // 0x4040000 + field public static final int DHCP_UNKNOWN_MSG_TYPE = 67436544; // 0x4050000 field public static final int L2_ERROR = 1; // 0x1 - field public static final int L2_TOO_SHORT; - field public static final int L2_WRONG_ETH_TYPE; + field public static final int L2_TOO_SHORT = 16842752; // 0x1010000 + field public static final int L2_WRONG_ETH_TYPE = 16908288; // 0x1020000 field public static final int L3_ERROR = 2; // 0x2 - field public static final int L3_INVALID_IP; - field public static final int L3_NOT_IPV4; - field public static final int L3_TOO_SHORT; + field public static final int L3_INVALID_IP = 33751040; // 0x2030000 + field public static final int L3_NOT_IPV4 = 33685504; // 0x2020000 + field public static final int L3_TOO_SHORT = 33619968; // 0x2010000 field public static final int L4_ERROR = 3; // 0x3 - field public static final int L4_NOT_UDP; - field public static final int L4_WRONG_PORT; + field public static final int L4_NOT_UDP = 50397184; // 0x3010000 + field public static final int L4_WRONG_PORT = 50462720; // 0x3020000 field public static final int MISC_ERROR = 5; // 0x5 - field public static final int PARSING_ERROR; - field public static final int RECEIVE_ERROR; + field public static final int PARSING_ERROR = 84082688; // 0x5030000 + field public static final int RECEIVE_ERROR = 84017152; // 0x5020000 } public class IpConnectivityLog { ctor public IpConnectivityLog(); - method public boolean log(long, android.net.metrics.IpConnectivityLog.Event); - method public boolean log(String, android.net.metrics.IpConnectivityLog.Event); - method public boolean log(android.net.Network, int[], android.net.metrics.IpConnectivityLog.Event); - method public boolean log(int, int[], android.net.metrics.IpConnectivityLog.Event); - method public boolean log(android.net.metrics.IpConnectivityLog.Event); + method public boolean log(long, @NonNull android.net.metrics.IpConnectivityLog.Event); + method public boolean log(@NonNull String, @NonNull android.net.metrics.IpConnectivityLog.Event); + method public boolean log(@NonNull android.net.Network, @NonNull int[], @NonNull android.net.metrics.IpConnectivityLog.Event); + method public boolean log(int, @NonNull int[], @NonNull android.net.metrics.IpConnectivityLog.Event); + method public boolean log(@NonNull android.net.metrics.IpConnectivityLog.Event); } public static interface IpConnectivityLog.Event extends android.os.Parcelable { @@ -1490,15 +1511,15 @@ package android.net.metrics { public final class RaEvent implements android.net.metrics.IpConnectivityLog.Event { } - public static class RaEvent.Builder { + public static final class RaEvent.Builder { ctor public RaEvent.Builder(); - method public android.net.metrics.RaEvent build(); - method public android.net.metrics.RaEvent.Builder updateDnsslLifetime(long); - method public android.net.metrics.RaEvent.Builder updatePrefixPreferredLifetime(long); - method public android.net.metrics.RaEvent.Builder updatePrefixValidLifetime(long); - method public android.net.metrics.RaEvent.Builder updateRdnssLifetime(long); - method public android.net.metrics.RaEvent.Builder updateRouteInfoLifetime(long); - method public android.net.metrics.RaEvent.Builder updateRouterLifetime(long); + method @NonNull public android.net.metrics.RaEvent build(); + method @NonNull public android.net.metrics.RaEvent.Builder updateDnsslLifetime(long); + method @NonNull public android.net.metrics.RaEvent.Builder updatePrefixPreferredLifetime(long); + method @NonNull public android.net.metrics.RaEvent.Builder updatePrefixValidLifetime(long); + method @NonNull public android.net.metrics.RaEvent.Builder updateRdnssLifetime(long); + method @NonNull public android.net.metrics.RaEvent.Builder updateRouteInfoLifetime(long); + method @NonNull public android.net.metrics.RaEvent.Builder updateRouterLifetime(long); } public final class ValidationProbeEvent implements android.net.metrics.IpConnectivityLog.Event { @@ -1513,12 +1534,12 @@ package android.net.metrics { field public static final int PROBE_PRIVDNS = 5; // 0x5 } - public static class ValidationProbeEvent.Builder { + public static final class ValidationProbeEvent.Builder { ctor public ValidationProbeEvent.Builder(); - method public android.net.metrics.ValidationProbeEvent build(); - method public android.net.metrics.ValidationProbeEvent.Builder setDurationMs(long); - method public android.net.metrics.ValidationProbeEvent.Builder setProbeType(int, boolean); - method public android.net.metrics.ValidationProbeEvent.Builder setReturnCode(int); + method @NonNull public android.net.metrics.ValidationProbeEvent build(); + method @NonNull public android.net.metrics.ValidationProbeEvent.Builder setDurationMs(long); + method @NonNull public android.net.metrics.ValidationProbeEvent.Builder setProbeType(int, boolean); + method @NonNull public android.net.metrics.ValidationProbeEvent.Builder setReturnCode(int); } } @@ -2240,7 +2261,7 @@ package android.service.appprediction { method @NonNull public final android.os.IBinder onBind(@NonNull android.content.Intent); method public void onCreatePredictionSession(@NonNull android.app.prediction.AppPredictionContext, @NonNull android.app.prediction.AppPredictionSessionId); method @MainThread public void onDestroyPredictionSession(@NonNull android.app.prediction.AppPredictionSessionId); - method @MainThread public abstract void onLocationShown(@NonNull android.app.prediction.AppPredictionSessionId, @NonNull String, @NonNull java.util.List<android.app.prediction.AppTargetId>); + method @MainThread public abstract void onLaunchLocationShown(@NonNull android.app.prediction.AppPredictionSessionId, @NonNull String, @NonNull java.util.List<android.app.prediction.AppTargetId>); method @MainThread public abstract void onRequestPredictionUpdate(@NonNull android.app.prediction.AppPredictionSessionId); method @MainThread public abstract void onSortAppTargets(@NonNull android.app.prediction.AppPredictionSessionId, @NonNull java.util.List<android.app.prediction.AppTarget>, @NonNull android.os.CancellationSignal, @NonNull java.util.function.Consumer<java.util.List<android.app.prediction.AppTarget>>); method @MainThread public void onStartPredictionUpdates(); @@ -2534,10 +2555,34 @@ package android.telecom { package android.telephony { + public final class AccessNetworkConstants { + field public static final int TRANSPORT_TYPE_WLAN = 2; // 0x2 + field public static final int TRANSPORT_TYPE_WWAN = 1; // 0x1 + } + public class CarrierConfigManager { method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void overrideConfig(int, @Nullable android.os.PersistableBundle); } + public final class DataSpecificRegistrationInfo implements android.os.Parcelable { + method public int describeContents(); + method @NonNull public android.telephony.LteVopsSupportInfo getLteVopsSupportInfo(); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.DataSpecificRegistrationInfo> CREATOR; + } + + public final class LteVopsSupportInfo implements android.os.Parcelable { + ctor public LteVopsSupportInfo(int, int); + method public int describeContents(); + method public int getEmcBearerSupport(); + method public int getVopsSupport(); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.LteVopsSupportInfo> CREATOR; + field public static final int LTE_STATUS_NOT_AVAILABLE = 1; // 0x1 + field public static final int LTE_STATUS_NOT_SUPPORTED = 3; // 0x3 + field public static final int LTE_STATUS_SUPPORTED = 2; // 0x2 + } + public class MbmsDownloadSession implements java.lang.AutoCloseable { field public static final String MBMS_DOWNLOAD_SERVICE_OVERRIDE_METADATA = "mbms-download-service-override"; } @@ -2550,7 +2595,52 @@ package android.telephony { field public static final String MBMS_STREAMING_SERVICE_OVERRIDE_METADATA = "mbms-streaming-service-override"; } + public final class NetworkRegistrationInfo implements android.os.Parcelable { + method public int describeContents(); + method public int getAccessNetworkTechnology(); + method @NonNull public java.util.List<java.lang.Integer> getAvailableServices(); + method @Nullable public android.telephony.CellIdentity getCellIdentity(); + method @Nullable public android.telephony.DataSpecificRegistrationInfo getDataSpecificInfo(); + method public int getDomain(); + method public int getRegistrationState(); + method public int getRejectCause(); + method public int getRoamingType(); + method public int getTransportType(); + method public boolean isEmergencyEnabled(); + method public boolean isRoaming(); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.NetworkRegistrationInfo> CREATOR; + field public static final int DOMAIN_CS = 1; // 0x1 + field public static final int DOMAIN_PS = 2; // 0x2 + field public static final int REGISTRATION_STATE_DENIED = 3; // 0x3 + field public static final int REGISTRATION_STATE_HOME = 1; // 0x1 + field public static final int REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING = 0; // 0x0 + field public static final int REGISTRATION_STATE_NOT_REGISTERED_SEARCHING = 2; // 0x2 + field public static final int REGISTRATION_STATE_ROAMING = 5; // 0x5 + field public static final int REGISTRATION_STATE_UNKNOWN = 4; // 0x4 + field public static final int SERVICE_TYPE_DATA = 2; // 0x2 + field public static final int SERVICE_TYPE_EMERGENCY = 5; // 0x5 + field public static final int SERVICE_TYPE_SMS = 3; // 0x3 + field public static final int SERVICE_TYPE_UNKNOWN = 0; // 0x0 + field public static final int SERVICE_TYPE_VIDEO = 4; // 0x4 + field public static final int SERVICE_TYPE_VOICE = 1; // 0x1 + } + + public static final class NetworkRegistrationInfo.Builder { + ctor public NetworkRegistrationInfo.Builder(); + method @NonNull public android.telephony.NetworkRegistrationInfo build(); + method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setAccessNetworkTechnology(int); + method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setAvailableServices(@NonNull java.util.List<java.lang.Integer>); + method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setCellIdentity(@Nullable android.telephony.CellIdentity); + method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setDomain(int); + method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setEmergencyOnly(boolean); + method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setRegistrationState(int); + method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setRejectCause(int); + method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setTransportType(int); + } + public class ServiceState implements android.os.Parcelable { + method public void addNetworkRegistrationInfo(android.telephony.NetworkRegistrationInfo); method public void setCdmaSystemAndNetworkId(int, int); method public void setCellBandwidths(int[]); method public void setChannelNumber(int); @@ -3185,10 +3275,6 @@ package android.view.inputmethod { package android.view.inspector { - @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE}) public @interface InspectableNodeName { - method public abstract String value(); - } - @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.FIELD}) public @interface InspectableProperty { method public abstract int attributeId() default android.content.res.Resources.ID_NULL; method public abstract android.view.inspector.InspectableProperty.EnumEntry[] enumMapping() default {}; diff --git a/cmds/idmap2/idmap2/Create.cpp b/cmds/idmap2/idmap2/Create.cpp index fdbb21044176..47617e045c12 100644 --- a/cmds/idmap2/idmap2/Create.cpp +++ b/cmds/idmap2/idmap2/Create.cpp @@ -98,12 +98,10 @@ Result<Unit> Create(const std::vector<std::string>& args) { return Error("failed to load apk %s", overlay_apk_path.c_str()); } - std::stringstream stream; - const std::unique_ptr<const Idmap> idmap = - Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, - fulfilled_policies, !ignore_overlayable, stream); + const auto idmap = Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, + *overlay_apk, fulfilled_policies, !ignore_overlayable); if (!idmap) { - return Error("failed to create idmap: %s", stream.str().c_str()); + return Error(idmap.GetError(), "failed to create idmap"); } umask(kIdmapFilePermissionMask); @@ -112,7 +110,7 @@ Result<Unit> Create(const std::vector<std::string>& args) { return Error("failed to open idmap path %s", idmap_path.c_str()); } BinaryStreamVisitor visitor(fout); - idmap->accept(&visitor); + (*idmap)->accept(&visitor); fout.close(); if (fout.fail()) { return Error("failed to write to idmap path %s", idmap_path.c_str()); diff --git a/cmds/idmap2/idmap2/Dump.cpp b/cmds/idmap2/idmap2/Dump.cpp index fd5822251188..8716bf313ed0 100644 --- a/cmds/idmap2/idmap2/Dump.cpp +++ b/cmds/idmap2/idmap2/Dump.cpp @@ -49,20 +49,19 @@ Result<Unit> Dump(const std::vector<std::string>& args) { if (!opts_ok) { return opts_ok.GetError(); } - std::stringstream stream; std::ifstream fin(idmap_path); - const std::unique_ptr<const Idmap> idmap = Idmap::FromBinaryStream(fin, stream); + const auto idmap = Idmap::FromBinaryStream(fin); fin.close(); if (!idmap) { - return Error("failed to load idmap: %s", stream.str().c_str()); + return Error(idmap.GetError(), "failed to load idmap"); } if (verbose) { RawPrintVisitor visitor(std::cout); - idmap->accept(&visitor); + (*idmap)->accept(&visitor); } else { PrettyPrintVisitor visitor(std::cout); - idmap->accept(&visitor); + (*idmap)->accept(&visitor); } return Unit{}; diff --git a/cmds/idmap2/idmap2d/Idmap2Service.cpp b/cmds/idmap2/idmap2d/Idmap2Service.cpp index e03a9cc1032e..4f653796ce3f 100644 --- a/cmds/idmap2/idmap2d/Idmap2Service.cpp +++ b/cmds/idmap2/idmap2d/Idmap2Service.cpp @@ -138,12 +138,10 @@ Status Idmap2Service::createIdmap(const std::string& target_apk_path, return error("failed to load apk " + overlay_apk_path); } - std::stringstream err; - const std::unique_ptr<const Idmap> idmap = - Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, - policy_bitmask, enforce_overlayable, err); + const auto idmap = Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, + *overlay_apk, policy_bitmask, enforce_overlayable); if (!idmap) { - return error(err.str()); + return error(idmap.GetErrorMessage()); } umask(kIdmapFilePermissionMask); @@ -152,7 +150,7 @@ Status Idmap2Service::createIdmap(const std::string& target_apk_path, return error("failed to open idmap path " + idmap_path); } BinaryStreamVisitor visitor(fout); - idmap->accept(&visitor); + (*idmap)->accept(&visitor); fout.close(); if (fout.fail()) { return error("failed to write to idmap path " + idmap_path); diff --git a/cmds/idmap2/include/idmap2/Idmap.h b/cmds/idmap2/include/idmap2/Idmap.h index 673d18d25907..5cc0664b2bed 100644 --- a/cmds/idmap2/include/idmap2/Idmap.h +++ b/cmds/idmap2/include/idmap2/Idmap.h @@ -228,17 +228,18 @@ class Idmap { static std::string CanonicalIdmapPathFor(const std::string& absolute_dir, const std::string& absolute_apk_path); - static std::unique_ptr<const Idmap> FromBinaryStream(std::istream& stream, - std::ostream& out_error); + static Result<std::unique_ptr<const Idmap>> FromBinaryStream(std::istream& stream); // In the current version of idmap, the first package in each resources.arsc // file is used; change this in the next version of idmap to use a named // package instead; also update FromApkAssets to take additional parameters: // the target and overlay package names - static std::unique_ptr<const Idmap> FromApkAssets( - const std::string& target_apk_path, const ApkAssets& target_apk_assets, - const std::string& overlay_apk_path, const ApkAssets& overlay_apk_assets, - const PolicyBitmask& fulfilled_policies, bool enforce_overlayable, std::ostream& out_error); + static Result<std::unique_ptr<const Idmap>> FromApkAssets(const std::string& target_apk_path, + const ApkAssets& target_apk_assets, + const std::string& overlay_apk_path, + const ApkAssets& overlay_apk_assets, + const PolicyBitmask& fulfilled_policies, + bool enforce_overlayable); inline const std::unique_ptr<const IdmapHeader>& GetHeader() const { return header_; diff --git a/cmds/idmap2/libidmap2/Idmap.cpp b/cmds/idmap2/libidmap2/Idmap.cpp index 9afdd437491f..6d5fe7b3446a 100644 --- a/cmds/idmap2/libidmap2/Idmap.cpp +++ b/cmds/idmap2/libidmap2/Idmap.cpp @@ -56,7 +56,7 @@ class MatchingResources { } inline const std::map<TypeId, std::set<std::pair<ResourceId, ResourceId>>>& WARN_UNUSED - Map() const { + Map() const { return map_; } @@ -124,7 +124,7 @@ Result<uint32_t> GetCrc(const ZipFile& zip) { const Result<uint32_t> b = zip.Crc("AndroidManifest.xml"); return a && b ? Result<uint32_t>(*a ^ *b) - : Error("Couldn't get CRC for \"%s\"", a ? "AndroidManifest.xml" : "resources.arsc"); + : Error("failed to get CRC for \"%s\"", a ? "AndroidManifest.xml" : "resources.arsc"); } } // namespace @@ -244,15 +244,13 @@ std::string Idmap::CanonicalIdmapPathFor(const std::string& absolute_dir, return absolute_dir + "/" + copy + "@idmap"; } -std::unique_ptr<const Idmap> Idmap::FromBinaryStream(std::istream& stream, - std::ostream& out_error) { +Result<std::unique_ptr<const Idmap>> Idmap::FromBinaryStream(std::istream& stream) { SYSTRACE << "Idmap::FromBinaryStream"; std::unique_ptr<Idmap> idmap(new Idmap()); idmap->header_ = IdmapHeader::FromBinaryStream(stream); if (!idmap->header_) { - out_error << "error: failed to parse idmap header" << std::endl; - return nullptr; + return Error("failed to parse idmap header"); } // idmap version 0x01 does not specify the number of data blocks that follow @@ -260,13 +258,12 @@ std::unique_ptr<const Idmap> Idmap::FromBinaryStream(std::istream& stream, for (int i = 0; i < 1; i++) { std::unique_ptr<const IdmapData> data = IdmapData::FromBinaryStream(stream); if (!data) { - out_error << "error: failed to parse data block " << i << std::endl; - return nullptr; + return Error("failed to parse data block %d", i); } idmap->data_.push_back(std::move(data)); } - return std::move(idmap); + return {std::move(idmap)}; } std::string ConcatPolicies(const std::vector<std::string>& policies) { @@ -323,63 +320,56 @@ Result<Unit> CheckOverlayable(const LoadedPackage& target_package, return Result<Unit>({}); } -std::unique_ptr<const Idmap> Idmap::FromApkAssets( - const std::string& target_apk_path, const ApkAssets& target_apk_assets, - const std::string& overlay_apk_path, const ApkAssets& overlay_apk_assets, - const PolicyBitmask& fulfilled_policies, bool enforce_overlayable, std::ostream& out_error) { +Result<std::unique_ptr<const Idmap>> Idmap::FromApkAssets(const std::string& target_apk_path, + const ApkAssets& target_apk_assets, + const std::string& overlay_apk_path, + const ApkAssets& overlay_apk_assets, + const PolicyBitmask& fulfilled_policies, + bool enforce_overlayable) { SYSTRACE << "Idmap::FromApkAssets"; AssetManager2 target_asset_manager; if (!target_asset_manager.SetApkAssets({&target_apk_assets}, true, false)) { - out_error << "error: failed to create target asset manager" << std::endl; - return nullptr; + return Error("failed to create target asset manager"); } AssetManager2 overlay_asset_manager; if (!overlay_asset_manager.SetApkAssets({&overlay_apk_assets}, true, false)) { - out_error << "error: failed to create overlay asset manager" << std::endl; - return nullptr; + return Error("failed to create overlay asset manager"); } const LoadedArsc* target_arsc = target_apk_assets.GetLoadedArsc(); if (target_arsc == nullptr) { - out_error << "error: failed to load target resources.arsc" << std::endl; - return nullptr; + return Error("failed to load target resources.arsc"); } const LoadedArsc* overlay_arsc = overlay_apk_assets.GetLoadedArsc(); if (overlay_arsc == nullptr) { - out_error << "error: failed to load overlay resources.arsc" << std::endl; - return nullptr; + return Error("failed to load overlay resources.arsc"); } const LoadedPackage* target_pkg = GetPackageAtIndex0(*target_arsc); if (target_pkg == nullptr) { - out_error << "error: failed to load target package from resources.arsc" << std::endl; - return nullptr; + return Error("failed to load target package from resources.arsc"); } const LoadedPackage* overlay_pkg = GetPackageAtIndex0(*overlay_arsc); if (overlay_pkg == nullptr) { - out_error << "error: failed to load overlay package from resources.arsc" << std::endl; - return nullptr; + return Error("failed to load overlay package from resources.arsc"); } const std::unique_ptr<const ZipFile> target_zip = ZipFile::Open(target_apk_path); if (!target_zip) { - out_error << "error: failed to open target as zip" << std::endl; - return nullptr; + return Error("failed to open target as zip"); } const std::unique_ptr<const ZipFile> overlay_zip = ZipFile::Open(overlay_apk_path); if (!overlay_zip) { - out_error << "error: failed to open overlay as zip" << std::endl; - return nullptr; + return Error("failed to open overlay as zip"); } auto overlay_info = utils::ExtractOverlayManifestInfo(overlay_apk_path); if (!overlay_info) { - out_error << "error: " << overlay_info.GetErrorMessage() << std::endl; - return nullptr; + return overlay_info.GetError(); } std::unique_ptr<IdmapHeader> header(new IdmapHeader()); @@ -388,30 +378,26 @@ std::unique_ptr<const Idmap> Idmap::FromApkAssets( Result<uint32_t> crc = GetCrc(*target_zip); if (!crc) { - out_error << "error: failed to get zip crc for target" << std::endl; - return nullptr; + return Error(crc.GetError(), "failed to get zip CRC for target"); } header->target_crc_ = *crc; crc = GetCrc(*overlay_zip); if (!crc) { - out_error << "error: failed to get zip crc for overlay" << std::endl; - return nullptr; + return Error(crc.GetError(), "failed to get zip CRC for overlay"); } header->overlay_crc_ = *crc; if (target_apk_path.size() > sizeof(header->target_path_)) { - out_error << "error: target apk path \"" << target_apk_path << "\" longer that maximum size " - << sizeof(header->target_path_) << std::endl; - return nullptr; + return Error("target apk path \"%s\" longer than maximum size %zu", target_apk_path.c_str(), + sizeof(header->target_path_)); } memset(header->target_path_, 0, sizeof(header->target_path_)); memcpy(header->target_path_, target_apk_path.data(), target_apk_path.size()); if (overlay_apk_path.size() > sizeof(header->overlay_path_)) { - out_error << "error: overlay apk path \"" << overlay_apk_path << "\" longer that maximum size " - << sizeof(header->overlay_path_) << std::endl; - return nullptr; + return Error("overlay apk path \"%s\" longer than maximum size %zu", target_apk_path.c_str(), + sizeof(header->target_path_)); } memset(header->overlay_path_, 0, sizeof(header->overlay_path_)); memcpy(header->overlay_path_, overlay_apk_path.data(), overlay_apk_path.size()); @@ -451,9 +437,8 @@ std::unique_ptr<const Idmap> Idmap::FromApkAssets( } if (matching_resources.Map().empty()) { - out_error << "overlay \"" << overlay_apk_path << "\" does not successfully overlay any resource" - << std::endl; - return nullptr; + return Error("overlay \"%s\" does not successfully overlay any resource", + overlay_apk_path.c_str()); } // encode idmap data @@ -484,7 +469,7 @@ std::unique_ptr<const Idmap> Idmap::FromApkAssets( idmap->data_.push_back(std::move(data)); - return std::move(idmap); + return {std::move(idmap)}; } void IdmapHeader::accept(Visitor* v) const { diff --git a/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp b/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp index 9a0412efbde4..9a5b6331cb20 100644 --- a/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp +++ b/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp @@ -17,6 +17,7 @@ #include <memory> #include <sstream> #include <string> +#include <utility> #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -37,16 +38,17 @@ TEST(BinaryStreamVisitorTests, CreateBinaryStreamViaBinaryStreamVisitor) { std::string raw(reinterpret_cast<const char*>(idmap_raw_data), idmap_raw_data_len); std::istringstream raw_stream(raw); - std::stringstream error; - std::unique_ptr<const Idmap> idmap1 = Idmap::FromBinaryStream(raw_stream, error); - ASSERT_THAT(idmap1, NotNull()); + auto result1 = Idmap::FromBinaryStream(raw_stream); + ASSERT_TRUE(result1); + const auto idmap1 = std::move(*result1); std::stringstream stream; BinaryStreamVisitor visitor(stream); idmap1->accept(&visitor); - std::unique_ptr<const Idmap> idmap2 = Idmap::FromBinaryStream(stream, error); - ASSERT_THAT(idmap2, NotNull()); + auto result2 = Idmap::FromBinaryStream(stream); + ASSERT_TRUE(result2); + const auto idmap2 = std::move(*result2); ASSERT_EQ(idmap1->GetHeader()->GetTargetCrc(), idmap2->GetHeader()->GetTargetCrc()); ASSERT_EQ(idmap1->GetHeader()->GetTargetPath(), idmap2->GetHeader()->GetTargetPath()); @@ -76,15 +78,14 @@ TEST(BinaryStreamVisitorTests, CreateIdmapFromApkAssetsInteropWithLoadedIdmap) { std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path); ASSERT_THAT(overlay_apk, NotNull()); - std::stringstream error; - std::unique_ptr<const Idmap> idmap = + const auto idmap = Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, - PolicyFlags::POLICY_PUBLIC, /* enforce_overlayable */ true, error); - ASSERT_THAT(idmap, NotNull()); + PolicyFlags::POLICY_PUBLIC, /* enforce_overlayable */ true); + ASSERT_TRUE(idmap); std::stringstream stream; BinaryStreamVisitor visitor(stream); - idmap->accept(&visitor); + (*idmap)->accept(&visitor); const std::string str = stream.str(); const StringPiece data(str); std::unique_ptr<const LoadedIdmap> loaded_idmap = LoadedIdmap::Load(data); diff --git a/cmds/idmap2/tests/Idmap2BinaryTests.cpp b/cmds/idmap2/tests/Idmap2BinaryTests.cpp index a6a2ada76712..91bc4ddb397f 100644 --- a/cmds/idmap2/tests/Idmap2BinaryTests.cpp +++ b/cmds/idmap2/tests/Idmap2BinaryTests.cpp @@ -100,13 +100,12 @@ TEST_F(Idmap2BinaryTests, Create) { struct stat st; ASSERT_EQ(stat(GetIdmapPath().c_str(), &st), 0); - std::stringstream error; std::ifstream fin(GetIdmapPath()); - std::unique_ptr<const Idmap> idmap = Idmap::FromBinaryStream(fin, error); + const auto idmap = Idmap::FromBinaryStream(fin); fin.close(); - ASSERT_THAT(idmap, NotNull()); - ASSERT_IDMAP(*idmap, GetTargetApkPath(), GetOverlayApkPath()); + ASSERT_TRUE(idmap); + ASSERT_IDMAP(**idmap, GetTargetApkPath(), GetOverlayApkPath()); unlink(GetIdmapPath().c_str()); } @@ -193,24 +192,23 @@ TEST_F(Idmap2BinaryTests, Scan) { expected << idmap_static_2_path << std::endl; ASSERT_EQ(result->stdout, expected.str()); - std::stringstream error; auto idmap_static_no_name_raw_string = utils::ReadFile(idmap_static_no_name_path); auto idmap_static_no_name_raw_stream = std::istringstream(*idmap_static_no_name_raw_string); - auto idmap_static_no_name = Idmap::FromBinaryStream(idmap_static_no_name_raw_stream, error); - ASSERT_THAT(idmap_static_no_name, NotNull()); - ASSERT_IDMAP(*idmap_static_no_name, GetTargetApkPath(), overlay_static_no_name_apk_path); + auto idmap_static_no_name = Idmap::FromBinaryStream(idmap_static_no_name_raw_stream); + ASSERT_TRUE(idmap_static_no_name); + ASSERT_IDMAP(**idmap_static_no_name, GetTargetApkPath(), overlay_static_no_name_apk_path); auto idmap_static_1_raw_string = utils::ReadFile(idmap_static_1_path); auto idmap_static_1_raw_stream = std::istringstream(*idmap_static_1_raw_string); - auto idmap_static_1 = Idmap::FromBinaryStream(idmap_static_1_raw_stream, error); - ASSERT_THAT(idmap_static_1, NotNull()); - ASSERT_IDMAP(*idmap_static_1, GetTargetApkPath(), overlay_static_1_apk_path); + auto idmap_static_1 = Idmap::FromBinaryStream(idmap_static_1_raw_stream); + ASSERT_TRUE(idmap_static_1); + ASSERT_IDMAP(**idmap_static_1, GetTargetApkPath(), overlay_static_1_apk_path); auto idmap_static_2_raw_string = utils::ReadFile(idmap_static_2_path); auto idmap_static_2_raw_stream = std::istringstream(*idmap_static_2_raw_string); - auto idmap_static_2 = Idmap::FromBinaryStream(idmap_static_2_raw_stream, error); - ASSERT_THAT(idmap_static_2, NotNull()); - ASSERT_IDMAP(*idmap_static_2, GetTargetApkPath(), overlay_static_2_apk_path); + auto idmap_static_2 = Idmap::FromBinaryStream(idmap_static_2_raw_stream); + ASSERT_TRUE(idmap_static_2); + ASSERT_IDMAP(**idmap_static_2, GetTargetApkPath(), overlay_static_2_apk_path); unlink(idmap_static_no_name_path.c_str()); unlink(idmap_static_2_path.c_str()); diff --git a/cmds/idmap2/tests/IdmapTests.cpp b/cmds/idmap2/tests/IdmapTests.cpp index c20ae7b798a3..621f50337aa3 100644 --- a/cmds/idmap2/tests/IdmapTests.cpp +++ b/cmds/idmap2/tests/IdmapTests.cpp @@ -20,6 +20,7 @@ #include <memory> #include <sstream> #include <string> +#include <utility> #include <vector> #include "gmock/gmock.h" @@ -127,9 +128,9 @@ TEST(IdmapTests, CreateIdmapFromBinaryStream) { std::string raw(reinterpret_cast<const char*>(idmap_raw_data), idmap_raw_data_len); std::istringstream stream(raw); - std::stringstream error; - std::unique_ptr<const Idmap> idmap = Idmap::FromBinaryStream(stream, error); - ASSERT_THAT(idmap, NotNull()); + auto result = Idmap::FromBinaryStream(stream); + ASSERT_TRUE(result); + const auto idmap = std::move(*result); ASSERT_THAT(idmap->GetHeader(), NotNull()); ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U); @@ -168,9 +169,8 @@ TEST(IdmapTests, GracefullyFailToCreateIdmapFromCorruptBinaryStream) { 10); // data too small std::istringstream stream(raw); - std::stringstream error; - std::unique_ptr<const Idmap> idmap = Idmap::FromBinaryStream(stream, error); - ASSERT_THAT(idmap, IsNull()); + const auto result = Idmap::FromBinaryStream(stream); + ASSERT_FALSE(result); } void CreateIdmap(const StringPiece& target_apk_path, const StringPiece& overlay_apk_path, @@ -182,10 +182,10 @@ void CreateIdmap(const StringPiece& target_apk_path, const StringPiece& overlay_ std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path.to_string()); ASSERT_THAT(overlay_apk, NotNull()); - std::stringstream error; - *out_idmap = + auto result = Idmap::FromApkAssets(target_apk_path.to_string(), *target_apk, overlay_apk_path.to_string(), - *overlay_apk, fulfilled_policies, enforce_overlayable, error); + *overlay_apk, fulfilled_policies, enforce_overlayable); + *out_idmap = result ? std::move(*result) : nullptr; } TEST(IdmapTests, CreateIdmapFromApkAssets) { @@ -471,11 +471,10 @@ TEST(IdmapTests, FailToCreateIdmapFromApkAssetsIfPathTooLong) { std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path); ASSERT_THAT(overlay_apk, NotNull()); - std::stringstream error; - std::unique_ptr<const Idmap> idmap = + const auto result = Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, - PolicyFlags::POLICY_PUBLIC, /* enforce_overlayable */ true, error); - ASSERT_THAT(idmap, IsNull()); + PolicyFlags::POLICY_PUBLIC, /* enforce_overlayable */ true); + ASSERT_FALSE(result); } TEST(IdmapTests, IdmapHeaderIsUpToDate) { @@ -489,11 +488,11 @@ TEST(IdmapTests, IdmapHeaderIsUpToDate) { std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path); ASSERT_THAT(overlay_apk, NotNull()); - std::stringstream error; - std::unique_ptr<const Idmap> idmap = Idmap::FromApkAssets( - target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, PolicyFlags::POLICY_PUBLIC, - /* enforce_overlayable */ true, error); - ASSERT_THAT(idmap, NotNull()); + auto result = Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, + PolicyFlags::POLICY_PUBLIC, + /* enforce_overlayable */ true); + ASSERT_TRUE(result); + const auto idmap = std::move(*result); std::stringstream stream; BinaryStreamVisitor visitor(stream); @@ -609,13 +608,12 @@ TEST(IdmapTests, TestVisitor) { std::string raw(reinterpret_cast<const char*>(idmap_raw_data), idmap_raw_data_len); std::istringstream stream(raw); - std::stringstream error; - std::unique_ptr<const Idmap> idmap = Idmap::FromBinaryStream(stream, error); - ASSERT_THAT(idmap, NotNull()); + const auto idmap = Idmap::FromBinaryStream(stream); + ASSERT_TRUE(idmap); std::stringstream test_stream; TestVisitor visitor(test_stream); - idmap->accept(&visitor); + (*idmap)->accept(&visitor); ASSERT_EQ(test_stream.str(), "TestVisitor::visit(Idmap)\n" diff --git a/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp b/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp index eaa47cd79533..27a3880f67b6 100644 --- a/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp +++ b/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp @@ -46,15 +46,14 @@ TEST(PrettyPrintVisitorTests, CreatePrettyPrintVisitor) { std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path); ASSERT_THAT(overlay_apk, NotNull()); - std::stringstream error; - std::unique_ptr<const Idmap> idmap = + const auto idmap = Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, - PolicyFlags::POLICY_PUBLIC, /* enforce_overlayable */ true, error); - ASSERT_THAT(idmap, NotNull()); + PolicyFlags::POLICY_PUBLIC, /* enforce_overlayable */ true); + ASSERT_TRUE(idmap); std::stringstream stream; PrettyPrintVisitor visitor(stream); - idmap->accept(&visitor); + (*idmap)->accept(&visitor); ASSERT_NE(stream.str().find("target apk path : "), std::string::npos); ASSERT_NE(stream.str().find("overlay apk path : "), std::string::npos); @@ -67,13 +66,12 @@ TEST(PrettyPrintVisitorTests, CreatePrettyPrintVisitorWithoutAccessToApks) { std::string raw(reinterpret_cast<const char*>(idmap_raw_data), idmap_raw_data_len); std::istringstream raw_stream(raw); - std::stringstream error; - std::unique_ptr<const Idmap> idmap = Idmap::FromBinaryStream(raw_stream, error); - ASSERT_THAT(idmap, NotNull()); + const auto idmap = Idmap::FromBinaryStream(raw_stream); + ASSERT_TRUE(idmap); std::stringstream stream; PrettyPrintVisitor visitor(stream); - idmap->accept(&visitor); + (*idmap)->accept(&visitor); ASSERT_NE(stream.str().find("target apk path : "), std::string::npos); ASSERT_NE(stream.str().find("overlay apk path : "), std::string::npos); diff --git a/cmds/idmap2/tests/RawPrintVisitorTests.cpp b/cmds/idmap2/tests/RawPrintVisitorTests.cpp index 7ec13ed0ade7..7372148f0f0e 100644 --- a/cmds/idmap2/tests/RawPrintVisitorTests.cpp +++ b/cmds/idmap2/tests/RawPrintVisitorTests.cpp @@ -40,15 +40,14 @@ TEST(RawPrintVisitorTests, CreateRawPrintVisitor) { std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path); ASSERT_THAT(overlay_apk, NotNull()); - std::stringstream error; - std::unique_ptr<const Idmap> idmap = + const auto idmap = Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, - PolicyFlags::POLICY_PUBLIC, /* enforce_overlayable */ true, error); - ASSERT_THAT(idmap, NotNull()); + PolicyFlags::POLICY_PUBLIC, /* enforce_overlayable */ true); + ASSERT_TRUE(idmap); std::stringstream stream; RawPrintVisitor visitor(stream); - idmap->accept(&visitor); + (*idmap)->accept(&visitor); ASSERT_NE(stream.str().find("00000000: 504d4449 magic\n"), std::string::npos); ASSERT_NE(stream.str().find("00000004: 00000001 version\n"), std::string::npos); @@ -64,13 +63,12 @@ TEST(RawPrintVisitorTests, CreateRawPrintVisitorWithoutAccessToApks) { std::string raw(reinterpret_cast<const char*>(idmap_raw_data), idmap_raw_data_len); std::istringstream raw_stream(raw); - std::stringstream error; - std::unique_ptr<const Idmap> idmap = Idmap::FromBinaryStream(raw_stream, error); - ASSERT_THAT(idmap, NotNull()); + const auto idmap = Idmap::FromBinaryStream(raw_stream); + ASSERT_TRUE(idmap); std::stringstream stream; RawPrintVisitor visitor(stream); - idmap->accept(&visitor); + (*idmap)->accept(&visitor); ASSERT_NE(stream.str().find("00000000: 504d4449 magic\n"), std::string::npos); ASSERT_NE(stream.str().find("00000004: 00000001 version\n"), std::string::npos); diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto index d331c0f026f6..d6ea7e6572c9 100644 --- a/cmds/statsd/src/atoms.proto +++ b/cmds/statsd/src/atoms.proto @@ -40,6 +40,7 @@ import "frameworks/base/core/proto/android/server/job/enums.proto"; import "frameworks/base/core/proto/android/server/location/enums.proto"; import "frameworks/base/core/proto/android/service/procstats_enum.proto"; import "frameworks/base/core/proto/android/service/usb.proto"; +import "frameworks/base/core/proto/android/stats/connectivity/network_stack.proto"; import "frameworks/base/core/proto/android/stats/enums.proto"; import "frameworks/base/core/proto/android/stats/docsui/docsui_enums.proto"; import "frameworks/base/core/proto/android/stats/devicepolicy/device_policy.proto"; @@ -252,6 +253,7 @@ message Atom { StyleUIChanged style_ui_changed = 179; PrivacyIndicatorsInteracted privacy_indicators_interacted = 180; AppInstallOnExternalStorageReported app_install_on_external_storage_reported = 181; + NetworkStackReported network_stack_reported = 182; } // Pulled events will start at field 10000. @@ -3422,7 +3424,6 @@ message HiddenApiUsed { * - When user clicks privacy chip * - How does the user exit the Privacy Dialog * Logged from: - * packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyDialog.kt * packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java */ message PrivacyIndicatorsInteracted { @@ -5852,3 +5853,14 @@ message SystemIonHeapSize { // Size of the system ion heap in bytes. optional int64 size_in_bytes = 1; } + +/** + * Push network stack events. + * + * Log from: + * frameworks/base/packages/NetworkStack/ + */ +message NetworkStackReported { + optional int32 eventId = 1; + optional android.stats.connectivity.NetworkStackEventData network_stack_event = 2 [(log_mode) = MODE_BYTES]; +} diff --git a/config/boot-image-profile.txt b/config/boot-image-profile.txt index d740961cac2a..a3776c4b4d32 100644 --- a/config/boot-image-profile.txt +++ b/config/boot-image-profile.txt @@ -4759,7 +4759,6 @@ HPLandroid/os/IDeviceIdleController$Stub$Proxy;->addPowerSaveTempWhitelistAppFor HPLandroid/os/IDeviceIdleController$Stub$Proxy;->addPowerSaveTempWhitelistAppForSms(Ljava/lang/String;ILjava/lang/String;)J HPLandroid/os/IDeviceIdleController$Stub;->getDefaultTransactionName(I)Ljava/lang/String; HPLandroid/os/IDeviceIdleController$Stub;->onTransact(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z -HPLandroid/os/IDynamicAndroidService$Stub;->onTransact(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z HPLandroid/os/IHardwarePropertiesManager$Stub;->getDefaultTransactionName(I)Ljava/lang/String; HPLandroid/os/IHardwarePropertiesManager$Stub;->onTransact(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z HPLandroid/os/IInstalld$Stub$Proxy;->clearAppData(Ljava/lang/String;Ljava/lang/String;IIJ)V @@ -5081,6 +5080,7 @@ HPLandroid/os/health/HealthStatsWriter;->writeLongsMap(Landroid/os/Parcel;Landro HPLandroid/os/health/HealthStatsWriter;->writeParcelableMap(Landroid/os/Parcel;Landroid/util/ArrayMap;)V HPLandroid/os/health/TimerStat;-><init>(IJ)V HPLandroid/os/health/TimerStat;->writeToParcel(Landroid/os/Parcel;I)V +HPLandroid/os/image/IDynamicSystemService$Stub;->onTransact(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z HPLandroid/os/storage/IStorageEventListener$Stub$Proxy;->onStorageStateChanged(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V HPLandroid/os/storage/IStorageManager$Stub$Proxy;->allocateBytes(Ljava/lang/String;JILjava/lang/String;)V HPLandroid/os/storage/IStorageManager$Stub$Proxy;->changeEncryptionPassword(ILjava/lang/String;)I @@ -24027,7 +24027,6 @@ HSPLandroid/os/IDeviceIdleController$Stub$Proxy;->isPowerSaveWhitelistApp(Ljava/ HSPLandroid/os/IDeviceIdleController$Stub;-><init>()V HSPLandroid/os/IDeviceIdleController$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/IDeviceIdleController; HSPLandroid/os/IDumpstate$Stub;-><init>()V -HSPLandroid/os/IDynamicAndroidService$Stub;-><init>()V HSPLandroid/os/IExternalVibratorService$Stub;-><init>()V HSPLandroid/os/IHardwarePropertiesManager$Stub;-><init>()V HSPLandroid/os/IIncidentCompanion$Stub;-><init>()V @@ -24837,6 +24836,7 @@ HSPLandroid/os/ZygoteProcess;->waitForConnectionToZygote(Ljava/lang/String;)V HSPLandroid/os/ZygoteProcess;->zygoteSendArgsAndGetResult(Landroid/os/ZygoteProcess$ZygoteState;ZLjava/util/ArrayList;)Landroid/os/Process$ProcessStartResult; HSPLandroid/os/health/HealthStatsParceler$1;-><init>()V HSPLandroid/os/health/TimerStat$1;-><init>()V +HSPLandroid/os/image/IDynamicSystemService$Stub;-><init>()V HSPLandroid/os/storage/IStorageEventListener$Stub$Proxy;->asBinder()Landroid/os/IBinder; HSPLandroid/os/storage/IStorageEventListener$Stub;->asBinder()Landroid/os/IBinder; HSPLandroid/os/storage/IStorageManager$Stub$Proxy;->getVolumeList(ILjava/lang/String;I)[Landroid/os/storage/StorageVolume; @@ -47386,7 +47386,6 @@ Landroid/os/DeviceIdleManager; Landroid/os/DropBoxManager$Entry$1; Landroid/os/DropBoxManager$Entry; Landroid/os/DropBoxManager; -Landroid/os/DynamicAndroidManager; Landroid/os/Environment$UserEnvironment; Landroid/os/Environment; Landroid/os/EventLogTags; @@ -47428,8 +47427,6 @@ Landroid/os/IDeviceIdleController$Stub; Landroid/os/IDeviceIdleController; Landroid/os/IDumpstate$Stub; Landroid/os/IDumpstate; -Landroid/os/IDynamicAndroidService$Stub; -Landroid/os/IDynamicAndroidService; Landroid/os/IExternalVibratorService$Stub; Landroid/os/IExternalVibratorService; Landroid/os/IHardwarePropertiesManager$Stub; @@ -47689,6 +47686,10 @@ Landroid/os/health/HealthStatsWriter; Landroid/os/health/SystemHealthManager; Landroid/os/health/TimerStat$1; Landroid/os/health/TimerStat; +Landroid/os/image/DynamicSystemClient; +Landroid/os/image/DynamicSystemManager; +Landroid/os/image/IDynamicSystemService$Stub; +Landroid/os/image/IDynamicSystemService; Landroid/os/storage/DiskInfo; Landroid/os/storage/IObbActionListener$Stub; Landroid/os/storage/IObbActionListener; diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt index b3f003730c53..79cdb77bbd11 100644 --- a/config/hiddenapi-greylist.txt +++ b/config/hiddenapi-greylist.txt @@ -123,7 +123,6 @@ Landroid/bluetooth/IBluetoothStateChangeCallback$Stub;-><init>()V Landroid/companion/ICompanionDeviceDiscoveryService$Stub;-><init>()V Landroid/companion/ICompanionDeviceDiscoveryServiceCallback;->onDeviceSelected(Ljava/lang/String;ILjava/lang/String;)V Landroid/companion/ICompanionDeviceDiscoveryServiceCallback;->onDeviceSelectionCancel()V -Landroid/companion/IFindDeviceCallback;->onSuccess(Landroid/app/PendingIntent;)V Landroid/content/IClipboard$Stub$Proxy;-><init>(Landroid/os/IBinder;)V Landroid/content/IClipboard$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/IClipboard; Landroid/content/IContentService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V @@ -198,8 +197,6 @@ Landroid/database/IContentObserver$Stub;->asInterface(Landroid/os/IBinder;)Landr Landroid/database/IContentObserver;->onChange(ZLandroid/net/Uri;I)V Landroid/database/sqlite/SQLiteConnectionPool;->$assertionsDisabled:Z Landroid/database/sqlite/SQLiteDatabase;->$assertionsDisabled:Z -Landroid/filterfw/GraphEnvironment;->addReferences([Ljava/lang/Object;)V -Landroid/hardware/camera2/utils/HashCodeHelpers;->hashCode([I)I Landroid/hardware/display/IDisplayManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/display/IDisplayManager; Landroid/hardware/fingerprint/IFingerprintService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V Landroid/hardware/fingerprint/IFingerprintService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/fingerprint/IFingerprintService; @@ -211,8 +208,6 @@ Landroid/hardware/location/IActivityRecognitionHardwareClient$Stub;-><init>()V Landroid/hardware/location/IContextHubService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/location/IContextHubService; Landroid/hardware/usb/IUsbManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V Landroid/hardware/usb/IUsbManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/usb/IUsbManager; -Landroid/inputmethodservice/IInputMethodSessionWrapper;->mCaller:Lcom/android/internal/os/HandlerCaller; -Landroid/inputmethodservice/IInputMethodWrapper;->mCaller:Lcom/android/internal/os/HandlerCaller; Landroid/location/ICountryDetector$Stub;->asInterface(Landroid/os/IBinder;)Landroid/location/ICountryDetector; Landroid/location/ICountryListener$Stub;-><init>()V Landroid/location/IGeocodeProvider$Stub;-><init>()V @@ -230,7 +225,6 @@ Landroid/location/LocationManager$ListenerTransport;-><init>(Landroid/location/L Landroid/Manifest$permission;->CAPTURE_SECURE_VIDEO_OUTPUT:Ljava/lang/String; Landroid/Manifest$permission;->CAPTURE_VIDEO_OUTPUT:Ljava/lang/String; Landroid/Manifest$permission;->READ_FRAME_BUFFER:Ljava/lang/String; -Landroid/media/effect/SingleFilterEffect;-><init>(Landroid/media/effect/EffectContext;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)V Landroid/media/IAudioRoutesObserver$Stub;-><init>()V Landroid/media/IAudioService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V Landroid/media/IAudioService$Stub;-><init>()V @@ -266,7 +260,6 @@ Landroid/net/InterfaceConfiguration;-><init>()V Landroid/net/LinkProperties$ProvisioningChange;->values()[Landroid/net/LinkProperties$ProvisioningChange; Landroid/net/MobileLinkQualityInfo;-><init>()V Landroid/net/nsd/INsdManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/nsd/INsdManager; -Landroid/net/nsd/INsdManager;->getMessenger()Landroid/os/Messenger; Landroid/net/sip/ISipSession$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/sip/ISipSession; Landroid/net/SntpClient;-><init>()V Landroid/net/wifi/IWifiManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V @@ -295,7 +288,6 @@ Landroid/os/IPowerManager$Stub$Proxy;->isLightDeviceIdleMode()Z Landroid/os/IPowerManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/IPowerManager; Landroid/os/IPowerManager$Stub;->TRANSACTION_acquireWakeLock:I Landroid/os/IPowerManager$Stub;->TRANSACTION_goToSleep:I -Landroid/os/IPowerManager;->releaseWakeLock(Landroid/os/IBinder;I)V Landroid/os/IRecoverySystem$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/IRecoverySystem; Landroid/os/IRemoteCallback$Stub;-><init>()V Landroid/os/IUpdateEngine$Stub;-><init>()V @@ -310,7 +302,6 @@ Landroid/os/storage/IObbActionListener$Stub;-><init>()V Landroid/os/storage/IStorageManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V Landroid/os/storage/IStorageManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/storage/IStorageManager; Landroid/os/storage/StorageEventListener;-><init>()V -Landroid/preference/PreferenceGroupAdapter;->getItem(I)Landroid/preference/Preference; Landroid/R$styleable;->ActionBar:[I Landroid/R$styleable;->ActionBar_background:I Landroid/R$styleable;->ActionBar_backgroundSplit:I @@ -576,17 +567,6 @@ Landroid/R$styleable;->Window:[I Landroid/R$styleable;->Window_windowBackground:I Landroid/R$styleable;->Window_windowFrame:I Landroid/security/IKeyChainService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/security/IKeyChainService; -Landroid/security/keymaster/KeymasterBlobArgument;-><init>(ILandroid/os/Parcel;)V -Landroid/security/keymaster/KeymasterBlobArgument;-><init>(I[B)V -Landroid/security/keymaster/KeymasterBlobArgument;->blob:[B -Landroid/security/keymaster/KeymasterBooleanArgument;-><init>(ILandroid/os/Parcel;)V -Landroid/security/keymaster/KeymasterDateArgument;-><init>(ILandroid/os/Parcel;)V -Landroid/security/keymaster/KeymasterIntArgument;-><init>(II)V -Landroid/security/keymaster/KeymasterIntArgument;-><init>(ILandroid/os/Parcel;)V -Landroid/security/keymaster/KeymasterIntArgument;->value:I -Landroid/security/keymaster/KeymasterLongArgument;-><init>(IJ)V -Landroid/security/keymaster/KeymasterLongArgument;-><init>(ILandroid/os/Parcel;)V -Landroid/security/keymaster/KeymasterLongArgument;->value:J Landroid/security/keystore/IKeystoreService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/security/keystore/IKeystoreService; Landroid/security/keystore/IKeystoreService;->clear_uid(J)I Landroid/security/keystore/IKeystoreService;->del(Ljava/lang/String;I)I @@ -599,24 +579,17 @@ Landroid/security/keystore/IKeystoreService;->list(Ljava/lang/String;I)[Ljava/la Landroid/security/keystore/IKeystoreService;->reset()I Landroid/security/keystore/IKeystoreService;->ungrant(Ljava/lang/String;I)I Landroid/service/dreams/IDreamManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/dreams/IDreamManager; -Landroid/service/dreams/IDreamManager;->awaken()V -Landroid/service/dreams/IDreamManager;->dream()V Landroid/service/dreams/IDreamManager;->getDreamComponents()[Landroid/content/ComponentName; -Landroid/service/dreams/IDreamManager;->isDreaming()Z -Landroid/service/dreams/IDreamManager;->setDreamComponents([Landroid/content/ComponentName;)V Landroid/service/euicc/IEuiccService$Stub;-><init>()V Landroid/service/notification/INotificationListener$Stub;-><init>()V Landroid/service/persistentdata/IPersistentDataBlockService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/persistentdata/IPersistentDataBlockService; Landroid/service/vr/IVrManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/vr/IVrManager; Landroid/service/wallpaper/IWallpaperConnection$Stub;-><init>()V Landroid/service/wallpaper/IWallpaperService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/wallpaper/IWallpaperService; -Landroid/telecom/Log;->i(Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)V -Landroid/telecom/Log;->w(Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)V Landroid/telephony/ims/compat/feature/MMTelFeature;-><init>()V Landroid/telephony/ims/compat/ImsService;-><init>()V Landroid/telephony/ims/compat/stub/ImsCallSessionImplBase;-><init>()V Landroid/telephony/ims/compat/stub/ImsUtListenerImplBase;-><init>()V -Landroid/telephony/JapanesePhoneNumberFormatter;->format(Landroid/text/Editable;)V Landroid/telephony/mbms/IMbmsStreamingSessionCallback$Stub;-><init>()V Landroid/telephony/mbms/IStreamingServiceCallback$Stub;-><init>()V Landroid/telephony/mbms/vendor/IMbmsStreamingService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/telephony/mbms/vendor/IMbmsStreamingService; @@ -646,14 +619,8 @@ Landroid/telephony/SmsCbMessage;->isCmasMessage()Z Landroid/telephony/SmsCbMessage;->isEmergencyMessage()Z Landroid/telephony/TelephonyManager$MultiSimVariants;->values()[Landroid/telephony/TelephonyManager$MultiSimVariants; Landroid/util/Singleton;-><init>()V -Landroid/util/XmlPullAttributes;-><init>(Lorg/xmlpull/v1/XmlPullParser;)V -Landroid/util/XmlPullAttributes;->mParser:Lorg/xmlpull/v1/XmlPullParser; -Landroid/view/accessibility/IAccessibilityInteractionConnectionCallback;->setFindAccessibilityNodeInfoResult(Landroid/view/accessibility/AccessibilityNodeInfo;I)V -Landroid/view/accessibility/IAccessibilityInteractionConnectionCallback;->setFindAccessibilityNodeInfosResult(Ljava/util/List;I)V -Landroid/view/accessibility/IAccessibilityInteractionConnectionCallback;->setPerformAccessibilityActionResult(ZI)V Landroid/view/accessibility/IAccessibilityManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V Landroid/view/accessibility/IAccessibilityManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/view/accessibility/IAccessibilityManager; -Landroid/view/accessibility/IAccessibilityManager;->getEnabledAccessibilityServiceList(II)Ljava/util/List; Landroid/view/AccessibilityIterators$AbstractTextSegmentIterator;-><init>()V Landroid/view/autofill/IAutoFillManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V Landroid/view/autofill/IAutoFillManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/view/autofill/IAutoFillManager; @@ -1713,7 +1680,6 @@ Lcom/android/internal/widget/LockPatternUtils;->patternToHash(Ljava/util/List;)[ Lcom/android/internal/widget/LockPatternUtils;->patternToString(Ljava/util/List;)Ljava/lang/String; Lcom/android/internal/widget/LockPatternUtils;->reportFailedPasswordAttempt(I)V Lcom/android/internal/widget/LockPatternUtils;->reportSuccessfulPasswordAttempt(I)V -Lcom/android/internal/widget/LockPatternUtils;->saveLockPassword(Ljava/lang/String;Ljava/lang/String;II)V Lcom/android/internal/widget/LockPatternUtils;->setLockoutAttemptDeadline(II)J Lcom/android/internal/widget/LockPatternUtils;->setLong(Ljava/lang/String;JI)V Lcom/android/internal/widget/LockPatternUtils;->setOwnerInfo(Ljava/lang/String;I)V diff --git a/config/preloaded-classes b/config/preloaded-classes index fda028de33f3..abdbab2a29eb 100644 --- a/config/preloaded-classes +++ b/config/preloaded-classes @@ -2724,7 +2724,6 @@ android.os.DeviceIdleManager android.os.DropBoxManager$Entry$1 android.os.DropBoxManager$Entry android.os.DropBoxManager -android.os.DynamicAndroidManager android.os.Environment$UserEnvironment android.os.Environment android.os.EventLogTags @@ -2909,6 +2908,8 @@ android.os.health.HealthStatsParceler android.os.health.SystemHealthManager android.os.health.TimerStat$1 android.os.health.TimerStat +android.os.image.DynamicSystemClient +android.os.image.DynamicSystemManager android.os.storage.IObbActionListener$Stub android.os.storage.IObbActionListener android.os.storage.IStorageManager$Stub$Proxy diff --git a/core/java/android/accessibilityservice/AccessibilityButtonController.java b/core/java/android/accessibilityservice/AccessibilityButtonController.java index a70085cbde4f..af5af9cb9b17 100644 --- a/core/java/android/accessibilityservice/AccessibilityButtonController.java +++ b/core/java/android/accessibilityservice/AccessibilityButtonController.java @@ -17,7 +17,6 @@ package android.accessibilityservice; import android.annotation.NonNull; -import android.annotation.Nullable; import android.os.Handler; import android.os.Looper; import android.os.RemoteException; @@ -76,13 +75,16 @@ public final class AccessibilityButtonController { * available to the calling service, {@code false} otherwise */ public boolean isAccessibilityButtonAvailable() { - try { - return mServiceConnection.isAccessibilityButtonAvailable(); - } catch (RemoteException re) { - Slog.w(LOG_TAG, "Failed to get accessibility button availability.", re); - re.rethrowFromSystemServer(); - return false; + if (mServiceConnection != null) { + try { + return mServiceConnection.isAccessibilityButtonAvailable(); + } catch (RemoteException re) { + Slog.w(LOG_TAG, "Failed to get accessibility button availability.", re); + re.rethrowFromSystemServer(); + return false; + } } + return false; } /** diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index 7a0639eef8cc..404e52011c39 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -536,6 +536,19 @@ public class ApplicationPackageManager extends PackageManager { } } + @NonNull + @Override + public List<SharedLibraryInfo> getDeclaredSharedLibraries(@NonNull String packageName, + @InstallFlags int flags) { + try { + ParceledListSlice<SharedLibraryInfo> sharedLibraries = mPM.getDeclaredSharedLibraries( + packageName, flags, mContext.getUserId()); + return sharedLibraries != null ? sharedLibraries.getList() : Collections.emptyList(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** @hide */ @Override public @NonNull String getServicesSystemSharedLibraryPackageName() { diff --git a/core/java/android/app/AutomaticZenRule.java b/core/java/android/app/AutomaticZenRule.java index ec2825edebe6..7180c01143a5 100644 --- a/core/java/android/app/AutomaticZenRule.java +++ b/core/java/android/app/AutomaticZenRule.java @@ -231,7 +231,7 @@ public final class AutomaticZenRule implements Parcelable { * Sets the zen policy. */ public void setZenPolicy(ZenPolicy zenPolicy) { - this.mZenPolicy = zenPolicy; + this.mZenPolicy = (zenPolicy == null ? null : zenPolicy.copy()); } /** diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 5945eef52b2c..11000df5b993 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -1090,7 +1090,6 @@ class ContextImpl extends Context { @Override public void sendBroadcastAsUserMultiplePermissions(Intent intent, UserHandle user, String[] receiverPermissions) { - warnIfCallingFromSystemProcess(); String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); try { intent.prepareToLeaveProcess(this); diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl index 15084de0d7dd..7884872a7ef3 100644 --- a/core/java/android/app/INotificationManager.aidl +++ b/core/java/android/app/INotificationManager.aidl @@ -70,6 +70,10 @@ interface INotificationManager boolean areNotificationsEnabled(String pkg); int getPackageImportance(String pkg); + List<String> getAllowedAssistantCapabilities(String pkg); + void allowAssistantCapability(String adjustmentType); + void disallowAssistantCapability(String adjustmentType); + boolean shouldHideSilentStatusIcons(String callingPkg); void setHideSilentStatusIcons(boolean hide); @@ -86,10 +90,10 @@ interface INotificationManager NotificationChannelGroup getPopulatedNotificationChannelGroupForPackage(String pkg, int uid, String groupId, boolean includeDeleted); void updateNotificationChannelGroupForPackage(String pkg, int uid, in NotificationChannelGroup group); void updateNotificationChannelForPackage(String pkg, int uid, in NotificationChannel channel); - NotificationChannel getNotificationChannel(String pkg, String channelId); + NotificationChannel getNotificationChannel(String callingPkg, int userId, String pkg, String channelId); NotificationChannel getNotificationChannelForPackage(String pkg, int uid, String channelId, boolean includeDeleted); void deleteNotificationChannel(String pkg, String channelId); - ParceledListSlice getNotificationChannels(String pkg); + ParceledListSlice getNotificationChannels(String callingPkg, String targetPkg, int userId); ParceledListSlice getNotificationChannelsForPackage(String pkg, int uid, boolean includeDeleted); int getNumNotificationChannelsForPackage(String pkg, int uid, boolean includeDeleted); int getDeletedChannelCount(String pkg, int uid); diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index c9bd95da5c42..d634aa578429 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -16,6 +16,8 @@ package android.app; +import static android.graphics.drawable.Icon.TYPE_BITMAP; + import static com.android.internal.util.ContrastColorUtil.satisfiesTextContrast; import android.annotation.ColorInt; @@ -8583,17 +8585,6 @@ public class Notification implements Parcelable } /** - * @return the title that will appear along with the app content defined by - * {@link #getIntent()} for this bubble. - * - * @deprecated titles are no longer required or shown. - */ - @Deprecated - public CharSequence getTitle() { - return ""; - } - - /** * @return the icon that will be displayed for this bubble when it is collapsed. */ @NonNull @@ -8704,30 +8695,30 @@ public class Notification implements Parcelable } /** - * Sets the title that will appear along with the app content for this bubble. - * - * <p>A title is required and should expect to fit on a single line and make sense when - * shown with the content defined by {@link #setIntent(PendingIntent)}.</p> - * - * @deprecated titles are no longer required or shown. - */ - @Deprecated - public BubbleMetadata.Builder setTitle(CharSequence title) { - return this; - } - - /** * Sets the icon that will represent the bubble when it is collapsed. * * <p>An icon is required and should be representative of the content within the bubble. * If your app produces multiple bubbles, the image should be unique for each of them. * </p> + * + * <p>The shape of a bubble icon is adaptive and can match the device theme. + * + * If your icon is bitmap-based, you should create it using + * {@link Icon#createWithAdaptiveBitmap(Bitmap)}, otherwise this method will throw. + * + * If your icon is not bitmap-based, you should expect that the icon will be tinted. + * </p> */ @NonNull public BubbleMetadata.Builder setIcon(@NonNull Icon icon) { if (icon == null) { throw new IllegalArgumentException("Bubbles require non-null icon"); } + if (icon.getType() == TYPE_BITMAP) { + throw new IllegalArgumentException("When using bitmap based icons, Bubbles " + + "require TYPE_ADAPTIVE_BITMAP, please use" + + " Icon#createWithAdaptiveBitmap instead"); + } mIcon = icon; return this; } diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java index 6a301c91bb06..0bec21fcda90 100644 --- a/core/java/android/app/NotificationManager.java +++ b/core/java/android/app/NotificationManager.java @@ -42,6 +42,7 @@ import android.os.ServiceManager; import android.os.StrictMode; import android.os.UserHandle; import android.provider.Settings.Global; +import android.service.notification.Adjustment; import android.service.notification.Condition; import android.service.notification.StatusBarNotification; import android.service.notification.ZenModeConfig; @@ -314,7 +315,8 @@ public class NotificationManager { * This tag should contain a localized name of the type of the zen rule provided by the * activity. */ - public static final String META_DATA_AUTOMATIC_RULE_TYPE = "android.app.automatic.ruleType"; + public static final String META_DATA_AUTOMATIC_RULE_TYPE = + "android.service.zen.automatic.ruleType"; /** * An optional {@code meta-data} tag for activities that handle @@ -324,7 +326,7 @@ public class NotificationManager { * can be created for this rule type. Omit or enter a value <= 0 to allow unlimited instances. */ public static final String META_DATA_RULE_INSTANCE_LIMIT = - "android.app.zen.automatic.ruleInstanceLimit"; + "android.service.zen.automatic.ruleInstanceLimit"; /** Value signifying that the user has not expressed a per-app visibility override value. * @hide */ @@ -715,12 +717,16 @@ public class NotificationManager { /** * Returns the notification channel settings for a given channel id. * - * The channel must belong to your package, or it will not be returned. + * <p>The channel must belong to your package, or to a package you are an approved notification + * delegate for (see {@link #canNotifyAsPackage(String)}), or it will not be returned. To query + * a channel as a notification delegate, call this method from a context created for that + * package (see {@link Context#createPackageContext(String, int)}).</p> */ public NotificationChannel getNotificationChannel(String channelId) { INotificationManager service = getService(); try { - return service.getNotificationChannel(mContext.getPackageName(), channelId); + return service.getNotificationChannel(mContext.getOpPackageName(), + mContext.getUserId(), mContext.getPackageName(), channelId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -728,11 +734,17 @@ public class NotificationManager { /** * Returns all notification channels belonging to the calling package. + * + * <p>Approved notification delegates (see {@link #canNotifyAsPackage(String)}) can query + * notification channels belonging to packages they are the delegate for. To do so, call this + * method from a context created for that package (see + * {@link Context#createPackageContext(String, int)}).</p> */ public List<NotificationChannel> getNotificationChannels() { INotificationManager service = getService(); try { - return service.getNotificationChannels(mContext.getPackageName()).getList(); + return service.getNotificationChannels(mContext.getOpPackageName(), + mContext.getPackageName(), mContext.getUserId()).getList(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1182,6 +1194,25 @@ public class NotificationManager { } } + /** + * Returns the list of {@link android.service.notification.Adjustment adjustment keys} that can + * be modified by the current {@link android.service.notification.NotificationAssistantService}. + * + * <p>Only callable by the current + * {@link android.service.notification.NotificationAssistantService}. + * See {@link #isNotificationAssistantAccessGranted(ComponentName)}</p> + * @hide + */ + @SystemApi + public @NonNull @Adjustment.Keys List<String> getAllowedAssistantCapabilities() { + INotificationManager service = getService(); + try { + return service.getAllowedAssistantCapabilities(mContext.getOpPackageName()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** @hide */ public boolean isNotificationPolicyAccessGrantedForPackage(String pkg) { INotificationManager service = getService(); diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index 4d280b76b3fa..d67bfb6c9c84 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -131,13 +131,11 @@ import android.os.BugreportManager; import android.os.Build; import android.os.DeviceIdleManager; import android.os.DropBoxManager; -import android.os.DynamicAndroidManager; import android.os.HardwarePropertiesManager; import android.os.IBatteryPropertiesRegistrar; import android.os.IBinder; import android.os.IDeviceIdleController; import android.os.IDumpstate; -import android.os.IDynamicAndroidService; import android.os.IHardwarePropertiesManager; import android.os.IPowerManager; import android.os.IRecoverySystem; @@ -155,6 +153,8 @@ import android.os.UserHandle; import android.os.UserManager; import android.os.Vibrator; import android.os.health.SystemHealthManager; +import android.os.image.DynamicSystemManager; +import android.os.image.IDynamicSystemService; import android.os.storage.StorageManager; import android.permission.PermissionControllerManager; import android.permission.PermissionManager; @@ -1275,15 +1275,15 @@ final class SystemServiceRegistry { IRollbackManager.Stub.asInterface(b)); }}); - registerService(Context.DYNAMIC_ANDROID_SERVICE, DynamicAndroidManager.class, - new CachedServiceFetcher<DynamicAndroidManager>() { + registerService(Context.DYNAMIC_SYSTEM_SERVICE, DynamicSystemManager.class, + new CachedServiceFetcher<DynamicSystemManager>() { @Override - public DynamicAndroidManager createService(ContextImpl ctx) + public DynamicSystemManager createService(ContextImpl ctx) throws ServiceNotFoundException { IBinder b = ServiceManager.getServiceOrThrow( - Context.DYNAMIC_ANDROID_SERVICE); - return new DynamicAndroidManager( - IDynamicAndroidService.Stub.asInterface(b)); + Context.DYNAMIC_SYSTEM_SERVICE); + return new DynamicSystemManager( + IDynamicSystemService.Stub.asInterface(b)); }}); //CHECKSTYLE:ON IndentationCheck } diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 20e85e6793f1..3660ddcb9ac8 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -4358,6 +4358,7 @@ public class DevicePolicyManager { /** * Disable text entry into notifications on secure keyguard screens (e.g. PIN/Pattern/Password). + * This flag has no effect starting from version {@link android.os.Build.VERSION_CODES#N} */ public static final int KEYGUARD_DISABLE_REMOTE_INPUT = 1 << 6; diff --git a/core/java/android/app/admin/PasswordMetrics.java b/core/java/android/app/admin/PasswordMetrics.java index d71d3553db7e..992985528fca 100644 --- a/core/java/android/app/admin/PasswordMetrics.java +++ b/core/java/android/app/admin/PasswordMetrics.java @@ -24,8 +24,12 @@ import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC; import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC; import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_COMPLEX; import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC; +import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING; import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; +import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD; +import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PATTERN; + import android.annotation.IntDef; import android.annotation.NonNull; import android.app.admin.DevicePolicyManager.PasswordComplexity; @@ -33,13 +37,15 @@ import android.os.Parcel; import android.os.Parcelable; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.util.Preconditions; +import com.android.internal.widget.LockPatternUtils.CredentialType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** - * A class that represents the metrics of a password that are used to decide whether or not a - * password meets the requirements. + * A class that represents the metrics of a credential that are used to decide whether or not a + * credential meets the requirements. If the credential is a pattern, only quality matters. * * {@hide} */ @@ -48,8 +54,6 @@ public class PasswordMetrics implements Parcelable { // consider it a complex PIN/password. public static final int MAX_ALLOWED_SEQUENCE = 3; - // TODO(b/120536847): refactor isActivePasswordSufficient logic so that the actual password - // quality is not overwritten public int quality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; public int length = 0; public int letters = 0; @@ -222,6 +226,25 @@ public class PasswordMetrics implements Parcelable { }; /** + * Returnsthe {@code PasswordMetrics} for a given credential. + * + * If the credential is a pin or a password, equivalent to {@link #computeForPassword(byte[])}. + * {@code credential} cannot be null when {@code type} is + * {@link com.android.internal.widget.LockPatternUtils#CREDENTIAL_TYPE_PASSWORD}. + */ + public static PasswordMetrics computeForCredential( + @CredentialType int type, byte[] credential) { + if (type == CREDENTIAL_TYPE_PASSWORD) { + Preconditions.checkNotNull(credential, "credential cannot be null"); + return PasswordMetrics.computeForPassword(credential); + } else if (type == CREDENTIAL_TYPE_PATTERN) { + return new PasswordMetrics(PASSWORD_QUALITY_SOMETHING); + } else /* if (type == CREDENTIAL_TYPE_NONE) */ { + return new PasswordMetrics(PASSWORD_QUALITY_UNSPECIFIED); + } + } + + /** * Returns the {@code PasswordMetrics} for a given password */ public static PasswordMetrics computeForPassword(@NonNull byte[] password) { @@ -233,8 +256,8 @@ public class PasswordMetrics implements Parcelable { int symbols = 0; int nonLetter = 0; final int length = password.length; - for (int i = 0; i < length; i++) { - switch (categoryChar((char) password[i])) { + for (byte b : password) { + switch (categoryChar((char) b)) { case CHAR_LOWER_CASE: letters++; lowerCase++; diff --git a/core/java/android/app/admin/SecurityLog.java b/core/java/android/app/admin/SecurityLog.java index 638657342066..19f4335893cb 100644 --- a/core/java/android/app/admin/SecurityLog.java +++ b/core/java/android/app/admin/SecurityLog.java @@ -136,8 +136,11 @@ public class SecurityLog { public static final int TAG_APP_PROCESS_START = SecurityLogTags.SECURITY_APP_PROCESS_START; /** - * Indicates that keyguard has been dismissed. + * Indicates that keyguard has been dismissed. This event is only logged if the device + * has a secure keyguard. It is logged regardless of how keyguard is dismissed, including + * via PIN/pattern/password, biometrics or via a trust agent. * There is no extra payload in the log event. + * @see #TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT */ public static final int TAG_KEYGUARD_DISMISSED = SecurityLogTags.SECURITY_KEYGUARD_DISMISSED; diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java index bcc4974e4e64..25caaaa6e5ad 100644 --- a/core/java/android/app/backup/BackupManager.java +++ b/core/java/android/app/backup/BackupManager.java @@ -16,6 +16,7 @@ package android.app.backup; +import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SystemApi; @@ -502,32 +503,76 @@ public class BackupManager { * @param transportComponent The identity of the transport being described. * @param name A {@link String} with the new name for the transport. This is NOT for * identification. MUST NOT be {@code null}. - * @param configurationIntent An {@link Intent} that can be passed to - * {@link Context#startActivity} in order to launch the transport's configuration UI. It may - * be {@code null} if the transport does not offer any user-facing configuration UI. + * @param configurationIntent An {@link Intent} that can be passed to {@link + * Context#startActivity} in order to launch the transport's configuration UI. It may be + * {@code null} if the transport does not offer any user-facing configuration UI. * @param currentDestinationString A {@link String} describing the destination to which the * transport is currently sending data. MUST NOT be {@code null}. - * @param dataManagementIntent An {@link Intent} that can be passed to - * {@link Context#startActivity} in order to launch the transport's data-management UI. It - * may be {@code null} if the transport does not offer any user-facing data - * management UI. + * @param dataManagementIntent An {@link Intent} that can be passed to {@link + * Context#startActivity} in order to launch the transport's data-management UI. It may be + * {@code null} if the transport does not offer any user-facing data management UI. * @param dataManagementLabel A {@link String} to be used as the label for the transport's data - * management affordance. This MUST be {@code null} when dataManagementIntent is - * {@code null} and MUST NOT be {@code null} when dataManagementIntent is not {@code null}. + * management affordance. This MUST be {@code null} when dataManagementIntent is {@code + * null} and MUST NOT be {@code null} when dataManagementIntent is not {@code null}. * @throws SecurityException If the UID of the calling process differs from the package UID of * {@code transportComponent} or if the caller does NOT have BACKUP permission. - * + * @deprecated Since Android Q, please use the variant {@link + * #updateTransportAttributes(ComponentName, String, Intent, String, Intent, CharSequence)} + * instead. * @hide */ + @Deprecated @SystemApi @RequiresPermission(android.Manifest.permission.BACKUP) public void updateTransportAttributes( - ComponentName transportComponent, - String name, + @NonNull ComponentName transportComponent, + @NonNull String name, @Nullable Intent configurationIntent, - String currentDestinationString, + @NonNull String currentDestinationString, @Nullable Intent dataManagementIntent, @Nullable String dataManagementLabel) { + updateTransportAttributes( + transportComponent, + name, + configurationIntent, + currentDestinationString, + dataManagementIntent, + (CharSequence) dataManagementLabel); + } + + /** + * Update the attributes of the transport identified by {@code transportComponent}. If the + * specified transport has not been bound at least once (for registration), this call will be + * ignored. Only the host process of the transport can change its description, otherwise a + * {@link SecurityException} will be thrown. + * + * @param transportComponent The identity of the transport being described. + * @param name A {@link String} with the new name for the transport. This is NOT for + * identification. MUST NOT be {@code null}. + * @param configurationIntent An {@link Intent} that can be passed to {@link + * Context#startActivity} in order to launch the transport's configuration UI. It may be + * {@code null} if the transport does not offer any user-facing configuration UI. + * @param currentDestinationString A {@link String} describing the destination to which the + * transport is currently sending data. MUST NOT be {@code null}. + * @param dataManagementIntent An {@link Intent} that can be passed to {@link + * Context#startActivity} in order to launch the transport's data-management UI. It may be + * {@code null} if the transport does not offer any user-facing data management UI. + * @param dataManagementLabel A {@link CharSequence} to be used as the label for the transport's + * data management affordance. This MUST be {@code null} when dataManagementIntent is {@code + * null} and MUST NOT be {@code null} when dataManagementIntent is not {@code null}. + * @throws SecurityException If the UID of the calling process differs from the package UID of + * {@code transportComponent} or if the caller does NOT have BACKUP permission. + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.BACKUP) + public void updateTransportAttributes( + @NonNull ComponentName transportComponent, + @NonNull String name, + @Nullable Intent configurationIntent, + @NonNull String currentDestinationString, + @Nullable Intent dataManagementIntent, + @Nullable CharSequence dataManagementLabel) { checkServiceBinder(); if (sService != null) { try { @@ -796,7 +841,7 @@ public class BackupManager { /** * Returns an {@link Intent} for the specified transport's configuration UI. * This value is set by {@link #updateTransportAttributes(ComponentName, String, Intent, String, - * Intent, String)}. + * Intent, CharSequence)}. * @param transportName The name of the registered transport. * @hide */ @@ -818,7 +863,7 @@ public class BackupManager { /** * Returns a {@link String} describing where the specified transport is sending data. * This value is set by {@link #updateTransportAttributes(ComponentName, String, Intent, String, - * Intent, String)}. + * Intent, CharSequence)}. * @param transportName The name of the registered transport. * @hide */ @@ -840,7 +885,7 @@ public class BackupManager { /** * Returns an {@link Intent} for the specified transport's data management UI. * This value is set by {@link #updateTransportAttributes(ComponentName, String, Intent, String, - * Intent, String)}. + * Intent, CharSequence)}. * @param transportName The name of the registered transport. * @hide */ @@ -861,23 +906,43 @@ public class BackupManager { /** * Returns a {@link String} describing what the specified transport's data management intent is - * used for. - * This value is set by {@link #updateTransportAttributes(ComponentName, String, Intent, String, - * Intent, String)}. + * used for. This value is set by {@link #updateTransportAttributes(ComponentName, String, + * Intent, String, Intent, CharSequence)}. * * @param transportName The name of the registered transport. + * @deprecated Since Android Q, please use the variant {@link + * #getDataManagementIntentLabel(String)} instead. * @hide */ + @Deprecated @SystemApi @TestApi @RequiresPermission(android.Manifest.permission.BACKUP) - public String getDataManagementLabel(String transportName) { + @Nullable + public String getDataManagementLabel(@NonNull String transportName) { + CharSequence label = getDataManagementIntentLabel(transportName); + return label == null ? null : label.toString(); + } + + /** + * Returns a {@link CharSequence} describing what the specified transport's data management + * intent is used for. This value is set by {@link #updateTransportAttributes(ComponentName, + * String, Intent, String, Intent, CharSequence)}. + * + * @param transportName The name of the registered transport. + * @hide + */ + @SystemApi + @TestApi + @RequiresPermission(android.Manifest.permission.BACKUP) + @Nullable + public CharSequence getDataManagementIntentLabel(@NonNull String transportName) { checkServiceBinder(); if (sService != null) { try { return sService.getDataManagementLabelForUser(mContext.getUserId(), transportName); } catch (RemoteException e) { - Log.e(TAG, "getDataManagementLabel() couldn't connect"); + Log.e(TAG, "getDataManagementIntentLabel() couldn't connect"); } } return null; diff --git a/core/java/android/app/backup/BackupTransport.java b/core/java/android/app/backup/BackupTransport.java index 0963594bc00e..c8f2ff34a70c 100644 --- a/core/java/android/app/backup/BackupTransport.java +++ b/core/java/android/app/backup/BackupTransport.java @@ -16,6 +16,7 @@ package android.app.backup; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.content.Intent; import android.content.pm.PackageInfo; @@ -164,19 +165,36 @@ public class BackupTransport { } /** - * On demand, supply a short string that can be shown to the user as the label - * on an overflow menu item used to invoked the data management UI. + * On demand, supply a short string that can be shown to the user as the label on an overflow + * menu item used to invoke the data management UI. * - * @return A string to be used as the label for the transport's data management - * affordance. If the transport supplies a data management intent, this - * method must not return {@code null}. + * @return A string to be used as the label for the transport's data management affordance. If + * the transport supplies a data management intent, this method must not return {@code + * null}. + * @deprecated Since Android Q, please use the variant {@link #dataManagementIntentLabel()} + * instead. */ + @Deprecated + @Nullable public String dataManagementLabel() { throw new UnsupportedOperationException( "Transport dataManagementLabel() not implemented"); } /** + * On demand, supply a short CharSequence that can be shown to the user as the label on an + * overflow menu item used to invoke the data management UI. + * + * @return A CharSequence to be used as the label for the transport's data management + * affordance. If the transport supplies a data management intent, this method must not + * return {@code null}. + */ + @Nullable + public CharSequence dataManagementIntentLabel() { + return dataManagementLabel(); + } + + /** * Ask the transport where, on local device storage, to keep backup state blobs. * This is per-transport so that mock transports used for testing can coexist with * "live" backup services without interfering with the live bookkeeping. The @@ -651,8 +669,8 @@ public class BackupTransport { } @Override - public String dataManagementLabel() { - return BackupTransport.this.dataManagementLabel(); + public CharSequence dataManagementIntentLabel() { + return BackupTransport.this.dataManagementIntentLabel(); } @Override diff --git a/core/java/android/app/backup/IBackupManager.aidl b/core/java/android/app/backup/IBackupManager.aidl index 70ecdae92652..2dfaad759d3f 100644 --- a/core/java/android/app/backup/IBackupManager.aidl +++ b/core/java/android/app/backup/IBackupManager.aidl @@ -353,16 +353,16 @@ interface IBackupManager { * {@link Context#startActivity} in order to launch the transport's data-management UI. It * may be {@code null} if the transport does not offer any user-facing data * management UI. - * @param dataManagementLabel A {@link String} to be used as the label for the transport's data - * management affordance. This MUST be {@code null} when dataManagementIntent is - * {@code null} and MUST NOT be {@code null} when dataManagementIntent is not {@code null}. + * @param dataManagementLabel A {@link CharSequence} to be used as the label for the transport's + * data management affordance. This MUST be {@code null} when dataManagementIntent is {@code + * null} and MUST NOT be {@code null} when dataManagementIntent is not {@code null}. * @throws SecurityException If the UID of the calling process differs from the package UID of * {@code transportComponent} or if the caller does NOT have BACKUP permission. */ void updateTransportAttributesForUser(int userId, in ComponentName transportComponent, in String name, in Intent configurationIntent, in String currentDestinationString, - in Intent dataManagementIntent, in String dataManagementLabel); + in Intent dataManagementIntent, in CharSequence dataManagementLabel); /** * Identify the currently selected transport. Callers must hold the @@ -525,13 +525,7 @@ interface IBackupManager { * * @param userId User id for which the manage-data menu label should be reported. */ - String getDataManagementLabelForUser(int userId, String transport); - - /** - * {@link android.app.backup.IBackupManager.getDataManagementLabelForUser} for the calling user - * id. - */ - String getDataManagementLabel(String transport); + CharSequence getDataManagementLabelForUser(int userId, String transport); /** * Begin a restore session. Either or both of packageName and transportID diff --git a/core/java/android/app/prediction/AppPredictor.java b/core/java/android/app/prediction/AppPredictor.java index 3e4e8dc2db72..3f2f2090bf33 100644 --- a/core/java/android/app/prediction/AppPredictor.java +++ b/core/java/android/app/prediction/AppPredictor.java @@ -131,14 +131,14 @@ public final class AppPredictor { * @param launchLocation The launch location where the targets are shown to the user. * @param targetIds List of {@link AppTargetId}s that are shown to the user. */ - public void notifyLocationShown(@NonNull String launchLocation, + public void notifyLaunchLocationShown(@NonNull String launchLocation, @NonNull List<AppTargetId> targetIds) { if (mIsClosed.get()) { throw new IllegalStateException("This client has already been destroyed."); } try { - mPredictionManager.notifyLocationShown(mSessionId, launchLocation, + mPredictionManager.notifyLaunchLocationShown(mSessionId, launchLocation, new ParceledListSlice<>(targetIds)); } catch (RemoteException e) { Log.e(TAG, "Failed to notify location shown event", e); diff --git a/core/java/android/app/prediction/AppTarget.java b/core/java/android/app/prediction/AppTarget.java index bb1b96ce5f00..826c149b2e05 100644 --- a/core/java/android/app/prediction/AppTarget.java +++ b/core/java/android/app/prediction/AppTarget.java @@ -43,20 +43,13 @@ public final class AppTarget implements Parcelable { private final ShortcutInfo mShortcutInfo; - private int mRank; + private final int mRank; /** - * Creates an instance of AppTarget that represent a launchable component. - * - * @param id A unique id for this launchable target. - * @param packageName Package name of the target. - * @param className Class name of the target. - * @param user The UserHandle of the user which this target belongs to. - * + * @deprecated use the Builder class * @hide */ - @SystemApi - @TestApi + @Deprecated public AppTarget(@NonNull AppTargetId id, @NonNull String packageName, @Nullable String className, @NonNull UserHandle user) { mId = id; @@ -65,18 +58,14 @@ public final class AppTarget implements Parcelable { mPackageName = Preconditions.checkNotNull(packageName); mClassName = className; mUser = Preconditions.checkNotNull(user); + mRank = 0; } /** - * Creates an instance of AppTarget that represent a launchable shortcut. - * - * @param id A unique id for this launchable target. - * @param shortcutInfo The {@link ShortcutInfo} that is represented with this target. - * @param className Class name fo the target. - * + * @deprecated use the Builder class * @hide */ - @SystemApi + @Deprecated public AppTarget(@NonNull AppTargetId id, @NonNull ShortcutInfo shortcutInfo, @Nullable String className) { mId = id; @@ -85,6 +74,17 @@ public final class AppTarget implements Parcelable { mPackageName = mShortcutInfo.getPackage(); mUser = mShortcutInfo.getUserHandle(); mClassName = className; + mRank = 0; + } + + private AppTarget(AppTargetId id, String packageName, UserHandle user, + ShortcutInfo shortcutInfo, String className, int rank) { + mId = id; + mShortcutInfo = shortcutInfo; + mPackageName = packageName; + mClassName = className; + mUser = user; + mRank = rank; } private AppTarget(Parcel parcel) { @@ -142,17 +142,6 @@ public final class AppTarget implements Parcelable { } /** - * Sets the rank of the for the target. - * @hide - */ - public void setRank(@IntRange(from = 0) int rank) { - if (rank < 0) { - throw new IllegalArgumentException("rank cannot be a negative value"); - } - mRank = rank; - } - - /** * Returns the rank for the target. Rank of an AppTarget is a non-negative integer that * represents the importance of this target compared to other candidate targets. A smaller value * means higher importance in the list. @@ -196,6 +185,101 @@ public final class AppTarget implements Parcelable { dest.writeInt(mRank); } + /** + * A builder for app targets. + * @hide + */ + @SystemApi + @TestApi + public static final class Builder { + + @NonNull + private final AppTargetId mId; + + private String mPackageName; + private UserHandle mUser; + private ShortcutInfo mShortcutInfo; + + private String mClassName; + private int mRank; + + /** + * @param id A unique id for this launchable target. + * @hide + */ + @SystemApi + @TestApi + public Builder(@NonNull AppTargetId id) { + mId = id; + } + + /** + * Sets the target to be an app. + * + * @param packageName PackageName of the app + * @param user The UserHandle of the user which this target belongs to. + * + * @throws IllegalArgumentException is the target is already set + */ + @NonNull + public Builder setTarget(@NonNull String packageName, @NonNull UserHandle user) { + if (mPackageName == null) { + throw new IllegalArgumentException("Target is already set"); + } + mPackageName = Preconditions.checkNotNull(packageName); + mUser = Preconditions.checkNotNull(user); + return this; + } + + /** + * Sets the target to be a ShortcutInfo. + * + * @throws IllegalArgumentException is the target is already set + */ + @NonNull + public Builder setTarget(@NonNull ShortcutInfo info) { + setTarget(info.getPackage(), info.getUserHandle()); + mShortcutInfo = Preconditions.checkNotNull(info); + return this; + } + + /** + * Sets the className for the target + */ + @NonNull + public Builder setClassName(@NonNull String className) { + mClassName = Preconditions.checkNotNull(className); + return this; + } + + /** + * Sets the rank of the for the target. + */ + @NonNull + public Builder setRank(@IntRange(from = 0) int rank) { + if (rank < 0) { + throw new IllegalArgumentException("rank cannot be a negative value"); + } + mRank = rank; + return this; + } + + /** + * Builds a new AppTarget instance. + * + * @throws IllegalStateException if no target is set + * @see #setTarget(ShortcutInfo) + * @see #setTarget(String, UserHandle) + */ + @NonNull + public AppTarget build() { + if (mPackageName == null) { + throw new IllegalStateException("No target set"); + } + return new AppTarget(mId, mPackageName, mUser, mShortcutInfo, mClassName, mRank); + } + } + public static final @android.annotation.NonNull Parcelable.Creator<AppTarget> CREATOR = new Parcelable.Creator<AppTarget>() { public AppTarget createFromParcel(Parcel parcel) { diff --git a/core/java/android/app/prediction/IPredictionManager.aidl b/core/java/android/app/prediction/IPredictionManager.aidl index 114a1ffb0eb2..587e3fd52377 100644 --- a/core/java/android/app/prediction/IPredictionManager.aidl +++ b/core/java/android/app/prediction/IPredictionManager.aidl @@ -33,7 +33,7 @@ interface IPredictionManager { void notifyAppTargetEvent(in AppPredictionSessionId sessionId, in AppTargetEvent event); - void notifyLocationShown(in AppPredictionSessionId sessionId, in String launchLocation, + void notifyLaunchLocationShown(in AppPredictionSessionId sessionId, in String launchLocation, in ParceledListSlice targetIds); void sortAppTargets(in AppPredictionSessionId sessionId, in ParceledListSlice targets, diff --git a/core/java/android/attention/AttentionManagerInternal.java b/core/java/android/attention/AttentionManagerInternal.java index 6b7f10e8d426..ac195045a3bc 100644 --- a/core/java/android/attention/AttentionManagerInternal.java +++ b/core/java/android/attention/AttentionManagerInternal.java @@ -50,6 +50,13 @@ public abstract class AttentionManagerInternal { */ public abstract void cancelAttentionCheck(int requestCode); + /** + * Disables the dependants. + * + * Example: called if the service does not have sufficient permissions to perform the task. + */ + public abstract void disableSelf(); + /** Internal interface for attention callback. */ public abstract static class AttentionCallbackInternal { /** diff --git a/core/java/android/companion/IFindDeviceCallback.aidl b/core/java/android/companion/IFindDeviceCallback.aidl index 919e15198efa..4e9fa19e5ce5 100644 --- a/core/java/android/companion/IFindDeviceCallback.aidl +++ b/core/java/android/companion/IFindDeviceCallback.aidl @@ -20,6 +20,7 @@ import android.app.PendingIntent; /** @hide */ interface IFindDeviceCallback { + @UnsupportedAppUsage void onSuccess(in PendingIntent launcher); void onFailure(in CharSequence reason); } diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index fb933b1a7163..5139064dbb63 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -338,6 +338,14 @@ public abstract class Context { public static final int BIND_ADJUST_BELOW_PERCEPTIBLE = 0x0100; /** + * Flag for {@link #bindService}: If binding from an app that has specific capabilities + * due to its foreground state such as an activity or foreground service, then this flag will + * allow the bound app to get the same capabilities, as long as it has the required permissions + * as well. + */ + public static final int BIND_INCLUDE_CAPABILITIES = 0x00001000; + + /** * Flag for {@link #bindService}: This flag is intended to be used only by the system to adjust * the scheduling policy for IMEs (and any other out-of-process user-visible components that * work closely with the top app) so that UI hosted in such services can have the same @@ -4644,11 +4652,10 @@ public abstract class Context { /** * Use with {@link #getSystemService(String)} to retrieve an - * {@link android.os.DynamicAndroidManager}. + * {@link android.os.image.DynamicSystemManager}. * @hide */ - @SystemApi - public static final String DYNAMIC_ANDROID_SERVICE = "dynamic_android"; + public static final String DYNAMIC_SYSTEM_SERVICE = "dynamic_system"; /** * Determine whether the given permission is allowed for a particular diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 93a9daced987..a5f627ddf1b4 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -2078,6 +2078,9 @@ public class Intent implements Parcelable, Cloneable { * <p> * Output: Nothing. * </p> + * <p class="note"> + * This requires {@link android.Manifest.permission#GRANT_RUNTIME_PERMISSIONS} permission. + * </p> * * @see #EXTRA_PERMISSION_NAME * @see #EXTRA_PERMISSION_GROUP_NAME @@ -2086,15 +2089,16 @@ public class Intent implements Parcelable, Cloneable { * @hide */ @SystemApi + @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS) @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_REVIEW_PERMISSION_USAGE = "android.intent.action.REVIEW_PERMISSION_USAGE"; /** - * Activity action: Launch UI to review uses of permissions for a single app. + * Activity action: Launch UI to review ongoing app uses of permissions. * <p> - * Input: {@link #EXTRA_PACKAGE_NAME} specifies the package whose - * permissions will be reviewed (mandatory). + * Input: {@link #EXTRA_DURATION_MILLIS} specifies the minimum number of milliseconds of recent + * activity to show (optional). Must be non-negative. * </p> * <p> * Output: Nothing. @@ -2103,15 +2107,15 @@ public class Intent implements Parcelable, Cloneable { * This requires {@link android.Manifest.permission#GRANT_RUNTIME_PERMISSIONS} permission. * </p> * - * @see #EXTRA_PACKAGE_NAME + * @see #EXTRA_DURATION_MILLIS * * @hide */ @SystemApi @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS) @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) - public static final String ACTION_REVIEW_APP_PERMISSION_USAGE = - "android.intent.action.REVIEW_APP_PERMISSION_USAGE"; + public static final String ACTION_REVIEW_ONGOING_PERMISSION_USAGE = + "android.intent.action.REVIEW_ONGOING_PERMISSION_USAGE"; /** * Activity action: Launch UI to review running accessibility services. @@ -3473,6 +3477,7 @@ public class Intent implements Parcelable, Cloneable { * {@link android.Manifest.permission#MANAGE_USERS} to receive this broadcast. * @hide */ + @SystemApi public static final String ACTION_USER_ADDED = "android.intent.action.USER_ADDED"; diff --git a/core/java/android/content/om/OverlayManager.java b/core/java/android/content/om/OverlayManager.java index ceea0435a254..f2716fedc186 100644 --- a/core/java/android/content/om/OverlayManager.java +++ b/core/java/android/content/om/OverlayManager.java @@ -18,6 +18,7 @@ package android.content.om; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.SystemService; import android.content.Context; @@ -61,40 +62,57 @@ public class OverlayManager { * Request that an overlay package is enabled and any other overlay packages with the same * target package and category are disabled. * + * If a set of overlay packages share the same category, single call to this method is + * equivalent to multiple calls to {@link #setEnabled(String, boolean, UserHandle)}. + * * @param packageName the name of the overlay package to enable. - * @param userId The user for which to change the overlay. - * @return true if the system successfully registered the request, false otherwise. + * @param user The user for which to change the overlay. * * @hide */ @SystemApi - public boolean setEnabledExclusiveInCategory(@Nullable final String packageName, - int userId) { + @RequiresPermission(anyOf = { + "android.permission.INTERACT_ACROSS_USERS", + "android.permission.INTERACT_ACROSS_USERS_FULL" + }) + public void setEnabledExclusiveInCategory(@NonNull final String packageName, + @NonNull UserHandle user) { try { - return mService.setEnabledExclusiveInCategory(packageName, userId); + if (!mService.setEnabledExclusiveInCategory(packageName, user.getIdentifier())) { + throw new IllegalStateException("setEnabledExclusiveInCategory failed"); + } } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** - * Request that an overlay package is enabled. + * Request that an overlay package is enabled or disabled. + * + * While {@link #setEnabledExclusiveInCategory(String, UserHandle)} doesn't support disabling + * every overlay in a category, this method allows you to disable everything. * * @param packageName the name of the overlay package to enable. * @param enable {@code false} if the overlay should be turned off. - * @param userId The user for which to change the overlay. - * @return true if the system successfully registered the request, false otherwise. + * @param user The user for which to change the overlay. * * @hide */ @SystemApi - public boolean setEnabled(@Nullable final String packageName, final boolean enable, - int userId) { + @RequiresPermission(anyOf = { + "android.permission.INTERACT_ACROSS_USERS", + "android.permission.INTERACT_ACROSS_USERS_FULL" + }) + public void setEnabled(@NonNull final String packageName, final boolean enable, + @NonNull UserHandle user) { try { - return mService.setEnabled(packageName, enable, userId); + if (!mService.setEnabled(packageName, enable, user.getIdentifier())) { + throw new IllegalStateException("setEnabled failed"); + } } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } + return; } /** @@ -113,7 +131,7 @@ public class OverlayManager { public OverlayInfo getOverlayInfo(@NonNull final String packageName, @NonNull final UserHandle userHandle) { try { - return mService.getOverlayInfo(packageName, userHandle.myUserId()); + return mService.getOverlayInfo(packageName, userHandle.getIdentifier()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -125,17 +143,22 @@ public class OverlayManager { * overlay priority with the highest priority at the end of the list. * * @param targetPackageName The name of the target package. - * @param userId The user to get the OverlayInfos for. + * @param user The user to get the OverlayInfos for. * @return A list of OverlayInfo objects; if no overlays exist for the * requested package, an empty list is returned. * * @hide */ @SystemApi - public List<OverlayInfo> getOverlayInfosForTarget(@Nullable final String targetPackageName, - int userId) { + @RequiresPermission(anyOf = { + "android.permission.INTERACT_ACROSS_USERS", + "android.permission.INTERACT_ACROSS_USERS_FULL" + }) + @NonNull + public List<OverlayInfo> getOverlayInfosForTarget(@NonNull final String targetPackageName, + @NonNull UserHandle user) { try { - return mService.getOverlayInfosForTarget(targetPackageName, userId); + return mService.getOverlayInfosForTarget(targetPackageName, user.getIdentifier()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index 464e866e0b31..c798270d1fdc 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -714,6 +714,8 @@ interface IPackageManager { ParceledListSlice getSharedLibraries(in String packageName, int flags, int userId); + ParceledListSlice getDeclaredSharedLibraries(in String packageName, int flags, int userId); + boolean canRequestPackageInstalls(String packageName, int userId); void deletePreloadsFileCache(); diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index fa5247c955d7..961faa0c19b6 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -4239,6 +4239,24 @@ public abstract class PackageManager { @InstallFlags int flags, @UserIdInt int userId); /** + * Get the list of shared libraries declared by a package. + * + * @param packageName the package name to query + * @param flags the flags to filter packages + * @return the shared library list + * + * @hide + */ + @NonNull + @RequiresPermission(Manifest.permission.ACCESS_SHARED_LIBRARIES) + @SystemApi + public List<SharedLibraryInfo> getDeclaredSharedLibraries(@NonNull String packageName, + @InstallFlags int flags) { + throw new UnsupportedOperationException( + "getDeclaredSharedLibraries() not implemented in subclass"); + } + + /** * Get the name of the package hosting the services shared library. * * @return The library host package. @@ -5653,7 +5671,9 @@ public abstract class PackageManager { * @deprecated This function no longer does anything. It is the platform's * responsibility to assign preferred activities and this cannot be modified * directly. To determine the activities resolved by the platform, use - * {@link #resolveActivity} or {@link #queryIntentActivities}. + * {@link #resolveActivity} or {@link #queryIntentActivities}. To configure + * an app to be responsible for a particular role and to check current role + * holders, see {@link android.app.role.RoleManager}. */ @Deprecated public abstract void addPackageToPreferred(String packageName); @@ -5662,7 +5682,9 @@ public abstract class PackageManager { * @deprecated This function no longer does anything. It is the platform's * responsibility to assign preferred activities and this cannot be modified * directly. To determine the activities resolved by the platform, use - * {@link #resolveActivity} or {@link #queryIntentActivities}. + * {@link #resolveActivity} or {@link #queryIntentActivities}. To configure + * an app to be responsible for a particular role and to check current role + * holders, see {@link android.app.role.RoleManager}. */ @Deprecated public abstract void removePackageFromPreferred(String packageName); @@ -5679,7 +5701,9 @@ public abstract class PackageManager { * @deprecated This function no longer does anything. It is the platform's * responsibility to assign preferred activities and this cannot be modified * directly. To determine the activities resolved by the platform, use - * {@link #resolveActivity} or {@link #queryIntentActivities}. + * {@link #resolveActivity} or {@link #queryIntentActivities}. To configure + * an app to be responsible for a particular role and to check current role + * holders, see {@link android.app.role.RoleManager}. */ @Deprecated public abstract List<PackageInfo> getPreferredPackages(@PackageInfoFlags int flags); @@ -5702,7 +5726,9 @@ public abstract class PackageManager { * @deprecated This function no longer does anything. It is the platform's * responsibility to assign preferred activities and this cannot be modified * directly. To determine the activities resolved by the platform, use - * {@link #resolveActivity} or {@link #queryIntentActivities}. + * {@link #resolveActivity} or {@link #queryIntentActivities}. To configure + * an app to be responsible for a particular role and to check current role + * holders, see {@link android.app.role.RoleManager}. */ @Deprecated public abstract void addPreferredActivity(IntentFilter filter, int match, @@ -5717,7 +5743,9 @@ public abstract class PackageManager { * @deprecated This function no longer does anything. It is the platform's * responsibility to assign preferred activities and this cannot be modified * directly. To determine the activities resolved by the platform, use - * {@link #resolveActivity} or {@link #queryIntentActivities}. + * {@link #resolveActivity} or {@link #queryIntentActivities}. To configure + * an app to be responsible for a particular role and to check current role + * holders, see {@link android.app.role.RoleManager}. */ @Deprecated @UnsupportedAppUsage @@ -5747,7 +5775,9 @@ public abstract class PackageManager { * @deprecated This function no longer does anything. It is the platform's * responsibility to assign preferred activities and this cannot be modified * directly. To determine the activities resolved by the platform, use - * {@link #resolveActivity} or {@link #queryIntentActivities}. + * {@link #resolveActivity} or {@link #queryIntentActivities}. To configure + * an app to be responsible for a particular role and to check current role + * holders, see {@link android.app.role.RoleManager}. */ @Deprecated @UnsupportedAppUsage @@ -5773,7 +5803,9 @@ public abstract class PackageManager { * @deprecated This function no longer does anything. It is the platform's * responsibility to assign preferred activities and this cannot be modified * directly. To determine the activities resolved by the platform, use - * {@link #resolveActivity} or {@link #queryIntentActivities}. + * {@link #resolveActivity} or {@link #queryIntentActivities}. To configure + * an app to be responsible for a particular role and to check current role + * holders, see {@link android.app.role.RoleManager}. */ @Deprecated @SystemApi @@ -5788,7 +5820,9 @@ public abstract class PackageManager { * @deprecated This function no longer does anything. It is the platform's * responsibility to assign preferred activities and this cannot be modified * directly. To determine the activities resolved by the platform, use - * {@link #resolveActivity} or {@link #queryIntentActivities}. + * {@link #resolveActivity} or {@link #queryIntentActivities}. To configure + * an app to be responsible for a particular role and to check current role + * holders, see {@link android.app.role.RoleManager}. */ @Deprecated @UnsupportedAppUsage @@ -5809,7 +5843,9 @@ public abstract class PackageManager { * @deprecated This function no longer does anything. It is the platform's * responsibility to assign preferred activities and this cannot be modified * directly. To determine the activities resolved by the platform, use - * {@link #resolveActivity} or {@link #queryIntentActivities}. + * {@link #resolveActivity} or {@link #queryIntentActivities}. To configure + * an app to be responsible for a particular role and to check current role + * holders, see {@link android.app.role.RoleManager}. */ @Deprecated public abstract void clearPackagePreferredActivities(String packageName); @@ -5834,7 +5870,9 @@ public abstract class PackageManager { * @deprecated This function no longer does anything. It is the platform's * responsibility to assign preferred activities and this cannot be modified * directly. To determine the activities resolved by the platform, use - * {@link #resolveActivity} or {@link #queryIntentActivities}. + * {@link #resolveActivity} or {@link #queryIntentActivities}. To configure + * an app to be responsible for a particular role and to check current role + * holders, see {@link android.app.role.RoleManager}. */ @Deprecated public abstract int getPreferredActivities(@NonNull List<IntentFilter> outFilters, @@ -5901,9 +5939,8 @@ public abstract class PackageManager { * @param packageName The package name of the app * @return Returns the enabled state for the synthetic app details activity. * - * @hide + * */ - @SystemApi public boolean getSyntheticAppDetailsActivityEnabled(@NonNull String packageName) { throw new UnsupportedOperationException( "getSyntheticAppDetailsActivityEnabled not implemented"); diff --git a/core/java/android/hardware/camera2/utils/HashCodeHelpers.java b/core/java/android/hardware/camera2/utils/HashCodeHelpers.java index 731da8b6a721..526f086f4baa 100644 --- a/core/java/android/hardware/camera2/utils/HashCodeHelpers.java +++ b/core/java/android/hardware/camera2/utils/HashCodeHelpers.java @@ -16,6 +16,8 @@ package android.hardware.camera2.utils; +import android.annotation.UnsupportedAppUsage; + /** * Provide hashing functions using the Modified Bernstein hash */ @@ -30,6 +32,7 @@ public final class HashCodeHelpers { * * @return the numeric hash code */ + @UnsupportedAppUsage public static int hashCode(int... array) { if (array == null) { return 0; diff --git a/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java b/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java index ffae361e76d4..7d4849f7562d 100644 --- a/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java +++ b/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java @@ -16,6 +16,7 @@ package android.inputmethodservice; +import android.annotation.UnsupportedAppUsage; import android.content.Context; import android.graphics.Rect; import android.os.Bundle; @@ -53,6 +54,7 @@ class IInputMethodSessionWrapper extends IInputMethodSession.Stub private static final int DO_VIEW_CLICKED = 115; private static final int DO_NOTIFY_IME_HIDDEN = 120; + @UnsupportedAppUsage HandlerCaller mCaller; InputMethodSession mInputMethodSession; InputChannel mChannel; diff --git a/core/java/android/inputmethodservice/IInputMethodWrapper.java b/core/java/android/inputmethodservice/IInputMethodWrapper.java index 37b25c8fec0c..a47f601033cf 100644 --- a/core/java/android/inputmethodservice/IInputMethodWrapper.java +++ b/core/java/android/inputmethodservice/IInputMethodWrapper.java @@ -18,6 +18,7 @@ package android.inputmethodservice; import android.annotation.BinderThread; import android.annotation.MainThread; +import android.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.pm.PackageManager; import android.os.Binder; @@ -74,6 +75,7 @@ class IInputMethodWrapper extends IInputMethod.Stub final WeakReference<AbstractInputMethodService> mTarget; final Context mContext; + @UnsupportedAppUsage final HandlerCaller mCaller; final WeakReference<InputMethod> mInputMethod; final int mTargetSdkVersion; diff --git a/core/java/android/net/CaptivePortal.java b/core/java/android/net/CaptivePortal.java index 7873fc021b92..133943226c0d 100644 --- a/core/java/android/net/CaptivePortal.java +++ b/core/java/android/net/CaptivePortal.java @@ -15,6 +15,7 @@ */ package android.net; +import android.annotation.NonNull; import android.annotation.SystemApi; import android.annotation.TestApi; import android.os.IBinder; @@ -63,9 +64,7 @@ public class CaptivePortal implements Parcelable { private final IBinder mBinder; /** @hide */ - @SystemApi - @TestApi - public CaptivePortal(IBinder binder) { + public CaptivePortal(@NonNull IBinder binder) { mBinder = binder; } @@ -142,7 +141,7 @@ public class CaptivePortal implements Parcelable { */ @SystemApi @TestApi - public void logEvent(int eventId, String packageName) { + public void logEvent(int eventId, @NonNull String packageName) { try { ICaptivePortal.Stub.asInterface(mBinder).logEvent(eventId, packageName); } catch (RemoteException e) { diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index e5802c23eb6f..428c2e7bc0c4 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -4088,7 +4088,7 @@ public class ConnectivityManager { @SystemApi @TestApi @RequiresPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) - public void startCaptivePortalApp(Network network, Bundle appExtras) { + public void startCaptivePortalApp(@NonNull Network network, @NonNull Bundle appExtras) { try { mService.startCaptivePortalAppInternal(network, appExtras); } catch (RemoteException e) { @@ -4101,9 +4101,12 @@ public class ConnectivityManager { * @hide */ @SystemApi - public boolean getAvoidBadWifi() { + @RequiresPermission(anyOf = { + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, + android.Manifest.permission.NETWORK_STACK}) + public boolean shouldAvoidBadWifi() { try { - return mService.getAvoidBadWifi(); + return mService.shouldAvoidBadWifi(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/net/DnsResolver.java b/core/java/android/net/DnsResolver.java index 93b8cf801d45..59802514c7a3 100644 --- a/core/java/android/net/DnsResolver.java +++ b/core/java/android/net/DnsResolver.java @@ -16,6 +16,7 @@ package android.net; +import static android.net.NetworkUtils.resNetworkCancel; import static android.net.NetworkUtils.resNetworkQuery; import static android.net.NetworkUtils.resNetworkResult; import static android.net.NetworkUtils.resNetworkSend; @@ -26,6 +27,7 @@ import android.annotation.CallbackExecutor; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.os.CancellationSignal; import android.os.Looper; import android.system.ErrnoException; import android.util.Log; @@ -191,11 +193,18 @@ public final class DnsResolver { * @param query blob message * @param flags flags as a combination of the FLAGS_* constants * @param executor The {@link Executor} that the callback should be executed on. + * @param cancellationSignal used by the caller to signal if the query should be + * cancelled. May be {@code null}. * @param callback an {@link AnswerCallback} which will be called to notify the caller - * of the result of dns query. + * of the result of dns query. */ public <T> void query(@Nullable Network network, @NonNull byte[] query, @QueryFlag int flags, - @NonNull @CallbackExecutor Executor executor, @NonNull AnswerCallback<T> callback) { + @NonNull @CallbackExecutor Executor executor, + @Nullable CancellationSignal cancellationSignal, + @NonNull AnswerCallback<T> callback) { + if (cancellationSignal != null && cancellationSignal.isCanceled()) { + return; + } final FileDescriptor queryfd; try { queryfd = resNetworkSend((network != null @@ -205,6 +214,7 @@ public final class DnsResolver { return; } + maybeAddCancellationSignal(cancellationSignal, queryfd); registerFDListener(executor, queryfd, callback); } @@ -219,12 +229,19 @@ public final class DnsResolver { * @param nsType dns resource record (RR) type as one of the TYPE_* constants * @param flags flags as a combination of the FLAGS_* constants * @param executor The {@link Executor} that the callback should be executed on. + * @param cancellationSignal used by the caller to signal if the query should be + * cancelled. May be {@code null}. * @param callback an {@link AnswerCallback} which will be called to notify the caller - * of the result of dns query. + * of the result of dns query. */ public <T> void query(@Nullable Network network, @NonNull String domain, @QueryClass int nsClass, @QueryType int nsType, @QueryFlag int flags, - @NonNull @CallbackExecutor Executor executor, @NonNull AnswerCallback<T> callback) { + @NonNull @CallbackExecutor Executor executor, + @Nullable CancellationSignal cancellationSignal, + @NonNull AnswerCallback<T> callback) { + if (cancellationSignal != null && cancellationSignal.isCanceled()) { + return; + } final FileDescriptor queryfd; try { queryfd = resNetworkQuery((network != null @@ -233,6 +250,8 @@ public final class DnsResolver { callback.onQueryException(e); return; } + + maybeAddCancellationSignal(cancellationSignal, queryfd); registerFDListener(executor, queryfd, callback); } @@ -264,6 +283,17 @@ public final class DnsResolver { }); } + private void maybeAddCancellationSignal(@Nullable CancellationSignal cancellationSignal, + @NonNull FileDescriptor queryfd) { + if (cancellationSignal == null) return; + cancellationSignal.setOnCancelListener( + () -> { + Looper.getMainLooper().getQueue() + .removeOnFileDescriptorEventListener(queryfd); + resNetworkCancel(queryfd); + }); + } + private static class DnsAddressAnswer extends DnsPacket { private static final String TAG = "DnsResolver.DnsAddressAnswer"; private static final boolean DBG = false; diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl index 24e6a855ffe8..61648dc7f1d8 100644 --- a/core/java/android/net/IConnectivityManager.aidl +++ b/core/java/android/net/IConnectivityManager.aidl @@ -182,7 +182,7 @@ interface IConnectivityManager void startCaptivePortalApp(in Network network); void startCaptivePortalAppInternal(in Network network, in Bundle appExtras); - boolean getAvoidBadWifi(); + boolean shouldAvoidBadWifi(); int getMultipathPreference(in Network Network); NetworkRequest getDefaultRequest(); diff --git a/core/java/android/net/IpPrefix.java b/core/java/android/net/IpPrefix.java index 21bbd304a81b..402bffdc2a97 100644 --- a/core/java/android/net/IpPrefix.java +++ b/core/java/android/net/IpPrefix.java @@ -16,6 +16,7 @@ package android.net; +import android.annotation.NonNull; import android.annotation.SystemApi; import android.annotation.TestApi; import android.os.Parcel; @@ -70,7 +71,7 @@ public final class IpPrefix implements Parcelable { * * @hide */ - public IpPrefix(byte[] address, int prefixLength) { + public IpPrefix(@NonNull byte[] address, int prefixLength) { this.address = address.clone(); this.prefixLength = prefixLength; checkAndMaskAddressAndPrefixLength(); @@ -87,7 +88,7 @@ public final class IpPrefix implements Parcelable { */ @SystemApi @TestApi - public IpPrefix(InetAddress address, int prefixLength) { + public IpPrefix(@NonNull InetAddress address, int prefixLength) { // We don't reuse the (byte[], int) constructor because it calls clone() on the byte array, // which is unnecessary because getAddress() already returns a clone. this.address = address.getAddress(); @@ -106,7 +107,7 @@ public final class IpPrefix implements Parcelable { */ @SystemApi @TestApi - public IpPrefix(String prefix) { + public IpPrefix(@NonNull String prefix) { // We don't reuse the (InetAddress, int) constructor because "error: call to this must be // first statement in constructor". We could factor out setting the member variables to an // init() method, but if we did, then we'd have to make the members non-final, or "error: diff --git a/core/java/android/net/LinkAddress.java b/core/java/android/net/LinkAddress.java index 78a4e7293947..333603f3a0f2 100644 --- a/core/java/android/net/LinkAddress.java +++ b/core/java/android/net/LinkAddress.java @@ -26,6 +26,7 @@ import static android.system.OsConstants.RT_SCOPE_SITE; import static android.system.OsConstants.RT_SCOPE_UNIVERSE; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.TestApi; import android.annotation.UnsupportedAppUsage; @@ -107,8 +108,8 @@ public class LinkAddress implements Parcelable { * * Per RFC 4193 section 8, fc00::/7 identifies these addresses. */ - private boolean isIPv6ULA() { - if (isIPv6()) { + private boolean isIpv6ULA() { + if (isIpv6()) { byte[] bytes = address.getAddress(); return ((bytes[0] & (byte)0xfe) == (byte)0xfc); } @@ -121,17 +122,29 @@ public class LinkAddress implements Parcelable { */ @TestApi @SystemApi - public boolean isIPv6() { + public boolean isIpv6() { return address instanceof Inet6Address; } /** + * For backward compatibility. + * This was annotated with @UnsupportedAppUsage in P, so we can't remove the method completely + * just yet. + * @return true if the address is IPv6. + * @hide + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) + public boolean isIPv6() { + return isIpv6(); + } + + /** * @return true if the address is IPv4 or is a mapped IPv4 address. * @hide */ @TestApi @SystemApi - public boolean isIPv4() { + public boolean isIpv4() { return address instanceof Inet4Address; } @@ -217,7 +230,7 @@ public class LinkAddress implements Parcelable { */ @SystemApi @TestApi - public LinkAddress(String address, int flags, int scope) { + public LinkAddress(@NonNull String address, int flags, int scope) { // This may throw an IllegalArgumentException; catching it is the caller's responsibility. // TODO: consider rejecting mapped IPv4 addresses such as "::ffff:192.0.2.5/24". Pair<InetAddress, Integer> ipAndMask = NetworkUtils.parseIpAndMask(address); @@ -276,7 +289,10 @@ public class LinkAddress implements Parcelable { */ @TestApi @SystemApi - public boolean isSameAddressAs(LinkAddress other) { + public boolean isSameAddressAs(@Nullable LinkAddress other) { + if (other == null) { + return false; + } return address.equals(other.address) && prefixLength == other.prefixLength; } @@ -331,10 +347,10 @@ public class LinkAddress implements Parcelable { * state has cleared either DAD has succeeded or failed, and both * flags are cleared regardless). */ - return (scope == RT_SCOPE_UNIVERSE && - !isIPv6ULA() && - (flags & (IFA_F_DADFAILED | IFA_F_DEPRECATED)) == 0L && - ((flags & IFA_F_TENTATIVE) == 0L || (flags & IFA_F_OPTIMISTIC) != 0L)); + return (scope == RT_SCOPE_UNIVERSE + && !isIpv6ULA() + && (flags & (IFA_F_DADFAILED | IFA_F_DEPRECATED)) == 0L + && ((flags & IFA_F_TENTATIVE) == 0L || (flags & IFA_F_OPTIMISTIC) != 0L)); } /** diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java index b52b15e6dd51..d5ca6642a3c3 100644 --- a/core/java/android/net/LinkProperties.java +++ b/core/java/android/net/LinkProperties.java @@ -54,11 +54,11 @@ public final class LinkProperties implements Parcelable { // The interface described by the network link. @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) private String mIfaceName; - private ArrayList<LinkAddress> mLinkAddresses = new ArrayList<>(); - private ArrayList<InetAddress> mDnses = new ArrayList<>(); + private final ArrayList<LinkAddress> mLinkAddresses = new ArrayList<>(); + private final ArrayList<InetAddress> mDnses = new ArrayList<>(); // PCSCF addresses are addresses of SIP proxies that only exist for the IMS core service. - private ArrayList<InetAddress> mPcscfs = new ArrayList<InetAddress>(); - private ArrayList<InetAddress> mValidatedPrivateDnses = new ArrayList<>(); + private final ArrayList<InetAddress> mPcscfs = new ArrayList<InetAddress>(); + private final ArrayList<InetAddress> mValidatedPrivateDnses = new ArrayList<>(); private boolean mUsePrivateDns; private String mPrivateDnsServerName; private String mDomains; @@ -150,8 +150,8 @@ public final class LinkProperties implements Parcelable { // connections getting stuck until timeouts fire and other // baffling failures. Therefore, loss of either IPv4 or IPv6 on a // previously dual-stack network is deemed a lost of provisioning. - if ((before.isIPv4Provisioned() && !after.isIPv4Provisioned()) || - (before.isIPv6Provisioned() && !after.isIPv6Provisioned())) { + if ((before.isIpv4Provisioned() && !after.isIpv4Provisioned()) + || (before.isIpv6Provisioned() && !after.isIpv6Provisioned())) { return ProvisioningChange.LOST_PROVISIONING; } return ProvisioningChange.STILL_PROVISIONED; @@ -165,9 +165,8 @@ public final class LinkProperties implements Parcelable { } /** - * @hide + * Constructs a new {@code LinkProperties} with default values. */ - @SystemApi public LinkProperties() { } @@ -176,7 +175,7 @@ public final class LinkProperties implements Parcelable { */ @SystemApi @TestApi - public LinkProperties(LinkProperties source) { + public LinkProperties(@Nullable LinkProperties source) { if (source != null) { mIfaceName = source.mIfaceName; mLinkAddresses.addAll(source.mLinkAddresses); @@ -202,10 +201,8 @@ public final class LinkProperties implements Parcelable { * will have their interface changed to match this new value. * * @param iface The name of the network interface used for this link. - * @hide */ - @SystemApi - public void setInterfaceName(String iface) { + public void setInterfaceName(@Nullable String iface) { mIfaceName = iface; ArrayList<RouteInfo> newRoutes = new ArrayList<>(mRoutes.size()); for (RouteInfo route : mRoutes) { @@ -227,7 +224,7 @@ public final class LinkProperties implements Parcelable { * @hide */ @UnsupportedAppUsage - public List<String> getAllInterfaceNames() { + public @NonNull List<String> getAllInterfaceNames() { List<String> interfaceNames = new ArrayList<>(mStackedLinks.size() + 1); if (mIfaceName != null) interfaceNames.add(mIfaceName); for (LinkProperties stacked: mStackedLinks.values()) { @@ -247,8 +244,8 @@ public final class LinkProperties implements Parcelable { * @hide */ @UnsupportedAppUsage - public List<InetAddress> getAddresses() { - List<InetAddress> addresses = new ArrayList<>(); + public @NonNull List<InetAddress> getAddresses() { + final List<InetAddress> addresses = new ArrayList<>(); for (LinkAddress linkAddress : mLinkAddresses) { addresses.add(linkAddress.getAddress()); } @@ -260,7 +257,7 @@ public final class LinkProperties implements Parcelable { * @hide */ @UnsupportedAppUsage - public List<InetAddress> getAllAddresses() { + public @NonNull List<InetAddress> getAllAddresses() { List<InetAddress> addresses = new ArrayList<>(); for (LinkAddress linkAddress : mLinkAddresses) { addresses.add(linkAddress.getAddress()); @@ -289,7 +286,7 @@ public final class LinkProperties implements Parcelable { */ @SystemApi @TestApi - public boolean addLinkAddress(LinkAddress address) { + public boolean addLinkAddress(@NonNull LinkAddress address) { if (address == null) { return false; } @@ -318,7 +315,10 @@ public final class LinkProperties implements Parcelable { */ @SystemApi @TestApi - public boolean removeLinkAddress(LinkAddress toRemove) { + public boolean removeLinkAddress(@NonNull LinkAddress toRemove) { + if (toRemove == null) { + return false; + } int i = findLinkAddressIndex(toRemove); if (i >= 0) { mLinkAddresses.remove(i); @@ -333,7 +333,7 @@ public final class LinkProperties implements Parcelable { * * @return An unmodifiable {@link List} of {@link LinkAddress} for this link. */ - public List<LinkAddress> getLinkAddresses() { + public @NonNull List<LinkAddress> getLinkAddresses() { return Collections.unmodifiableList(mLinkAddresses); } @@ -356,10 +356,8 @@ public final class LinkProperties implements Parcelable { * * @param addresses The {@link Collection} of {@link LinkAddress} to set in this * object. - * @hide */ - @SystemApi - public void setLinkAddresses(Collection<LinkAddress> addresses) { + public void setLinkAddresses(@NonNull Collection<LinkAddress> addresses) { mLinkAddresses.clear(); for (LinkAddress address: addresses) { addLinkAddress(address); @@ -375,7 +373,7 @@ public final class LinkProperties implements Parcelable { */ @TestApi @SystemApi - public boolean addDnsServer(InetAddress dnsServer) { + public boolean addDnsServer(@NonNull InetAddress dnsServer) { if (dnsServer != null && !mDnses.contains(dnsServer)) { mDnses.add(dnsServer); return true; @@ -392,7 +390,7 @@ public final class LinkProperties implements Parcelable { */ @TestApi @SystemApi - public boolean removeDnsServer(InetAddress dnsServer) { + public boolean removeDnsServer(@NonNull InetAddress dnsServer) { if (dnsServer != null) { return mDnses.remove(dnsServer); } @@ -404,10 +402,8 @@ public final class LinkProperties implements Parcelable { * the given {@link Collection} of {@link InetAddress} objects. * * @param dnsServers The {@link Collection} of DNS servers to set in this object. - * @hide */ - @SystemApi - public void setDnsServers(Collection<InetAddress> dnsServers) { + public void setDnsServers(@NonNull Collection<InetAddress> dnsServers) { mDnses.clear(); for (InetAddress dnsServer: dnsServers) { addDnsServer(dnsServer); @@ -420,7 +416,7 @@ public final class LinkProperties implements Parcelable { * @return An unmodifiable {@link List} of {@link InetAddress} for DNS servers on * this link. */ - public List<InetAddress> getDnsServers() { + public @NonNull List<InetAddress> getDnsServers() { return Collections.unmodifiableList(mDnses); } @@ -490,7 +486,7 @@ public final class LinkProperties implements Parcelable { * @return true if the DNS server was added, false if it was already present. * @hide */ - public boolean addValidatedPrivateDnsServer(InetAddress dnsServer) { + public boolean addValidatedPrivateDnsServer(@NonNull InetAddress dnsServer) { if (dnsServer != null && !mValidatedPrivateDnses.contains(dnsServer)) { mValidatedPrivateDnses.add(dnsServer); return true; @@ -506,11 +502,8 @@ public final class LinkProperties implements Parcelable { * @return true if the DNS server was removed, false if it did not exist. * @hide */ - public boolean removeValidatedPrivateDnsServer(InetAddress dnsServer) { - if (dnsServer != null) { - return mValidatedPrivateDnses.remove(dnsServer); - } - return false; + public boolean removeValidatedPrivateDnsServer(@NonNull InetAddress dnsServer) { + return mValidatedPrivateDnses.remove(dnsServer); } /** @@ -523,7 +516,7 @@ public final class LinkProperties implements Parcelable { */ @TestApi @SystemApi - public void setValidatedPrivateDnsServers(Collection<InetAddress> dnsServers) { + public void setValidatedPrivateDnsServers(@NonNull Collection<InetAddress> dnsServers) { mValidatedPrivateDnses.clear(); for (InetAddress dnsServer: dnsServers) { addValidatedPrivateDnsServer(dnsServer); @@ -534,13 +527,13 @@ public final class LinkProperties implements Parcelable { * Returns all the {@link InetAddress} for validated private DNS servers on this link. * These are resolved from the private DNS server name. * - * @return An umodifiable {@link List} of {@link InetAddress} for validated private + * @return An unmodifiable {@link List} of {@link InetAddress} for validated private * DNS servers on this link. * @hide */ @TestApi @SystemApi - public List<InetAddress> getValidatedPrivateDnsServers() { + public @NonNull List<InetAddress> getValidatedPrivateDnsServers() { return Collections.unmodifiableList(mValidatedPrivateDnses); } @@ -551,7 +544,7 @@ public final class LinkProperties implements Parcelable { * @return true if the PCSCF server was added, false otherwise. * @hide */ - public boolean addPcscfServer(InetAddress pcscfServer) { + public boolean addPcscfServer(@NonNull InetAddress pcscfServer) { if (pcscfServer != null && !mPcscfs.contains(pcscfServer)) { mPcscfs.add(pcscfServer); return true; @@ -562,27 +555,24 @@ public final class LinkProperties implements Parcelable { /** * Removes the given {@link InetAddress} from the list of PCSCF servers. * - * @param pcscf Server The {@link InetAddress} to remove from the list of PCSCF servers. + * @param pcscfServer The {@link InetAddress} to remove from the list of PCSCF servers. * @return true if the PCSCF server was removed, false otherwise. * @hide */ - public boolean removePcscfServer(InetAddress pcscfServer) { - if (pcscfServer != null) { - return mPcscfs.remove(pcscfServer); - } - return false; + public boolean removePcscfServer(@NonNull InetAddress pcscfServer) { + return mPcscfs.remove(pcscfServer); } /** * Replaces the PCSCF servers in this {@code LinkProperties} with * the given {@link Collection} of {@link InetAddress} objects. * - * @param addresses The {@link Collection} of PCSCF servers to set in this object. + * @param pcscfServers The {@link Collection} of PCSCF servers to set in this object. * @hide */ @SystemApi @TestApi - public void setPcscfServers(Collection<InetAddress> pcscfServers) { + public void setPcscfServers(@NonNull Collection<InetAddress> pcscfServers) { mPcscfs.clear(); for (InetAddress pcscfServer: pcscfServers) { addPcscfServer(pcscfServer); @@ -598,7 +588,7 @@ public final class LinkProperties implements Parcelable { */ @SystemApi @TestApi - public List<InetAddress> getPcscfServers() { + public @NonNull List<InetAddress> getPcscfServers() { return Collections.unmodifiableList(mPcscfs); } @@ -607,20 +597,18 @@ public final class LinkProperties implements Parcelable { * * @param domains A {@link String} listing in priority order the comma separated * domains to search when resolving host names on this link. - * @hide */ - @SystemApi - public void setDomains(String domains) { + public void setDomains(@Nullable String domains) { mDomains = domains; } /** - * Get the DNS domains search path set for this link. + * Get the DNS domains search path set for this link. May be {@code null} if not set. * - * @return A {@link String} containing the comma separated domains to search when resolving - * host names on this link. + * @return A {@link String} containing the comma separated domains to search when resolving host + * names on this link or {@code null}. */ - public String getDomains() { + public @Nullable String getDomains() { return mDomains; } @@ -630,9 +618,7 @@ public final class LinkProperties implements Parcelable { * 10000 will be ignored. * * @param mtu The MTU to use for this link. - * @hide */ - @SystemApi public void setMtu(int mtu) { mMtu = mtu; } @@ -657,20 +643,20 @@ public final class LinkProperties implements Parcelable { */ @TestApi @SystemApi - public void setTcpBufferSizes(String tcpBufferSizes) { + public void setTcpBufferSizes(@Nullable String tcpBufferSizes) { mTcpBufferSizes = tcpBufferSizes; } /** - * Gets the tcp buffer sizes. + * Gets the tcp buffer sizes. May be {@code null} if not set. * - * @return the tcp buffer sizes to use when this link is the system default. + * @return the tcp buffer sizes to use when this link is the system default or {@code null}. * * @hide */ @TestApi @SystemApi - public String getTcpBufferSizes() { + public @Nullable String getTcpBufferSizes() { return mTcpBufferSizes; } @@ -690,23 +676,18 @@ public final class LinkProperties implements Parcelable { * * @param route A {@link RouteInfo} to add to this object. * @return {@code false} if the route was already present, {@code true} if it was added. - * - * @hide */ - @SystemApi - public boolean addRoute(RouteInfo route) { - if (route != null) { - String routeIface = route.getInterface(); - if (routeIface != null && !routeIface.equals(mIfaceName)) { - throw new IllegalArgumentException( - "Route added with non-matching interface: " + routeIface + - " vs. " + mIfaceName); - } - route = routeWithInterface(route); - if (!mRoutes.contains(route)) { - mRoutes.add(route); - return true; - } + public boolean addRoute(@NonNull RouteInfo route) { + String routeIface = route.getInterface(); + if (routeIface != null && !routeIface.equals(mIfaceName)) { + throw new IllegalArgumentException( + "Route added with non-matching interface: " + routeIface + + " vs. " + mIfaceName); + } + route = routeWithInterface(route); + if (!mRoutes.contains(route)) { + mRoutes.add(route); + return true; } return false; } @@ -722,10 +703,8 @@ public final class LinkProperties implements Parcelable { */ @TestApi @SystemApi - public boolean removeRoute(RouteInfo route) { - return route != null && - Objects.equals(mIfaceName, route.getInterface()) && - mRoutes.remove(route); + public boolean removeRoute(@NonNull RouteInfo route) { + return Objects.equals(mIfaceName, route.getInterface()) && mRoutes.remove(route); } /** @@ -733,7 +712,7 @@ public final class LinkProperties implements Parcelable { * * @return An unmodifiable {@link List} of {@link RouteInfo} for this link. */ - public List<RouteInfo> getRoutes() { + public @NonNull List<RouteInfo> getRoutes() { return Collections.unmodifiableList(mRoutes); } @@ -753,7 +732,7 @@ public final class LinkProperties implements Parcelable { * @hide */ @UnsupportedAppUsage - public List<RouteInfo> getAllRoutes() { + public @NonNull List<RouteInfo> getAllRoutes() { List<RouteInfo> routes = new ArrayList<>(mRoutes); for (LinkProperties stacked: mStackedLinks.values()) { routes.addAll(stacked.getAllRoutes()); @@ -767,26 +746,24 @@ public final class LinkProperties implements Parcelable { * not enforce it and applications may ignore them. * * @param proxy A {@link ProxyInfo} defining the HTTP Proxy to use on this link. - * @hide */ - @SystemApi - public void setHttpProxy(ProxyInfo proxy) { + public void setHttpProxy(@Nullable ProxyInfo proxy) { mHttpProxy = proxy; } /** * Gets the recommended {@link ProxyInfo} (or {@code null}) set on this link. * - * @return The {@link ProxyInfo} set on this link + * @return The {@link ProxyInfo} set on this link or {@code null}. */ - public ProxyInfo getHttpProxy() { + public @Nullable ProxyInfo getHttpProxy() { return mHttpProxy; } /** * Returns the NAT64 prefix in use on this link, if any. * - * @return the NAT64 prefix. + * @return the NAT64 prefix or {@code null}. * @hide */ @SystemApi @@ -799,14 +776,14 @@ public final class LinkProperties implements Parcelable { * Sets the NAT64 prefix in use on this link. * * Currently, only 96-bit prefixes (i.e., where the 32-bit IPv4 address is at the end of the - * 128-bit IPv6 address) are supported. + * 128-bit IPv6 address) are supported or {@code null} for no prefix. * * @param prefix the NAT64 prefix. * @hide */ @SystemApi @TestApi - public void setNat64Prefix(IpPrefix prefix) { + public void setNat64Prefix(@Nullable IpPrefix prefix) { if (prefix != null && prefix.getPrefixLength() != 96) { throw new IllegalArgumentException("Only 96-bit prefixes are supported: " + prefix); } @@ -818,15 +795,15 @@ public final class LinkProperties implements Parcelable { * * If there is already a stacked link with the same interface name as link, * that link is replaced with link. Otherwise, link is added to the list - * of stacked links. If link is null, nothing changes. + * of stacked links. * * @param link The link to add. * @return true if the link was stacked, false otherwise. * @hide */ @UnsupportedAppUsage - public boolean addStackedLink(LinkProperties link) { - if (link != null && link.getInterfaceName() != null) { + public boolean addStackedLink(@NonNull LinkProperties link) { + if (link.getInterfaceName() != null) { mStackedLinks.put(link.getInterfaceName(), link); return true; } @@ -843,12 +820,9 @@ public final class LinkProperties implements Parcelable { * @return true if the link was removed, false otherwise. * @hide */ - public boolean removeStackedLink(String iface) { - if (iface != null) { - LinkProperties removed = mStackedLinks.remove(iface); - return removed != null; - } - return false; + public boolean removeStackedLink(@NonNull String iface) { + LinkProperties removed = mStackedLinks.remove(iface); + return removed != null; } /** @@ -860,7 +834,7 @@ public final class LinkProperties implements Parcelable { if (mStackedLinks.isEmpty()) { return Collections.emptyList(); } - List<LinkProperties> stacked = new ArrayList<>(); + final List<LinkProperties> stacked = new ArrayList<>(); for (LinkProperties link : mStackedLinks.values()) { stacked.add(new LinkProperties(link)); } @@ -869,9 +843,7 @@ public final class LinkProperties implements Parcelable { /** * Clears this object to its initial state. - * @hide */ - @SystemApi public void clear() { mIfaceName = null; mLinkAddresses.clear(); @@ -988,7 +960,7 @@ public final class LinkProperties implements Parcelable { */ @TestApi @SystemApi - public boolean hasIPv4Address() { + public boolean hasIpv4Address() { for (LinkAddress address : mLinkAddresses) { if (address.getAddress() instanceof Inet4Address) { return true; @@ -998,15 +970,27 @@ public final class LinkProperties implements Parcelable { } /** + * For backward compatibility. + * This was annotated with @UnsupportedAppUsage in P, so we can't remove the method completely + * just yet. + * @return {@code true} if there is an IPv4 address, {@code false} otherwise. + * @hide + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) + public boolean hasIPv4Address() { + return hasIpv4Address(); + } + + /** * Returns true if this link or any of its stacked interfaces has an IPv4 address. * * @return {@code true} if there is an IPv4 address, {@code false} otherwise. */ - private boolean hasIPv4AddressOnInterface(String iface) { + private boolean hasIpv4AddressOnInterface(String iface) { // mIfaceName can be null. - return (Objects.equals(iface, mIfaceName) && hasIPv4Address()) || - (iface != null && mStackedLinks.containsKey(iface) && - mStackedLinks.get(iface).hasIPv4Address()); + return (Objects.equals(iface, mIfaceName) && hasIpv4Address()) + || (iface != null && mStackedLinks.containsKey(iface) + && mStackedLinks.get(iface).hasIpv4Address()); } /** @@ -1017,7 +1001,7 @@ public final class LinkProperties implements Parcelable { */ @TestApi @SystemApi - public boolean hasGlobalIPv6Address() { + public boolean hasGlobalIpv6Address() { for (LinkAddress address : mLinkAddresses) { if (address.getAddress() instanceof Inet6Address && address.isGlobalPreferred()) { return true; @@ -1027,13 +1011,25 @@ public final class LinkProperties implements Parcelable { } /** + * For backward compatibility. + * This was annotated with @UnsupportedAppUsage in P, so we can't remove the method completely + * just yet. + * @return {@code true} if there is a global preferred IPv6 address, {@code false} otherwise. + * @hide + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) + public boolean hasGlobalIPv6Address() { + return hasGlobalIpv6Address(); + } + + /** * Returns true if this link has an IPv4 default route. * * @return {@code true} if there is an IPv4 default route, {@code false} otherwise. * @hide */ @UnsupportedAppUsage - public boolean hasIPv4DefaultRoute() { + public boolean hasIpv4DefaultRoute() { for (RouteInfo r : mRoutes) { if (r.isIPv4Default()) { return true; @@ -1043,6 +1039,18 @@ public final class LinkProperties implements Parcelable { } /** + * For backward compatibility. + * This was annotated with @UnsupportedAppUsage in P, so we can't remove the method completely + * just yet. + * @return {@code true} if there is an IPv4 default route, {@code false} otherwise. + * @hide + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) + public boolean hasIPv4DefaultRoute() { + return hasIpv4DefaultRoute(); + } + + /** * Returns true if this link has an IPv6 default route. * * @return {@code true} if there is an IPv6 default route, {@code false} otherwise. @@ -1050,7 +1058,7 @@ public final class LinkProperties implements Parcelable { */ @TestApi @SystemApi - public boolean hasIPv6DefaultRoute() { + public boolean hasIpv6DefaultRoute() { for (RouteInfo r : mRoutes) { if (r.isIPv6Default()) { return true; @@ -1060,13 +1068,25 @@ public final class LinkProperties implements Parcelable { } /** + * For backward compatibility. + * This was annotated with @UnsupportedAppUsage in P, so we can't remove the method completely + * just yet. + * @return {@code true} if there is an IPv6 default route, {@code false} otherwise. + * @hide + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) + public boolean hasIPv6DefaultRoute() { + return hasIpv6DefaultRoute(); + } + + /** * Returns true if this link has an IPv4 DNS server. * * @return {@code true} if there is an IPv4 DNS server, {@code false} otherwise. * @hide */ @UnsupportedAppUsage - public boolean hasIPv4DnsServer() { + public boolean hasIpv4DnsServer() { for (InetAddress ia : mDnses) { if (ia instanceof Inet4Address) { return true; @@ -1076,13 +1096,25 @@ public final class LinkProperties implements Parcelable { } /** + * For backward compatibility. + * This was annotated with @UnsupportedAppUsage in P, so we can't remove the method completely + * just yet. + * @return {@code true} if there is an IPv4 DNS server, {@code false} otherwise. + * @hide + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) + public boolean hasIPv4DnsServer() { + return hasIpv4DnsServer(); + } + + /** * Returns true if this link has an IPv6 DNS server. * * @return {@code true} if there is an IPv6 DNS server, {@code false} otherwise. * @hide */ @UnsupportedAppUsage - public boolean hasIPv6DnsServer() { + public boolean hasIpv6DnsServer() { for (InetAddress ia : mDnses) { if (ia instanceof Inet6Address) { return true; @@ -1092,12 +1124,24 @@ public final class LinkProperties implements Parcelable { } /** + * For backward compatibility. + * This was annotated with @UnsupportedAppUsage in P, so we can't remove the method completely + * just yet. + * @return {@code true} if there is an IPv6 DNS server, {@code false} otherwise. + * @hide + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) + public boolean hasIPv6DnsServer() { + return hasIpv6DnsServer(); + } + + /** * Returns true if this link has an IPv4 PCSCF server. * * @return {@code true} if there is an IPv4 PCSCF server, {@code false} otherwise. * @hide */ - public boolean hasIPv4PcscfServer() { + public boolean hasIpv4PcscfServer() { for (InetAddress ia : mPcscfs) { if (ia instanceof Inet4Address) { return true; @@ -1112,7 +1156,7 @@ public final class LinkProperties implements Parcelable { * @return {@code true} if there is an IPv6 PCSCF server, {@code false} otherwise. * @hide */ - public boolean hasIPv6PcscfServer() { + public boolean hasIpv6PcscfServer() { for (InetAddress ia : mPcscfs) { if (ia instanceof Inet6Address) { return true; @@ -1130,10 +1174,10 @@ public final class LinkProperties implements Parcelable { */ @TestApi @SystemApi - public boolean isIPv4Provisioned() { - return (hasIPv4Address() && - hasIPv4DefaultRoute() && - hasIPv4DnsServer()); + public boolean isIpv4Provisioned() { + return (hasIpv4Address() + && hasIpv4DefaultRoute() + && hasIpv4DnsServer()); } /** @@ -1145,12 +1189,25 @@ public final class LinkProperties implements Parcelable { */ @TestApi @SystemApi + public boolean isIpv6Provisioned() { + return (hasGlobalIpv6Address() + && hasIpv6DefaultRoute() + && hasIpv6DnsServer()); + } + + /** + * For backward compatibility. + * This was annotated with @UnsupportedAppUsage in P, so we can't remove the method completely + * just yet. + * @return {@code true} if the link is provisioned, {@code false} otherwise. + * @hide + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public boolean isIPv6Provisioned() { - return (hasGlobalIPv6Address() && - hasIPv6DefaultRoute() && - hasIPv6DnsServer()); + return isIpv6Provisioned(); } + /** * Returns true if this link is provisioned for global connectivity, * for at least one Internet Protocol family. @@ -1161,7 +1218,7 @@ public final class LinkProperties implements Parcelable { @TestApi @SystemApi public boolean isProvisioned() { - return (isIPv4Provisioned() || isIPv6Provisioned()); + return (isIpv4Provisioned() || isIpv6Provisioned()); } /** @@ -1173,7 +1230,7 @@ public final class LinkProperties implements Parcelable { */ @TestApi @SystemApi - public boolean isReachable(InetAddress ip) { + public boolean isReachable(@NonNull InetAddress ip) { final List<RouteInfo> allRoutes = getAllRoutes(); // If we don't have a route to this IP address, it's not reachable. final RouteInfo bestRoute = RouteInfo.selectBestRoute(allRoutes, ip); @@ -1185,7 +1242,7 @@ public final class LinkProperties implements Parcelable { if (ip instanceof Inet4Address) { // For IPv4, it suffices for now to simply have any address. - return hasIPv4AddressOnInterface(bestRoute.getInterface()); + return hasIpv4AddressOnInterface(bestRoute.getInterface()); } else if (ip instanceof Inet6Address) { if (ip.isLinkLocalAddress()) { // For now, just make sure link-local destinations have @@ -1196,7 +1253,7 @@ public final class LinkProperties implements Parcelable { // For non-link-local destinations check that either the best route // is directly connected or that some global preferred address exists. // TODO: reconsider all cases (disconnected ULA networks, ...). - return (!bestRoute.hasGateway() || hasGlobalIPv6Address()); + return (!bestRoute.hasGateway() || hasGlobalIpv6Address()); } } @@ -1211,7 +1268,7 @@ public final class LinkProperties implements Parcelable { * @hide */ @UnsupportedAppUsage - public boolean isIdenticalInterfaceName(LinkProperties target) { + public boolean isIdenticalInterfaceName(@NonNull LinkProperties target) { return TextUtils.equals(getInterfaceName(), target.getInterfaceName()); } @@ -1223,7 +1280,7 @@ public final class LinkProperties implements Parcelable { * @hide */ @UnsupportedAppUsage - public boolean isIdenticalAddresses(LinkProperties target) { + public boolean isIdenticalAddresses(@NonNull LinkProperties target) { Collection<InetAddress> targetAddresses = target.getAddresses(); Collection<InetAddress> sourceAddresses = getAddresses(); return (sourceAddresses.size() == targetAddresses.size()) ? @@ -1238,7 +1295,7 @@ public final class LinkProperties implements Parcelable { * @hide */ @UnsupportedAppUsage - public boolean isIdenticalDnses(LinkProperties target) { + public boolean isIdenticalDnses(@NonNull LinkProperties target) { Collection<InetAddress> targetDnses = target.getDnsServers(); String targetDomains = target.getDomains(); if (mDomains == null) { @@ -1258,7 +1315,7 @@ public final class LinkProperties implements Parcelable { * @return {@code true} if both are identical, {@code false} otherwise. * @hide */ - public boolean isIdenticalPrivateDns(LinkProperties target) { + public boolean isIdenticalPrivateDns(@NonNull LinkProperties target) { return (isPrivateDnsActive() == target.isPrivateDnsActive() && TextUtils.equals(getPrivateDnsServerName(), target.getPrivateDnsServerName())); @@ -1272,7 +1329,7 @@ public final class LinkProperties implements Parcelable { * @return {@code true} if both are identical, {@code false} otherwise. * @hide */ - public boolean isIdenticalValidatedPrivateDnses(LinkProperties target) { + public boolean isIdenticalValidatedPrivateDnses(@NonNull LinkProperties target) { Collection<InetAddress> targetDnses = target.getValidatedPrivateDnsServers(); return (mValidatedPrivateDnses.size() == targetDnses.size()) ? mValidatedPrivateDnses.containsAll(targetDnses) : false; @@ -1285,7 +1342,7 @@ public final class LinkProperties implements Parcelable { * @return {@code true} if both are identical, {@code false} otherwise. * @hide */ - public boolean isIdenticalPcscfs(LinkProperties target) { + public boolean isIdenticalPcscfs(@NonNull LinkProperties target) { Collection<InetAddress> targetPcscfs = target.getPcscfServers(); return (mPcscfs.size() == targetPcscfs.size()) ? mPcscfs.containsAll(targetPcscfs) : false; @@ -1299,7 +1356,7 @@ public final class LinkProperties implements Parcelable { * @hide */ @UnsupportedAppUsage - public boolean isIdenticalRoutes(LinkProperties target) { + public boolean isIdenticalRoutes(@NonNull LinkProperties target) { Collection<RouteInfo> targetRoutes = target.getRoutes(); return (mRoutes.size() == targetRoutes.size()) ? mRoutes.containsAll(targetRoutes) : false; @@ -1313,7 +1370,7 @@ public final class LinkProperties implements Parcelable { * @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) - public boolean isIdenticalHttpProxy(LinkProperties target) { + public boolean isIdenticalHttpProxy(@NonNull LinkProperties target) { return getHttpProxy() == null ? target.getHttpProxy() == null : getHttpProxy().equals(target.getHttpProxy()); } @@ -1326,7 +1383,7 @@ public final class LinkProperties implements Parcelable { * @hide */ @UnsupportedAppUsage - public boolean isIdenticalStackedLinks(LinkProperties target) { + public boolean isIdenticalStackedLinks(@NonNull LinkProperties target) { if (!mStackedLinks.keySet().equals(target.mStackedLinks.keySet())) { return false; } @@ -1347,7 +1404,7 @@ public final class LinkProperties implements Parcelable { * @return {@code true} if both are identical, {@code false} otherwise. * @hide */ - public boolean isIdenticalMtu(LinkProperties target) { + public boolean isIdenticalMtu(@NonNull LinkProperties target) { return getMtu() == target.getMtu(); } @@ -1358,7 +1415,7 @@ public final class LinkProperties implements Parcelable { * @return {@code true} if both are identical, {@code false} otherwise. * @hide */ - public boolean isIdenticalTcpBufferSizes(LinkProperties target) { + public boolean isIdenticalTcpBufferSizes(@NonNull LinkProperties target) { return Objects.equals(mTcpBufferSizes, target.mTcpBufferSizes); } @@ -1369,7 +1426,7 @@ public final class LinkProperties implements Parcelable { * @return {@code true} if both are identical, {@code false} otherwise. * @hide */ - public boolean isIdenticalNat64Prefix(LinkProperties target) { + public boolean isIdenticalNat64Prefix(@NonNull LinkProperties target) { return Objects.equals(mNat64Prefix, target.mNat64Prefix); } @@ -1421,7 +1478,7 @@ public final class LinkProperties implements Parcelable { * @return the differences between the addresses. * @hide */ - public CompareResult<LinkAddress> compareAddresses(LinkProperties target) { + public @NonNull CompareResult<LinkAddress> compareAddresses(@Nullable LinkProperties target) { /* * Duplicate the LinkAddresses into removed, we will be removing * address which are common between mLinkAddresses and target @@ -1441,7 +1498,7 @@ public final class LinkProperties implements Parcelable { * @return the differences between the DNS addresses. * @hide */ - public CompareResult<InetAddress> compareDnses(LinkProperties target) { + public @NonNull CompareResult<InetAddress> compareDnses(@Nullable LinkProperties target) { /* * Duplicate the InetAddresses into removed, we will be removing * dns address which are common between mDnses and target @@ -1460,7 +1517,8 @@ public final class LinkProperties implements Parcelable { * @return the differences between the DNS addresses. * @hide */ - public CompareResult<InetAddress> compareValidatedPrivateDnses(LinkProperties target) { + public @NonNull CompareResult<InetAddress> compareValidatedPrivateDnses( + @Nullable LinkProperties target) { return new CompareResult<>(mValidatedPrivateDnses, target != null ? target.getValidatedPrivateDnsServers() : null); } @@ -1473,7 +1531,7 @@ public final class LinkProperties implements Parcelable { * @return the differences between the routes. * @hide */ - public CompareResult<RouteInfo> compareAllRoutes(LinkProperties target) { + public @NonNull CompareResult<RouteInfo> compareAllRoutes(@Nullable LinkProperties target) { /* * Duplicate the RouteInfos into removed, we will be removing * routes which are common between mRoutes and target @@ -1491,7 +1549,8 @@ public final class LinkProperties implements Parcelable { * @return the differences between the interface names. * @hide */ - public CompareResult<String> compareAllInterfaceNames(LinkProperties target) { + public @NonNull CompareResult<String> compareAllInterfaceNames( + @Nullable LinkProperties target) { /* * Duplicate the interface names into removed, we will be removing * interface names which are common between this and target diff --git a/core/java/android/net/Network.java b/core/java/android/net/Network.java index 0fafdf76b491..3f56def6d7d5 100644 --- a/core/java/android/net/Network.java +++ b/core/java/android/net/Network.java @@ -16,6 +16,7 @@ package android.net; +import android.annotation.NonNull; import android.annotation.SystemApi; import android.annotation.TestApi; import android.annotation.UnsupportedAppUsage; @@ -125,7 +126,7 @@ public class Network implements Parcelable { */ @SystemApi @TestApi - public Network(Network that) { + public Network(@NonNull Network that) { this(that.netId, that.mPrivateDnsBypass); } @@ -163,7 +164,7 @@ public class Network implements Parcelable { */ @TestApi @SystemApi - public Network getPrivateDnsBypassingCopy() { + public @NonNull Network getPrivateDnsBypassingCopy() { return new Network(netId, true); } diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index c57ae0c9fc32..02145f2705c7 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/core/java/android/net/NetworkCapabilities.java @@ -17,6 +17,7 @@ package android.net; import android.annotation.IntDef; +import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.TestApi; @@ -91,7 +92,7 @@ public final class NetworkCapabilities implements Parcelable { * Set all contents of this object to the contents of a NetworkCapabilities. * @hide */ - public void set(NetworkCapabilities nc) { + public void set(@NonNull NetworkCapabilities nc) { mNetworkCapabilities = nc.mNetworkCapabilities; mTransportTypes = nc.mTransportTypes; mLinkUpBandwidthKbps = nc.mLinkUpBandwidthKbps; @@ -405,7 +406,7 @@ public final class NetworkCapabilities implements Parcelable { * @hide */ @UnsupportedAppUsage - public NetworkCapabilities addCapability(@NetCapability int capability) { + public @NonNull NetworkCapabilities addCapability(@NetCapability int capability) { checkValidCapability(capability); mNetworkCapabilities |= 1 << capability; mUnwantedNetworkCapabilities &= ~(1 << capability); // remove from unwanted capability list @@ -442,7 +443,7 @@ public final class NetworkCapabilities implements Parcelable { * @hide */ @UnsupportedAppUsage - public NetworkCapabilities removeCapability(@NetCapability int capability) { + public @NonNull NetworkCapabilities removeCapability(@NetCapability int capability) { checkValidCapability(capability); final long mask = ~(1 << capability); mNetworkCapabilities &= mask; @@ -456,7 +457,8 @@ public final class NetworkCapabilities implements Parcelable { * * @hide */ - public NetworkCapabilities setCapability(@NetCapability int capability, boolean value) { + public @NonNull NetworkCapabilities setCapability(@NetCapability int capability, + boolean value) { if (value) { addCapability(capability); } else { @@ -534,7 +536,7 @@ public final class NetworkCapabilities implements Parcelable { } /** Note this method may result in having the same capability in wanted and unwanted lists. */ - private void combineNetCapabilities(NetworkCapabilities nc) { + private void combineNetCapabilities(@NonNull NetworkCapabilities nc) { this.mNetworkCapabilities |= nc.mNetworkCapabilities; this.mUnwantedNetworkCapabilities |= nc.mUnwantedNetworkCapabilities; } @@ -546,7 +548,7 @@ public final class NetworkCapabilities implements Parcelable { * * @hide */ - public String describeFirstNonRequestableCapability() { + public @Nullable String describeFirstNonRequestableCapability() { final long nonRequestable = (mNetworkCapabilities | mUnwantedNetworkCapabilities) & NON_REQUESTABLE_CAPABILITIES; @@ -558,7 +560,8 @@ public final class NetworkCapabilities implements Parcelable { return null; } - private boolean satisfiedByNetCapabilities(NetworkCapabilities nc, boolean onlyImmutable) { + private boolean satisfiedByNetCapabilities(@NonNull NetworkCapabilities nc, + boolean onlyImmutable) { long requestedCapabilities = mNetworkCapabilities; long requestedUnwantedCapabilities = mUnwantedNetworkCapabilities; long providedCapabilities = nc.mNetworkCapabilities; @@ -572,12 +575,12 @@ public final class NetworkCapabilities implements Parcelable { } /** @hide */ - public boolean equalsNetCapabilities(NetworkCapabilities nc) { + public boolean equalsNetCapabilities(@NonNull NetworkCapabilities nc) { return (nc.mNetworkCapabilities == this.mNetworkCapabilities) && (nc.mUnwantedNetworkCapabilities == this.mUnwantedNetworkCapabilities); } - private boolean equalsNetCapabilitiesRequestable(NetworkCapabilities that) { + private boolean equalsNetCapabilitiesRequestable(@NonNull NetworkCapabilities that) { return ((this.mNetworkCapabilities & ~NON_REQUESTABLE_CAPABILITIES) == (that.mNetworkCapabilities & ~NON_REQUESTABLE_CAPABILITIES)) && ((this.mUnwantedNetworkCapabilities & ~NON_REQUESTABLE_CAPABILITIES) == @@ -713,7 +716,7 @@ public final class NetworkCapabilities implements Parcelable { * @hide */ @UnsupportedAppUsage - public NetworkCapabilities addTransportType(@Transport int transportType) { + public @NonNull NetworkCapabilities addTransportType(@Transport int transportType) { checkValidTransportType(transportType); mTransportTypes |= 1 << transportType; setNetworkSpecifier(mNetworkSpecifier); // used for exception checking @@ -727,7 +730,7 @@ public final class NetworkCapabilities implements Parcelable { * @return This NetworkCapabilities instance, to facilitate chaining. * @hide */ - public NetworkCapabilities removeTransportType(@Transport int transportType) { + public @NonNull NetworkCapabilities removeTransportType(@Transport int transportType) { checkValidTransportType(transportType); mTransportTypes &= ~(1 << transportType); setNetworkSpecifier(mNetworkSpecifier); // used for exception checking @@ -740,7 +743,8 @@ public final class NetworkCapabilities implements Parcelable { * * @hide */ - public NetworkCapabilities setTransportType(@Transport int transportType, boolean value) { + public @NonNull NetworkCapabilities setTransportType(@Transport int transportType, + boolean value) { if (value) { addTransportType(transportType); } else { @@ -757,7 +761,7 @@ public final class NetworkCapabilities implements Parcelable { */ @TestApi @SystemApi - public @Transport int[] getTransportTypes() { + @NonNull public @Transport int[] getTransportTypes() { return BitUtils.unpackBits(mTransportTypes); } @@ -847,7 +851,7 @@ public final class NetworkCapabilities implements Parcelable { * @param upKbps the estimated first hop upstream (device to network) bandwidth. * @hide */ - public NetworkCapabilities setLinkUpstreamBandwidthKbps(int upKbps) { + public @NonNull NetworkCapabilities setLinkUpstreamBandwidthKbps(int upKbps) { mLinkUpBandwidthKbps = upKbps; return this; } @@ -877,7 +881,7 @@ public final class NetworkCapabilities implements Parcelable { * @param downKbps the estimated first hop downstream (network to device) bandwidth. * @hide */ - public NetworkCapabilities setLinkDownstreamBandwidthKbps(int downKbps) { + public @NonNull NetworkCapabilities setLinkDownstreamBandwidthKbps(int downKbps) { mLinkDownBandwidthKbps = downKbps; return this; } @@ -936,7 +940,7 @@ public final class NetworkCapabilities implements Parcelable { * @return This NetworkCapabilities instance, to facilitate chaining. * @hide */ - public NetworkCapabilities setNetworkSpecifier(NetworkSpecifier networkSpecifier) { + public @NonNull NetworkCapabilities setNetworkSpecifier(NetworkSpecifier networkSpecifier) { if (networkSpecifier != null && Long.bitCount(mTransportTypes) != 1) { throw new IllegalStateException("Must have a single transport specified to use " + "setNetworkSpecifier"); @@ -955,20 +959,20 @@ public final class NetworkCapabilities implements Parcelable { * @return This NetworkCapabilities instance, to facilitate chaining. * @hide */ - public NetworkCapabilities setTransportInfo(TransportInfo transportInfo) { + public @NonNull NetworkCapabilities setTransportInfo(TransportInfo transportInfo) { mTransportInfo = transportInfo; return this; } /** - * Gets the optional bearer specific network specifier. + * Gets the optional bearer specific network specifier. May be {@code null} if not set. * * @return The optional {@link NetworkSpecifier} specifying the bearer specific network - * specifier. See {@link #setNetworkSpecifier}. + * specifier or {@code null}. See {@link #setNetworkSpecifier}. * @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) - public NetworkSpecifier getNetworkSpecifier() { + public @Nullable NetworkSpecifier getNetworkSpecifier() { return mNetworkSpecifier; } @@ -1015,8 +1019,6 @@ public final class NetworkCapabilities implements Parcelable { /** * Magic value that indicates no signal strength provided. A request specifying this value is * always satisfied. - * - * @hide */ public static final int SIGNAL_STRENGTH_UNSPECIFIED = Integer.MIN_VALUE; @@ -1024,7 +1026,7 @@ public final class NetworkCapabilities implements Parcelable { * Signal strength. This is a signed integer, and higher values indicate better signal. * The exact units are bearer-dependent. For example, Wi-Fi uses RSSI. */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) private int mSignalStrength = SIGNAL_STRENGTH_UNSPECIFIED; /** @@ -1041,7 +1043,7 @@ public final class NetworkCapabilities implements Parcelable { * @hide */ @UnsupportedAppUsage - public NetworkCapabilities setSignalStrength(int signalStrength) { + public @NonNull NetworkCapabilities setSignalStrength(int signalStrength) { mSignalStrength = signalStrength; return this; } @@ -1060,9 +1062,7 @@ public final class NetworkCapabilities implements Parcelable { * Retrieves the signal strength. * * @return The bearer-specific signal strength. - * @hide */ - @SystemApi public int getSignalStrength() { return mSignalStrength; } @@ -1120,7 +1120,7 @@ public final class NetworkCapabilities implements Parcelable { * Convenience method to set the UIDs this network applies to to a single UID. * @hide */ - public NetworkCapabilities setSingleUid(int uid) { + public @NonNull NetworkCapabilities setSingleUid(int uid) { final ArraySet<UidRange> identity = new ArraySet<>(1); identity.add(new UidRange(uid, uid)); setUids(identity); @@ -1132,7 +1132,7 @@ public final class NetworkCapabilities implements Parcelable { * This makes a copy of the set so that callers can't modify it after the call. * @hide */ - public NetworkCapabilities setUids(Set<UidRange> uids) { + public @NonNull NetworkCapabilities setUids(Set<UidRange> uids) { if (null == uids) { mUids = null; } else { @@ -1146,7 +1146,7 @@ public final class NetworkCapabilities implements Parcelable { * This returns a copy of the set so that callers can't modify the original object. * @hide */ - public Set<UidRange> getUids() { + public @Nullable Set<UidRange> getUids() { return null == mUids ? null : new ArraySet<>(mUids); } @@ -1179,7 +1179,7 @@ public final class NetworkCapabilities implements Parcelable { * @hide */ @VisibleForTesting - public boolean equalsUids(NetworkCapabilities nc) { + public boolean equalsUids(@NonNull NetworkCapabilities nc) { Set<UidRange> comparedUids = nc.mUids; if (null == comparedUids) return null == mUids; if (null == mUids) return false; @@ -1212,7 +1212,7 @@ public final class NetworkCapabilities implements Parcelable { * @see #appliesToUid * @hide */ - public boolean satisfiedByUids(NetworkCapabilities nc) { + public boolean satisfiedByUids(@NonNull NetworkCapabilities nc) { if (null == nc.mUids || null == mUids) return true; // The network satisfies everything. for (UidRange requiredRange : mUids) { if (requiredRange.contains(nc.mEstablishingVpnAppUid)) return true; @@ -1232,7 +1232,7 @@ public final class NetworkCapabilities implements Parcelable { * @hide */ @VisibleForTesting - public boolean appliesToUidRange(UidRange requiredRange) { + public boolean appliesToUidRange(@Nullable UidRange requiredRange) { if (null == mUids) return true; for (UidRange uidRange : mUids) { if (uidRange.containsRange(requiredRange)) { @@ -1247,7 +1247,7 @@ public final class NetworkCapabilities implements Parcelable { * NetworkCapabilities apply to. * nc is assumed nonnull. */ - private void combineUids(NetworkCapabilities nc) { + private void combineUids(@NonNull NetworkCapabilities nc) { if (null == nc.mUids || null == mUids) { mUids = null; return; @@ -1268,7 +1268,7 @@ public final class NetworkCapabilities implements Parcelable { * Sets the SSID of this network. * @hide */ - public NetworkCapabilities setSSID(String ssid) { + public @NonNull NetworkCapabilities setSSID(@Nullable String ssid) { mSSID = ssid; return this; } @@ -1277,7 +1277,7 @@ public final class NetworkCapabilities implements Parcelable { * Gets the SSID of this network, or null if none or unknown. * @hide */ - public String getSSID() { + public @Nullable String getSSID() { return mSSID; } @@ -1285,7 +1285,7 @@ public final class NetworkCapabilities implements Parcelable { * Tests if the SSID of this network is the same as the SSID of the passed network. * @hide */ - public boolean equalsSSID(NetworkCapabilities nc) { + public boolean equalsSSID(@NonNull NetworkCapabilities nc) { return Objects.equals(mSSID, nc.mSSID); } @@ -1293,7 +1293,7 @@ public final class NetworkCapabilities implements Parcelable { * Check if the SSID requirements of this object are matched by the passed object. * @hide */ - public boolean satisfiedBySSID(NetworkCapabilities nc) { + public boolean satisfiedBySSID(@NonNull NetworkCapabilities nc) { return mSSID == null || mSSID.equals(nc.mSSID); } @@ -1304,7 +1304,7 @@ public final class NetworkCapabilities implements Parcelable { * equal. * @hide */ - private void combineSSIDs(NetworkCapabilities nc) { + private void combineSSIDs(@NonNull NetworkCapabilities nc) { if (mSSID != null && !mSSID.equals(nc.mSSID)) { throw new IllegalStateException("Can't combine two SSIDs"); } @@ -1319,7 +1319,7 @@ public final class NetworkCapabilities implements Parcelable { * both lists will never be satisfied. * @hide */ - public void combineCapabilities(NetworkCapabilities nc) { + public void combineCapabilities(@NonNull NetworkCapabilities nc) { combineNetCapabilities(nc); combineTransportTypes(nc); combineLinkBandwidths(nc); @@ -1359,7 +1359,7 @@ public final class NetworkCapabilities implements Parcelable { */ @TestApi @SystemApi - public boolean satisfiedByNetworkCapabilities(NetworkCapabilities nc) { + public boolean satisfiedByNetworkCapabilities(@Nullable NetworkCapabilities nc) { return satisfiedByNetworkCapabilities(nc, false); } @@ -1370,7 +1370,7 @@ public final class NetworkCapabilities implements Parcelable { * * @hide */ - public boolean satisfiedByImmutableNetworkCapabilities(NetworkCapabilities nc) { + public boolean satisfiedByImmutableNetworkCapabilities(@Nullable NetworkCapabilities nc) { return satisfiedByNetworkCapabilities(nc, true); } @@ -1381,7 +1381,7 @@ public final class NetworkCapabilities implements Parcelable { * * @hide */ - public String describeImmutableDifferences(NetworkCapabilities that) { + public String describeImmutableDifferences(@Nullable NetworkCapabilities that) { if (that == null) { return "other NetworkCapabilities was null"; } @@ -1420,7 +1420,7 @@ public final class NetworkCapabilities implements Parcelable { * * @hide */ - public boolean equalRequestableCapabilities(NetworkCapabilities nc) { + public boolean equalRequestableCapabilities(@Nullable NetworkCapabilities nc) { if (nc == null) return false; return (equalsNetCapabilitiesRequestable(nc) && equalsTransportTypes(nc) && @@ -1428,7 +1428,7 @@ public final class NetworkCapabilities implements Parcelable { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (obj == null || (obj instanceof NetworkCapabilities == false)) return false; NetworkCapabilities that = (NetworkCapabilities) obj; return (equalsNetCapabilities(that) @@ -1502,7 +1502,7 @@ public final class NetworkCapabilities implements Parcelable { }; @Override - public String toString() { + public @NonNull String toString() { final StringBuilder sb = new StringBuilder("["); if (0 != mTransportTypes) { sb.append(" Transports: "); @@ -1561,8 +1561,8 @@ public final class NetworkCapabilities implements Parcelable { /** * @hide */ - public static void appendStringRepresentationOfBitMaskToStringBuilder(StringBuilder sb, - long bitMask, NameOf nameFetcher, String separator) { + public static void appendStringRepresentationOfBitMaskToStringBuilder(@NonNull StringBuilder sb, + long bitMask, @NonNull NameOf nameFetcher, @NonNull String separator) { int bitPos = 0; boolean firstElementAdded = false; while (bitMask != 0) { @@ -1580,7 +1580,7 @@ public final class NetworkCapabilities implements Parcelable { } /** @hide */ - public void writeToProto(ProtoOutputStream proto, long fieldId) { + public void writeToProto(@NonNull ProtoOutputStream proto, long fieldId) { final long token = proto.start(fieldId); for (int transport : getTransportTypes()) { @@ -1610,7 +1610,7 @@ public final class NetworkCapabilities implements Parcelable { /** * @hide */ - public static String capabilityNamesOf(@NetCapability int[] capabilities) { + public static @NonNull String capabilityNamesOf(@Nullable @NetCapability int[] capabilities) { StringJoiner joiner = new StringJoiner("|"); if (capabilities != null) { for (int c : capabilities) { @@ -1623,7 +1623,7 @@ public final class NetworkCapabilities implements Parcelable { /** * @hide */ - public static String capabilityNameOf(@NetCapability int capability) { + public static @NonNull String capabilityNameOf(@NetCapability int capability) { switch (capability) { case NET_CAPABILITY_MMS: return "MMS"; case NET_CAPABILITY_SUPL: return "SUPL"; @@ -1658,7 +1658,7 @@ public final class NetworkCapabilities implements Parcelable { * @hide */ @UnsupportedAppUsage - public static String transportNamesOf(@Transport int[] types) { + public static @NonNull String transportNamesOf(@Nullable @Transport int[] types) { StringJoiner joiner = new StringJoiner("|"); if (types != null) { for (int t : types) { @@ -1671,7 +1671,7 @@ public final class NetworkCapabilities implements Parcelable { /** * @hide */ - public static String transportNameOf(@Transport int transport) { + public static @NonNull String transportNameOf(@Transport int transport) { if (!isValidTransport(transport)) { return "UNKNOWN"; } diff --git a/core/java/android/net/NetworkInfo.java b/core/java/android/net/NetworkInfo.java index cd835317a3a2..92f105f77172 100644 --- a/core/java/android/net/NetworkInfo.java +++ b/core/java/android/net/NetworkInfo.java @@ -16,6 +16,7 @@ package android.net; +import android.annotation.NonNull; import android.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; @@ -138,7 +139,9 @@ public class NetworkInfo implements Parcelable { private int mSubtype; private String mTypeName; private String mSubtypeName; + @NonNull private State mState; + @NonNull private DetailedState mDetailedState; private String mReason; private String mExtraInfo; @@ -451,7 +454,7 @@ public class NetworkInfo implements Parcelable { * the device and let apps react more easily and quickly to changes. */ @Deprecated - public DetailedState getDetailedState() { + public @NonNull DetailedState getDetailedState() { synchronized (this) { return mDetailedState; } diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java index dcb027d187b3..51cbed48e021 100644 --- a/core/java/android/net/NetworkRequest.java +++ b/core/java/android/net/NetworkRequest.java @@ -347,7 +347,7 @@ public class NetworkRequest implements Parcelable { * @hide */ @SystemApi - public Builder setSignalStrength(int signalStrength) { + public @NonNull Builder setSignalStrength(int signalStrength) { mNetworkCapabilities.setSignalStrength(signalStrength); return this; } diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java index ed410e277a42..5188866fe49d 100644 --- a/core/java/android/net/NetworkUtils.java +++ b/core/java/android/net/NetworkUtils.java @@ -177,6 +177,12 @@ public class NetworkUtils { public static native byte[] resNetworkResult(FileDescriptor fd) throws ErrnoException; /** + * DNS resolver series jni method. + * Attempts to cancel the in-progress query associated with the {@code fd}. + */ + public static native void resNetworkCancel(FileDescriptor fd); + + /** * Add an entry into the ARP cache. */ public static void addArpEntry(Inet4Address ipv4Addr, MacAddress ethAddr, String ifname, diff --git a/core/java/android/net/RouteInfo.java b/core/java/android/net/RouteInfo.java index c1c8f6eaf3c0..b0239c839348 100644 --- a/core/java/android/net/RouteInfo.java +++ b/core/java/android/net/RouteInfo.java @@ -16,6 +16,7 @@ package android.net; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.TestApi; import android.annotation.UnsupportedAppUsage; @@ -112,7 +113,8 @@ public final class RouteInfo implements Parcelable { */ @SystemApi @TestApi - public RouteInfo(IpPrefix destination, InetAddress gateway, String iface, int type) { + public RouteInfo(@Nullable IpPrefix destination, @Nullable InetAddress gateway, + @Nullable String iface, int type) { switch (type) { case RTN_UNICAST: case RTN_UNREACHABLE: diff --git a/core/java/android/net/StaticIpConfiguration.java b/core/java/android/net/StaticIpConfiguration.java index 8b264eeee3c9..e2531059ac61 100644 --- a/core/java/android/net/StaticIpConfiguration.java +++ b/core/java/android/net/StaticIpConfiguration.java @@ -16,6 +16,8 @@ package android.net; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.TestApi; import android.annotation.UnsupportedAppUsage; @@ -53,22 +55,26 @@ import java.util.Objects; public final class StaticIpConfiguration implements Parcelable { /** @hide */ @UnsupportedAppUsage + @Nullable public LinkAddress ipAddress; /** @hide */ @UnsupportedAppUsage + @Nullable public InetAddress gateway; /** @hide */ @UnsupportedAppUsage + @NonNull public final ArrayList<InetAddress> dnsServers; /** @hide */ @UnsupportedAppUsage + @Nullable public String domains; public StaticIpConfiguration() { dnsServers = new ArrayList<InetAddress>(); } - public StaticIpConfiguration(StaticIpConfiguration source) { + public StaticIpConfiguration(@Nullable StaticIpConfiguration source) { this(); if (source != null) { // All of these except dnsServers are immutable, so no need to make copies. @@ -86,38 +92,38 @@ public final class StaticIpConfiguration implements Parcelable { domains = null; } - public LinkAddress getIpAddress() { + public @Nullable LinkAddress getIpAddress() { return ipAddress; } - public void setIpAddress(LinkAddress ipAddress) { + public void setIpAddress(@Nullable LinkAddress ipAddress) { this.ipAddress = ipAddress; } - public InetAddress getGateway() { + public @Nullable InetAddress getGateway() { return gateway; } - public void setGateway(InetAddress gateway) { + public void setGateway(@Nullable InetAddress gateway) { this.gateway = gateway; } - public List<InetAddress> getDnsServers() { + public @NonNull List<InetAddress> getDnsServers() { return dnsServers; } - public String getDomains() { + public @Nullable String getDomains() { return domains; } - public void setDomains(String newDomains) { + public void setDomains(@Nullable String newDomains) { domains = newDomains; } /** * Add a DNS server to this configuration. */ - public void addDnsServer(InetAddress server) { + public void addDnsServer(@NonNull InetAddress server) { dnsServers.add(server); } @@ -128,7 +134,7 @@ public final class StaticIpConfiguration implements Parcelable { * route to the gateway as well. This configuration is arguably invalid, but it used to work * in K and earlier, and other OSes appear to accept it. */ - public List<RouteInfo> getRoutes(String iface) { + public @NonNull List<RouteInfo> getRoutes(String iface) { List<RouteInfo> routes = new ArrayList<RouteInfo>(3); if (ipAddress != null) { RouteInfo connectedRoute = new RouteInfo(ipAddress, null, iface); @@ -150,7 +156,7 @@ public final class StaticIpConfiguration implements Parcelable { * IPv6 configuration) will not be included. * @hide */ - public LinkProperties toLinkProperties(String iface) { + public @NonNull LinkProperties toLinkProperties(String iface) { LinkProperties lp = new LinkProperties(); lp.setInterfaceName(iface); if (ipAddress != null) { diff --git a/core/java/android/net/apf/ApfCapabilities.java b/core/java/android/net/apf/ApfCapabilities.java index d6023d701762..17a03c7c8933 100644 --- a/core/java/android/net/apf/ApfCapabilities.java +++ b/core/java/android/net/apf/ApfCapabilities.java @@ -16,6 +16,7 @@ package android.net.apf; +import android.annotation.NonNull; import android.annotation.SystemApi; import android.annotation.TestApi; import android.content.Context; @@ -115,14 +116,14 @@ public final class ApfCapabilities implements Parcelable { /** * @return Whether the APF Filter in the device should filter out IEEE 802.3 Frames. */ - public static boolean getApfDrop8023Frames(Context context) { + public static boolean getApfDrop8023Frames(@NonNull Context context) { return context.getResources().getBoolean(R.bool.config_apfDrop802_3Frames); } /** * @return An array of blacklisted EtherType, packets with EtherTypes within it will be dropped. */ - public static int[] getApfEthTypeBlackList(Context context) { + public static @NonNull int[] getApfEthTypeBlackList(@NonNull Context context) { return context.getResources().getIntArray(R.array.config_apfEthTypeBlackList); } } diff --git a/core/java/android/net/captiveportal/CaptivePortalProbeResult.java b/core/java/android/net/captiveportal/CaptivePortalProbeResult.java index 3930344e5d27..a1d3de248a96 100644 --- a/core/java/android/net/captiveportal/CaptivePortalProbeResult.java +++ b/core/java/android/net/captiveportal/CaptivePortalProbeResult.java @@ -16,6 +16,7 @@ package android.net.captiveportal; +import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.TestApi; @@ -39,14 +40,18 @@ public final class CaptivePortalProbeResult { */ public static final int PARTIAL_CODE = -1; + @NonNull public static final CaptivePortalProbeResult FAILED = new CaptivePortalProbeResult(FAILED_CODE); + @NonNull public static final CaptivePortalProbeResult SUCCESS = new CaptivePortalProbeResult(SUCCESS_CODE); public static final CaptivePortalProbeResult PARTIAL = new CaptivePortalProbeResult(PARTIAL_CODE); private final int mHttpResponseCode; // HTTP response code returned from Internet probe. + @Nullable public final String redirectUrl; // Redirect destination returned from Internet probe. + @Nullable public final String detectUrl; // URL where a 204 response code indicates // captive portal has been appeased. @Nullable @@ -56,12 +61,13 @@ public final class CaptivePortalProbeResult { this(httpResponseCode, null, null); } - public CaptivePortalProbeResult(int httpResponseCode, String redirectUrl, String detectUrl) { + public CaptivePortalProbeResult(int httpResponseCode, @Nullable String redirectUrl, + @Nullable String detectUrl) { this(httpResponseCode, redirectUrl, detectUrl, null); } - public CaptivePortalProbeResult(int httpResponseCode, String redirectUrl, String detectUrl, - CaptivePortalProbeSpec probeSpec) { + public CaptivePortalProbeResult(int httpResponseCode, @Nullable String redirectUrl, + @Nullable String detectUrl, @Nullable CaptivePortalProbeSpec probeSpec) { mHttpResponseCode = httpResponseCode; this.redirectUrl = redirectUrl; this.detectUrl = detectUrl; diff --git a/core/java/android/net/captiveportal/CaptivePortalProbeSpec.java b/core/java/android/net/captiveportal/CaptivePortalProbeSpec.java index 7ad4ecf2264c..6c6a16c4534e 100644 --- a/core/java/android/net/captiveportal/CaptivePortalProbeSpec.java +++ b/core/java/android/net/captiveportal/CaptivePortalProbeSpec.java @@ -19,6 +19,8 @@ package android.net.captiveportal; import static android.net.captiveportal.CaptivePortalProbeResult.PORTAL_CODE; import static android.net.captiveportal.CaptivePortalProbeResult.SUCCESS_CODE; +import static com.android.internal.util.Preconditions.checkNotNull; + import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; @@ -48,9 +50,10 @@ public abstract class CaptivePortalProbeSpec { private final String mEncodedSpec; private final URL mUrl; - CaptivePortalProbeSpec(String encodedSpec, URL url) { - mEncodedSpec = encodedSpec; - mUrl = url; + CaptivePortalProbeSpec(@NonNull String encodedSpec, @NonNull URL url) + throws NullPointerException { + mEncodedSpec = checkNotNull(encodedSpec); + mUrl = checkNotNull(url); } /** @@ -64,7 +67,7 @@ public abstract class CaptivePortalProbeSpec { */ @VisibleForTesting @NonNull - public static CaptivePortalProbeSpec parseSpec(String spec) throws ParseException, + public static CaptivePortalProbeSpec parseSpec(@NonNull String spec) throws ParseException, MalformedURLException { if (TextUtils.isEmpty(spec)) { throw new ParseException("Empty probe spec", 0 /* errorOffset */); @@ -84,7 +87,8 @@ public abstract class CaptivePortalProbeSpec { } @Nullable - private static Pattern parsePatternIfNonEmpty(String pattern, int pos) throws ParseException { + private static Pattern parsePatternIfNonEmpty(@Nullable String pattern, int pos) + throws ParseException { if (TextUtils.isEmpty(pattern)) { return null; } @@ -120,8 +124,9 @@ public abstract class CaptivePortalProbeSpec { * <p>Each spec is separated by @@,@@ and follows the format for {@link #parseSpec(String)}. * <p>This method does not throw but ignores any entry that could not be parsed. */ + @NonNull public static Collection<CaptivePortalProbeSpec> parseCaptivePortalProbeSpecs( - String settingsVal) { + @NonNull String settingsVal) { List<CaptivePortalProbeSpec> specs = new ArrayList<>(); if (settingsVal != null) { for (String spec : TextUtils.split(settingsVal, SPEC_SEPARATOR)) { @@ -142,12 +147,15 @@ public abstract class CaptivePortalProbeSpec { /** * Get the probe result from HTTP status and location header. */ + @NonNull public abstract CaptivePortalProbeResult getResult(int status, @Nullable String locationHeader); + @NonNull public String getEncodedSpec() { return mEncodedSpec; } + @NonNull public URL getUrl() { return mUrl; } diff --git a/core/java/android/net/metrics/ApfProgramEvent.java b/core/java/android/net/metrics/ApfProgramEvent.java index b30d8cb04f4c..2bd43782d523 100644 --- a/core/java/android/net/metrics/ApfProgramEvent.java +++ b/core/java/android/net/metrics/ApfProgramEvent.java @@ -17,6 +17,7 @@ package android.net.metrics; import android.annotation.IntDef; +import android.annotation.NonNull; import android.annotation.SystemApi; import android.annotation.TestApi; import android.annotation.UnsupportedAppUsage; @@ -95,7 +96,7 @@ public final class ApfProgramEvent implements IpConnectivityLog.Event { /** * Utility to create an instance of {@link ApfProgramEvent}. */ - public static class Builder { + public static final class Builder { private long mLifetime; private long mActualLifetime; private int mFilteredRas; @@ -106,6 +107,7 @@ public final class ApfProgramEvent implements IpConnectivityLog.Event { /** * Set the maximum computed lifetime of the program in seconds. */ + @NonNull public Builder setLifetime(long lifetime) { mLifetime = lifetime; return this; @@ -114,6 +116,7 @@ public final class ApfProgramEvent implements IpConnectivityLog.Event { /** * Set the effective program lifetime in seconds. */ + @NonNull public Builder setActualLifetime(long lifetime) { mActualLifetime = lifetime; return this; @@ -122,6 +125,7 @@ public final class ApfProgramEvent implements IpConnectivityLog.Event { /** * Set the number of RAs filtered by the APF program. */ + @NonNull public Builder setFilteredRas(int filteredRas) { mFilteredRas = filteredRas; return this; @@ -130,6 +134,7 @@ public final class ApfProgramEvent implements IpConnectivityLog.Event { /** * Set the total number of current RAs at generation time. */ + @NonNull public Builder setCurrentRas(int currentRas) { mCurrentRas = currentRas; return this; @@ -138,6 +143,7 @@ public final class ApfProgramEvent implements IpConnectivityLog.Event { /** * Set the length of the APF program in bytes. */ + @NonNull public Builder setProgramLength(int programLength) { mProgramLength = programLength; return this; @@ -146,6 +152,7 @@ public final class ApfProgramEvent implements IpConnectivityLog.Event { /** * Set the flags describing what an Apf program filters. */ + @NonNull public Builder setFlags(boolean hasIPv4, boolean multicastFilterOn) { mFlags = flagsFor(hasIPv4, multicastFilterOn); return this; @@ -154,6 +161,7 @@ public final class ApfProgramEvent implements IpConnectivityLog.Event { /** * Build a new {@link ApfProgramEvent}. */ + @NonNull public ApfProgramEvent build() { return new ApfProgramEvent(mLifetime, mActualLifetime, mFilteredRas, mCurrentRas, mProgramLength, mFlags); diff --git a/core/java/android/net/metrics/ApfStats.java b/core/java/android/net/metrics/ApfStats.java index e1c8888deff7..6c3b7af6b888 100644 --- a/core/java/android/net/metrics/ApfStats.java +++ b/core/java/android/net/metrics/ApfStats.java @@ -16,6 +16,7 @@ package android.net.metrics; +import android.annotation.NonNull; import android.annotation.SystemApi; import android.annotation.TestApi; import android.annotation.UnsupportedAppUsage; @@ -125,7 +126,7 @@ public final class ApfStats implements IpConnectivityLog.Event { */ @SystemApi @TestApi - public static class Builder { + public static final class Builder { private long mDurationMs; private int mReceivedRas; private int mMatchingRas; @@ -140,6 +141,7 @@ public final class ApfStats implements IpConnectivityLog.Event { /** * Set the time interval in milliseconds these statistics covers. */ + @NonNull public Builder setDurationMs(long durationMs) { mDurationMs = durationMs; return this; @@ -148,6 +150,7 @@ public final class ApfStats implements IpConnectivityLog.Event { /** * Set the number of received RAs. */ + @NonNull public Builder setReceivedRas(int receivedRas) { mReceivedRas = receivedRas; return this; @@ -156,6 +159,7 @@ public final class ApfStats implements IpConnectivityLog.Event { /** * Set the number of received RAs matching a known RA. */ + @NonNull public Builder setMatchingRas(int matchingRas) { mMatchingRas = matchingRas; return this; @@ -164,6 +168,7 @@ public final class ApfStats implements IpConnectivityLog.Event { /** * Set the number of received RAs ignored due to the MAX_RAS limit. */ + @NonNull public Builder setDroppedRas(int droppedRas) { mDroppedRas = droppedRas; return this; @@ -172,6 +177,7 @@ public final class ApfStats implements IpConnectivityLog.Event { /** * Set the number of received RAs with a minimum lifetime of 0. */ + @NonNull public Builder setZeroLifetimeRas(int zeroLifetimeRas) { mZeroLifetimeRas = zeroLifetimeRas; return this; @@ -180,6 +186,7 @@ public final class ApfStats implements IpConnectivityLog.Event { /** * Set the number of received RAs that could not be parsed. */ + @NonNull public Builder setParseErrors(int parseErrors) { mParseErrors = parseErrors; return this; @@ -188,6 +195,7 @@ public final class ApfStats implements IpConnectivityLog.Event { /** * Set the number of APF program updates from receiving RAs. */ + @NonNull public Builder setProgramUpdates(int programUpdates) { mProgramUpdates = programUpdates; return this; @@ -196,6 +204,7 @@ public final class ApfStats implements IpConnectivityLog.Event { /** * Set the total number of APF program updates. */ + @NonNull public Builder setProgramUpdatesAll(int programUpdatesAll) { mProgramUpdatesAll = programUpdatesAll; return this; @@ -204,6 +213,7 @@ public final class ApfStats implements IpConnectivityLog.Event { /** * Set the number of APF program updates from allowing multicast traffic. */ + @NonNull public Builder setProgramUpdatesAllowingMulticast(int programUpdatesAllowingMulticast) { mProgramUpdatesAllowingMulticast = programUpdatesAllowingMulticast; return this; @@ -212,6 +222,7 @@ public final class ApfStats implements IpConnectivityLog.Event { /** * Set the maximum APF program size advertised by hardware. */ + @NonNull public Builder setMaxProgramSize(int maxProgramSize) { mMaxProgramSize = maxProgramSize; return this; @@ -220,6 +231,7 @@ public final class ApfStats implements IpConnectivityLog.Event { /** * Create a new {@link ApfStats}. */ + @NonNull public ApfStats build() { return new ApfStats(mDurationMs, mReceivedRas, mMatchingRas, mDroppedRas, mZeroLifetimeRas, mParseErrors, mProgramUpdates, mProgramUpdatesAll, diff --git a/core/java/android/net/metrics/DhcpClientEvent.java b/core/java/android/net/metrics/DhcpClientEvent.java index e4faea9247d7..a3d0a20194f2 100644 --- a/core/java/android/net/metrics/DhcpClientEvent.java +++ b/core/java/android/net/metrics/DhcpClientEvent.java @@ -16,6 +16,7 @@ package android.net.metrics; +import android.annotation.NonNull; import android.annotation.SystemApi; import android.annotation.TestApi; import android.annotation.UnsupportedAppUsage; @@ -51,13 +52,14 @@ public final class DhcpClientEvent implements IpConnectivityLog.Event { /** * Utility to create an instance of {@link ApfProgramEvent}. */ - public static class Builder { + public static final class Builder { private String mMsg; private int mDurationMs; /** * Set the message of the event. */ + @NonNull public Builder setMsg(String msg) { mMsg = msg; return this; @@ -66,6 +68,7 @@ public final class DhcpClientEvent implements IpConnectivityLog.Event { /** * Set the duration of the event in milliseconds. */ + @NonNull public Builder setDurationMs(int durationMs) { mDurationMs = durationMs; return this; @@ -74,6 +77,7 @@ public final class DhcpClientEvent implements IpConnectivityLog.Event { /** * Create a new {@link DhcpClientEvent}. */ + @NonNull public DhcpClientEvent build() { return new DhcpClientEvent(mMsg, mDurationMs); } diff --git a/core/java/android/net/metrics/DhcpErrorEvent.java b/core/java/android/net/metrics/DhcpErrorEvent.java index 91318a2459d2..652ce5dd19a3 100644 --- a/core/java/android/net/metrics/DhcpErrorEvent.java +++ b/core/java/android/net/metrics/DhcpErrorEvent.java @@ -37,26 +37,26 @@ public final class DhcpErrorEvent implements IpConnectivityLog.Event { public static final int DHCP_ERROR = 4; public static final int MISC_ERROR = 5; - public static final int L2_TOO_SHORT = makeErrorCode(L2_ERROR, 1); - public static final int L2_WRONG_ETH_TYPE = makeErrorCode(L2_ERROR, 2); + public static final int L2_TOO_SHORT = (L2_ERROR << 24) | (1 << 16); + public static final int L2_WRONG_ETH_TYPE = (L2_ERROR << 24) | (2 << 16); - public static final int L3_TOO_SHORT = makeErrorCode(L3_ERROR, 1); - public static final int L3_NOT_IPV4 = makeErrorCode(L3_ERROR, 2); - public static final int L3_INVALID_IP = makeErrorCode(L3_ERROR, 3); + public static final int L3_TOO_SHORT = (L3_ERROR << 24) | (1 << 16); + public static final int L3_NOT_IPV4 = (L3_ERROR << 24) | (2 << 16); + public static final int L3_INVALID_IP = (L3_ERROR << 24) | (3 << 16); - public static final int L4_NOT_UDP = makeErrorCode(L4_ERROR, 1); - public static final int L4_WRONG_PORT = makeErrorCode(L4_ERROR, 2); + public static final int L4_NOT_UDP = (L4_ERROR << 24) | (1 << 16); + public static final int L4_WRONG_PORT = (L4_ERROR << 24) | (2 << 16); - public static final int BOOTP_TOO_SHORT = makeErrorCode(DHCP_ERROR, 1); - public static final int DHCP_BAD_MAGIC_COOKIE = makeErrorCode(DHCP_ERROR, 2); - public static final int DHCP_INVALID_OPTION_LENGTH = makeErrorCode(DHCP_ERROR, 3); - public static final int DHCP_NO_MSG_TYPE = makeErrorCode(DHCP_ERROR, 4); - public static final int DHCP_UNKNOWN_MSG_TYPE = makeErrorCode(DHCP_ERROR, 5); - public static final int DHCP_NO_COOKIE = makeErrorCode(DHCP_ERROR, 6); + public static final int BOOTP_TOO_SHORT = (DHCP_ERROR << 24) | (1 << 16); + public static final int DHCP_BAD_MAGIC_COOKIE = (DHCP_ERROR << 24) | (2 << 16); + public static final int DHCP_INVALID_OPTION_LENGTH = (DHCP_ERROR << 24) | (3 << 16); + public static final int DHCP_NO_MSG_TYPE = (DHCP_ERROR << 24) | (4 << 16); + public static final int DHCP_UNKNOWN_MSG_TYPE = (DHCP_ERROR << 24) | (5 << 16); + public static final int DHCP_NO_COOKIE = (DHCP_ERROR << 24) | (6 << 16); - public static final int BUFFER_UNDERFLOW = makeErrorCode(MISC_ERROR, 1); - public static final int RECEIVE_ERROR = makeErrorCode(MISC_ERROR, 2); - public static final int PARSING_ERROR = makeErrorCode(MISC_ERROR, 3); + public static final int BUFFER_UNDERFLOW = (MISC_ERROR << 24) | (1 << 16); + public static final int RECEIVE_ERROR = (MISC_ERROR << 24) | (2 << 16); + public static final int PARSING_ERROR = (MISC_ERROR << 24) | (3 << 16); // error code byte format (MSB to LSB): // byte 0: error type @@ -102,10 +102,6 @@ public final class DhcpErrorEvent implements IpConnectivityLog.Event { return (0xFFFF0000 & errorCode) | (0xFF & option); } - private static int makeErrorCode(int type, int subtype) { - return (type << 24) | ((0xFF & subtype) << 16); - } - @Override public String toString() { return String.format("DhcpErrorEvent(%s)", Decoder.constants.get(errorCode)); diff --git a/core/java/android/net/metrics/IpConnectivityLog.java b/core/java/android/net/metrics/IpConnectivityLog.java index 5b5a23578954..680c01573f98 100644 --- a/core/java/android/net/metrics/IpConnectivityLog.java +++ b/core/java/android/net/metrics/IpConnectivityLog.java @@ -16,6 +16,7 @@ package android.net.metrics; +import android.annotation.NonNull; import android.annotation.SystemApi; import android.annotation.TestApi; import android.net.ConnectivityMetricsEvent; @@ -41,7 +42,7 @@ public class IpConnectivityLog { /** @hide */ public static final String SERVICE_NAME = "connmetrics"; - + @NonNull private IIpConnectivityMetrics mService; /** @@ -57,7 +58,7 @@ public class IpConnectivityLog { /** @hide */ @VisibleForTesting - public IpConnectivityLog(IIpConnectivityMetrics service) { + public IpConnectivityLog(@NonNull IIpConnectivityMetrics service) { mService = service; } @@ -83,7 +84,7 @@ public class IpConnectivityLog { * @return true if the event was successfully logged. * @hide */ - public boolean log(ConnectivityMetricsEvent ev) { + public boolean log(@NonNull ConnectivityMetricsEvent ev) { if (!checkLoggerService()) { if (DBG) { Log.d(TAG, SERVICE_NAME + " service was not ready"); @@ -109,7 +110,7 @@ public class IpConnectivityLog { * @param data is a Parcelable instance representing the event. * @return true if the event was successfully logged. */ - public boolean log(long timestamp, Event data) { + public boolean log(long timestamp, @NonNull Event data) { ConnectivityMetricsEvent ev = makeEv(data); ev.timestamp = timestamp; return log(ev); @@ -121,7 +122,7 @@ public class IpConnectivityLog { * @param data is a Parcelable instance representing the event. * @return true if the event was successfully logged. */ - public boolean log(String ifname, Event data) { + public boolean log(@NonNull String ifname, @NonNull Event data) { ConnectivityMetricsEvent ev = makeEv(data); ev.ifname = ifname; return log(ev); @@ -135,7 +136,7 @@ public class IpConnectivityLog { * @param data is a Parcelable instance representing the event. * @return true if the event was successfully logged. */ - public boolean log(Network network, int[] transports, Event data) { + public boolean log(@NonNull Network network, @NonNull int[] transports, @NonNull Event data) { return log(network.netId, transports, data); } @@ -147,7 +148,7 @@ public class IpConnectivityLog { * @param data is a Parcelable instance representing the event. * @return true if the event was successfully logged. */ - public boolean log(int netid, int[] transports, Event data) { + public boolean log(int netid, @NonNull int[] transports, @NonNull Event data) { ConnectivityMetricsEvent ev = makeEv(data); ev.netId = netid; ev.transports = BitUtils.packBits(transports); @@ -159,7 +160,7 @@ public class IpConnectivityLog { * @param data is a Parcelable instance representing the event. * @return true if the event was successfully logged. */ - public boolean log(Event data) { + public boolean log(@NonNull Event data) { return log(makeEv(data)); } diff --git a/core/java/android/net/metrics/RaEvent.java b/core/java/android/net/metrics/RaEvent.java index 0d43f12e6537..b2f6585cc2fc 100644 --- a/core/java/android/net/metrics/RaEvent.java +++ b/core/java/android/net/metrics/RaEvent.java @@ -16,6 +16,7 @@ package android.net.metrics; +import android.annotation.NonNull; import android.annotation.SystemApi; import android.annotation.TestApi; import android.os.Parcel; @@ -107,7 +108,7 @@ public final class RaEvent implements IpConnectivityLog.Event { } }; - public static class Builder { + public static final class Builder { long routerLifetime = NO_LIFETIME; long prefixValidLifetime = NO_LIFETIME; @@ -119,37 +120,37 @@ public final class RaEvent implements IpConnectivityLog.Event { public Builder() { } - public RaEvent build() { + public @NonNull RaEvent build() { return new RaEvent(routerLifetime, prefixValidLifetime, prefixPreferredLifetime, routeInfoLifetime, rdnssLifetime, dnsslLifetime); } - public Builder updateRouterLifetime(long lifetime) { + public @NonNull Builder updateRouterLifetime(long lifetime) { routerLifetime = updateLifetime(routerLifetime, lifetime); return this; } - public Builder updatePrefixValidLifetime(long lifetime) { + public @NonNull Builder updatePrefixValidLifetime(long lifetime) { prefixValidLifetime = updateLifetime(prefixValidLifetime, lifetime); return this; } - public Builder updatePrefixPreferredLifetime(long lifetime) { + public @NonNull Builder updatePrefixPreferredLifetime(long lifetime) { prefixPreferredLifetime = updateLifetime(prefixPreferredLifetime, lifetime); return this; } - public Builder updateRouteInfoLifetime(long lifetime) { + public @NonNull Builder updateRouteInfoLifetime(long lifetime) { routeInfoLifetime = updateLifetime(routeInfoLifetime, lifetime); return this; } - public Builder updateRdnssLifetime(long lifetime) { + public @NonNull Builder updateRdnssLifetime(long lifetime) { rdnssLifetime = updateLifetime(rdnssLifetime, lifetime); return this; } - public Builder updateDnsslLifetime(long lifetime) { + public @NonNull Builder updateDnsslLifetime(long lifetime) { dnsslLifetime = updateLifetime(dnsslLifetime, lifetime); return this; } diff --git a/core/java/android/net/metrics/ValidationProbeEvent.java b/core/java/android/net/metrics/ValidationProbeEvent.java index 052758da7aba..45b665d45cc5 100644 --- a/core/java/android/net/metrics/ValidationProbeEvent.java +++ b/core/java/android/net/metrics/ValidationProbeEvent.java @@ -17,6 +17,7 @@ package android.net.metrics; import android.annotation.IntDef; +import android.annotation.NonNull; import android.annotation.SystemApi; import android.annotation.TestApi; import android.os.Parcel; @@ -81,7 +82,7 @@ public final class ValidationProbeEvent implements IpConnectivityLog.Event { /** * Utility to create an instance of {@link ValidationProbeEvent}. */ - public static class Builder { + public static final class Builder { private long mDurationMs; private int mProbeType; private int mReturnCode; @@ -89,6 +90,7 @@ public final class ValidationProbeEvent implements IpConnectivityLog.Event { /** * Set the duration of the probe in milliseconds. */ + @NonNull public Builder setDurationMs(long durationMs) { mDurationMs = durationMs; return this; @@ -97,6 +99,7 @@ public final class ValidationProbeEvent implements IpConnectivityLog.Event { /** * Set the probe type based on whether it was the first validation. */ + @NonNull public Builder setProbeType(int probeType, boolean firstValidation) { mProbeType = makeProbeType(probeType, firstValidation); return this; @@ -105,6 +108,7 @@ public final class ValidationProbeEvent implements IpConnectivityLog.Event { /** * Set the return code of the probe. */ + @NonNull public Builder setReturnCode(int returnCode) { mReturnCode = returnCode; return this; @@ -113,6 +117,7 @@ public final class ValidationProbeEvent implements IpConnectivityLog.Event { /** * Create a new {@link ValidationProbeEvent}. */ + @NonNull public ValidationProbeEvent build() { return new ValidationProbeEvent(mDurationMs, mProbeType, mReturnCode); } diff --git a/core/java/android/net/nsd/INsdManager.aidl b/core/java/android/net/nsd/INsdManager.aidl index 3361a7b84b53..9484c74bcb23 100644 --- a/core/java/android/net/nsd/INsdManager.aidl +++ b/core/java/android/net/nsd/INsdManager.aidl @@ -25,6 +25,7 @@ import android.os.Messenger; */ interface INsdManager { + @UnsupportedAppUsage Messenger getMessenger(); void setEnabled(boolean enable); } diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index 4fae3a8d52a8..b64fe007bcd9 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -200,13 +200,21 @@ public abstract class BatteryStats implements Parcelable { /** * Include only the current run in the stats. + * + * @deprecated As of {@link android.os.Build.VERSION_CODES#Q}, only {@link #STATS_SINCE_CHARGED} + * is supported. */ @UnsupportedAppUsage + @Deprecated public static final int STATS_CURRENT = 1; /** * Include only the run since the last time the device was unplugged in the stats. + * + * @deprecated As of {@link android.os.Build.VERSION_CODES#Q}, only {@link #STATS_SINCE_CHARGED} + * is supported. */ + @Deprecated public static final int STATS_SINCE_UNPLUGGED = 2; // NOTE: Update this list if you add/change any stats above. @@ -255,8 +263,10 @@ public abstract class BatteryStats implements Parcelable { * - Ambient display properly output in data dump. * New in version 33: * - Fixed bug in min learned capacity updating process. + * New in version 34: + * - Deprecated STATS_SINCE_UNPLUGGED and STATS_CURRENT. */ - static final int CHECKIN_VERSION = 33; + static final int CHECKIN_VERSION = 34; /** * Old version, we hit 9 and ran out of room, need to remove. @@ -3651,6 +3661,14 @@ public abstract class BatteryStats implements Parcelable { */ public final void dumpCheckinLocked(Context context, PrintWriter pw, int which, int reqUid, boolean wifiOnly) { + + if (which != BatteryStats.STATS_SINCE_CHARGED) { + dumpLine(pw, 0, STAT_NAMES[which], "err", + "ERROR: BatteryStats.dumpCheckin called for which type " + which + + " but only STATS_SINCE_CHARGED is supported."); + return; + } + final long rawUptime = SystemClock.uptimeMillis() * 1000; final long rawRealtimeMs = SystemClock.elapsedRealtime(); final long rawRealtime = rawRealtimeMs * 1000; @@ -3848,28 +3866,13 @@ public abstract class BatteryStats implements Parcelable { multicastWakeLockTimeTotalMicros / 1000, multicastWakeLockCountTotal); - if (which == STATS_SINCE_UNPLUGGED) { - dumpLine(pw, 0 /* uid */, category, BATTERY_LEVEL_DATA, getDischargeStartLevel(), - getDischargeCurrentLevel()); - } - - if (which == STATS_SINCE_UNPLUGGED) { - dumpLine(pw, 0 /* uid */, category, BATTERY_DISCHARGE_DATA, - getDischargeStartLevel()-getDischargeCurrentLevel(), - getDischargeStartLevel()-getDischargeCurrentLevel(), - getDischargeAmountScreenOn(), getDischargeAmountScreenOff(), - dischargeCount / 1000, dischargeScreenOffCount / 1000, - getDischargeAmountScreenDoze(), dischargeScreenDozeCount / 1000, - dischargeLightDozeCount / 1000, dischargeDeepDozeCount / 1000); - } else { - dumpLine(pw, 0 /* uid */, category, BATTERY_DISCHARGE_DATA, - getLowDischargeAmountSinceCharge(), getHighDischargeAmountSinceCharge(), - getDischargeAmountScreenOnSinceCharge(), - getDischargeAmountScreenOffSinceCharge(), - dischargeCount / 1000, dischargeScreenOffCount / 1000, - getDischargeAmountScreenDozeSinceCharge(), dischargeScreenDozeCount / 1000, - dischargeLightDozeCount / 1000, dischargeDeepDozeCount / 1000); - } + dumpLine(pw, 0 /* uid */, category, BATTERY_DISCHARGE_DATA, + getLowDischargeAmountSinceCharge(), getHighDischargeAmountSinceCharge(), + getDischargeAmountScreenOnSinceCharge(), + getDischargeAmountScreenOffSinceCharge(), + dischargeCount / 1000, dischargeScreenOffCount / 1000, + getDischargeAmountScreenDozeSinceCharge(), dischargeScreenDozeCount / 1000, + dischargeLightDozeCount / 1000, dischargeDeepDozeCount / 1000); if (reqUid < 0) { final Map<String, ? extends Timer> kernelWakelocks = getKernelWakelockStats(); @@ -4432,6 +4435,13 @@ public abstract class BatteryStats implements Parcelable { @SuppressWarnings("unused") public final void dumpLocked(Context context, PrintWriter pw, String prefix, final int which, int reqUid, boolean wifiOnly) { + + if (which != BatteryStats.STATS_SINCE_CHARGED) { + pw.println("ERROR: BatteryStats.dump called for which type " + which + + " but only STATS_SINCE_CHARGED is supported"); + return; + } + final long rawUptime = SystemClock.uptimeMillis() * 1000; final long rawRealtime = SystemClock.elapsedRealtime() * 1000; final long rawRealtimeMs = (rawRealtime + 500) / 1000; @@ -5044,41 +5054,18 @@ public abstract class BatteryStats implements Parcelable { pw.println(); - if (which == STATS_SINCE_UNPLUGGED) { - if (getIsOnBattery()) { - pw.print(prefix); pw.println(" Device is currently unplugged"); - pw.print(prefix); pw.print(" Discharge cycle start level: "); - pw.println(getDischargeStartLevel()); - pw.print(prefix); pw.print(" Discharge cycle current level: "); - pw.println(getDischargeCurrentLevel()); - } else { - pw.print(prefix); pw.println(" Device is currently plugged into power"); - pw.print(prefix); pw.print(" Last discharge cycle start level: "); - pw.println(getDischargeStartLevel()); - pw.print(prefix); pw.print(" Last discharge cycle end level: "); - pw.println(getDischargeCurrentLevel()); - } - pw.print(prefix); pw.print(" Amount discharged while screen on: "); - pw.println(getDischargeAmountScreenOn()); - pw.print(prefix); pw.print(" Amount discharged while screen off: "); - pw.println(getDischargeAmountScreenOff()); - pw.print(prefix); pw.print(" Amount discharged while screen doze: "); - pw.println(getDischargeAmountScreenDoze()); - pw.println(" "); - } else { - pw.print(prefix); pw.println(" Device battery use since last full charge"); - pw.print(prefix); pw.print(" Amount discharged (lower bound): "); - pw.println(getLowDischargeAmountSinceCharge()); - pw.print(prefix); pw.print(" Amount discharged (upper bound): "); - pw.println(getHighDischargeAmountSinceCharge()); - pw.print(prefix); pw.print(" Amount discharged while screen on: "); - pw.println(getDischargeAmountScreenOnSinceCharge()); - pw.print(prefix); pw.print(" Amount discharged while screen off: "); - pw.println(getDischargeAmountScreenOffSinceCharge()); - pw.print(prefix); pw.print(" Amount discharged while screen doze: "); - pw.println(getDischargeAmountScreenDozeSinceCharge()); - pw.println(); - } + pw.print(prefix); pw.println(" Device battery use since last full charge"); + pw.print(prefix); pw.print(" Amount discharged (lower bound): "); + pw.println(getLowDischargeAmountSinceCharge()); + pw.print(prefix); pw.print(" Amount discharged (upper bound): "); + pw.println(getHighDischargeAmountSinceCharge()); + pw.print(prefix); pw.print(" Amount discharged while screen on: "); + pw.println(getDischargeAmountScreenOnSinceCharge()); + pw.print(prefix); pw.print(" Amount discharged while screen off: "); + pw.println(getDischargeAmountScreenOffSinceCharge()); + pw.print(prefix); pw.print(" Amount discharged while screen doze: "); + pw.println(getDischargeAmountScreenDozeSinceCharge()); + pw.println(); final BatteryStatsHelper helper = new BatteryStatsHelper(context, false, wifiOnly); helper.create(this); diff --git a/core/java/android/os/DropBoxManager.java b/core/java/android/os/DropBoxManager.java index 320f471e4b3f..b92e71357503 100644 --- a/core/java/android/os/DropBoxManager.java +++ b/core/java/android/os/DropBoxManager.java @@ -92,6 +92,13 @@ public class DropBoxManager { public static final String EXTRA_TIME = "time"; /** + * Extra for {@link android.os.DropBoxManager#ACTION_DROPBOX_ENTRY_ADDED}: + * integer value containing number of broadcasts dropped due to rate limiting on + * this {@link android.os.DropBoxManager#EXTRA_TAG} + */ + public static final String EXTRA_DROPPED_COUNT = "android.os.extra.DROPPED_COUNT"; + + /** * A single entry retrieved from the drop box. * This may include a reference to a stream, so you must call * {@link #close()} when you are done using it. diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java index 707a404da4ed..41691d763673 100644 --- a/core/java/android/os/GraphicsEnvironment.java +++ b/core/java/android/os/GraphicsEnvironment.java @@ -63,7 +63,7 @@ public class GraphicsEnvironment { private static final long SYSTEM_DRIVER_VERSION_CODE = 0; private static final String PROPERTY_GFX_DRIVER = "ro.gfx.driver.0"; private static final String PROPERTY_GFX_DRIVER_BUILD_TIME = "ro.gfx.driver_build_time"; - private static final String METADATA_DRIVER_BUILD_TIME = "driver_build_time"; + private static final String METADATA_DRIVER_BUILD_TIME = "com.android.gamedriver.build_time"; private static final String ANGLE_RULES_FILE = "a4a_rules.json"; private static final String ANGLE_TEMP_RULES = "debug.angle.rules"; private static final String ACTION_ANGLE_FOR_ANDROID = "android.app.action.ANGLE_FOR_ANDROID"; @@ -702,7 +702,7 @@ public class GraphicsEnvironment { final String driverBuildTime = driverAppInfo.metaData.getString(METADATA_DRIVER_BUILD_TIME); if (driverBuildTime == null || driverBuildTime.isEmpty()) { - throw new IllegalArgumentException("driver_build_time meta-data is not set"); + throw new IllegalArgumentException("com.android.gamedriver.build_time is not set"); } // driver_build_time in the meta-data is in "L<Unix epoch timestamp>" format. e.g. L123456. // Long.parseLong will throw if the meta-data "driver_build_time" is not set properly. diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl index f62a999a7d39..6536fc991b30 100644 --- a/core/java/android/os/INetworkManagementService.aidl +++ b/core/java/android/os/INetworkManagementService.aidl @@ -242,27 +242,6 @@ interface INetworkManagementService void tetherLimitReached(ITetheringStatsProvider provider); /** - ** PPPD - **/ - - /** - * Returns the list of currently known TTY devices on the system - */ - String[] listTtys(); - - /** - * Attaches a PPP server daemon to the specified TTY with the specified - * local/remote addresses. - */ - void attachPppd(String tty, String localAddr, String remoteAddr, String dns1Addr, - String dns2Addr); - - /** - * Detaches a PPP server daemon from the specified TTY. - */ - void detachPppd(String tty); - - /** ** DATA USAGE RELATED **/ diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl index 423334008818..b5c6604c8b99 100644 --- a/core/java/android/os/IPowerManager.aidl +++ b/core/java/android/os/IPowerManager.aidl @@ -34,6 +34,7 @@ interface IPowerManager String historyTag); void acquireWakeLockWithUid(IBinder lock, int flags, String tag, String packageName, int uidtoblame); + @UnsupportedAppUsage void releaseWakeLock(IBinder lock, int flags); void updateWakeLockUids(IBinder lock, in int[] uids); oneway void powerHint(int hintId, int data); diff --git a/core/java/android/os/ServiceSpecificException.java b/core/java/android/os/ServiceSpecificException.java index 3b0f26ae8867..03d5d3e195e0 100644 --- a/core/java/android/os/ServiceSpecificException.java +++ b/core/java/android/os/ServiceSpecificException.java @@ -15,6 +15,7 @@ */ package android.os; +import android.annotation.Nullable; import android.annotation.SystemApi; /** @@ -34,7 +35,7 @@ import android.annotation.SystemApi; public class ServiceSpecificException extends RuntimeException { public final int errorCode; - public ServiceSpecificException(int errorCode, String message) { + public ServiceSpecificException(int errorCode, @Nullable String message) { super(message); this.errorCode = errorCode; } diff --git a/core/java/android/os/SystemClock.java b/core/java/android/os/SystemClock.java index e695a1b21593..64effb8fa0cc 100644 --- a/core/java/android/os/SystemClock.java +++ b/core/java/android/os/SystemClock.java @@ -20,6 +20,8 @@ import android.annotation.NonNull; import android.annotation.UnsupportedAppUsage; import android.app.IAlarmManager; import android.content.Context; +import android.location.ILocationManager; +import android.location.LocationTime; import android.util.Slog; import dalvik.annotation.optimization.CriticalNative; @@ -317,4 +319,33 @@ public final class SystemClock { } }; } + + /** + * Returns a {@link Clock} that starts at January 1, 1970 00:00:00.0 UTC, + * synchronized using the device's location provider. + * + * @throws DateTimeException when the location provider has not had a location fix since boot. + */ + public static @NonNull Clock currentGnssTimeClock() { + return new SimpleClock(ZoneOffset.UTC) { + private final ILocationManager mMgr = ILocationManager.Stub + .asInterface(ServiceManager.getService(Context.LOCATION_SERVICE)); + @Override + public long millis() { + LocationTime time; + try { + time = mMgr.getGnssTimeMillis(); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + return 0; + } + if (time == null) { + throw new DateTimeException("Gnss based time is not available."); + } + long currentNanos = elapsedRealtimeNanos(); + long deltaMs = (currentNanos - time.getElapsedRealtimeNanos()) / 1000000L; + return time.getTime() + deltaMs; + } + }; + } } diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java index c74cbff567c5..7958ddd29c70 100644 --- a/core/java/android/os/VibrationEffect.java +++ b/core/java/android/os/VibrationEffect.java @@ -23,7 +23,7 @@ import android.annotation.TestApi; import android.content.ContentResolver; import android.content.Context; import android.hardware.vibrator.V1_0.EffectStrength; -import android.hardware.vibrator.V1_2.Effect; +import android.hardware.vibrator.V1_3.Effect; import android.net.Uri; import android.util.MathUtils; @@ -94,6 +94,18 @@ public abstract class VibrationEffect implements Parcelable { */ public static final int EFFECT_HEAVY_CLICK = Effect.HEAVY_CLICK; + /** + * A texture effect meant to replicate soft ticks. + * + * Unlike normal effects, texture effects are meant to be called repeatedly, generally in + * response to some motion, in order to replicate the feeling of some texture underneath the + * user's fingers. + * + * @see #get(int) + * @hide + */ + public static final int EFFECT_TEXTURE_TICK = Effect.TEXTURE_TICK; + /** {@hide} */ @TestApi public static final int EFFECT_STRENGTH_LIGHT = EffectStrength.LIGHT; @@ -746,6 +758,7 @@ public abstract class VibrationEffect implements Parcelable { case EFFECT_CLICK: case EFFECT_DOUBLE_CLICK: case EFFECT_TICK: + case EFFECT_TEXTURE_TICK: case EFFECT_THUD: case EFFECT_POP: case EFFECT_HEAVY_CLICK: @@ -798,7 +811,7 @@ public abstract class VibrationEffect implements Parcelable { out.writeInt(mEffectStrength); } - public static final @android.annotation.NonNull Parcelable.Creator<Prebaked> CREATOR = + public static final @NonNull Parcelable.Creator<Prebaked> CREATOR = new Parcelable.Creator<Prebaked>() { @Override public Prebaked createFromParcel(Parcel in) { @@ -813,7 +826,7 @@ public abstract class VibrationEffect implements Parcelable { }; } - public static final @android.annotation.NonNull Parcelable.Creator<VibrationEffect> CREATOR = + public static final @NonNull Parcelable.Creator<VibrationEffect> CREATOR = new Parcelable.Creator<VibrationEffect>() { @Override public VibrationEffect createFromParcel(Parcel in) { diff --git a/core/java/android/os/health/SystemHealthManager.java b/core/java/android/os/health/SystemHealthManager.java index 71eda19e165b..a92e28a47660 100644 --- a/core/java/android/os/health/SystemHealthManager.java +++ b/core/java/android/os/health/SystemHealthManager.java @@ -37,11 +37,13 @@ import com.android.internal.app.IBatteryStats; * by the logging itself. It can be substantial. * <p> * <b>Battery Usage</b><br> - * The statistics related to power (battery) usage are recorded since the device - * was last unplugged. It is expected that applications schedule more work to do - * while the device is plugged in (e.g. using {@link android.app.job.JobScheduler - * JobScheduler}), and while that can affect charging rates, it is still preferable - * to actually draining the battery. + * Since Android version {@link android.os.Build.VERSION_CODES#Q}, the statistics related to power + * (battery) usage are recorded since the device was last considered fully charged (for previous + * versions, it is instead since the device was last unplugged). + * It is expected that applications schedule more work to do while the device is + * plugged in (e.g. using {@link android.app.job.JobScheduler JobScheduler}), and + * while that can affect charging rates, it is still preferable to actually draining + * the battery. */ @SystemService(Context.SYSTEM_HEALTH_SERVICE) public class SystemHealthManager { diff --git a/core/java/android/content/DynamicAndroidClient.java b/core/java/android/os/image/DynamicSystemClient.java index 571cba429ea9..33a6ee888d0a 100644 --- a/core/java/android/content/DynamicAndroidClient.java +++ b/core/java/android/os/image/DynamicSystemClient.java @@ -13,12 +13,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package android.content; +package android.os.image; +import android.annotation.BytesLong; import android.annotation.CallbackExecutor; import android.annotation.IntDef; import android.annotation.NonNull; +import android.annotation.RequiresPermission; import android.annotation.SystemApi; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; @@ -34,12 +40,28 @@ import java.lang.ref.WeakReference; import java.util.concurrent.Executor; /** - * This class contains methods and constants used to start DynamicAndroid - * installation, and a listener for progress update. + * <p>This class contains methods and constants used to start a {@code DynamicSystem} installation, + * and a listener for status updates.</p> + * + * <p>{@code DynamicSystem} allows user to run certified system images in a non destructive manner + * without needing to prior OEM unlock. While running in {@code DynamicSystem}, persitent storage + * for factory reset protection (FRP) remains unchanged. The new system is installed in a + * temporarily allocated partition. After the installation is completed, the device will be running + * in the new system on next reboot. Then, when the user reboots the device again, it will leave + * {@code DynamicSystem} and go back into the original system. Since the userdata for + * {@code DynamicSystem} is also newly created during the installation, running in + * {@code DynamicSystem} doesn't change user's app data.</p> + * + * <p>With {@link #setOnStatusChangedListener}, API users can register an + * {@link #OnStatusChangedListener} and get status updates and cause when the installation is + * started, stopped, or cancelled. It also sends progress updates during the installation. With + * {@link #start}, API users can start an installation with the {@link Uri} to a gzipped system + * image. The {@link Uri} can be a web URL or a content Uri to a local path.</p> + * * @hide */ @SystemApi -public class DynamicAndroidClient { +public class DynamicSystemClient { /** @hide */ @IntDef(prefix = { "STATUS_" }, value = { STATUS_UNKNOWN, @@ -64,23 +86,23 @@ public class DynamicAndroidClient { @Retention(RetentionPolicy.SOURCE) public @interface StatusChangedCause {} - private static final String TAG = "DynAndroidClient"; + private static final String TAG = "DynSystemClient"; private static final long DEFAULT_USERDATA_SIZE = (10L << 30); - /** Listener for installation status update. */ + /** Listener for installation status updates. */ public interface OnStatusChangedListener { /** * This callback is called when installation status is changed, and when the - * client is {@link #bind} to DynamicAndroid installation service. + * client is {@link #bind} to {@code DynamicSystem} installation service. * - * @param status status code, also defined in {@code DynamicAndroidClient}. - * @param cause cause code, also defined in {@code DynamicAndroidClient}. + * @param status status code, also defined in {@code DynamicSystemClient}. + * @param cause cause code, also defined in {@code DynamicSystemClient}. * @param progress number of bytes installed. */ void onStatusChanged(@InstallationStatus int status, @StatusChangedCause int cause, - long progress); + @BytesLong long progress); } /* @@ -98,7 +120,7 @@ public class DynamicAndroidClient { /** Installation is finished but the user has not launched it. */ public static final int STATUS_READY = 3; - /** Device is running in Dynamic Android. */ + /** Device is running in {@code DynamicSystem}. */ public static final int STATUS_IN_USE = 4; /* @@ -113,7 +135,7 @@ public class DynamicAndroidClient { /** Status changed because installation is cancelled. */ public static final int CAUSE_INSTALL_CANCELLED = 2; - /** Installation failed due to IOException. */ + /** Installation failed due to {@code IOException}. */ public static final int CAUSE_ERROR_IO = 3; /** Installation failed because the image URL source is not supported. */ @@ -141,7 +163,7 @@ public class DynamicAndroidClient { public static final int MSG_UNREGISTER_LISTENER = 2; /** - * Message for status update. + * Message for status updates. * @hide */ public static final int MSG_POST_STATUS = 3; @@ -150,7 +172,7 @@ public class DynamicAndroidClient { * Messages keys */ /** - * Message key, for progress update. + * Message key, for progress updates. * @hide */ public static final String KEY_INSTALLED_SIZE = "KEY_INSTALLED_SIZE"; @@ -163,14 +185,14 @@ public class DynamicAndroidClient { * @hide */ public static final String ACTION_START_INSTALL = - "android.content.action.START_INSTALL"; + "android.os.image.action.START_INSTALL"; /** - * Intent action: notify user if we are currently running in Dynamic Android. + * Intent action: notify user if we are currently running in {@code DynamicSystem}. * @hide */ public static final String ACTION_NOTIFY_IF_IN_USE = - "android.content.action.NOTIFY_IF_IN_USE"; + "android.os.image.action.NOTIFY_IF_IN_USE"; /* * Intent Keys @@ -195,16 +217,16 @@ public class DynamicAndroidClient { private static class IncomingHandler extends Handler { - private final WeakReference<DynamicAndroidClient> mWeakClient; + private final WeakReference<DynamicSystemClient> mWeakClient; - IncomingHandler(DynamicAndroidClient service) { + IncomingHandler(DynamicSystemClient service) { super(Looper.getMainLooper()); mWeakClient = new WeakReference<>(service); } @Override public void handleMessage(Message msg) { - DynamicAndroidClient service = mWeakClient.get(); + DynamicSystemClient service = mWeakClient.get(); if (service != null) { service.handleMessage(msg); @@ -212,9 +234,9 @@ public class DynamicAndroidClient { } } - private class DynAndroidServiceConnection implements ServiceConnection { + private class DynSystemServiceConnection implements ServiceConnection { public void onServiceConnected(ComponentName className, IBinder service) { - Slog.v(TAG, "DynAndroidService connected"); + Slog.v(TAG, "DynSystemService connected"); mService = new Messenger(service); @@ -232,13 +254,13 @@ public class DynamicAndroidClient { } public void onServiceDisconnected(ComponentName className) { - Slog.v(TAG, "DynAndroidService disconnected"); + Slog.v(TAG, "DynSystemService disconnected"); mService = null; } } private final Context mContext; - private final DynAndroidServiceConnection mConnection; + private final DynSystemServiceConnection mConnection; private final Messenger mMessenger; private boolean mBound; @@ -247,12 +269,16 @@ public class DynamicAndroidClient { private Messenger mService; /** + * Create a new {@code DynamicSystem} client. + * + * @param context a {@link Context} will be used to bind the installation service. + * * @hide */ @SystemApi - public DynamicAndroidClient(@NonNull Context context) { + public DynamicSystemClient(@NonNull Context context) { mContext = context; - mConnection = new DynAndroidServiceConnection(); + mConnection = new DynSystemServiceConnection(); mMessenger = new Messenger(new IncomingHandler(this)); } @@ -261,8 +287,8 @@ public class DynamicAndroidClient { * the executor. */ public void setOnStatusChangedListener( - @NonNull OnStatusChangedListener listener, - @NonNull @CallbackExecutor Executor executor) { + @NonNull @CallbackExecutor Executor executor, + @NonNull OnStatusChangedListener listener) { mListener = listener; mExecutor = executor; } @@ -278,12 +304,15 @@ public class DynamicAndroidClient { } /** - * Bind to DynamicAndroidInstallationService. + * Bind to {@code DynamicSystem} installation service. Binding to the installation service + * allows it to send status updates to {@link #OnStatusChangedListener}. It is recommanded + * to bind before calling {@link #start} and get status updates. */ + @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM) public void bind() { Intent intent = new Intent(); - intent.setClassName("com.android.dynandroid", - "com.android.dynandroid.DynamicAndroidInstallationService"); + intent.setClassName("com.android.dynsystem", + "com.android.dynsystem.DynamicSystemInstallationService"); mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE); @@ -291,8 +320,10 @@ public class DynamicAndroidClient { } /** - * Unbind from DynamicAndroidInstallationService. + * Unbind from {@code DynamicSystem} installation service. Unbinding from the installation + * service stops it from sending following status updates. */ + @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM) public void unbind() { if (!mBound) { return; @@ -315,27 +346,40 @@ public class DynamicAndroidClient { } /** - * Start installing DynamicAndroid from URL with default userdata size. + * Start installing {@code DynamicSystem} from URL with default userdata size. + * + * Calling this function will first start an Activity to confirm device credential, using + * {@link KeyguardManager}. If it's confirmed, the installation service will be started. + * + * This function doesn't require prior calling {@link #bind}. * * @param systemUrl A network URL or a file URL to system image. * @param systemSize size of system image. */ - public void start(String systemUrl, long systemSize) { + @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM) + public void start(@NonNull String systemUrl, @BytesLong long systemSize) { start(systemUrl, systemSize, DEFAULT_USERDATA_SIZE); } /** - * Start installing DynamicAndroid from URL. + * Start installing {@code DynamicSystem} from URL. + * + * Calling this function will first start an Activity to confirm device credential, using + * {@link KeyguardManager}. If it's confirmed, the installation service will be started. + * + * This function doesn't require prior calling {@link #bind}. * * @param systemUrl A network URL or a file URL to system image. * @param systemSize size of system image. * @param userdataSize bytes reserved for userdata. */ - public void start(String systemUrl, long systemSize, long userdataSize) { + @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM) + public void start(@NonNull String systemUrl, @BytesLong long systemSize, + @BytesLong long userdataSize) { Intent intent = new Intent(); - intent.setClassName("com.android.dynandroid", - "com.android.dynandroid.VerificationActivity"); + intent.setClassName("com.android.dynsystem", + "com.android.dynsystem.VerificationActivity"); intent.setAction(ACTION_START_INSTALL); diff --git a/core/java/android/os/DynamicAndroidManager.java b/core/java/android/os/image/DynamicSystemManager.java index 5238896016ee..0458c2a8b735 100644 --- a/core/java/android/os/DynamicAndroidManager.java +++ b/core/java/android/os/image/DynamicSystemManager.java @@ -14,50 +14,51 @@ * limitations under the License. */ -package android.os; +package android.os.image; import android.annotation.RequiresPermission; import android.annotation.SystemService; import android.content.Context; import android.gsi.GsiProgress; +import android.os.RemoteException; /** - * The DynamicAndroidManager offers a mechanism to use a new Android image temporarily. After the + * The DynamicSystemManager offers a mechanism to use a new system image temporarily. After the * installation, the device can reboot into this image with a new created /data. This image will * last until the next reboot and then the device will go back to the original image. However the * installed image and the new created /data are not deleted but disabled. Thus the application can * either re-enable the installed image by calling {@link #toggle} or use the {@link #remove} to * delete it completely. In other words, there are three device states: no installation, installed - * and running. The procedure to install a DynamicAndroid starts with a {@link #startInstallation}, + * and running. The procedure to install a DynamicSystem starts with a {@link #startInstallation}, * followed by a series of {@link #write} and ends with a {@link commit}. Once the installation is * complete, the device state changes from no installation to the installed state and a followed - * reboot will change its state to running. Note one instance of dynamic android can exist on a - * given device thus the {@link #startInstallation} will fail if the device is currently running a - * DynamicAndroid. + * reboot will change its state to running. Note one instance of DynamicSystem can exist on a given + * device thus the {@link #startInstallation} will fail if the device is currently running a + * DynamicSystem. * * @hide */ -@SystemService(Context.DYNAMIC_ANDROID_SERVICE) -public class DynamicAndroidManager { - private static final String TAG = "DynamicAndroidManager"; +@SystemService(Context.DYNAMIC_SYSTEM_SERVICE) +public class DynamicSystemManager { + private static final String TAG = "DynamicSystemManager"; - private final IDynamicAndroidService mService; + private final IDynamicSystemService mService; /** {@hide} */ - public DynamicAndroidManager(IDynamicAndroidService service) { + public DynamicSystemManager(IDynamicSystemService service) { mService = service; } - /** The DynamicAndroidManager.Session represents a started session for the installation. */ + /** The DynamicSystemManager.Session represents a started session for the installation. */ public class Session { private Session() {} /** - * Write a chunk of the DynamicAndroid system image + * Write a chunk of the DynamicSystem system image * * @return {@code true} if the call succeeds. {@code false} if there is any native runtime * error. */ - @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_ANDROID) + @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM) public boolean write(byte[] buf) { try { return mService.write(buf); @@ -72,7 +73,7 @@ public class DynamicAndroidManager { * @return {@code true} if the call succeeds. {@code false} if there is any native runtime * error. */ - @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_ANDROID) + @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM) public boolean commit() { try { return mService.commit(); @@ -82,16 +83,16 @@ public class DynamicAndroidManager { } } /** - * Start DynamicAndroid installation. This call may take an unbounded amount of time. The caller + * Start DynamicSystem installation. This call may take an unbounded amount of time. The caller * may use another thread to call the getStartProgress() to get the progress. * * @param systemSize system size in bytes * @param userdataSize userdata size in bytes * @return {@code true} if the call succeeds. {@code false} either the device does not contain - * enough space or a DynamicAndroid is currently in use where the {@link #isInUse} would be + * enough space or a DynamicSystem is currently in use where the {@link #isInUse} would be * true. */ - @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_ANDROID) + @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM) public Session startInstallation(long systemSize, long userdataSize) { try { if (mService.startInstallation(systemSize, userdataSize)) { @@ -112,7 +113,7 @@ public class DynamicAndroidManager { * status field can be IGsiService.STATUS_NO_OPERATION, IGsiService.STATUS_WORKING or * IGsiService.STATUS_COMPLETE. */ - @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_ANDROID) + @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM) public GsiProgress getInstallationProgress() { try { return mService.getInstallationProgress(); @@ -129,7 +130,7 @@ public class DynamicAndroidManager { * @return {@code true} if the call succeeds. {@code false} if there is no installation * currently. */ - @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_ANDROID) + @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM) public boolean abort() { try { return mService.abort(); @@ -138,8 +139,8 @@ public class DynamicAndroidManager { } } - /** @return {@code true} if the device is running a dynamic android */ - @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_ANDROID) + /** @return {@code true} if the device is running a dynamic system */ + @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM) public boolean isInUse() { try { return mService.isInUse(); @@ -148,8 +149,8 @@ public class DynamicAndroidManager { } } - /** @return {@code true} if the device has a dynamic android installed */ - @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_ANDROID) + /** @return {@code true} if the device has a dynamic system installed */ + @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM) public boolean isInstalled() { try { return mService.isInstalled(); @@ -159,11 +160,11 @@ public class DynamicAndroidManager { } /** - * Remove DynamicAndroid installation if present + * Remove DynamicSystem installation if present * * @return {@code true} if the call succeeds. {@code false} if there is no installed image. */ - @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_ANDROID) + @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM) public boolean remove() { try { return mService.remove(); @@ -173,11 +174,11 @@ public class DynamicAndroidManager { } /** - * Enable DynamicAndroid when it's not enabled, otherwise, disable it. + * Enable DynamicSystem when it's not enabled, otherwise, disable it. * * @return {@code true} if the call succeeds. {@code false} if there is no installed image. */ - @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_ANDROID) + @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM) public boolean toggle() { try { return mService.toggle(); diff --git a/core/java/android/os/IDynamicAndroidService.aidl b/core/java/android/os/image/IDynamicSystemService.aidl index 0b28799c8dd0..15f5b68e354b 100644 --- a/core/java/android/os/IDynamicAndroidService.aidl +++ b/core/java/android/os/image/IDynamicSystemService.aidl @@ -13,15 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package android.os; +package android.os.image; import android.gsi.GsiProgress; /** {@hide} */ -interface IDynamicAndroidService +interface IDynamicSystemService { /** - * Start DynamicAndroid installation. This call may take 60~90 seconds. The caller + * Start DynamicSystem installation. This call may take 60~90 seconds. The caller * may use another thread to call the getStartProgress() to get the progress. * * @param systemSize system size in bytes @@ -53,26 +53,26 @@ interface IDynamicAndroidService boolean isInUse(); /** - * @return true if the device has an DynamicAndroid image installed + * @return true if the device has an DynamicSystem image installed */ boolean isInstalled(); /** - * Remove DynamicAndroid installation if present + * Remove DynamicSystem installation if present * * @return true if the call succeeds */ boolean remove(); /** - * Enable DynamicAndroid when it's not enabled, otherwise, disable it. + * Enable DynamicSystem when it's not enabled, otherwise, disable it. * * @return true if the call succeeds */ boolean toggle(); /** - * Write a chunk of the DynamicAndroid system image + * Write a chunk of the DynamicSystem system image * * @return true if the call succeeds */ diff --git a/core/java/android/permission/RuntimePermissionUsageInfo.java b/core/java/android/permission/RuntimePermissionUsageInfo.java index 9f954f7dcbe9..863b0ad9c3d4 100644 --- a/core/java/android/permission/RuntimePermissionUsageInfo.java +++ b/core/java/android/permission/RuntimePermissionUsageInfo.java @@ -35,7 +35,7 @@ import android.os.Parcelable; */ @SystemApi public final class RuntimePermissionUsageInfo implements Parcelable { - private final @NonNull CharSequence mName; + private final @NonNull String mName; private final int mNumUsers; /** @@ -44,7 +44,7 @@ public final class RuntimePermissionUsageInfo implements Parcelable { * @param name The permission group name. * @param numUsers The number of apps that have used this permission. */ - public RuntimePermissionUsageInfo(@NonNull CharSequence name, int numUsers) { + public RuntimePermissionUsageInfo(@NonNull String name, int numUsers) { checkNotNull(name); checkArgumentNonnegative(numUsers); @@ -53,7 +53,7 @@ public final class RuntimePermissionUsageInfo implements Parcelable { } private RuntimePermissionUsageInfo(Parcel parcel) { - this(parcel.readCharSequence(), parcel.readInt()); + this(parcel.readString(), parcel.readInt()); } /** @@ -68,7 +68,7 @@ public final class RuntimePermissionUsageInfo implements Parcelable { * * @return The name. */ - public @NonNull CharSequence getName() { + public @NonNull String getName() { return mName; } @@ -79,7 +79,7 @@ public final class RuntimePermissionUsageInfo implements Parcelable { @Override public void writeToParcel(Parcel parcel, int flags) { - parcel.writeCharSequence(mName); + parcel.writeString(mName); parcel.writeInt(mNumUsers); } diff --git a/core/java/android/preference/PreferenceGroupAdapter.java b/core/java/android/preference/PreferenceGroupAdapter.java index fb41ea8218b7..dcc5d4c58784 100644 --- a/core/java/android/preference/PreferenceGroupAdapter.java +++ b/core/java/android/preference/PreferenceGroupAdapter.java @@ -16,6 +16,7 @@ package android.preference; +import android.annotation.UnsupportedAppUsage; import android.graphics.drawable.Drawable; import android.os.Handler; import android.preference.Preference.OnPreferenceChangeInternalListener; @@ -215,6 +216,7 @@ public class PreferenceGroupAdapter extends BaseAdapter return mPreferenceList.size(); } + @UnsupportedAppUsage public Preference getItem(int position) { if (position < 0 || position >= getCount()) return null; return mPreferenceList.get(position); diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java index 7fc07b05771c..4322a59cd3cd 100644 --- a/core/java/android/provider/DeviceConfig.java +++ b/core/java/android/provider/DeviceConfig.java @@ -241,6 +241,14 @@ public final class DeviceConfig { public static final String NAMESPACE_SYSTEMUI = "systemui"; /** + * Telephony related properties. + * + * @hide + */ + @SystemApi + public static final String NAMESPACE_TELEPHONY = "telephony"; + + /** * Namespace for TextClassifier related features. * * @hide @@ -285,7 +293,6 @@ public final class DeviceConfig { * * @hide */ - @SystemApi public interface Telephony { String NAMESPACE = "telephony"; /** diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java index 14863338f182..368ba3c1de30 100644 --- a/core/java/android/provider/MediaStore.java +++ b/core/java/android/provider/MediaStore.java @@ -873,7 +873,7 @@ public final class MediaStore { */ public interface MediaColumns extends BaseColumns { /** - * Path to the media item on disk. + * Absolute filesystem path to the media item on disk. * <p> * Note that apps may not have filesystem permissions to directly access * this path. Instead of trying to open this path directly, apps should @@ -920,6 +920,10 @@ public final class MediaStore { /** * The display name of the media item. + * <p> + * For example, an item stored at + * {@code /storage/0000-0000/DCIM/Vacation/IMG1024.JPG} would have a + * display name of {@code IMG1024.JPG}. */ @Column(Cursor.FIELD_TYPE_STRING) public static final String DISPLAY_NAME = "_display_name"; @@ -985,7 +989,8 @@ public final class MediaStore { /** * Flag indicating if a media item is pending, and still being inserted - * by its owner. + * by its owner. While this flag is set, only the owner of the item can + * open the underlying file; requests from other apps will be rejected. * * @see MediaStore#setIncludePending(Uri) */ @@ -1033,17 +1038,53 @@ public final class MediaStore { public static final String OWNER_PACKAGE_NAME = "owner_package_name"; /** + * Relative path of this media item within the storage device where it + * is persisted. For example, an item stored at + * {@code /storage/0000-0000/DCIM/Vacation/IMG1024.JPG} would have a + * path of {@code DCIM/Vacation}. + * <p> + * This value should only be used for organizational purposes, and you + * should not attempt to construct or access a raw filesystem path using + * this value. If you need to open a media item, use an API like + * {@link ContentResolver#openFileDescriptor(Uri, String)}. + * <p> + * When this value is set to {@code NULL} during an + * {@link ContentResolver#insert} operation, the newly created item will + * be placed in a relevant default location based on the type of media + * being inserted. For example, a {@code image/jpeg} item will be placed + * under {@link Environment#DIRECTORY_PICTURES}. + * <p> + * You can modify this column during an {@link ContentResolver#update} + * call, which will move the underlying file on disk. + * <p> + * In both cases above, content must be placed under a top-level + * directory that is relevant to the media type. For example, attempting + * to place a {@code audio/mpeg} file under + * {@link Environment#DIRECTORY_PICTURES} will be rejected. + */ + @Column(Cursor.FIELD_TYPE_STRING) + public static final String RELATIVE_PATH = "relative_path"; + + /** * The primary directory name this media exists under. The value may be * {@code NULL} if the media doesn't have a primary directory name. + * + * @removed + * @deprecated Replaced by {@link #RELATIVE_PATH}. */ @Column(Cursor.FIELD_TYPE_STRING) + @Deprecated public static final String PRIMARY_DIRECTORY = "primary_directory"; /** * The secondary directory name this media exists under. The value may * be {@code NULL} if the media doesn't have a secondary directory name. + * + * @removed + * @deprecated Replaced by {@link #RELATIVE_PATH}. */ @Column(Cursor.FIELD_TYPE_STRING) + @Deprecated public static final String SECONDARY_DIRECTORY = "secondary_directory"; /** @@ -3344,6 +3385,10 @@ public final class MediaStore { * substantial changes, and that data should be rescanned. * <p> * No other assumptions should be made about the meaning of the version. + * + * @param volumeName specific volume to obtain an opaque version string for. + * Must be one of the values returned from + * {@link #getAllVolumeNames(Context)}. */ public static @NonNull String getVersion(@NonNull Context context, @NonNull String volumeName) { final ContentResolver resolver = context.getContentResolver(); diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 63235a1c17e7..d4908caea9ed 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -1261,6 +1261,25 @@ public final class Settings { = "android.settings.NOTIFICATION_POLICY_ACCESS_SETTINGS"; /** + * Activity Action: Show do not disturb setting page for app. + * <p> + * Users can grant and deny access to Do Not Disturb configuration for an app from here. + * See {@link android.app.NotificationManager#isNotificationPolicyAccessGranted()} for more + * details. + * <p> + * Input: Intent's data URI set with an application name, using the + * "package" schema (like "package:com.my.app"). + * <p> + * Output: Nothing. + * + * @hide + */ + @SystemApi + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_NOTIFICATION_POLICY_ACCESS_DETAIL_SETTINGS = + "android.settings.NOTIFICATION_POLICY_ACCESS_DETAIL_SETTINGS"; + + /** * @hide */ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) @@ -5613,6 +5632,17 @@ public final class Settings { private static final Validator ODI_CAPTIONS_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR; /** + * Setting to indicate that on device captions cannot be shown because the app + * which is currently playing media had opted out. + * + * @hide + */ + @SystemApi + public static final String ODI_CAPTIONS_OPTED_OUT = "odi_captions_opted_out"; + + private static final Validator ODI_CAPTIONS_OPTED_OUT_VALIDATOR = BOOLEAN_VALIDATOR; + + /** * On Android 8.0 (API level 26) and higher versions of the platform, * a 64-bit number (expressed as a hexadecimal string), unique to * each combination of app-signing key, user, and device. @@ -8576,38 +8606,6 @@ public final class Settings { "packages_to_clear_data_before_full_restore"; /** - * Indicates the location state should be maintained after sensor privacy is disabled. - * @hide - */ - public static final String MAINTAIN_LOCATION_AFTER_SP_DISABLED = "0"; - - /** - * Indicates location should be reenabled after sensor privacy is disabled. - * @hide - */ - public static final String REENABLE_LOCATION_AFTER_SP_DISABLED = "1"; - - /** - * Indicates the state of airplane mode should be maintained after sensor privacy is - * disabled. - * @hide - */ - public static final String MAINTAIN_AIRPLANE_MODE_AFTER_SP_DISABLED = "0"; - - /** - * Indicates airplane mode should be disabled after sensor privacy is disabled. - * @hide - */ - public static final String DISABLE_AIRPLANE_MODE_AFTER_SP_DISABLED = "1"; - - /** - * The state of all sensors managed by SensorPrivacyService when sensor privacy is enabled. - * @hide - */ - public static final String SENSOR_PRIVACY_SENSOR_STATE = - "sensor_privacy_sensor_state"; - - /** * Setting to determine whether to use the new notification priority handling features. * @hide */ @@ -8979,6 +8977,7 @@ public final class Settings { VALIDATORS.put(SILENCE_CALL_GESTURE_COUNT, SILENCE_GESTURE_COUNT_VALIDATOR); VALIDATORS.put(SILENCE_NOTIFICATION_GESTURE_COUNT, SILENCE_GESTURE_COUNT_VALIDATOR); VALIDATORS.put(ODI_CAPTIONS_ENABLED, ODI_CAPTIONS_ENABLED_VALIDATOR); + VALIDATORS.put(ODI_CAPTIONS_OPTED_OUT, ODI_CAPTIONS_OPTED_OUT_VALIDATOR); } /** diff --git a/core/java/android/security/keymaster/KeymasterBlobArgument.java b/core/java/android/security/keymaster/KeymasterBlobArgument.java index 541d33ef614f..fc562bd2174e 100644 --- a/core/java/android/security/keymaster/KeymasterBlobArgument.java +++ b/core/java/android/security/keymaster/KeymasterBlobArgument.java @@ -16,14 +16,17 @@ package android.security.keymaster; +import android.annotation.UnsupportedAppUsage; import android.os.Parcel; /** * @hide */ class KeymasterBlobArgument extends KeymasterArgument { + @UnsupportedAppUsage public final byte[] blob; + @UnsupportedAppUsage public KeymasterBlobArgument(int tag, byte[] blob) { super(tag); switch (KeymasterDefs.getTagType(tag)) { @@ -36,6 +39,7 @@ class KeymasterBlobArgument extends KeymasterArgument { this.blob = blob; } + @UnsupportedAppUsage public KeymasterBlobArgument(int tag, Parcel in) { super(tag); blob = in.createByteArray(); diff --git a/core/java/android/security/keymaster/KeymasterBooleanArgument.java b/core/java/android/security/keymaster/KeymasterBooleanArgument.java index 67b3281a8a64..4286aa0d4ae3 100644 --- a/core/java/android/security/keymaster/KeymasterBooleanArgument.java +++ b/core/java/android/security/keymaster/KeymasterBooleanArgument.java @@ -16,6 +16,7 @@ package android.security.keymaster; +import android.annotation.UnsupportedAppUsage; import android.os.Parcel; /** @@ -36,6 +37,7 @@ class KeymasterBooleanArgument extends KeymasterArgument { } } + @UnsupportedAppUsage public KeymasterBooleanArgument(int tag, Parcel in) { super(tag); } diff --git a/core/java/android/security/keymaster/KeymasterDateArgument.java b/core/java/android/security/keymaster/KeymasterDateArgument.java index aa15e34e3e86..3e04c1543117 100644 --- a/core/java/android/security/keymaster/KeymasterDateArgument.java +++ b/core/java/android/security/keymaster/KeymasterDateArgument.java @@ -16,6 +16,7 @@ package android.security.keymaster; +import android.annotation.UnsupportedAppUsage; import android.os.Parcel; import java.util.Date; @@ -36,6 +37,7 @@ class KeymasterDateArgument extends KeymasterArgument { this.date = date; } + @UnsupportedAppUsage public KeymasterDateArgument(int tag, Parcel in) { super(tag); date = new Date(in.readLong()); diff --git a/core/java/android/security/keymaster/KeymasterIntArgument.java b/core/java/android/security/keymaster/KeymasterIntArgument.java index 578d2498612d..4aadce458395 100644 --- a/core/java/android/security/keymaster/KeymasterIntArgument.java +++ b/core/java/android/security/keymaster/KeymasterIntArgument.java @@ -16,14 +16,17 @@ package android.security.keymaster; +import android.annotation.UnsupportedAppUsage; import android.os.Parcel; /** * @hide */ class KeymasterIntArgument extends KeymasterArgument { + @UnsupportedAppUsage public final int value; + @UnsupportedAppUsage public KeymasterIntArgument(int tag, int value) { super(tag); switch (KeymasterDefs.getTagType(tag)) { @@ -38,6 +41,7 @@ class KeymasterIntArgument extends KeymasterArgument { this.value = value; } + @UnsupportedAppUsage public KeymasterIntArgument(int tag, Parcel in) { super(tag); value = in.readInt(); diff --git a/core/java/android/security/keymaster/KeymasterLongArgument.java b/core/java/android/security/keymaster/KeymasterLongArgument.java index d3d40ba0cb9d..bc2255e22a69 100644 --- a/core/java/android/security/keymaster/KeymasterLongArgument.java +++ b/core/java/android/security/keymaster/KeymasterLongArgument.java @@ -16,14 +16,17 @@ package android.security.keymaster; +import android.annotation.UnsupportedAppUsage; import android.os.Parcel; /** * @hide */ class KeymasterLongArgument extends KeymasterArgument { + @UnsupportedAppUsage public final long value; + @UnsupportedAppUsage public KeymasterLongArgument(int tag, long value) { super(tag); switch (KeymasterDefs.getTagType(tag)) { @@ -36,6 +39,7 @@ class KeymasterLongArgument extends KeymasterArgument { this.value = value; } + @UnsupportedAppUsage public KeymasterLongArgument(int tag, Parcel in) { super(tag); value = in.readLong(); diff --git a/core/java/android/service/appprediction/AppPredictionService.java b/core/java/android/service/appprediction/AppPredictionService.java index ff13e0361ab8..c1323bc8fd4c 100644 --- a/core/java/android/service/appprediction/AppPredictionService.java +++ b/core/java/android/service/appprediction/AppPredictionService.java @@ -86,11 +86,12 @@ public abstract class AppPredictionService extends Service { } @Override - public void notifyLocationShown(AppPredictionSessionId sessionId, String launchLocation, - ParceledListSlice targetIds) { + public void notifyLaunchLocationShown(AppPredictionSessionId sessionId, + String launchLocation, ParceledListSlice targetIds) { mHandler.sendMessage( - obtainMessage(AppPredictionService::onLocationShown, AppPredictionService.this, - sessionId, launchLocation, targetIds.getList())); + obtainMessage(AppPredictionService::onLaunchLocationShown, + AppPredictionService.this, sessionId, launchLocation, + targetIds.getList())); } @Override @@ -158,7 +159,7 @@ public abstract class AppPredictionService extends Service { * Called by a client app to indication a particular location has been shown to the user. */ @MainThread - public abstract void onLocationShown(@NonNull AppPredictionSessionId sessionId, + public abstract void onLaunchLocationShown(@NonNull AppPredictionSessionId sessionId, @NonNull String launchLocation, @NonNull List<AppTargetId> targetIds); private void doCreatePredictionSession(@NonNull AppPredictionContext context, diff --git a/core/java/android/service/appprediction/IPredictionService.aidl b/core/java/android/service/appprediction/IPredictionService.aidl index 3a6d1666f4b9..0f3df8561743 100644 --- a/core/java/android/service/appprediction/IPredictionService.aidl +++ b/core/java/android/service/appprediction/IPredictionService.aidl @@ -35,7 +35,7 @@ oneway interface IPredictionService { void notifyAppTargetEvent(in AppPredictionSessionId sessionId, in AppTargetEvent event); - void notifyLocationShown(in AppPredictionSessionId sessionId, in String launchLocation, + void notifyLaunchLocationShown(in AppPredictionSessionId sessionId, in String launchLocation, in ParceledListSlice targetIds); void sortAppTargets(in AppPredictionSessionId sessionId, in ParceledListSlice targets, diff --git a/core/java/android/service/attention/AttentionService.java b/core/java/android/service/attention/AttentionService.java index 32f4ea9a23ed..84f440f2de82 100644 --- a/core/java/android/service/attention/AttentionService.java +++ b/core/java/android/service/attention/AttentionService.java @@ -21,11 +21,13 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.app.Service; +import android.attention.AttentionManagerInternal; import android.content.Intent; import android.os.IBinder; import android.os.RemoteException; import com.android.internal.util.Preconditions; +import com.android.server.LocalServices; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -65,14 +67,20 @@ public abstract class AttentionService extends Service { /** Attention is present. */ public static final int ATTENTION_SUCCESS_PRESENT = 1; + /** Unknown reasons for failing to determine the attention. */ + public static final int ATTENTION_FAILURE_UNKNOWN = 2; + + /** Request has been cancelled. */ + public static final int ATTENTION_FAILURE_CANCELLED = 3; + /** Preempted by other client. */ - public static final int ATTENTION_FAILURE_PREEMPTED = 2; + public static final int ATTENTION_FAILURE_PREEMPTED = 4; /** Request timed out. */ - public static final int ATTENTION_FAILURE_TIMED_OUT = 3; + public static final int ATTENTION_FAILURE_TIMED_OUT = 5; - /** Unknown reasons for failing to determine the attention. */ - public static final int ATTENTION_FAILURE_UNKNOWN = 4; + /** Camera permission is not granted. */ + public static final int ATTENTION_FAILURE_CAMERA_PERMISSION_ABSENT = 6; /** * Result codes for when attention check was successful. @@ -90,8 +98,9 @@ public abstract class AttentionService extends Service { * * @hide */ - @IntDef(prefix = {"ATTENTION_FAILURE_"}, value = {ATTENTION_FAILURE_PREEMPTED, - ATTENTION_FAILURE_TIMED_OUT, ATTENTION_FAILURE_UNKNOWN}) + @IntDef(prefix = {"ATTENTION_FAILURE_"}, value = {ATTENTION_FAILURE_UNKNOWN, + ATTENTION_FAILURE_CANCELLED, ATTENTION_FAILURE_PREEMPTED, ATTENTION_FAILURE_TIMED_OUT, + ATTENTION_FAILURE_CAMERA_PERMISSION_ABSENT}) @Retention(RetentionPolicy.SOURCE) public @interface AttentionFailureCodes { } @@ -122,6 +131,19 @@ public abstract class AttentionService extends Service { } /** + * Disables the dependants. + * + * Example: called if the service does not have sufficient permissions to perform the task. + */ + public final void disableSelf() { + AttentionManagerInternal attentionManager = LocalServices.getService( + AttentionManagerInternal.class); + if (attentionManager != null) { + attentionManager.disableSelf(); + } + } + + /** * Checks the user attention and calls into the provided callback. * * @param requestCode an identifier that could be used to cancel the request @@ -132,7 +154,6 @@ public abstract class AttentionService extends Service { /** Cancels the attention check for a given request code. */ public abstract void onCancelAttentionCheck(int requestCode); - /** Callbacks for AttentionService results. */ public static final class AttentionCallback { private final IAttentionCallback mCallback; diff --git a/core/java/android/service/dreams/IDreamManager.aidl b/core/java/android/service/dreams/IDreamManager.aidl index b84e6c9bc962..d3f2a70029f7 100644 --- a/core/java/android/service/dreams/IDreamManager.aidl +++ b/core/java/android/service/dreams/IDreamManager.aidl @@ -23,12 +23,16 @@ import android.os.IBinder; /** @hide */ interface IDreamManager { + @UnsupportedAppUsage void dream(); + @UnsupportedAppUsage void awaken(); + @UnsupportedAppUsage void setDreamComponents(in ComponentName[] componentNames); ComponentName[] getDreamComponents(); ComponentName getDefaultDreamComponent(); void testDream(in ComponentName componentName); + @UnsupportedAppUsage boolean isDreaming(); void finishSelf(in IBinder token, boolean immediate); void startDozing(in IBinder token, int screenState, int screenBrightness); diff --git a/core/java/android/service/notification/Adjustment.java b/core/java/android/service/notification/Adjustment.java index 1cdb62fe8934..8ba9a8357c65 100644 --- a/core/java/android/service/notification/Adjustment.java +++ b/core/java/android/service/notification/Adjustment.java @@ -16,6 +16,7 @@ package android.service.notification; import android.annotation.NonNull; +import android.annotation.StringDef; import android.annotation.SystemApi; import android.app.Notification; import android.os.Bundle; @@ -23,6 +24,9 @@ import android.os.Parcel; import android.os.Parcelable; import android.os.UserHandle; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + /** * Ranking updates from the Assistant. * @@ -43,6 +47,14 @@ public final class Adjustment implements Parcelable { private final Bundle mSignals; private final int mUser; + /** @hide */ + @StringDef (prefix = { "KEY_" }, value = { + KEY_CONTEXTUAL_ACTIONS, KEY_GROUP_KEY, KEY_IMPORTANCE, KEY_PEOPLE, KEY_SNOOZE_CRITERIA, + KEY_TEXT_REPLIES, KEY_USER_SENTIMENT + }) + @Retention(RetentionPolicy.SOURCE) + public @interface Keys {} + /** * Data type: ArrayList of {@code String}, where each is a representation of a * {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI}. diff --git a/core/java/android/service/notification/NotificationAssistantService.java b/core/java/android/service/notification/NotificationAssistantService.java index 780b576d71f3..a1932b8861b0 100644 --- a/core/java/android/service/notification/NotificationAssistantService.java +++ b/core/java/android/service/notification/NotificationAssistantService.java @@ -25,6 +25,7 @@ import android.annotation.SdkConstant; import android.annotation.SystemApi; import android.app.Notification; import android.app.NotificationChannel; +import android.app.NotificationManager; import android.app.admin.DevicePolicyManager; import android.content.ComponentName; import android.content.Context; @@ -141,7 +142,6 @@ public abstract class NotificationAssistantService extends NotificationListenerS return onNotificationEnqueued(sbn); } - /** * Implement this method to learn when notifications are removed, how they were interacted with * before removal, and why they were removed. @@ -216,6 +216,15 @@ public abstract class NotificationAssistantService extends NotificationListenerS } /** + * Implement this to know when a user has changed which features of + * their notifications the assistant can modify. + * <p> Query {@link NotificationManager#getAllowedAssistantCapabilities()} to see what + * {@link Adjustment adjustments} you are currently allowed to make.</p> + */ + public void onCapabilitiesChanged() { + } + + /** * Updates a notification. N.B. this won’t cause * an existing notification to alert, but might allow a future update to * this notification to alert. diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index c042a8c8ae1c..e1762dffeef5 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -320,7 +320,7 @@ public abstract class WallpaperService extends Service { public void resized(Rect frame, Rect overscanInsets, Rect contentInsets, Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw, MergedConfiguration mergedConfiguration, Rect backDropRect, boolean forceLayout, - boolean alwaysConsumeNavBar, int displayId, + boolean alwaysConsumeSystemBars, int displayId, DisplayCutout.ParcelableWrapper displayCutout) { Message msg = mCaller.obtainMessageIO(MSG_WINDOW_RESIZED, reportDraw ? 1 : 0, outsets); diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java index de10ffb80bee..04bb0e3b50e2 100644 --- a/core/java/android/util/FeatureFlagUtils.java +++ b/core/java/android/util/FeatureFlagUtils.java @@ -52,7 +52,7 @@ public class FeatureFlagUtils { DEFAULT_FLAGS.put("settings_slice_injection", "true"); DEFAULT_FLAGS.put("settings_systemui_theme", "true"); DEFAULT_FLAGS.put("settings_mainline_module", "true"); - DEFAULT_FLAGS.put("settings_dynamic_android", "false"); + DEFAULT_FLAGS.put("settings_dynamic_system", "false"); DEFAULT_FLAGS.put(SEAMLESS_TRANSFER, "false"); DEFAULT_FLAGS.put(HEARING_AID_SETTINGS, "false"); DEFAULT_FLAGS.put(SAFETY_HUB, "false"); diff --git a/core/java/android/util/XmlPullAttributes.java b/core/java/android/util/XmlPullAttributes.java index cb35eb5c12a3..32fe16fcb2b1 100644 --- a/core/java/android/util/XmlPullAttributes.java +++ b/core/java/android/util/XmlPullAttributes.java @@ -18,6 +18,7 @@ package android.util; import org.xmlpull.v1.XmlPullParser; +import android.annotation.UnsupportedAppUsage; import android.util.AttributeSet; import com.android.internal.util.XmlUtils; @@ -26,6 +27,7 @@ import com.android.internal.util.XmlUtils; * Provides an implementation of AttributeSet on top of an XmlPullParser. */ class XmlPullAttributes implements AttributeSet { + @UnsupportedAppUsage public XmlPullAttributes(XmlPullParser parser) { mParser = parser; } @@ -147,5 +149,6 @@ class XmlPullAttributes implements AttributeSet { return getAttributeResourceValue(null, "style", 0); } + @UnsupportedAppUsage /*package*/ XmlPullParser mParser; } diff --git a/core/java/android/view/IRecentsAnimationController.aidl b/core/java/android/view/IRecentsAnimationController.aidl index b1f934a44cdb..597b34bf8554 100644 --- a/core/java/android/view/IRecentsAnimationController.aidl +++ b/core/java/android/view/IRecentsAnimationController.aidl @@ -73,4 +73,33 @@ interface IRecentsAnimationController { * Hides the current input method if one is showing. */ void hideCurrentInputMethod(); + + /** + * Set a state for controller whether would like to cancel recents animations with deferred + * task screenshot presentation. + * + * When we cancel the recents animation due to a stack order change, we can't just cancel it + * immediately as it would lead to a flicker in Launcher if we just remove the task from the + * leash. Instead we screenshot the previous task and replace the child of the leash with the + * screenshot, so that Launcher can still control the leash lifecycle & make the next app + * transition animate smoothly without flickering. + * + * @param screenshot When set {@code true}, means recents animation will be canceled when the + * next app launch. System will take previous task's screenshot when the next + * app transition starting, and skip previous task's animation. + * Set {@code false} means will not take screenshot & skip animation + * for previous task. + * + * @see #cleanupScreenshot() + * @see IRecentsAnimationRunner#onCancelled + */ + void setCancelWithDeferredScreenshot(boolean screenshot); + + /** + * Clean up the screenshot of previous task which was created during recents animation that + * was cancelled by a stack order change. + * + * @see {@link IRecentsAnimationRunner#onAnimationCanceled} + */ + void cleanupScreenshot(); } diff --git a/core/java/android/view/IRecentsAnimationRunner.aidl b/core/java/android/view/IRecentsAnimationRunner.aidl index 6e382f416b62..9c652a8d990b 100644 --- a/core/java/android/view/IRecentsAnimationRunner.aidl +++ b/core/java/android/view/IRecentsAnimationRunner.aidl @@ -32,9 +32,17 @@ oneway interface IRecentsAnimationRunner { * Called when the system needs to cancel the current animation. This can be due to the * wallpaper not drawing in time, or the handler not finishing the animation within a predefined * amount of time. + * + * @param deferredWithScreenshot If set to {@code true}, the contents of the task will be + * replaced with a screenshot, such that the runner's leash is + * still active. As soon as the runner doesn't need the leash + * anymore, it can call + * {@link IRecentsAnimationController#cleanupScreenshot). + * + * @see {@link RecentsAnimationController#cleanupScreenshot} */ @UnsupportedAppUsage - void onAnimationCanceled() = 1; + void onAnimationCanceled(boolean deferredWithScreenshot) = 1; /** * Called when the system is ready for the handler to start animating all the visible tasks. diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl index c06a1fe0a257..699e795be980 100644 --- a/core/java/android/view/IWindow.aidl +++ b/core/java/android/view/IWindow.aidl @@ -53,7 +53,7 @@ oneway interface IWindow { void resized(in Rect frame, in Rect overscanInsets, in Rect contentInsets, in Rect visibleInsets, in Rect stableInsets, in Rect outsets, boolean reportDraw, in MergedConfiguration newMergedConfiguration, in Rect backDropFrame, - boolean forceLayout, boolean alwaysConsumeNavBar, int displayId, + boolean forceLayout, boolean alwaysConsumeSystemBars, int displayId, in DisplayCutout.ParcelableWrapper displayCutout); /** diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index b91b93f7e09c..6c37319c6303 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -304,6 +304,16 @@ interface IWindowManager oneway void statusBarVisibilityChanged(int displayId, int visibility); /** + * When set to {@code true} the system bars will always be shown. This is true even if an app + * requests to be fullscreen by setting the system ui visibility flags. The + * functionality was added for the automotive case as a way to guarantee required content stays + * on screen at all times. + * + * @hide + */ + oneway void setForceShowSystemBars(boolean show); + + /** * Called by System UI to notify of changes to the visibility of Recents. */ oneway void setRecentsVisibility(boolean visible); diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java index 08f2e8d87352..bf16e3dedd49 100644 --- a/core/java/android/view/InsetsController.java +++ b/core/java/android/view/InsetsController.java @@ -134,7 +134,7 @@ public class InsetsController implements WindowInsetsController { } WindowInsets insets = state.calculateInsets(mFrame, mLastInsets.isRound(), - mLastInsets.shouldAlwaysConsumeNavBar(), mLastInsets.getDisplayCutout(), + mLastInsets.shouldAlwaysConsumeSystemBars(), mLastInsets.getDisplayCutout(), mLastLegacyContentInsets, mLastLegacyStableInsets, mLastLegacySoftInputMode, null /* typeSideMap */); mViewRoot.mView.dispatchWindowInsetsAnimationProgress(insets); @@ -177,12 +177,12 @@ public class InsetsController implements WindowInsetsController { */ @VisibleForTesting public WindowInsets calculateInsets(boolean isScreenRound, - boolean alwaysConsumeNavBar, DisplayCutout cutout, Rect legacyContentInsets, + boolean alwaysConsumeSystemBars, DisplayCutout cutout, Rect legacyContentInsets, Rect legacyStableInsets, int legacySoftInputMode) { mLastLegacyContentInsets.set(legacyContentInsets); mLastLegacyStableInsets.set(legacyStableInsets); mLastLegacySoftInputMode = legacySoftInputMode; - mLastInsets = mState.calculateInsets(mFrame, isScreenRound, alwaysConsumeNavBar, cutout, + mLastInsets = mState.calculateInsets(mFrame, isScreenRound, alwaysConsumeSystemBars, cutout, legacyContentInsets, legacyStableInsets, legacySoftInputMode, null /* typeSideMap */); return mLastInsets; diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java index 6129b38104af..13b0cc038fce 100644 --- a/core/java/android/view/InsetsState.java +++ b/core/java/android/view/InsetsState.java @@ -17,9 +17,6 @@ package android.view; import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL; -import static android.view.ViewRootImpl.NEW_INSETS_MODE_IME; -import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE; -import static android.view.WindowInsets.Type.IME; import static android.view.WindowInsets.Type.SIZE; import static android.view.WindowInsets.Type.indexOf; @@ -31,7 +28,6 @@ import android.os.Parcel; import android.os.Parcelable; import android.util.ArrayMap; import android.util.ArraySet; -import android.util.SparseArray; import android.util.SparseIntArray; import android.view.WindowInsets.Type; import android.view.WindowInsets.Type.InsetType; @@ -40,7 +36,6 @@ import android.view.WindowManager.LayoutParams; import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; -import java.util.ArrayList; import java.util.Objects; /** @@ -130,7 +125,7 @@ public class InsetsState implements Parcelable { * @return The calculated insets. */ public WindowInsets calculateInsets(Rect frame, boolean isScreenRound, - boolean alwaysConsumeNavBar, DisplayCutout cutout, + boolean alwaysConsumeSystemBars, DisplayCutout cutout, @Nullable Rect legacyContentInsets, @Nullable Rect legacyStableInsets, int legacySoftInputMode, @Nullable @InsetSide SparseIntArray typeSideMap) { Insets[] typeInsetsMap = new Insets[Type.SIZE]; @@ -180,7 +175,7 @@ public class InsetsState implements Parcelable { } } return new WindowInsets(typeInsetsMap, typeMaxInsetsMap, typeVisibilityMap, isScreenRound, - alwaysConsumeNavBar, cutout); + alwaysConsumeSystemBars, cutout); } private void processSource(InsetsSource source, Rect relativeFrame, boolean ignoreVisibility, diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 75067d3668b3..2357db46771a 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -28200,11 +28200,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, final Rect mOutsets = new Rect(); /** - * In multi-window we force show the navigation bar. Because we don't want that the surface - * size changes in this mode, we instead have a flag whether the navigation bar size should - * always be consumed, so the app is treated like there is no virtual navigation bar at all. + * In multi-window we force show the system bars. Because we don't want that the surface + * size changes in this mode, we instead have a flag whether the system bars sizes should + * always be consumed, so the app is treated like there are no virtual system bars at all. */ - boolean mAlwaysConsumeNavBar; + boolean mAlwaysConsumeSystemBars; /** * The internal insets given by this window. This value is diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 6d04cd3187ef..2880e7f13545 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -512,7 +512,7 @@ public final class ViewRootImpl implements ViewParent, final Rect mPendingBackDropFrame = new Rect(); final DisplayCutout.ParcelableWrapper mPendingDisplayCutout = new DisplayCutout.ParcelableWrapper(DisplayCutout.NO_CUTOUT); - boolean mPendingAlwaysConsumeNavBar; + boolean mPendingAlwaysConsumeSystemBars; private InsetsState mTempInsets = new InsetsState(); final ViewTreeObserver.InternalInsetsInfo mLastGivenInsets = new ViewTreeObserver.InternalInsetsInfo(); @@ -921,9 +921,9 @@ public final class ViewRootImpl implements ViewParent, mPendingStableInsets.set(mAttachInfo.mStableInsets); mPendingDisplayCutout.set(mAttachInfo.mDisplayCutout); mPendingVisibleInsets.set(0, 0, 0, 0); - mAttachInfo.mAlwaysConsumeNavBar = - (res & WindowManagerGlobal.ADD_FLAG_ALWAYS_CONSUME_NAV_BAR) != 0; - mPendingAlwaysConsumeNavBar = mAttachInfo.mAlwaysConsumeNavBar; + mAttachInfo.mAlwaysConsumeSystemBars = + (res & WindowManagerGlobal.ADD_FLAG_ALWAYS_CONSUME_SYSTEM_BARS) != 0; + mPendingAlwaysConsumeSystemBars = mAttachInfo.mAlwaysConsumeSystemBars; mInsetsController.onStateChanged(mTempInsets); if (DEBUG_LAYOUT) Log.v(mTag, "Added window " + mWindow); if (res < WindowManagerGlobal.ADD_OKAY) { @@ -1918,12 +1918,12 @@ public final class ViewRootImpl implements ViewParent, if (sNewInsetsMode != NEW_INSETS_MODE_NONE) { mLastWindowInsets = mInsetsController.calculateInsets( mContext.getResources().getConfiguration().isScreenRound(), - mAttachInfo.mAlwaysConsumeNavBar, displayCutout, + mAttachInfo.mAlwaysConsumeSystemBars, displayCutout, contentInsets, stableInsets, mWindowAttributes.softInputMode); } else { mLastWindowInsets = new WindowInsets(contentInsets, stableInsets, mContext.getResources().getConfiguration().isScreenRound(), - mAttachInfo.mAlwaysConsumeNavBar, displayCutout); + mAttachInfo.mAlwaysConsumeSystemBars, displayCutout); } } return mLastWindowInsets; @@ -2126,7 +2126,7 @@ public final class ViewRootImpl implements ViewParent, if (!mPendingOutsets.equals(mAttachInfo.mOutsets)) { insetsChanged = true; } - if (mPendingAlwaysConsumeNavBar != mAttachInfo.mAlwaysConsumeNavBar) { + if (mPendingAlwaysConsumeSystemBars != mAttachInfo.mAlwaysConsumeSystemBars) { insetsChanged = true; } if (lp.width == ViewGroup.LayoutParams.WRAP_CONTENT @@ -2326,8 +2326,8 @@ public final class ViewRootImpl implements ViewParent, final boolean surfaceSizeChanged = (relayoutResult & WindowManagerGlobal.RELAYOUT_RES_SURFACE_RESIZED) != 0; surfaceChanged |= surfaceSizeChanged; - final boolean alwaysConsumeNavBarChanged = - mPendingAlwaysConsumeNavBar != mAttachInfo.mAlwaysConsumeNavBar; + final boolean alwaysConsumeSystemBarsChanged = + mPendingAlwaysConsumeSystemBars != mAttachInfo.mAlwaysConsumeSystemBars; final boolean colorModeChanged = hasColorModeChanged(lp.getColorMode()); if (contentInsetsChanged) { mAttachInfo.mContentInsets.set(mPendingContentInsets); @@ -2356,8 +2356,8 @@ public final class ViewRootImpl implements ViewParent, // Need to relayout with content insets. contentInsetsChanged = true; } - if (alwaysConsumeNavBarChanged) { - mAttachInfo.mAlwaysConsumeNavBar = mPendingAlwaysConsumeNavBar; + if (alwaysConsumeSystemBarsChanged) { + mAttachInfo.mAlwaysConsumeSystemBars = mPendingAlwaysConsumeSystemBars; contentInsetsChanged = true; } if (contentInsetsChanged || mLastSystemUiVisibility != @@ -4633,7 +4633,7 @@ public final class ViewRootImpl implements ViewParent, mPendingOutsets.set((Rect) args.arg7); mPendingBackDropFrame.set((Rect) args.arg8); mForceNextWindowRelayout = args.argi1 != 0; - mPendingAlwaysConsumeNavBar = args.argi2 != 0; + mPendingAlwaysConsumeSystemBars = args.argi2 != 0; args.recycle(); @@ -7084,8 +7084,8 @@ public final class ViewRootImpl implements ViewParent, destroySurface(); } - mPendingAlwaysConsumeNavBar = - (relayoutResult & WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_NAV_BAR) != 0; + mPendingAlwaysConsumeSystemBars = + (relayoutResult & WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_SYSTEM_BARS) != 0; if (restore) { params.restore(); @@ -7374,7 +7374,7 @@ public final class ViewRootImpl implements ViewParent, private void dispatchResized(Rect frame, Rect overscanInsets, Rect contentInsets, Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw, MergedConfiguration mergedConfiguration, Rect backDropFrame, boolean forceLayout, - boolean alwaysConsumeNavBar, int displayId, + boolean alwaysConsumeSystemBars, int displayId, DisplayCutout.ParcelableWrapper displayCutout) { if (DEBUG_LAYOUT) Log.v(mTag, "Resizing " + this + ": frame=" + frame.toShortString() + " contentInsets=" + contentInsets.toShortString() @@ -7414,7 +7414,7 @@ public final class ViewRootImpl implements ViewParent, args.arg8 = sameProcessCall ? new Rect(backDropFrame) : backDropFrame; args.arg9 = displayCutout.get(); // DisplayCutout is immutable. args.argi1 = forceLayout ? 1 : 0; - args.argi2 = alwaysConsumeNavBar ? 1 : 0; + args.argi2 = alwaysConsumeSystemBars ? 1 : 0; args.argi3 = displayId; msg.obj = args; mHandler.sendMessage(msg); @@ -8498,13 +8498,14 @@ public final class ViewRootImpl implements ViewParent, public void resized(Rect frame, Rect overscanInsets, Rect contentInsets, Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw, MergedConfiguration mergedConfiguration, Rect backDropFrame, boolean forceLayout, - boolean alwaysConsumeNavBar, int displayId, + boolean alwaysConsumeSystemBars, int displayId, DisplayCutout.ParcelableWrapper displayCutout) { final ViewRootImpl viewAncestor = mViewAncestor.get(); if (viewAncestor != null) { viewAncestor.dispatchResized(frame, overscanInsets, contentInsets, visibleInsets, stableInsets, outsets, reportDraw, mergedConfiguration, - backDropFrame, forceLayout, alwaysConsumeNavBar, displayId, displayCutout); + backDropFrame, forceLayout, alwaysConsumeSystemBars, displayId, + displayCutout); } } diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java index aac0e34de0da..ffa769a424a9 100644 --- a/core/java/android/view/WindowInsets.java +++ b/core/java/android/view/WindowInsets.java @@ -83,7 +83,7 @@ public final class WindowInsets { * changes in this mode, we instead have a flag whether the navigation bar size should always * be consumed, so the app is treated like there is no virtual navigation bar at all. */ - private final boolean mAlwaysConsumeNavBar; + private final boolean mAlwaysConsumeSystemBars; private final boolean mSystemWindowInsetsConsumed; private final boolean mStableInsetsConsumed; @@ -111,10 +111,10 @@ public final class WindowInsets { * @deprecated Use {@link WindowInsets(SparseArray, SparseArray, boolean, boolean, DisplayCutout)} */ public WindowInsets(Rect systemWindowInsetsRect, Rect stableInsetsRect, - boolean isRound, boolean alwaysConsumeNavBar, DisplayCutout displayCutout) { + boolean isRound, boolean alwaysConsumeSystemBars, DisplayCutout displayCutout) { this(createCompatTypeMap(systemWindowInsetsRect), createCompatTypeMap(stableInsetsRect), createCompatVisibilityMap(createCompatTypeMap(systemWindowInsetsRect)), - isRound, alwaysConsumeNavBar, displayCutout); + isRound, alwaysConsumeSystemBars, displayCutout); } /** @@ -133,7 +133,7 @@ public final class WindowInsets { @Nullable Insets[] typeMaxInsetsMap, boolean[] typeVisibilityMap, boolean isRound, - boolean alwaysConsumeNavBar, DisplayCutout displayCutout) { + boolean alwaysConsumeSystemBars, DisplayCutout displayCutout) { mSystemWindowInsetsConsumed = typeInsetsMap == null; mTypeInsetsMap = mSystemWindowInsetsConsumed ? new Insets[SIZE] @@ -146,7 +146,7 @@ public final class WindowInsets { mTypeVisibilityMap = typeVisibilityMap; mIsRound = isRound; - mAlwaysConsumeNavBar = alwaysConsumeNavBar; + mAlwaysConsumeSystemBars = alwaysConsumeSystemBars; mDisplayCutoutConsumed = displayCutout == null; mDisplayCutout = (mDisplayCutoutConsumed || displayCutout.isEmpty()) @@ -160,7 +160,7 @@ public final class WindowInsets { */ public WindowInsets(WindowInsets src) { this(src.mTypeInsetsMap, src.mTypeMaxInsetsMap, src.mTypeVisibilityMap, src.mIsRound, - src.mAlwaysConsumeNavBar, displayCutoutCopyConstructorArgument(src)); + src.mAlwaysConsumeSystemBars, displayCutoutCopyConstructorArgument(src)); } private static DisplayCutout displayCutoutCopyConstructorArgument(WindowInsets w) { @@ -443,7 +443,7 @@ public final class WindowInsets { return new WindowInsets(mSystemWindowInsetsConsumed ? null : mTypeInsetsMap, mStableInsetsConsumed ? null : mTypeMaxInsetsMap, mTypeVisibilityMap, - mIsRound, mAlwaysConsumeNavBar, + mIsRound, mAlwaysConsumeSystemBars, null /* displayCutout */); } @@ -489,7 +489,7 @@ public final class WindowInsets { public WindowInsets consumeSystemWindowInsets() { return new WindowInsets(null, mStableInsetsConsumed ? null : mTypeMaxInsetsMap, mTypeVisibilityMap, - mIsRound, mAlwaysConsumeNavBar, + mIsRound, mAlwaysConsumeSystemBars, displayCutoutCopyConstructorArgument(this)); } @@ -729,15 +729,15 @@ public final class WindowInsets { @NonNull public WindowInsets consumeStableInsets() { return new WindowInsets(mSystemWindowInsetsConsumed ? null : mTypeInsetsMap, null, - mTypeVisibilityMap, mIsRound, mAlwaysConsumeNavBar, + mTypeVisibilityMap, mIsRound, mAlwaysConsumeSystemBars, displayCutoutCopyConstructorArgument(this)); } /** * @hide */ - public boolean shouldAlwaysConsumeNavBar() { - return mAlwaysConsumeNavBar; + public boolean shouldAlwaysConsumeSystemBars() { + return mAlwaysConsumeSystemBars; } @Override @@ -809,7 +809,7 @@ public final class WindowInsets { ? null : insetInsets(mTypeMaxInsetsMap, left, top, right, bottom), mTypeVisibilityMap, - mIsRound, mAlwaysConsumeNavBar, + mIsRound, mAlwaysConsumeSystemBars, mDisplayCutoutConsumed ? null : mDisplayCutout == null @@ -824,7 +824,7 @@ public final class WindowInsets { WindowInsets that = (WindowInsets) o; return mIsRound == that.mIsRound - && mAlwaysConsumeNavBar == that.mAlwaysConsumeNavBar + && mAlwaysConsumeSystemBars == that.mAlwaysConsumeSystemBars && mSystemWindowInsetsConsumed == that.mSystemWindowInsetsConsumed && mStableInsetsConsumed == that.mStableInsetsConsumed && mDisplayCutoutConsumed == that.mDisplayCutoutConsumed @@ -837,8 +837,9 @@ public final class WindowInsets { @Override public int hashCode() { return Objects.hash(Arrays.hashCode(mTypeInsetsMap), Arrays.hashCode(mTypeMaxInsetsMap), - Arrays.hashCode(mTypeVisibilityMap), mIsRound, mDisplayCutout, mAlwaysConsumeNavBar, - mSystemWindowInsetsConsumed, mStableInsetsConsumed, mDisplayCutoutConsumed); + Arrays.hashCode(mTypeVisibilityMap), mIsRound, mDisplayCutout, + mAlwaysConsumeSystemBars, mSystemWindowInsetsConsumed, mStableInsetsConsumed, + mDisplayCutoutConsumed); } @@ -900,7 +901,7 @@ public final class WindowInsets { private DisplayCutout mDisplayCutout; private boolean mIsRound; - private boolean mAlwaysConsumeNavBar; + private boolean mAlwaysConsumeSystemBars; /** * Creates a builder where all insets are initially consumed. @@ -924,7 +925,7 @@ public final class WindowInsets { mStableInsetsConsumed = insets.mStableInsetsConsumed; mDisplayCutout = displayCutoutCopyConstructorArgument(insets); mIsRound = insets.mIsRound; - mAlwaysConsumeNavBar = insets.mAlwaysConsumeNavBar; + mAlwaysConsumeSystemBars = insets.mAlwaysConsumeSystemBars; } /** @@ -1119,8 +1120,8 @@ public final class WindowInsets { /** @hide */ @NonNull - public Builder setAlwaysConsumeNavBar(boolean alwaysConsumeNavBar) { - mAlwaysConsumeNavBar = alwaysConsumeNavBar; + public Builder setAlwaysConsumeSystemBars(boolean alwaysConsumeSystemBars) { + mAlwaysConsumeSystemBars = alwaysConsumeSystemBars; return this; } @@ -1133,7 +1134,7 @@ public final class WindowInsets { public WindowInsets build() { return new WindowInsets(mSystemInsetsConsumed ? null : mTypeInsetsMap, mStableInsetsConsumed ? null : mTypeMaxInsetsMap, mTypeVisibilityMap, - mIsRound, mAlwaysConsumeNavBar, mDisplayCutout); + mIsRound, mAlwaysConsumeSystemBars, mDisplayCutout); } } diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java index 453c5e32a178..8a111cf86658 100644 --- a/core/java/android/view/WindowManagerGlobal.java +++ b/core/java/android/view/WindowManagerGlobal.java @@ -93,11 +93,11 @@ public final class WindowManagerGlobal { public static final int RELAYOUT_RES_SURFACE_RESIZED = 0x20; /** - * In multi-window we force show the navigation bar. Because we don't want that the surface size - * changes in this mode, we instead have a flag whether the navigation bar size should always be - * consumed, so the app is treated like there is no virtual navigation bar at all. + * In multi-window we force show the system bars. Because we don't want that the surface size + * changes in this mode, we instead have a flag whether the system bar sizes should always be + * consumed, so the app is treated like there is no virtual system bars at all. */ - public static final int RELAYOUT_RES_CONSUME_ALWAYS_NAV_BAR = 0x40; + public static final int RELAYOUT_RES_CONSUME_ALWAYS_SYSTEM_BARS = 0x40; /** * Flag for relayout: the client will be later giving @@ -118,9 +118,10 @@ public final class WindowManagerGlobal { public static final int ADD_FLAG_IN_TOUCH_MODE = RELAYOUT_RES_IN_TOUCH_MODE; /** - * Like {@link #RELAYOUT_RES_CONSUME_ALWAYS_NAV_BAR}, but as a "hint" when adding the window. + * Like {@link #RELAYOUT_RES_CONSUME_ALWAYS_SYSTEM_BARS}, but as a "hint" when adding the + * window. */ - public static final int ADD_FLAG_ALWAYS_CONSUME_NAV_BAR = 0x4; + public static final int ADD_FLAG_ALWAYS_CONSUME_SYSTEM_BARS = 0x4; public static final int ADD_OKAY = 0; public static final int ADD_BAD_APP_TOKEN = -1; diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java index 384cdbb3831c..d12777fe908e 100644 --- a/core/java/android/view/accessibility/AccessibilityManager.java +++ b/core/java/android/view/accessibility/AccessibilityManager.java @@ -848,7 +848,7 @@ public final class AccessibilityManager { if (mRequestPreparerLists == null) { mRequestPreparerLists = new SparseArray<>(1); } - int id = preparer.getView().getAccessibilityViewId(); + int id = preparer.getAccessibilityViewId(); List<AccessibilityRequestPreparer> requestPreparerList = mRequestPreparerLists.get(id); if (requestPreparerList == null) { requestPreparerList = new ArrayList<>(1); @@ -864,7 +864,7 @@ public final class AccessibilityManager { if (mRequestPreparerLists == null) { return; } - int viewId = preparer.getView().getAccessibilityViewId(); + int viewId = preparer.getAccessibilityViewId(); List<AccessibilityRequestPreparer> requestPreparerList = mRequestPreparerLists.get(viewId); if (requestPreparerList != null) { requestPreparerList.remove(preparer); diff --git a/core/java/android/view/accessibility/AccessibilityRequestPreparer.java b/core/java/android/view/accessibility/AccessibilityRequestPreparer.java index 4dcb18766347..8108d37a8814 100644 --- a/core/java/android/view/accessibility/AccessibilityRequestPreparer.java +++ b/core/java/android/view/accessibility/AccessibilityRequestPreparer.java @@ -51,6 +51,7 @@ public abstract class AccessibilityRequestPreparer { public @interface RequestTypes {} private final WeakReference<View> mViewRef; + private final int mAccessibilityViewId; private final int mRequestTypes; /** @@ -68,6 +69,7 @@ public abstract class AccessibilityRequestPreparer { throw new IllegalStateException("View must be attached to a window"); } mViewRef = new WeakReference<>(view); + mAccessibilityViewId = view.getAccessibilityViewId(); mRequestTypes = requestTypes; view.addOnAttachStateChangeListener(new ViewAttachStateListener()); } @@ -118,4 +120,8 @@ public abstract class AccessibilityRequestPreparer { v.removeOnAttachStateChangeListener(this); } } + + int getAccessibilityViewId() { + return mAccessibilityViewId; + } } diff --git a/core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl b/core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl index c1a3ab770989..f96f0acd6082 100644 --- a/core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl +++ b/core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl @@ -33,6 +33,7 @@ oneway interface IAccessibilityInteractionConnectionCallback { * @param infos The result {@link AccessibilityNodeInfo}. * @param interactionId The interaction id to match the result with the request. */ + @UnsupportedAppUsage void setFindAccessibilityNodeInfoResult(in AccessibilityNodeInfo info, int interactionId); /** @@ -41,6 +42,7 @@ oneway interface IAccessibilityInteractionConnectionCallback { * @param infos The result {@link AccessibilityNodeInfo}s. * @param interactionId The interaction id to match the result with the request. */ + @UnsupportedAppUsage void setFindAccessibilityNodeInfosResult(in List<AccessibilityNodeInfo> infos, int interactionId); @@ -50,5 +52,6 @@ oneway interface IAccessibilityInteractionConnectionCallback { * @param Whether the action was performed. * @param interactionId The interaction id to match the result with the request. */ + @UnsupportedAppUsage void setPerformAccessibilityActionResult(boolean succeeded, int interactionId); } diff --git a/core/java/android/view/accessibility/IAccessibilityManager.aidl b/core/java/android/view/accessibility/IAccessibilityManager.aidl index 486b35d9cc0f..0d5c7c941a56 100644 --- a/core/java/android/view/accessibility/IAccessibilityManager.aidl +++ b/core/java/android/view/accessibility/IAccessibilityManager.aidl @@ -42,6 +42,7 @@ interface IAccessibilityManager { List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList(int userId); + @UnsupportedAppUsage List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int feedbackType, int userId); int addAccessibilityInteractionConnection(IWindow windowToken, diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java index 8cb04cbdc994..77a0c4c5f4ee 100644 --- a/core/java/android/view/autofill/AutofillManager.java +++ b/core/java/android/view/autofill/AutofillManager.java @@ -16,7 +16,6 @@ package android.view.autofill; -import static android.service.autofill.FillRequest.FLAG_AUGMENTED_AUTOFILL_REQUEST; import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST; import static android.view.autofill.Helper.sDebug; import static android.view.autofill.Helper.sVerbose; @@ -228,6 +227,7 @@ public final class AutofillManager { /** @hide */ public static final int FLAG_ADD_CLIENT_ENABLED = 0x1; /** @hide */ public static final int FLAG_ADD_CLIENT_DEBUG = 0x2; /** @hide */ public static final int FLAG_ADD_CLIENT_VERBOSE = 0x4; + /** @hide */ public static final int FLAG_ADD_CLIENT_ENABLED_FOR_AUGMENTED_AUTOFILL_ONLY = 0x8; /** @hide */ public static final int FLAG_SESSION_FOR_AUGMENTED_AUTOFILL_ONLY = 0x1; @@ -520,6 +520,13 @@ public final class AutofillManager { @GuardedBy("mLock") private boolean mForAugmentedAutofillOnly; + /** + * When set, standard autofill is enabled, but sessions can still be created for augmented + * autofill only. + */ + @GuardedBy("mLock") + private boolean mEnabledForAugmentedAutofillOnly; + /** @hide */ public interface AutofillClient { /** @@ -946,7 +953,7 @@ public final class AutofillManager { ensureServiceClientAddedIfNeededLocked(); - if (!mEnabled) { + if (!mEnabled && !mEnabledForAugmentedAutofillOnly) { if (sVerbose) Log.v(TAG, "ignoring notifyViewEntered(" + id + "): disabled"); if (mCallback != null) { @@ -988,7 +995,7 @@ public final class AutofillManager { void notifyViewExitedLocked(@NonNull View view) { ensureServiceClientAddedIfNeededLocked(); - if (mEnabled && isActiveLocked()) { + if ((mEnabled || mEnabledForAugmentedAutofillOnly) && isActiveLocked()) { // dont notify exited when Activity is already in background if (!isClientDisablingEnterExitEvent()) { final AutofillId id = view.getAutofillId(); @@ -1104,7 +1111,7 @@ public final class AutofillManager { ensureServiceClientAddedIfNeededLocked(); - if (!mEnabled) { + if (!mEnabled && !mEnabledForAugmentedAutofillOnly) { if (sVerbose) { Log.v(TAG, "ignoring notifyViewEntered(" + id + "): disabled"); } @@ -1155,7 +1162,7 @@ public final class AutofillManager { private void notifyViewExitedLocked(@NonNull View view, int virtualId) { ensureServiceClientAddedIfNeededLocked(); - if (mEnabled && isActiveLocked()) { + if ((mEnabled || mEnabledForAugmentedAutofillOnly) && isActiveLocked()) { // don't notify exited when Activity is already in background if (!isClientDisablingEnterExitEvent()) { final AutofillId id = getAutofillId(view, virtualId); @@ -1674,14 +1681,17 @@ public final class AutofillManager { private void startSessionLocked(@NonNull AutofillId id, @NonNull Rect bounds, @NonNull AutofillValue value, int flags) { if (mEnteredForAugmentedAutofillIds != null - && mEnteredForAugmentedAutofillIds.contains(id)) { + && mEnteredForAugmentedAutofillIds.contains(id) + || mEnabledForAugmentedAutofillOnly) { if (sVerbose) Log.v(TAG, "Starting session for augmented autofill on " + id); - flags |= FLAG_AUGMENTED_AUTOFILL_REQUEST; + flags |= FLAG_ADD_CLIENT_ENABLED_FOR_AUGMENTED_AUTOFILL_ONLY; } if (sVerbose) { Log.v(TAG, "startSessionLocked(): id=" + id + ", bounds=" + bounds + ", value=" + value + ", flags=" + flags + ", state=" + getStateAsStringLocked() + ", compatMode=" + isCompatibilityModeEnabledLocked() + + ", augmentedOnly=" + mForAugmentedAutofillOnly + + ", enabledAugmentedOnly=" + mEnabledForAugmentedAutofillOnly + ", enteredIds=" + mEnteredIds); } if (mState != STATE_UNKNOWN && !isFinishedLocked() && (flags & FLAG_MANUAL_REQUEST) == 0) { @@ -1776,7 +1786,8 @@ public final class AutofillManager { @GuardedBy("mLock") private void ensureServiceClientAddedIfNeededLocked() { - if (getClient() == null) { + final AutofillClient client = getClient(); + if (client == null) { return; } @@ -1785,11 +1796,18 @@ public final class AutofillManager { try { final int userId = mContext.getUserId(); final SyncResultReceiver receiver = new SyncResultReceiver(SYNC_CALLS_TIMEOUT_MS); - mService.addClient(mServiceClient, userId, receiver); + mService.addClient(mServiceClient, client.autofillClientGetComponentName(), + userId, receiver); final int flags = receiver.getIntResult(); mEnabled = (flags & FLAG_ADD_CLIENT_ENABLED) != 0; sDebug = (flags & FLAG_ADD_CLIENT_DEBUG) != 0; sVerbose = (flags & FLAG_ADD_CLIENT_VERBOSE) != 0; + mEnabledForAugmentedAutofillOnly = (flags + & FLAG_ADD_CLIENT_ENABLED_FOR_AUGMENTED_AUTOFILL_ONLY) != 0; + if (sVerbose) { + Log.v(TAG, "receiver results: flags=" + flags + " enabled=" + mEnabled + + ", enabledForAugmentedOnly: " + mEnabledForAugmentedAutofillOnly); + } final IAutoFillManager service = mService; final IAutoFillManagerClient serviceClient = mServiceClient; mServiceClientCleaner = Cleaner.create(this, () -> { @@ -2406,6 +2424,7 @@ public final class AutofillManager { pw.print(" ("); pw.print(client.autofillClientGetActivityToken()); pw.println(')'); } pw.print(pfx); pw.print("enabled: "); pw.println(mEnabled); + pw.print(pfx); pw.print("enabledAugmentedOnly: "); pw.println(mForAugmentedAutofillOnly); pw.print(pfx); pw.print("hasService: "); pw.println(mService != null); pw.print(pfx); pw.print("hasCallback: "); pw.println(mCallback != null); pw.print(pfx); pw.print("onInvisibleCalled "); pw.println(mOnInvisibleCalled); diff --git a/core/java/android/view/autofill/IAutoFillManager.aidl b/core/java/android/view/autofill/IAutoFillManager.aidl index 9e6a4afe5414..a507e74c30ab 100644 --- a/core/java/android/view/autofill/IAutoFillManager.aidl +++ b/core/java/android/view/autofill/IAutoFillManager.aidl @@ -37,7 +37,8 @@ import com.android.internal.os.IResultReceiver; */ oneway interface IAutoFillManager { // Returns flags: FLAG_ADD_CLIENT_ENABLED | FLAG_ADD_CLIENT_DEBUG | FLAG_ADD_CLIENT_VERBOSE - void addClient(in IAutoFillManagerClient client, int userId, in IResultReceiver result); + void addClient(in IAutoFillManagerClient client, in ComponentName componentName, int userId, + in IResultReceiver result); void removeClient(in IAutoFillManagerClient client, int userId); void startSession(IBinder activityToken, in IBinder appCallback, in AutofillId autoFillId, in Rect bounds, in AutofillValue value, int userId, boolean hasCallback, int flags, diff --git a/core/java/android/view/inspector/InspectableNodeName.java b/core/java/android/view/inspector/InspectableNodeName.java deleted file mode 100644 index 7b9a507ee45d..000000000000 --- a/core/java/android/view/inspector/InspectableNodeName.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2018 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.view.inspector; - -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -import android.annotation.TestApi; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -/** - * Marks the node name to display to a developer in the inspection tree. - * - * This annotation is optional to marking a class as inspectable. If it is omitted, the node name - * will be inferred using the semantics of {@link Class#getSimpleName()}. The fully qualified class - * name is always available in the tree, this is for display purposes only. If a class is inflated - * from XML and the tag it inflates from does not match its simple name, this annotation should be - * used to inform the inspector to display the XML tag name in the inspection tree view. - * - * This annotation does not inherit. If a class extends an annotated parent class, but does not - * annotate itself, its node name will be inferred from its Java name. - * - * @see InspectionCompanion#getNodeName() - * @hide - */ -@Target({TYPE}) -@Retention(SOURCE) -@TestApi -public @interface InspectableNodeName { - /** - * The display name for nodes of this type. - * - * @return The name for nodes of this type - */ - String value(); -} diff --git a/core/java/android/view/inspector/InspectionCompanion.java b/core/java/android/view/inspector/InspectionCompanion.java index 62d769b6d963..a633a58065a0 100644 --- a/core/java/android/view/inspector/InspectionCompanion.java +++ b/core/java/android/view/inspector/InspectionCompanion.java @@ -17,7 +17,6 @@ package android.view.inspector; import android.annotation.NonNull; -import android.annotation.Nullable; /** * An interface for companion objects used to inspect views. @@ -33,11 +32,6 @@ import android.annotation.Nullable; * parent class via the parent's inspection companion, and the child companion will only read * properties added or changed since the parent was defined. * - * Only one child traversal is considered for each class. If a descendant class defines a - * different child traversal than its parent, only the bottom traversal is used. If a class does - * not define its own child traversal, but one of its ancestors does, the bottom-most ancestor's - * traversal will be used. - * * @param <T> The type of inspectable this is the companion to */ public interface InspectionCompanion<T> { @@ -68,22 +62,6 @@ public interface InspectionCompanion<T> { void readProperties(@NonNull T inspectable, @NonNull PropertyReader propertyReader); /** - * Get an optional name to display to developers for inspection nodes of this companion's type. - * - * The default implementation returns null, which will cause the runtime to use the class's - * simple name as defined by {@link Class#getSimpleName()} as the node name. - * - * If the type of this companion is inflated from XML, this method should be overridden to - * return the string used as the tag name for this type in XML. - * - * @return A string to use as the node name, or null to use the simple class name fallback. - */ - @Nullable - default String getNodeName() { - return null; - } - - /** * Thrown by {@link #readProperties(Object, PropertyReader)} if called before * {@link #mapProperties(PropertyMapper)}. */ diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java index 8f5f0a376c35..cb44f79465ef 100644 --- a/core/java/android/view/textclassifier/TextClassifierImpl.java +++ b/core/java/android/view/textclassifier/TextClassifierImpl.java @@ -177,8 +177,7 @@ public final class TextClassifierImpl implements TextClassifier { final String localesString = concatenateLocales(request.getDefaultLocales()); final String detectLanguageTags = detectLanguageTagsFromText(request.getText()); final ZonedDateTime refTime = ZonedDateTime.now(); - final AnnotatorModel annotatorImpl = - getAnnotatorImpl(request.getDefaultLocales()); + final AnnotatorModel annotatorImpl = getAnnotatorImpl(request.getDefaultLocales()); final int start; final int end; if (mSettings.isModelDarkLaunchEnabled() && !request.isDarkLaunchAllowed()) { @@ -417,7 +416,8 @@ public final class TextClassifierImpl implements TextClassifier { nativeConversation, null, mContext, - getResourceLocalesString()); + getResourceLocalesString(), + getAnnotatorImpl(LocaleList.getDefault())); return createConversationActionResult(request, nativeSuggestions); } catch (Throwable t) { // Avoid throwing from this method. Log the error. @@ -583,8 +583,7 @@ public final class TextClassifierImpl implements TextClassifier { new File(bestModel.getPath()), ParcelFileDescriptor.MODE_READ_ONLY); try { if (pfd != null) { - mActionsImpl = new ActionsSuggestionsModel( - pfd.getFd(), getAnnotatorImpl(LocaleList.getDefault())); + mActionsImpl = new ActionsSuggestionsModel(pfd.getFd()); mActionModelInUse = bestModel; } } finally { diff --git a/core/java/com/android/internal/app/AbstractResolverComparator.java b/core/java/com/android/internal/app/AbstractResolverComparator.java new file mode 100644 index 000000000000..3576b6bb4236 --- /dev/null +++ b/core/java/com/android/internal/app/AbstractResolverComparator.java @@ -0,0 +1,63 @@ +package com.android.internal.app; + +import android.content.ComponentName; +import com.android.internal.app.ResolverActivity.ResolvedComponentInfo; +import java.util.Comparator; +import java.util.List; + +/** + * Used to sort resolved activities in {@link ResolverListController}. + */ +abstract class AbstractResolverComparator implements Comparator<ResolvedComponentInfo> { + + protected AfterCompute mAfterCompute; + + /** + * Callback to be called when {@link #compute(List)} finishes. This signals to stop waiting. + */ + public interface AfterCompute { + + public void afterCompute(); + } + + public void setCallBack(AfterCompute afterCompute) { + mAfterCompute = afterCompute; + } + + /** + * Computes features for each target. This will be called before calls to {@link + * #getScore(ComponentName)} or {@link #compare(Object, Object)}, in order to prepare the + * comparator for those calls. Note that {@link #getScore(ComponentName)} uses {@link + * ComponentName}, so the implementation will have to be prepared to identify a {@link + * ResolvedComponentInfo} by {@link ComponentName}. + */ + public abstract void compute(List<ResolvedComponentInfo> targets); + + /** + * Returns the score that was calculated for the corresponding {@link ResolvedComponentInfo} + * when {@link #compute(List)} was called before this. + */ + public abstract float getScore(ComponentName name); + + /** + * Reports to UsageStats what was chosen. + */ + // TODO(b/129014961) Move implemetation here and make final. + public abstract void updateChooserCounts(String packageName, int userId, String action); + + /** + * Updates the model used to rank the componentNames. + * + * <p>Default implementation does nothing, as we could have simple model that does not train + * online. + * + * @param componentName the component that the user clicked + */ + public void updateModel(ComponentName componentName) { + } + + /** + * Called when the {@link ResolverActivity} is destroyed. + */ + public abstract void destroy(); +} diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java index faf0c7dbed37..702b5075e1f0 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -58,6 +58,7 @@ import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; +import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.Icon; import android.metrics.LogMaker; @@ -876,10 +877,17 @@ public class ChooserActivity extends ResolverActivity { } mChooserRowAdapter = new ChooserRowAdapter(mChooserListAdapter); mChooserRowAdapter.registerDataSetObserver(new OffsetDataSetObserver(adapterView)); - adapterView.setAdapter(mChooserRowAdapter); if (listView != null) { listView.setItemsCanFocus(true); + listView.addOnLayoutChangeListener( + (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> { + if (mChooserRowAdapter.calculateMaxTargetsPerRow(right - left)) { + adapterView.setAdapter(mChooserRowAdapter); + } + }); } + + adapterView.setAdapter(mChooserRowAdapter); } @Override @@ -1269,11 +1277,10 @@ public class ChooserActivity extends ResolverActivity { } mAppPredictor.notifyAppTargetEvent( new AppTargetEvent.Builder( - new AppTarget( - new AppTargetId(shortcutId), - componentName.getPackageName(), - componentName.getClassName(), - getUser()), + new AppTarget.Builder(new AppTargetId(shortcutId)) + .setTarget(componentName.getPackageName(), getUser()) + .setClassName(componentName.getClassName()) + .build(), AppTargetEvent.ACTION_LAUNCH ).setLaunchLocation(LAUNCH_LOCATON_DIRECT_SHARE) .build()); @@ -1465,14 +1472,6 @@ public class ChooserActivity extends ResolverActivity { return null; } - public Drawable getBadgeIcon() { - return null; - } - - public CharSequence getBadgeContentDescription() { - return null; - } - public TargetInfo cloneFilledIn(Intent fillInIntent, int flags) { return null; } @@ -1561,31 +1560,49 @@ public class ChooserActivity extends ResolverActivity { */ // TODO(121287224): Refactor code to apply the suggestion above private Drawable getChooserTargetIconDrawable(ChooserTarget target) { + Drawable directShareIcon = null; + + // First get the target drawable and associated activity info final Icon icon = target.getIcon(); if (icon != null) { - return icon.loadDrawable(ChooserActivity.this); - } - if (!USE_SHORTCUT_MANAGER_FOR_DIRECT_TARGETS) { - return null; + directShareIcon = icon.loadDrawable(ChooserActivity.this); + } else if (USE_SHORTCUT_MANAGER_FOR_DIRECT_TARGETS) { + Bundle extras = target.getIntentExtras(); + if (extras != null && extras.containsKey(Intent.EXTRA_SHORTCUT_ID)) { + CharSequence shortcutId = extras.getCharSequence(Intent.EXTRA_SHORTCUT_ID); + LauncherApps launcherApps = (LauncherApps) getSystemService( + Context.LAUNCHER_APPS_SERVICE); + final LauncherApps.ShortcutQuery q = new LauncherApps.ShortcutQuery(); + q.setPackage(target.getComponentName().getPackageName()); + q.setShortcutIds(Arrays.asList(shortcutId.toString())); + q.setQueryFlags(LauncherApps.ShortcutQuery.FLAG_MATCH_DYNAMIC); + final List<ShortcutInfo> shortcuts = launcherApps.getShortcuts(q, getUser()); + if (shortcuts != null && shortcuts.size() > 0) { + directShareIcon = launcherApps.getShortcutIconDrawable(shortcuts.get(0), 0); + } + } } - Bundle extras = target.getIntentExtras(); - if (extras == null || !extras.containsKey(Intent.EXTRA_SHORTCUT_ID)) { - return null; - } - CharSequence shortcutId = extras.getCharSequence(Intent.EXTRA_SHORTCUT_ID); - LauncherApps launcherApps = (LauncherApps) getSystemService( - Context.LAUNCHER_APPS_SERVICE); - final LauncherApps.ShortcutQuery q = new LauncherApps.ShortcutQuery(); - q.setPackage(target.getComponentName().getPackageName()); - q.setShortcutIds(Arrays.asList(shortcutId.toString())); - q.setQueryFlags(LauncherApps.ShortcutQuery.FLAG_MATCH_DYNAMIC); - final List<ShortcutInfo> shortcuts = launcherApps.getShortcuts(q, getUser()); - if (shortcuts != null && shortcuts.size() > 0) { - return launcherApps.getShortcutIconDrawable(shortcuts.get(0), 0); + if (directShareIcon == null) return null; + + ActivityInfo info = null; + try { + info = mPm.getActivityInfo(target.getComponentName(), 0); + } catch (NameNotFoundException error) { + Log.e(TAG, "Could not find activity associated with ChooserTarget"); } - return null; + if (info == null) return null; + + // Now fetch app icon and raster with no badging even in work profile + Bitmap appIcon = (new ActivityInfoPresentationGetter(info)).getIconBitmap(); + + // Raster target drawable with appIcon as a badge + SimpleIconFactory sif = SimpleIconFactory.obtain(ChooserActivity.this); + Bitmap directShareBadgedIcon = sif.createAppBadgedIconBitmap(directShareIcon, appIcon); + sif.recycle(); + + return new BitmapDrawable(getResources(), directShareBadgedIcon); } public float getModifiedScore() { @@ -1683,16 +1700,6 @@ public class ChooserActivity extends ResolverActivity { return mDisplayIcon; } - @Override - public Drawable getBadgeIcon() { - return mBadgeIcon; - } - - @Override - public CharSequence getBadgeContentDescription() { - return mBadgeContentDescription; - } - public ChooserTarget getChooserTarget() { return mChooserTarget; } @@ -2062,7 +2069,7 @@ public class ChooserActivity extends ResolverActivity { class ChooserRowAdapter extends BaseAdapter { private ChooserListAdapter mChooserListAdapter; private final LayoutInflater mLayoutInflater; - private int mAnimationCount = 0; + private int mCalculatedMaxTargetsPerRow = MAX_TARGETS_PER_ROW_LANDSCAPE; private DirectShareViewHolder mDirectShareViewHolder; @@ -2070,6 +2077,9 @@ public class ChooserActivity extends ResolverActivity { private static final int VIEW_TYPE_NORMAL = 1; private static final int VIEW_TYPE_CONTENT_PREVIEW = 2; + private static final int MAX_TARGETS_PER_ROW_PORTRAIT = 4; + private static final int MAX_TARGETS_PER_ROW_LANDSCAPE = 8; + public ChooserRowAdapter(ChooserListAdapter wrappedAdapter) { mChooserListAdapter = wrappedAdapter; mLayoutInflater = LayoutInflater.from(ChooserActivity.this); @@ -2089,9 +2099,40 @@ public class ChooserActivity extends ResolverActivity { }); } + /** + * Determine how many targets can comfortably fit in a single row. + * + * @param width The new row width to use for recalculation + * @return true if the numbers of targets per row has changed + */ + public boolean calculateMaxTargetsPerRow(int width) { + int targetWidth = getResources().getDimensionPixelSize( + R.dimen.chooser_target_width); + + if (targetWidth == 0 || width == 0) { + return false; + } + + int margin = getResources().getDimensionPixelSize( + R.dimen.chooser_edge_margin_normal); + + int newCount = (width - margin * 2) / targetWidth; + if (newCount != mCalculatedMaxTargetsPerRow) { + mCalculatedMaxTargetsPerRow = newCount; + return true; + } + + return false; + } + private int getMaxTargetsPerRow() { - // this will soon hold logic for portrait/landscape - return 4; + int maxTargets = MAX_TARGETS_PER_ROW_PORTRAIT; + if (getResources().getConfiguration().orientation + == Configuration.ORIENTATION_LANDSCAPE) { + maxTargets = MAX_TARGETS_PER_ROW_LANDSCAPE; + } + + return Math.min(maxTargets, mCalculatedMaxTargetsPerRow); } @Override @@ -2158,9 +2199,7 @@ public class ChooserActivity extends ResolverActivity { holder = (RowViewHolder) convertView.getTag(); } - bindViewHolder(position, holder, - viewType == VIEW_TYPE_DIRECT_SHARE - ? ChooserListAdapter.MAX_SERVICE_TARGETS : getMaxTargetsPerRow()); + bindViewHolder(position, holder); return holder.getViewGroup(); } @@ -2277,7 +2316,7 @@ public class ChooserActivity extends ResolverActivity { } } - void bindViewHolder(int rowPosition, RowViewHolder holder, int columnCount) { + void bindViewHolder(int rowPosition, RowViewHolder holder) { final int start = getFirstRowPosition(rowPosition); final int startType = mChooserListAdapter.getPositionTargetType(start); @@ -2294,6 +2333,7 @@ public class ChooserActivity extends ResolverActivity { setVertPadding(row, 0, 0); } + int columnCount = holder.getColumnCount(); int end = start + columnCount - 1; while (mChooserListAdapter.getPositionTargetType(end) != startType && end >= start) { end--; @@ -2328,36 +2368,15 @@ public class ChooserActivity extends ResolverActivity { for (int i = 0; i < columnCount; i++) { final View v = holder.getView(i); if (start + i <= end) { - setCellVisibility(holder, i, View.VISIBLE); + holder.setViewVisibility(i, View.VISIBLE); holder.setItemIndex(i, start + i); mChooserListAdapter.bindView(holder.getItemIndex(i), v); } else { - setCellVisibility(holder, i, View.INVISIBLE); + holder.setViewVisibility(i, View.INVISIBLE); } } } - private void setCellVisibility(RowViewHolder holder, int i, int visibility) { - final View v = holder.getView(i); - if (visibility == View.VISIBLE) { - holder.setViewVisibility(i, true); - v.setVisibility(visibility); - v.setAlpha(1.0f); - } else if (visibility == View.INVISIBLE && holder.getViewVisibility(i)) { - holder.setViewVisibility(i, false); - - ValueAnimator fadeAnim = ObjectAnimator.ofFloat(v, "alpha", 1.0f, 0f); - fadeAnim.setDuration(NO_DIRECT_SHARE_ANIM_IN_MILLIS); - fadeAnim.setInterpolator(new AccelerateInterpolator(1.0f)); - fadeAnim.addListener(new AnimatorListenerAdapter() { - public void onAnimationEnd(Animator animation) { - v.setVisibility(View.INVISIBLE); - } - }); - fadeAnim.start(); - } - } - private void setVertPadding(ViewGroup row, int top, int bottom) { row.setPadding(row.getPaddingLeft(), top, row.getPaddingRight(), bottom); } @@ -2393,13 +2412,11 @@ public class ChooserActivity extends ResolverActivity { protected int mMeasuredRowHeight; private int[] mItemIndices; protected final View[] mCells; - private final boolean[] mCellVisibility; private final int mColumnCount; RowViewHolder(int cellCount) { this.mCells = new View[cellCount]; this.mItemIndices = new int[cellCount]; - this.mCellVisibility = new boolean[cellCount]; this.mColumnCount = cellCount; } @@ -2409,18 +2426,12 @@ public class ChooserActivity extends ResolverActivity { abstract ViewGroup getRow(int index); + abstract void setViewVisibility(int i, int visibility); + public int getColumnCount() { return mColumnCount; } - public void setViewVisibility(int index, boolean visibility) { - mCellVisibility[index] = visibility; - } - - public boolean getViewVisibility(int index) { - return mCellVisibility[index]; - } - public void measure() { final int spec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); getViewGroup().measure(spec, spec); @@ -2476,6 +2487,10 @@ public class ChooserActivity extends ResolverActivity { return mRow; } + + public void setViewVisibility(int i, int visibility) { + getView(i).setVisibility(visibility); + } } class DirectShareViewHolder extends RowViewHolder { @@ -2488,12 +2503,15 @@ public class ChooserActivity extends ResolverActivity { private int mDirectShareCurrHeight = 0; private int mDirectShareMaxHeight = 0; + private final boolean[] mCellVisibility; + DirectShareViewHolder(ViewGroup parent, List<ViewGroup> rows, int cellCountPerRow) { super(rows.size() * cellCountPerRow); this.mParent = parent; this.mRows = rows; this.mCellCountPerRow = cellCountPerRow; + this.mCellVisibility = new boolean[rows.size() * cellCountPerRow]; } public ViewGroup addView(int index, View v) { @@ -2532,6 +2550,27 @@ public class ChooserActivity extends ResolverActivity { return mDirectShareCurrHeight; } + public void setViewVisibility(int i, int visibility) { + final View v = getView(i); + if (visibility == View.VISIBLE) { + mCellVisibility[i] = true; + v.setVisibility(visibility); + v.setAlpha(1.0f); + } else if (visibility == View.INVISIBLE && mCellVisibility[i]) { + mCellVisibility[i] = false; + + ValueAnimator fadeAnim = ObjectAnimator.ofFloat(v, "alpha", 1.0f, 0f); + fadeAnim.setDuration(NO_DIRECT_SHARE_ANIM_IN_MILLIS); + fadeAnim.setInterpolator(new AccelerateInterpolator(1.0f)); + fadeAnim.addListener(new AnimatorListenerAdapter() { + public void onAnimationEnd(Animator animation) { + v.setVisibility(View.INVISIBLE); + } + }); + fadeAnim.start(); + } + } + public void handleScroll(AbsListView view, int y, int oldy, int maxTargetsPerRow) { // only expand if we have more than 4 targets, and delay that decision until // they start to scroll diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java index 12942abc8159..21152ae428ed 100644 --- a/core/java/com/android/internal/app/ResolverActivity.java +++ b/core/java/com/android/internal/app/ResolverActivity.java @@ -42,7 +42,7 @@ import android.content.pm.ResolveInfo; import android.content.pm.UserInfo; import android.content.res.Configuration; import android.content.res.Resources; -import android.graphics.Color; +import android.graphics.Bitmap; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.net.Uri; @@ -133,8 +133,6 @@ public class ResolverActivity extends Activity { /** See {@link #setRetainInOnStop}. */ private boolean mRetainInOnStop; - SimpleIconFactory mSimpleIconFactory; - private final PackageMonitor mPackageMonitor = new PackageMonitor() { @Override public void onSomePackagesChanged() { mAdapter.handlePackagesChanged(); @@ -311,11 +309,6 @@ public class ResolverActivity extends Activity { // as to mitigate Intent Capturing vulnerability mSupportsAlwaysUseOption = supportsAlwaysUseOption && !mUseLayoutForBrowsables; - final int iconSize = getResources().getDimensionPixelSize(R.dimen.resolver_icon_size); - final int badgeSize = getResources().getDimensionPixelSize(R.dimen.resolver_badge_size); - mSimpleIconFactory = new SimpleIconFactory(this, mIconDpi, iconSize, badgeSize); - mSimpleIconFactory.setWrapperBackgroundColor(Color.WHITE); - if (configureContentView(mIntents, initialIntents, rList)) { return; } @@ -500,64 +493,150 @@ public class ResolverActivity extends Activity { } } - @Nullable - Drawable getIcon(Resources res, int resId) { - Drawable result; - try { - result = res.getDrawableForDensity(resId, mIconDpi); - } catch (Resources.NotFoundException e) { - result = null; - } - - return result; - } /** - * Loads the icon for the provided ResolveInfo. Defaults to using the application icon over + * Loads the icon for the provided ApplicationInfo. Defaults to using the application icon over * any IntentFilter or Activity icon to increase user understanding, with an exception for * applications that hold the right permission. Always attempts to use icon resources over * PackageManager loading mechanisms so badging can be done by iconloader. */ - Drawable loadIconForResolveInfo(ResolveInfo ri) { - Drawable dr = null; + private abstract class TargetPresentationGetter { + @Nullable abstract Drawable getIconSubstitute(); + @Nullable abstract String getAppSubLabel(); - // Allow for app icon override given the right permission - if (PackageManager.PERMISSION_GRANTED == mPm.checkPermission( - android.Manifest.permission.SUBSTITUTE_SHARE_TARGET_APP_NAME_AND_ICON, - ri.activityInfo.applicationInfo.packageName)) { - try { - if (ri.resolvePackageName != null && ri.icon != 0) { - dr = getIcon(mPm.getResourcesForApplication(ri.resolvePackageName), ri.icon); - } - if (dr == null) { - final int iconRes = ri.getIconResource(); - if (iconRes != 0) { - dr = getIcon(mPm.getResourcesForApplication(ri.activityInfo.packageName), - iconRes); + private final ApplicationInfo mAi; + private final boolean mHasSubstitutePermission; + + TargetPresentationGetter(ApplicationInfo ai) { + mAi = ai; + mHasSubstitutePermission = PackageManager.PERMISSION_GRANTED == mPm.checkPermission( + android.Manifest.permission.SUBSTITUTE_SHARE_TARGET_APP_NAME_AND_ICON, + mAi.packageName); + } + + Drawable getIcon() { + return new BitmapDrawable(getResources(), getIconBitmap()); + } + + Bitmap getIconBitmap() { + Drawable dr = null; + if (mHasSubstitutePermission) { + dr = getIconSubstitute(); + } + + if (dr == null) { + try { + if (mAi.icon != 0) { + dr = loadIconFromResource(mPm.getResourcesForApplication(mAi), mAi.icon); } + } catch (NameNotFoundException ignore) { + } + } + + // Fall back to ApplicationInfo#loadIcon if nothing has been loaded + if (dr == null) { + dr = mAi.loadIcon(mPm); + } + + SimpleIconFactory sif = SimpleIconFactory.obtain(ResolverActivity.this); + Bitmap icon = sif.createUserBadgedIconBitmap(dr, Process.myUserHandle()); + sif.recycle(); + + return icon; + } + + String getLabel() { + String label = null; + // Apps with the substitute permission will always show the sublabel as their label + if (mHasSubstitutePermission) { + label = getAppSubLabel(); + } + + if (label == null) { + label = (String) mAi.loadLabel(mPm); + } + + return label; + } + + String getSubLabel() { + // Apps with the substitute permission will never have a sublabel + if (mHasSubstitutePermission) return null; + return getAppSubLabel(); + } + + @Nullable + protected Drawable loadIconFromResource(Resources res, int resId) { + return res.getDrawableForDensity(resId, mIconDpi); + } + + } + + protected class ResolveInfoPresentationGetter extends TargetPresentationGetter { + + private final ResolveInfo mRi; + + ResolveInfoPresentationGetter(ResolveInfo ri) { + super(ri.activityInfo.applicationInfo); + mRi = ri; + } + + @Override + Drawable getIconSubstitute() { + Drawable dr = null; + try { + // Do not use ResolveInfo#getIconResource() as it defaults to the app + if (mRi.resolvePackageName != null && mRi.icon != 0) { + dr = loadIconFromResource( + mPm.getResourcesForApplication(mRi.resolvePackageName), mRi.icon); } } catch (NameNotFoundException e) { Log.e(TAG, "SUBSTITUTE_SHARE_TARGET_APP_NAME_AND_ICON permission granted but " + "couldn't find resources for package", e); } + + return dr; + } + + @Override + String getAppSubLabel() { + return (String) mRi.loadLabel(mPm); + } + } + + protected class ActivityInfoPresentationGetter extends TargetPresentationGetter { + private final ActivityInfo mActivityInfo; + protected ActivityInfoPresentationGetter(ActivityInfo activityInfo) { + super(activityInfo.applicationInfo); + mActivityInfo = activityInfo; } - // Use app icons for better user association - if (dr == null) { + @Override + Drawable getIconSubstitute() { + Drawable dr = null; try { - dr = getIcon(mPm.getResourcesForApplication(ri.activityInfo.applicationInfo), - ri.activityInfo.applicationInfo.icon); - } catch (NameNotFoundException ignore) { + // Do not use ActivityInfo#getIconResource() as it defaults to the app + if (mActivityInfo.icon != 0) { + dr = loadIconFromResource( + mPm.getResourcesForApplication(mActivityInfo.applicationInfo), + mActivityInfo.icon); + } + } catch (NameNotFoundException e) { + Log.e(TAG, "SUBSTITUTE_SHARE_TARGET_APP_NAME_AND_ICON permission granted but " + + "couldn't find resources for package", e); } + + return dr; } - // Fall back to ApplicationInfo#loadIcon if nothing has been loaded - if (dr == null) { - dr = ri.activityInfo.applicationInfo.loadIcon(mPm); + @Override + String getAppSubLabel() { + return (String) mActivityInfo.loadLabel(mPm); } + } - return new BitmapDrawable(this.getResources(), - mSimpleIconFactory.createUserBadgedIconBitmap(dr, Process.myUserHandle())); + Drawable loadIconForResolveInfo(ResolveInfo ri) { + return (new ResolveInfoPresentationGetter(ri)).getIcon(); } @Override @@ -1250,33 +1329,6 @@ public class ResolverActivity extends Activity { return mDisplayIcon; } - public Drawable getBadgeIcon() { - // We only expose a badge if we have extended info. - // The badge is a higher-priority disambiguation signal - // but we don't need one if we wouldn't show extended info at all. - if (TextUtils.isEmpty(getExtendedInfo())) { - return null; - } - - if (mBadge == null && mResolveInfo != null && mResolveInfo.activityInfo != null - && mResolveInfo.activityInfo.applicationInfo != null) { - if (mResolveInfo.activityInfo.icon == 0 || mResolveInfo.activityInfo.icon - == mResolveInfo.activityInfo.applicationInfo.icon) { - // Badging an icon with exactly the same icon is silly. - // If the activityInfo icon resid is 0 it will fall back - // to the application's icon, making it a match. - return null; - } - mBadge = mResolveInfo.activityInfo.applicationInfo.loadIcon(mPm); - } - return mBadge; - } - - @Override - public CharSequence getBadgeContentDescription() { - return null; - } - @Override public TargetInfo cloneFilledIn(Intent fillInIntent, int flags) { return new DisplayResolveInfo(this, fillInIntent, flags); @@ -1413,21 +1465,11 @@ public class ResolverActivity extends Activity { CharSequence getExtendedInfo(); /** - * @return The drawable that should be used to represent this target + * @return The drawable that should be used to represent this target including badge */ Drawable getDisplayIcon(); /** - * @return The (small) icon to badge the target with - */ - Drawable getBadgeIcon(); - - /** - * @return The content description for the badge icon - */ - CharSequence getBadgeContentDescription(); - - /** * Clone this target with the given fill-in information. */ TargetInfo cloneFilledIn(Intent fillInIntent, int flags); @@ -1963,16 +2005,6 @@ public class ResolverActivity extends Activity { new LoadAdapterIconTask((DisplayResolveInfo) info).execute(); } holder.icon.setImageDrawable(info.getDisplayIcon()); - if (holder.badge != null) { - final Drawable badge = info.getBadgeIcon(); - if (badge != null) { - holder.badge.setImageDrawable(badge); - holder.badge.setContentDescription(info.getBadgeContentDescription()); - holder.badge.setVisibility(View.VISIBLE); - } else { - holder.badge.setVisibility(View.GONE); - } - } } } @@ -2027,13 +2059,11 @@ public class ResolverActivity extends Activity { public TextView text; public TextView text2; public ImageView icon; - public ImageView badge; public ViewHolder(View view) { text = (TextView) view.findViewById(com.android.internal.R.id.text1); text2 = (TextView) view.findViewById(com.android.internal.R.id.text2); icon = (ImageView) view.findViewById(R.id.icon); - badge = (ImageView) view.findViewById(R.id.target_badge); } } diff --git a/core/java/com/android/internal/app/ResolverListController.java b/core/java/com/android/internal/app/ResolverListController.java index f48102a9fcd4..156baf03f563 100644 --- a/core/java/com/android/internal/app/ResolverListController.java +++ b/core/java/com/android/internal/app/ResolverListController.java @@ -55,7 +55,7 @@ public class ResolverListController { private static final String TAG = "ResolverListController"; private static final boolean DEBUG = false; - private ResolverComparator mResolverComparator; + private AbstractResolverComparator mResolverComparator; private boolean isComputed = false; public ResolverListController( @@ -70,7 +70,8 @@ public class ResolverListController { mTargetIntent = targetIntent; mReferrerPackage = referrerPackage; mResolverComparator = - new ResolverComparator(mContext, mTargetIntent, mReferrerPackage, null); + new ResolverRankerServiceResolverComparator( + mContext, mTargetIntent, mReferrerPackage, null); } @VisibleForTesting @@ -221,7 +222,7 @@ public class ResolverListController { return listToReturn; } - private class ComputeCallback implements ResolverComparator.AfterCompute { + private class ComputeCallback implements AbstractResolverComparator.AfterCompute { private CountDownLatch mFinishComputeSignal; diff --git a/core/java/com/android/internal/app/ResolverComparator.java b/core/java/com/android/internal/app/ResolverRankerServiceResolverComparator.java index b9f67e6e0521..a88a80f199a4 100644 --- a/core/java/com/android/internal/app/ResolverComparator.java +++ b/core/java/com/android/internal/app/ResolverRankerServiceResolverComparator.java @@ -46,7 +46,6 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import java.text.Collator; import java.util.ArrayList; -import java.util.Comparator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -54,10 +53,10 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; /** - * Ranks and compares packages based on usage stats. + * Ranks and compares packages based on usage stats and uses the {@link ResolverRankerService}. */ -class ResolverComparator implements Comparator<ResolvedComponentInfo> { - private static final String TAG = "ResolverComparator"; +class ResolverRankerServiceResolverComparator extends AbstractResolverComparator { + private static final String TAG = "RRSResolverComparator"; private static final boolean DEBUG = false; @@ -100,7 +99,6 @@ class ResolverComparator implements Comparator<ResolvedComponentInfo> { private ComponentName mRankerServiceName; private IResolverRankerService mRanker; private ResolverRankerServiceConnection mConnection; - private AfterCompute mAfterCompute; private Context mContext; private CountDownLatch mConnectSignal; @@ -155,12 +153,8 @@ class ResolverComparator implements Comparator<ResolvedComponentInfo> { } }; - public interface AfterCompute { - public void afterCompute (); - } - - public ResolverComparator(Context context, Intent intent, String referrerPackage, - AfterCompute afterCompute) { + public ResolverRankerServiceResolverComparator(Context context, Intent intent, + String referrerPackage, AfterCompute afterCompute) { mCollator = Collator.getInstance(context.getResources().getConfiguration().locale); String scheme = intent.getScheme(); mHttp = "http".equals(scheme) || "https".equals(scheme); @@ -185,7 +179,7 @@ class ResolverComparator implements Comparator<ResolvedComponentInfo> { } // get annotations of content from intent. - public void getContentAnnotations(Intent intent) { + private void getContentAnnotations(Intent intent) { ArrayList<String> annotations = intent.getStringArrayListExtra( Intent.EXTRA_CONTENT_ANNOTATIONS); if (annotations != null) { @@ -200,11 +194,8 @@ class ResolverComparator implements Comparator<ResolvedComponentInfo> { } } - public void setCallBack(AfterCompute afterCompute) { - mAfterCompute = afterCompute; - } - // compute features for each target according to usage stats of targets. + @Override public void compute(List<ResolvedComponentInfo> targets) { reset(); @@ -349,6 +340,7 @@ class ResolverComparator implements Comparator<ResolvedComponentInfo> { return mCollator.compare(sa.toString().trim(), sb.toString().trim()); } + @Override public float getScore(ComponentName name) { final ResolverTarget target = mTargetsDict.get(name); if (target != null) { @@ -357,6 +349,7 @@ class ResolverComparator implements Comparator<ResolvedComponentInfo> { return 0; } + @Override public void updateChooserCounts(String packageName, int userId, String action) { if (mUsm != null) { mUsm.reportChooserSelection(packageName, userId, mContentType, mAnnotations, action); @@ -364,6 +357,7 @@ class ResolverComparator implements Comparator<ResolvedComponentInfo> { } // update ranking model when the connection to it is valid. + @Override public void updateModel(ComponentName componentName) { synchronized (mLock) { if (mRanker != null) { @@ -397,6 +391,7 @@ class ResolverComparator implements Comparator<ResolvedComponentInfo> { } // unbind the service and clear unhandled messges. + @Override public void destroy() { mHandler.removeMessages(RESOLVER_RANKER_SERVICE_RESULT); mHandler.removeMessages(RESOLVER_RANKER_RESULT_TIMEOUT); @@ -478,8 +473,8 @@ class ResolverComparator implements Comparator<ResolvedComponentInfo> { if (!ResolverRankerService.BIND_PERMISSION.equals(perm)) { Log.w(TAG, "ResolverRankerService " + componentName + " does not require" + " permission " + ResolverRankerService.BIND_PERMISSION - + " - this service will not be queried for ResolverComparator." - + " add android:permission=\"" + + " - this service will not be queried for " + + "ResolverRankerServiceResolverComparator. add android:permission=\"" + ResolverRankerService.BIND_PERMISSION + "\"" + " to the <service> tag for " + componentName + " in the manifest."); @@ -490,7 +485,8 @@ class ResolverComparator implements Comparator<ResolvedComponentInfo> { resolveInfo.serviceInfo.packageName)) { Log.w(TAG, "ResolverRankerService " + componentName + " does not hold" + " permission " + ResolverRankerService.HOLD_PERMISSION - + " - this service will not be queried for ResolverComparator."); + + " - this service will not be queried for " + + "ResolverRankerServiceResolverComparator."); continue; } } catch (NameNotFoundException e) { diff --git a/core/java/com/android/internal/app/SimpleIconFactory.java b/core/java/com/android/internal/app/SimpleIconFactory.java index eb1530e97b7f..a85485d3969b 100644 --- a/core/java/com/android/internal/app/SimpleIconFactory.java +++ b/core/java/com/android/internal/app/SimpleIconFactory.java @@ -16,11 +16,13 @@ package com.android.internal.app; +import static android.content.Context.ACTIVITY_SERVICE; import static android.graphics.Paint.DITHER_FLAG; import static android.graphics.Paint.FILTER_BITMAP_FLAG; import android.annotation.NonNull; import android.annotation.Nullable; +import android.app.ActivityManager; import android.content.Context; import android.content.pm.PackageManager; import android.content.res.Resources; @@ -42,6 +44,7 @@ import android.graphics.drawable.DrawableWrapper; import android.os.Process; import android.os.UserHandle; import android.util.AttributeSet; +import android.util.Pools.SynchronizedPool; import com.android.internal.R; @@ -58,6 +61,9 @@ import java.nio.ByteBuffer; @Deprecated public class SimpleIconFactory { + private static final SynchronizedPool<SimpleIconFactory> sPool = + new SynchronizedPool<>(Runtime.getRuntime().availableProcessors()); + private static final int DEFAULT_WRAPPER_BACKGROUND = Color.WHITE; private static final float BLUR_FACTOR = 0.5f / 48; @@ -74,10 +80,45 @@ public class SimpleIconFactory { private final Rect mOldBounds = new Rect(); /** + * Obtain a SimpleIconFactory from a pool objects. + * + * @deprecated Do not use, functionality will be replaced by iconloader lib eventually. + */ + @Deprecated + public static SimpleIconFactory obtain(Context ctx) { + SimpleIconFactory instance = sPool.acquire(); + if (instance == null) { + final ActivityManager am = (ActivityManager) ctx.getSystemService(ACTIVITY_SERVICE); + final int iconDpi = (am == null) ? 0 : am.getLauncherLargeIconDensity(); + + final Resources r = ctx.getResources(); + final int iconSize = r.getDimensionPixelSize(R.dimen.resolver_icon_size); + final int badgeSize = r.getDimensionPixelSize(R.dimen.resolver_badge_size); + + instance = new SimpleIconFactory(ctx, iconDpi, iconSize, badgeSize); + instance.setWrapperBackgroundColor(Color.WHITE); + } + + return instance; + } + + /** + * Recycles the SimpleIconFactory so others may use it. + * + * @deprecated Do not use, functionality will be replaced by iconloader lib eventually. + */ + @Deprecated + public void recycle() { + // Return to default background color + setWrapperBackgroundColor(Color.WHITE); + sPool.release(this); + } + + /** * @deprecated Do not use, functionality will be replaced by iconloader lib eventually. */ @Deprecated - SimpleIconFactory(Context context, int fillResIconDpi, int iconBitmapSize, + private SimpleIconFactory(Context context, int fillResIconDpi, int iconBitmapSize, int badgeBitmapSize) { mContext = context.getApplicationContext(); mPm = mContext.getPackageManager(); @@ -170,7 +211,7 @@ public class SimpleIconFactory { * @deprecated Do not use, functionality will be replaced by iconloader lib eventually. */ @Deprecated - public Bitmap createAppBadgedIconBitmap(@Nullable Drawable icon, Bitmap renderedAppIcon) { + Bitmap createAppBadgedIconBitmap(@Nullable Drawable icon, Bitmap renderedAppIcon) { // Flatten the passed in icon float [] scale = new float[1]; diff --git a/core/java/com/android/internal/backup/IBackupTransport.aidl b/core/java/com/android/internal/backup/IBackupTransport.aidl index f8117a7e9260..c9baf004d798 100644 --- a/core/java/com/android/internal/backup/IBackupTransport.aidl +++ b/core/java/com/android/internal/backup/IBackupTransport.aidl @@ -79,14 +79,14 @@ interface IBackupTransport { Intent dataManagementIntent(); /** - * On demand, supply a short string that can be shown to the user as the label - * on an overflow menu item used to invoked the data management UI. + * On demand, supply a short {@link CharSequence} that can be shown to the user as the label on + * an overflow menu item used to invoke the data management UI. * - * @return A string to be used as the label for the transport's data management + * @return A {@link CharSequence} to be used as the label for the transport's data management * affordance. If the transport supplies a data management intent, this * method must not return {@code null}. */ - String dataManagementLabel(); + CharSequence dataManagementIntentLabel(); /** * Ask the transport where, on local device storage, to keep backup state blobs. diff --git a/core/java/com/android/internal/os/BatteryStatsHelper.java b/core/java/com/android/internal/os/BatteryStatsHelper.java index ead98e7eee3c..e85508ed7891 100644 --- a/core/java/com/android/internal/os/BatteryStatsHelper.java +++ b/core/java/com/android/internal/os/BatteryStatsHelper.java @@ -368,6 +368,11 @@ public class BatteryStatsHelper { public void refreshStats(int statsType, SparseArray<UserHandle> asUsers, long rawRealtimeUs, long rawUptimeUs) { + if (statsType != BatteryStats.STATS_SINCE_CHARGED) { + Log.w(TAG, "refreshStats called for statsType " + statsType + " but only " + + "STATS_SINCE_CHARGED is supported. Using STATS_SINCE_CHARGED instead."); + } + // Initialize mStats if necessary. getStats(); diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 8679dcba2f80..1fc76351254b 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -145,7 +145,7 @@ public class BatteryStatsImpl extends BatteryStats { private static final int MAGIC = 0xBA757475; // 'BATSTATS' // Current on-disk Parcel version - static final int VERSION = 185 + (USE_OLD_HISTORY ? 1000 : 0); + static final int VERSION = 186 + (USE_OLD_HISTORY ? 1000 : 0); // The maximum number of names wakelocks we will keep track of // per uid; once the limit is reached, we batch the remaining wakelocks @@ -991,8 +991,6 @@ public class BatteryStatsImpl extends BatteryStats { private int mPhoneSimStateRaw = -1; private int mNumConnectivityChange; - private int mLoadedNumConnectivityChange; - private int mUnpluggedNumConnectivityChange; private int mEstimatedBatteryCapacity = -1; @@ -1225,27 +1223,11 @@ public class BatteryStatsImpl extends BatteryStats { } public long computeUptime(long curTime, int which) { - switch (which) { - case STATS_SINCE_CHARGED: - return mUptime + getUptime(curTime); - case STATS_CURRENT: - return getUptime(curTime); - case STATS_SINCE_UNPLUGGED: - return getUptime(curTime) - mUnpluggedUptime; - } - return 0; + return mUptime + getUptime(curTime); } public long computeRealtime(long curTime, int which) { - switch (which) { - case STATS_SINCE_CHARGED: - return mRealtime + getRealtime(curTime); - case STATS_CURRENT: - return getRealtime(curTime); - case STATS_SINCE_UNPLUGGED: - return getRealtime(curTime) - mUnpluggedRealtime; - } - return 0; + return mRealtime + getRealtime(curTime); } public long getUptime(long curTime) { @@ -1352,16 +1334,10 @@ public class BatteryStatsImpl extends BatteryStats { @UnsupportedAppUsage final AtomicInteger mCount = new AtomicInteger(); final TimeBase mTimeBase; - int mLoadedCount; - int mUnpluggedCount; - int mPluggedCount; public Counter(TimeBase timeBase, Parcel in) { mTimeBase = timeBase; - mPluggedCount = in.readInt(); - mCount.set(mPluggedCount); - mLoadedCount = in.readInt(); - mUnpluggedCount = in.readInt(); + mCount.set(in.readInt()); timeBase.add(this); } @@ -1372,18 +1348,14 @@ public class BatteryStatsImpl extends BatteryStats { public void writeToParcel(Parcel out) { out.writeInt(mCount.get()); - out.writeInt(mLoadedCount); - out.writeInt(mUnpluggedCount); } @Override public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) { - mUnpluggedCount = mPluggedCount; } @Override public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) { - mPluggedCount = mCount.get(); } /** @@ -1417,21 +1389,11 @@ public class BatteryStatsImpl extends BatteryStats { @Override public int getCountLocked(int which) { - int val = mCount.get(); - if (which == STATS_SINCE_UNPLUGGED) { - val -= mUnpluggedCount; - } else if (which != STATS_SINCE_CHARGED) { - val -= mLoadedCount; - } - - return val; + return mCount.get(); } public void logState(Printer pw, String prefix) { - pw.println(prefix + "mCount=" + mCount.get() - + " mLoadedCount=" + mLoadedCount - + " mUnpluggedCount=" + mUnpluggedCount - + " mPluggedCount=" + mPluggedCount); + pw.println(prefix + "mCount=" + mCount.get()); } @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) @@ -1453,7 +1415,6 @@ public class BatteryStatsImpl extends BatteryStats { @Override public boolean reset(boolean detachIfReset) { mCount.set(0); - mLoadedCount = mPluggedCount = mUnpluggedCount = 0; if (detachIfReset) { detach(); } @@ -1467,15 +1428,12 @@ public class BatteryStatsImpl extends BatteryStats { @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) public void writeSummaryFromParcelLocked(Parcel out) { - int count = mCount.get(); - out.writeInt(count); + out.writeInt(mCount.get()); } @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) public void readSummaryFromParcelLocked(Parcel in) { - mLoadedCount = in.readInt(); - mCount.set(mLoadedCount); - mUnpluggedCount = mPluggedCount = mLoadedCount; + mCount.set(in.readInt()); } } @@ -1483,14 +1441,10 @@ public class BatteryStatsImpl extends BatteryStats { public static class LongSamplingCounterArray extends LongCounterArray implements TimeBaseObs { final TimeBase mTimeBase; public long[] mCounts; - public long[] mLoadedCounts; - public long[] mUnpluggedCounts; private LongSamplingCounterArray(TimeBase timeBase, Parcel in) { mTimeBase = timeBase; mCounts = in.createLongArray(); - mLoadedCounts = in.createLongArray(); - mUnpluggedCounts = in.createLongArray(); timeBase.add(this); } @@ -1501,13 +1455,10 @@ public class BatteryStatsImpl extends BatteryStats { private void writeToParcel(Parcel out) { out.writeLongArray(mCounts); - out.writeLongArray(mLoadedCounts); - out.writeLongArray(mUnpluggedCounts); } @Override public void onTimeStarted(long elapsedRealTime, long baseUptime, long baseRealtime) { - mUnpluggedCounts = copyArray(mCounts, mUnpluggedCounts); } @Override @@ -1516,20 +1467,12 @@ public class BatteryStatsImpl extends BatteryStats { @Override public long[] getCountsLocked(int which) { - long[] val = copyArray(mCounts, null); - if (which == STATS_SINCE_UNPLUGGED) { - subtract(val, mUnpluggedCounts); - } else if (which != STATS_SINCE_CHARGED) { - subtract(val, mLoadedCounts); - } - return val; + return mCounts == null ? null : Arrays.copyOf(mCounts, mCounts.length); } @Override public void logState(Printer pw, String prefix) { - pw.println(prefix + "mCounts=" + Arrays.toString(mCounts) - + " mLoadedCounts=" + Arrays.toString(mLoadedCounts) - + " mUnpluggedCounts=" + Arrays.toString(mUnpluggedCounts)); + pw.println(prefix + "mCounts=" + Arrays.toString(mCounts)); } public void addCountLocked(long[] counts) { @@ -1559,9 +1502,9 @@ public class BatteryStatsImpl extends BatteryStats { */ @Override public boolean reset(boolean detachIfReset) { - fillArray(mCounts, 0); - fillArray(mLoadedCounts, 0); - fillArray(mUnpluggedCounts, 0); + if (mCounts != null) { + Arrays.fill(mCounts, 0); + } if (detachIfReset) { detach(); } @@ -1579,8 +1522,6 @@ public class BatteryStatsImpl extends BatteryStats { private void readSummaryFromParcelLocked(Parcel in) { mCounts = in.createLongArray(); - mLoadedCounts = copyArray(mCounts, mLoadedCounts); - mUnpluggedCounts = copyArray(mCounts, mUnpluggedCounts); } public static void writeToParcel(Parcel out, LongSamplingCounterArray counterArray) { @@ -1621,49 +1562,16 @@ public class BatteryStatsImpl extends BatteryStats { return null; } } - - private static void fillArray(long[] a, long val) { - if (a != null) { - Arrays.fill(a, val); - } - } - - private static void subtract(@NonNull long[] val, long[] toSubtract) { - if (toSubtract == null) { - return; - } - for (int i = 0; i < val.length; i++) { - val[i] -= toSubtract[i]; - } - } - - private static long[] copyArray(long[] src, long[] dest) { - if (src == null) { - return null; - } else { - if (dest == null) { - dest = new long[src.length]; - } - System.arraycopy(src, 0, dest, 0, src.length); - return dest; - } - } } @VisibleForTesting public static class LongSamplingCounter extends LongCounter implements TimeBaseObs { final TimeBase mTimeBase; - public long mCount; - public long mCurrentCount; - public long mLoadedCount; - public long mUnpluggedCount; + private long mCount; public LongSamplingCounter(TimeBase timeBase, Parcel in) { mTimeBase = timeBase; mCount = in.readLong(); - mCurrentCount = in.readLong(); - mLoadedCount = in.readLong(); - mUnpluggedCount = in.readLong(); timeBase.add(this); } @@ -1674,14 +1582,10 @@ public class BatteryStatsImpl extends BatteryStats { public void writeToParcel(Parcel out) { out.writeLong(mCount); - out.writeLong(mCurrentCount); - out.writeLong(mLoadedCount); - out.writeLong(mUnpluggedCount); } @Override public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) { - mUnpluggedCount = mCount; } @Override @@ -1689,43 +1593,22 @@ public class BatteryStatsImpl extends BatteryStats { } public long getCountLocked(int which) { - long val = mCount; - if (which == STATS_SINCE_UNPLUGGED) { - val -= mUnpluggedCount; - } else if (which != STATS_SINCE_CHARGED) { - val -= mLoadedCount; - } - return val; + return mCount; } @Override public void logState(Printer pw, String prefix) { - pw.println(prefix + "mCount=" + mCount - + " mCurrentCount=" + mCurrentCount - + " mLoadedCount=" + mLoadedCount - + " mUnpluggedCount=" + mUnpluggedCount); + pw.println(prefix + "mCount=" + mCount); } public void addCountLocked(long count) { - update(mCurrentCount + count, mTimeBase.isRunning()); + addCountLocked(count, mTimeBase.isRunning()); } public void addCountLocked(long count, boolean isRunning) { - update(mCurrentCount + count, isRunning); - } - - public void update(long count) { - update(count, mTimeBase.isRunning()); - } - - public void update(long count, boolean isRunning) { - if (count < mCurrentCount) { - mCurrentCount = 0; - } if (isRunning) { - mCount += count - mCurrentCount; + mCount += count; } - mCurrentCount = count; } /** @@ -1734,7 +1617,6 @@ public class BatteryStatsImpl extends BatteryStats { @Override public boolean reset(boolean detachIfReset) { mCount = 0; - mLoadedCount = mUnpluggedCount = 0; if (detachIfReset) { detach(); } @@ -1751,7 +1633,7 @@ public class BatteryStatsImpl extends BatteryStats { } public void readSummaryFromParcelLocked(Parcel in) { - mCount = mUnpluggedCount= mLoadedCount = in.readLong(); + mCount = in.readLong(); } } @@ -1764,9 +1646,6 @@ public class BatteryStatsImpl extends BatteryStats { protected final TimeBase mTimeBase; protected int mCount; - protected int mLoadedCount; - protected int mLastCount; - protected int mUnpluggedCount; // Times are in microseconds for better accuracy when dividing by the // lock count, and are in "battery realtime" units. @@ -1779,25 +1658,6 @@ public class BatteryStatsImpl extends BatteryStats { protected long mTotalTime; /** - * The total time we loaded for the previous runs. Subtract this from - * mTotalTime to find the time for the current run of the system. - */ - protected long mLoadedTime; - - /** - * The run time of the last run of the system, as loaded from the - * saved data. - */ - protected long mLastTime; - - /** - * The value of mTotalTime when unplug() was last called. Subtract - * this from mTotalTime to find the time since the last unplug from - * power. - */ - protected long mUnpluggedTime; - - /** * The total time this timer has been running until the latest mark has been set. * Subtract this from mTotalTime to get the time spent running since the mark was set. */ @@ -1815,13 +1675,7 @@ public class BatteryStatsImpl extends BatteryStats { mTimeBase = timeBase; mCount = in.readInt(); - mLoadedCount = in.readInt(); - mLastCount = 0; - mUnpluggedCount = in.readInt(); mTotalTime = in.readLong(); - mLoadedTime = in.readLong(); - mLastTime = 0; - mUnpluggedTime = in.readLong(); mTimeBeforeMark = in.readLong(); timeBase.add(this); if (DEBUG) Log.i(TAG, "**** READ TIMER #" + mType + ": mTotalTime=" + mTotalTime); @@ -1834,6 +1688,16 @@ public class BatteryStatsImpl extends BatteryStats { timeBase.add(this); } + public void writeToParcel(Parcel out, long elapsedRealtimeUs) { + if (DEBUG) { + Log.i(TAG, "**** WRITING TIMER #" + mType + ": mTotalTime=" + + computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs))); + } + out.writeInt(computeCurrentCountLocked()); + out.writeLong(computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs))); + out.writeLong(mTimeBeforeMark); + } + protected abstract long computeRunTimeLocked(long curBatteryRealtime); protected abstract int computeCurrentCountLocked(); @@ -1844,8 +1708,8 @@ public class BatteryStatsImpl extends BatteryStats { */ @Override public boolean reset(boolean detachIfReset) { - mTotalTime = mLoadedTime = mLastTime = mTimeBeforeMark = 0; - mCount = mLoadedCount = mLastCount = 0; + mTotalTime = mTimeBeforeMark = 0; + mCount = 0; if (detachIfReset) { detach(); } @@ -1857,32 +1721,8 @@ public class BatteryStatsImpl extends BatteryStats { mTimeBase.remove(this); } - public void writeToParcel(Parcel out, long elapsedRealtimeUs) { - if (DEBUG) Log.i(TAG, "**** WRITING TIMER #" + mType + ": mTotalTime=" - + computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs))); - out.writeInt(computeCurrentCountLocked()); - out.writeInt(mLoadedCount); - out.writeInt(mUnpluggedCount); - out.writeLong(computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs))); - out.writeLong(mLoadedTime); - out.writeLong(mUnpluggedTime); - out.writeLong(mTimeBeforeMark); - } - @Override public void onTimeStarted(long elapsedRealtime, long timeBaseUptime, long baseRealtime) { - if (DEBUG && mType < 0) { - Log.v(TAG, "unplug #" + mType + ": realtime=" + baseRealtime - + " old mUnpluggedTime=" + mUnpluggedTime - + " old mUnpluggedCount=" + mUnpluggedCount); - } - mUnpluggedTime = computeRunTimeLocked(baseRealtime); - mUnpluggedCount = computeCurrentCountLocked(); - if (DEBUG && mType < 0) { - Log.v(TAG, "unplug #" + mType - + ": new mUnpluggedTime=" + mUnpluggedTime - + " new mUnpluggedCount=" + mUnpluggedCount); - } } @Override @@ -1894,8 +1734,7 @@ public class BatteryStatsImpl extends BatteryStats { mTotalTime = computeRunTimeLocked(baseRealtime); mCount = computeCurrentCountLocked(); if (DEBUG && mType < 0) { - Log.v(TAG, "plug #" + mType - + ": new mTotalTime=" + mTotalTime); + Log.v(TAG, "plug #" + mType + ": new mTotalTime=" + mTotalTime); } } @@ -1912,34 +1751,19 @@ public class BatteryStatsImpl extends BatteryStats { return; } out.writeInt(1); // indicates non-null - timer.writeToParcel(out, elapsedRealtimeUs); } @Override @UnsupportedAppUsage public long getTotalTimeLocked(long elapsedRealtimeUs, int which) { - long val = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs)); - if (which == STATS_SINCE_UNPLUGGED) { - val -= mUnpluggedTime; - } else if (which != STATS_SINCE_CHARGED) { - val -= mLoadedTime; - } - - return val; + return computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs)); } @Override @UnsupportedAppUsage public int getCountLocked(int which) { - int val = computeCurrentCountLocked(); - if (which == STATS_SINCE_UNPLUGGED) { - val -= mUnpluggedCount; - } else if (which != STATS_SINCE_CHARGED) { - val -= mLoadedCount; - } - - return val; + return computeCurrentCountLocked(); } @Override @@ -1950,13 +1774,8 @@ public class BatteryStatsImpl extends BatteryStats { @Override public void logState(Printer pw, String prefix) { - pw.println(prefix + "mCount=" + mCount - + " mLoadedCount=" + mLoadedCount + " mLastCount=" + mLastCount - + " mUnpluggedCount=" + mUnpluggedCount); - pw.println(prefix + "mTotalTime=" + mTotalTime - + " mLoadedTime=" + mLoadedTime); - pw.println(prefix + "mLastTime=" + mLastTime - + " mUnpluggedTime=" + mUnpluggedTime); + pw.println(prefix + "mCount=" + mCount); + pw.println(prefix + "mTotalTime=" + mTotalTime); } @@ -1968,13 +1787,8 @@ public class BatteryStatsImpl extends BatteryStats { public void readSummaryFromParcelLocked(Parcel in) { // Multiply by 1000 for backwards compatibility - mTotalTime = mLoadedTime = in.readLong(); - mLastTime = 0; - mUnpluggedTime = mTotalTime; - mCount = mLoadedCount = in.readInt(); - mLastCount = 0; - mUnpluggedCount = mCount; - + mTotalTime = in.readLong(); + mCount = in.readInt(); // When reading the summary, we set the mark to be the latest information. mTimeBeforeMark = mTotalTime; } @@ -2233,7 +2047,7 @@ public class BatteryStatsImpl extends BatteryStats { private long computeOverage(long curTime) { if (mLastAddedTime > 0) { - return mLastTime + mLastAddedDuration - curTime; + return mLastAddedDuration - curTime; } return 0; } @@ -2452,7 +2266,7 @@ public class BatteryStatsImpl extends BatteryStats { mTotalDurationMs = 0; mCurrentDurationMs = 0; if (mNesting > 0) { - mStartTimeMs = mTimeBase.getRealtime(mClocks.elapsedRealtime()*1000) / 1000; + mStartTimeMs = mTimeBase.getRealtime(mClocks.elapsedRealtime() * 1000) / 1000; } else { mStartTimeMs = -1; } @@ -2491,7 +2305,7 @@ public class BatteryStatsImpl extends BatteryStats { public long getCurrentDurationMsLocked(long elapsedRealtimeMs) { long durationMs = mCurrentDurationMs; if (mNesting > 0 && mTimeBase.isRunning()) { - durationMs += (mTimeBase.getRealtime(elapsedRealtimeMs*1000)/1000) + durationMs += (mTimeBase.getRealtime(elapsedRealtimeMs * 1000) / 1000) - mStartTimeMs; } return durationMs; @@ -6401,13 +6215,7 @@ public class BatteryStatsImpl extends BatteryStats { } @Override public int getNumConnectivityChange(int which) { - int val = mNumConnectivityChange; - if (which == STATS_CURRENT) { - val -= mLoadedNumConnectivityChange; - } else if (which == STATS_SINCE_UNPLUGGED) { - val -= mUnpluggedNumConnectivityChange; - } - return val; + return mNumConnectivityChange; } @Override public long getGpsSignalQualityTime(int strengthBin, @@ -9122,66 +8930,6 @@ public class BatteryStatsImpl extends BatteryStats { */ int mNumAnrs; - /** - * The amount of user time loaded from a previous save. - */ - long mLoadedUserTime; - - /** - * The amount of system time loaded from a previous save. - */ - long mLoadedSystemTime; - - /** - * The amount of foreground time loaded from a previous save. - */ - long mLoadedForegroundTime; - - /** - * The number of times the process has started from a previous save. - */ - int mLoadedStarts; - - /** - * Number of times the process has crashed from a previous save. - */ - int mLoadedNumCrashes; - - /** - * Number of times the process has had an ANR from a previous save. - */ - int mLoadedNumAnrs; - - /** - * The amount of user time when last unplugged. - */ - long mUnpluggedUserTime; - - /** - * The amount of system time when last unplugged. - */ - long mUnpluggedSystemTime; - - /** - * The amount of foreground time since unplugged. - */ - long mUnpluggedForegroundTime; - - /** - * The number of times the process has started before unplugged. - */ - int mUnpluggedStarts; - - /** - * Number of times the process has crashed before unplugged. - */ - int mUnpluggedNumCrashes; - - /** - * Number of times the process has had an ANR before unplugged. - */ - int mUnpluggedNumAnrs; - ArrayList<ExcessivePower> mExcessivePower; public Proc(BatteryStatsImpl bsi, String name) { @@ -9191,12 +8939,6 @@ public class BatteryStatsImpl extends BatteryStats { } public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) { - mUnpluggedUserTime = mUserTime; - mUnpluggedSystemTime = mSystemTime; - mUnpluggedForegroundTime = mForegroundTime; - mUnpluggedStarts = mStarts; - mUnpluggedNumCrashes = mNumCrashes; - mUnpluggedNumAnrs = mNumAnrs; } public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) { @@ -9283,18 +9025,6 @@ public class BatteryStatsImpl extends BatteryStats { out.writeInt(mStarts); out.writeInt(mNumCrashes); out.writeInt(mNumAnrs); - out.writeLong(mLoadedUserTime); - out.writeLong(mLoadedSystemTime); - out.writeLong(mLoadedForegroundTime); - out.writeInt(mLoadedStarts); - out.writeInt(mLoadedNumCrashes); - out.writeInt(mLoadedNumAnrs); - out.writeLong(mUnpluggedUserTime); - out.writeLong(mUnpluggedSystemTime); - out.writeLong(mUnpluggedForegroundTime); - out.writeInt(mUnpluggedStarts); - out.writeInt(mUnpluggedNumCrashes); - out.writeInt(mUnpluggedNumAnrs); writeExcessivePowerToParcelLocked(out); } @@ -9305,18 +9035,6 @@ public class BatteryStatsImpl extends BatteryStats { mStarts = in.readInt(); mNumCrashes = in.readInt(); mNumAnrs = in.readInt(); - mLoadedUserTime = in.readLong(); - mLoadedSystemTime = in.readLong(); - mLoadedForegroundTime = in.readLong(); - mLoadedStarts = in.readInt(); - mLoadedNumCrashes = in.readInt(); - mLoadedNumAnrs = in.readInt(); - mUnpluggedUserTime = in.readLong(); - mUnpluggedSystemTime = in.readLong(); - mUnpluggedForegroundTime = in.readLong(); - mUnpluggedStarts = in.readInt(); - mUnpluggedNumCrashes = in.readInt(); - mUnpluggedNumAnrs = in.readInt(); readExcessivePowerFromParcelLocked(in); } @@ -9358,71 +9076,35 @@ public class BatteryStatsImpl extends BatteryStats { @Override @UnsupportedAppUsage public long getUserTime(int which) { - long val = mUserTime; - if (which == STATS_CURRENT) { - val -= mLoadedUserTime; - } else if (which == STATS_SINCE_UNPLUGGED) { - val -= mUnpluggedUserTime; - } - return val; + return mUserTime; } @Override @UnsupportedAppUsage public long getSystemTime(int which) { - long val = mSystemTime; - if (which == STATS_CURRENT) { - val -= mLoadedSystemTime; - } else if (which == STATS_SINCE_UNPLUGGED) { - val -= mUnpluggedSystemTime; - } - return val; + return mSystemTime; } @Override @UnsupportedAppUsage public long getForegroundTime(int which) { - long val = mForegroundTime; - if (which == STATS_CURRENT) { - val -= mLoadedForegroundTime; - } else if (which == STATS_SINCE_UNPLUGGED) { - val -= mUnpluggedForegroundTime; - } - return val; + return mForegroundTime; } @Override @UnsupportedAppUsage public int getStarts(int which) { - int val = mStarts; - if (which == STATS_CURRENT) { - val -= mLoadedStarts; - } else if (which == STATS_SINCE_UNPLUGGED) { - val -= mUnpluggedStarts; - } - return val; + return mStarts; } @Override public int getNumCrashes(int which) { - int val = mNumCrashes; - if (which == STATS_CURRENT) { - val -= mLoadedNumCrashes; - } else if (which == STATS_SINCE_UNPLUGGED) { - val -= mUnpluggedNumCrashes; - } - return val; + return mNumCrashes; } @Override public int getNumAnrs(int which) { - int val = mNumAnrs; - if (which == STATS_CURRENT) { - val -= mLoadedNumAnrs; - } else if (which == STATS_SINCE_UNPLUGGED) { - val -= mUnpluggedNumAnrs; - } - return val; + return mNumAnrs; } } @@ -9588,54 +9270,6 @@ public class BatteryStatsImpl extends BatteryStats { protected int mLaunches; /** - * The amount of time spent started loaded from a previous save - * (ms in battery uptime). - */ - protected long mLoadedStartTime; - - /** - * The number of starts loaded from a previous save. - */ - protected int mLoadedStarts; - - /** - * The number of launches loaded from a previous save. - */ - protected int mLoadedLaunches; - - /** - * The amount of time spent started as of the last run (ms - * in battery uptime). - */ - protected long mLastStartTime; - - /** - * The number of starts as of the last run. - */ - protected int mLastStarts; - - /** - * The number of launches as of the last run. - */ - protected int mLastLaunches; - - /** - * The amount of time spent started when last unplugged (ms - * in battery uptime). - */ - protected long mUnpluggedStartTime; - - /** - * The number of starts when last unplugged. - */ - protected int mUnpluggedStarts; - - /** - * The number of launches when last unplugged. - */ - protected int mUnpluggedLaunches; - - /** * Construct a Serv. Also adds it to the on-battery time base as a listener. */ public Serv(BatteryStatsImpl bsi) { @@ -9645,9 +9279,6 @@ public class BatteryStatsImpl extends BatteryStats { public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) { - mUnpluggedStartTime = getStartTimeToNowLocked(baseUptime); - mUnpluggedStarts = mStarts; - mUnpluggedLaunches = mLaunches; } public void onTimeStopped(long elapsedRealtime, long baseUptime, @@ -9679,15 +9310,6 @@ public class BatteryStatsImpl extends BatteryStats { mLaunchedSince = in.readLong(); mLaunched = in.readInt() != 0; mLaunches = in.readInt(); - mLoadedStartTime = in.readLong(); - mLoadedStarts = in.readInt(); - mLoadedLaunches = in.readInt(); - mLastStartTime = 0; - mLastStarts = 0; - mLastLaunches = 0; - mUnpluggedStartTime = in.readLong(); - mUnpluggedStarts = in.readInt(); - mUnpluggedLaunches = in.readInt(); } public void writeToParcelLocked(Parcel out) { @@ -9699,12 +9321,6 @@ public class BatteryStatsImpl extends BatteryStats { out.writeLong(mLaunchedSince); out.writeInt(mLaunched ? 1 : 0); out.writeInt(mLaunches); - out.writeLong(mLoadedStartTime); - out.writeInt(mLoadedStarts); - out.writeInt(mLoadedLaunches); - out.writeLong(mUnpluggedStartTime); - out.writeInt(mUnpluggedStarts); - out.writeInt(mUnpluggedLaunches); } public long getLaunchTimeToNowLocked(long batteryUptime) { @@ -9768,36 +9384,17 @@ public class BatteryStatsImpl extends BatteryStats { @Override public int getLaunches(int which) { - int val = mLaunches; - if (which == STATS_CURRENT) { - val -= mLoadedLaunches; - } else if (which == STATS_SINCE_UNPLUGGED) { - val -= mUnpluggedLaunches; - } - return val; + return mLaunches; } @Override public long getStartTime(long now, int which) { - long val = getStartTimeToNowLocked(now); - if (which == STATS_CURRENT) { - val -= mLoadedStartTime; - } else if (which == STATS_SINCE_UNPLUGGED) { - val -= mUnpluggedStartTime; - } - return val; + return getStartTimeToNowLocked(now); } @Override public int getStarts(int which) { - int val = mStarts; - if (which == STATS_CURRENT) { - val -= mLoadedStarts; - } else if (which == STATS_SINCE_UNPLUGGED) { - val -= mUnpluggedStarts; - } - - return val; + return mStarts; } } @@ -10932,7 +10529,7 @@ public class BatteryStatsImpl extends BatteryStats { } mBluetoothActivity.reset(false); mModemActivity.reset(false); - mNumConnectivityChange = mLoadedNumConnectivityChange = mUnpluggedNumConnectivityChange = 0; + mNumConnectivityChange = 0; for (int i=0; i<mUidStats.size(); i++) { if (mUidStats.valueAt(i).reset(uptimeMillis * 1000, elapsedRealtimeMillis * 1000)) { @@ -12668,7 +12265,7 @@ public class BatteryStatsImpl extends BatteryStats { startRecordingHistory(elapsedRealtime, uptime, true); } } else if (level < 96 && - status != BatteryManager.BATTERY_STATUS_UNKNOWN) { + status != BatteryManager.BATTERY_STATUS_UNKNOWN) { if (!mRecordingHistory) { mRecordingHistory = true; startRecordingHistory(elapsedRealtime, uptime, true); @@ -12817,8 +12414,8 @@ public class BatteryStatsImpl extends BatteryStats { } } if (!onBattery && - (status == BatteryManager.BATTERY_STATUS_FULL || - status == BatteryManager.BATTERY_STATUS_UNKNOWN)) { + (status == BatteryManager.BATTERY_STATUS_FULL || + status == BatteryManager.BATTERY_STATUS_UNKNOWN)) { // We don't record history while we are plugged in and fully charged // (or when battery is not present). The next time we are // unplugged, history will be cleared. @@ -12855,7 +12452,9 @@ public class BatteryStatsImpl extends BatteryStats { @UnsupportedAppUsage public long getAwakeTimeBattery() { - return computeBatteryUptime(getBatteryUptimeLocked(), STATS_CURRENT); + // This previously evaluated to mOnBatteryTimeBase.getUptime(getBatteryUptimeLocked()); + // for over a decade, but surely that was a mistake. + return getBatteryUptimeLocked(); } @UnsupportedAppUsage @@ -12865,22 +12464,12 @@ public class BatteryStatsImpl extends BatteryStats { @Override public long computeUptime(long curTime, int which) { - switch (which) { - case STATS_SINCE_CHARGED: return mUptime + (curTime-mUptimeStart); - case STATS_CURRENT: return (curTime-mUptimeStart); - case STATS_SINCE_UNPLUGGED: return (curTime-mOnBatteryTimeBase.getUptimeStart()); - } - return 0; + return mUptime + (curTime - mUptimeStart); } @Override public long computeRealtime(long curTime, int which) { - switch (which) { - case STATS_SINCE_CHARGED: return mRealtime + (curTime-mRealtimeStart); - case STATS_CURRENT: return (curTime-mRealtimeStart); - case STATS_SINCE_UNPLUGGED: return (curTime-mOnBatteryTimeBase.getRealtimeStart()); - } - return 0; + return mRealtime + (curTime - mRealtimeStart); } @Override @@ -14074,7 +13663,7 @@ public class BatteryStatsImpl extends BatteryStats { mHasBluetoothReporting = in.readInt() != 0; mHasModemReporting = in.readInt() != 0; - mNumConnectivityChange = mLoadedNumConnectivityChange = in.readInt(); + mNumConnectivityChange = in.readInt(); mFlashlightOnNesting = 0; mFlashlightOnTimer.readSummaryFromParcelLocked(in); mCameraOnNesting = 0; @@ -14383,12 +13972,12 @@ public class BatteryStatsImpl extends BatteryStats { for (int ip = 0; ip < NP; ip++) { String procName = in.readString(); Uid.Proc p = u.getProcessStatsLocked(procName); - p.mUserTime = p.mLoadedUserTime = in.readLong(); - p.mSystemTime = p.mLoadedSystemTime = in.readLong(); - p.mForegroundTime = p.mLoadedForegroundTime = in.readLong(); - p.mStarts = p.mLoadedStarts = in.readInt(); - p.mNumCrashes = p.mLoadedNumCrashes = in.readInt(); - p.mNumAnrs = p.mLoadedNumAnrs = in.readInt(); + p.mUserTime = in.readLong(); + p.mSystemTime = in.readLong(); + p.mForegroundTime = in.readLong(); + p.mStarts = in.readInt(); + p.mNumCrashes = in.readInt(); + p.mNumAnrs = in.readInt(); p.readExcessivePowerFromParcelLocked(in); } @@ -14405,7 +13994,7 @@ public class BatteryStatsImpl extends BatteryStats { throw new ParcelFormatException("File corrupt: too many wakeup alarms " + NWA); } p.mWakeupAlarms.clear(); - for (int iwa=0; iwa<NWA; iwa++) { + for (int iwa = 0; iwa < NWA; iwa++) { String tag = in.readString(); Counter c = new Counter(mOnBatteryScreenOffTimeBase); c.readSummaryFromParcelLocked(in); @@ -14418,9 +14007,9 @@ public class BatteryStatsImpl extends BatteryStats { for (int is = 0; is < NS; is++) { String servName = in.readString(); Uid.Pkg.Serv s = u.getServiceStatsLocked(pkgName, servName); - s.mStartTime = s.mLoadedStartTime = in.readLong(); - s.mStarts = s.mLoadedStarts = in.readInt(); - s.mLaunches = s.mLoadedLaunches = in.readInt(); + s.mStartTime = in.readLong(); + s.mStarts = in.readInt(); + s.mLaunches = in.readInt(); } } } @@ -15054,9 +14643,8 @@ public class BatteryStatsImpl extends BatteryStats { mHasModemReporting = in.readInt() != 0; mNumConnectivityChange = in.readInt(); - mLoadedNumConnectivityChange = in.readInt(); - mUnpluggedNumConnectivityChange = in.readInt(); mAudioOnNesting = 0; + // TODO: It's likely a mistake that mAudioOnTimer/mVideoOnTimer don't write/read to parcel! mAudioOnTimer = new StopwatchTimer(mClocks, null, -7, null, mOnBatteryTimeBase); mVideoOnNesting = 0; mVideoOnTimer = new StopwatchTimer(mClocks, null, -8, null, mOnBatteryTimeBase); @@ -15256,8 +14844,6 @@ public class BatteryStatsImpl extends BatteryStats { out.writeInt(mHasModemReporting ? 1 : 0); out.writeInt(mNumConnectivityChange); - out.writeInt(mLoadedNumConnectivityChange); - out.writeInt(mUnpluggedNumConnectivityChange); mFlashlightOnTimer.writeToParcel(out, uSecRealtime); mCameraOnTimer.writeToParcel(out, uSecRealtime); mBluetoothScanTimer.writeToParcel(out, uSecRealtime); diff --git a/core/java/com/android/internal/os/PowerCalculator.java b/core/java/com/android/internal/os/PowerCalculator.java index cd69d6892eb4..e31c9ded5a42 100644 --- a/core/java/com/android/internal/os/PowerCalculator.java +++ b/core/java/com/android/internal/os/PowerCalculator.java @@ -27,9 +27,10 @@ public abstract class PowerCalculator { * @param u The recorded stats for the app. * @param rawRealtimeUs The raw system realtime in microseconds. * @param rawUptimeUs The raw system uptime in microseconds. - * @param statsType The type of stats. Can be {@link BatteryStats#STATS_CURRENT}, - * {@link BatteryStats#STATS_SINCE_CHARGED}, or - * {@link BatteryStats#STATS_SINCE_UNPLUGGED}. + * @param statsType The type of stats. As of {@link android.os.Build.VERSION_CODES#Q}, this can + * only be {@link BatteryStats#STATS_SINCE_CHARGED}, since + * {@link BatteryStats#STATS_CURRENT} and + * {@link BatteryStats#STATS_SINCE_UNPLUGGED} are deprecated. */ public abstract void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs, long rawUptimeUs, int statsType); @@ -40,9 +41,10 @@ public abstract class PowerCalculator { * @param stats The BatteryStats object from which to retrieve data. * @param rawRealtimeUs The raw system realtime in microseconds. * @param rawUptimeUs The raw system uptime in microseconds. - * @param statsType The type of stats. Can be {@link BatteryStats#STATS_CURRENT}, - * {@link BatteryStats#STATS_SINCE_CHARGED}, or - * {@link BatteryStats#STATS_SINCE_UNPLUGGED}. + * @param statsType The type of stats. As of {@link android.os.Build.VERSION_CODES#Q}, this can + * only be {@link BatteryStats#STATS_SINCE_CHARGED}, since + * {@link BatteryStats#STATS_CURRENT} and + * {@link BatteryStats#STATS_SINCE_UNPLUGGED} are deprecated. */ public void calculateRemaining(BatterySipper app, BatteryStats stats, long rawRealtimeUs, long rawUptimeUs, int statsType) { diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java index c4626c2093e8..b3cfa499de9f 100644 --- a/core/java/com/android/internal/policy/DecorView.java +++ b/core/java/com/android/internal/policy/DecorView.java @@ -218,7 +218,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind private boolean mLastHasRightStableInset = false; private boolean mLastHasLeftStableInset = false; private int mLastWindowFlags = 0; - private boolean mLastShouldAlwaysConsumeNavBar = false; + private boolean mLastShouldAlwaysConsumeSystemBars = false; private int mRootScrollY = 0; @@ -1102,7 +1102,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind disallowAnimate |= (hasLeftStableInset != mLastHasLeftStableInset); mLastHasLeftStableInset = hasLeftStableInset; - mLastShouldAlwaysConsumeNavBar = insets.shouldAlwaysConsumeNavBar(); + mLastShouldAlwaysConsumeSystemBars = insets.shouldAlwaysConsumeSystemBars(); } boolean navBarToRightEdge = isNavBarToRightEdge(mLastBottomInset, mLastRightInset); @@ -1133,7 +1133,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind (attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0 && (sysUiVisibility & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) == 0 && (sysUiVisibility & SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0 - || mLastShouldAlwaysConsumeNavBar; + || mLastShouldAlwaysConsumeSystemBars; // If we didn't request fullscreen layout, but we still got it because of the // mForceWindowDrawsStatusBarBackground flag, also consume top inset. @@ -1142,7 +1142,8 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind && (attrs.flags & FLAG_LAYOUT_IN_SCREEN) == 0 && (attrs.flags & FLAG_LAYOUT_INSET_DECOR) == 0 && mForceWindowDrawsStatusBarBackground - && mLastTopInset != 0; + && mLastTopInset != 0 + || mLastShouldAlwaysConsumeSystemBars; int consumedTop = consumingStatusBar ? mLastTopInset : 0; int consumedRight = consumingNavBar ? mLastRightInset : 0; diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java index ae5c67df8f1e..fb9ff15c79ac 100644 --- a/core/java/com/android/internal/view/BaseIWindow.java +++ b/core/java/com/android/internal/view/BaseIWindow.java @@ -44,7 +44,7 @@ public class BaseIWindow extends IWindow.Stub { public void resized(Rect frame, Rect overscanInsets, Rect contentInsets, Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw, MergedConfiguration mergedConfiguration, Rect backDropFrame, boolean forceLayout, - boolean alwaysConsumeNavBar, int displayId, + boolean alwaysConsumeSystemBars, int displayId, DisplayCutout.ParcelableWrapper displayCutout) { if (reportDraw) { try { diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl index 41e2fc84593e..b36c3fa79251 100644 --- a/core/java/com/android/internal/widget/ILockSettings.aidl +++ b/core/java/com/android/internal/widget/ILockSettings.aidl @@ -42,7 +42,7 @@ interface ILockSettings { long getLong(in String key, in long defaultValue, in int userId); @UnsupportedAppUsage String getString(in String key, in String defaultValue, in int userId); - void setLockCredential(in byte[] credential, int type, in byte[] savedCredential, int requestedQuality, int userId); + void setLockCredential(in byte[] credential, int type, in byte[] savedCredential, int requestedQuality, int userId, boolean allowUntrustedChange); void resetKeyStore(int userId); VerifyCredentialResponse checkCredential(in byte[] credential, int type, int userId, in ICheckCredentialProgressCallback progressCallback); diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index 1965609ff959..dd48c15e836b 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -78,7 +78,6 @@ import java.util.StringJoiner; public class LockPatternUtils { private static final String TAG = "LockPatternUtils"; - private static final boolean DEBUG = false; private static final boolean FRP_CREDENTIAL_ENABLED = true; /** @@ -87,12 +86,6 @@ public class LockPatternUtils { public static final String LEGACY_LOCK_PATTERN_ENABLED = "legacy_lock_pattern_enabled"; /** - * The number of incorrect attempts before which we fall back on an alternative - * method of verifying the user, and resetting their lock pattern. - */ - public static final int FAILED_ATTEMPTS_BEFORE_RESET = 20; - - /** * The interval of the countdown for showing progress of the lockout. */ public static final long FAILED_ATTEMPT_COUNTDOWN_INTERVAL_MS = 1000L; @@ -115,18 +108,23 @@ public class LockPatternUtils { public static final int MIN_LOCK_PASSWORD_SIZE = 4; /** - * The minimum number of dots the user must include in a wrong pattern - * attempt for it to be counted against the counts that affect - * {@link #FAILED_ATTEMPTS_BEFORE_TIMEOUT} and {@link #FAILED_ATTEMPTS_BEFORE_RESET} + * The minimum number of dots the user must include in a wrong pattern attempt for it to be + * counted. */ public static final int MIN_PATTERN_REGISTER_FAIL = MIN_LOCK_PATTERN_SIZE; public static final int CREDENTIAL_TYPE_NONE = -1; - public static final int CREDENTIAL_TYPE_PATTERN = 1; - public static final int CREDENTIAL_TYPE_PASSWORD = 2; + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = {"CREDENTIAL_TYPE_"}, value = { + CREDENTIAL_TYPE_NONE, + CREDENTIAL_TYPE_PATTERN, + CREDENTIAL_TYPE_PASSWORD, // Either pin or password. + }) + public @interface CredentialType {} + /** * Special user id for triggering the FRP verification flow. */ @@ -671,17 +669,25 @@ public class LockPatternUtils { /** * Clear any lock pattern or password. */ - public void clearLock(byte[] savedCredential, int userHandle) { + public boolean clearLock(byte[] savedCredential, int userHandle) { + return clearLock(savedCredential, userHandle, false); + } + + /** + * Clear any lock pattern or password, with the option to ignore incorrect existing credential. + */ + public boolean clearLock(byte[] savedCredential, int userHandle, boolean allowUntrustedChange) { final int currentQuality = getKeyguardStoredPasswordQuality(userHandle); setKeyguardStoredPasswordQuality(PASSWORD_QUALITY_UNSPECIFIED, userHandle); try{ getLockSettings().setLockCredential(null, CREDENTIAL_TYPE_NONE, - savedCredential, PASSWORD_QUALITY_UNSPECIFIED, userHandle); + savedCredential, PASSWORD_QUALITY_UNSPECIFIED, userHandle, + allowUntrustedChange); } catch (Exception e) { Log.e(TAG, "Failed to clear lock", e); setKeyguardStoredPasswordQuality(currentQuality, userHandle); - return; + return false; } if (userHandle == UserHandle.USER_SYSTEM) { @@ -691,6 +697,7 @@ public class LockPatternUtils { } onAfterChangingPassword(userHandle); + return true; } /** @@ -728,19 +735,28 @@ public class LockPatternUtils { /** * Save a lock pattern. * @param pattern The new pattern to save. + * @param savedPattern The previously saved pattern, converted to byte[] format * @param userId the user whose pattern is to be saved. + * + * @return whether this was successful or not. */ - public void saveLockPattern(List<LockPatternView.Cell> pattern, int userId) { - this.saveLockPattern(pattern, null, userId); + public boolean saveLockPattern(List<LockPatternView.Cell> pattern, byte[] savedPattern, + int userId) { + return saveLockPattern(pattern, savedPattern, userId, false); } + /** * Save a lock pattern. * @param pattern The new pattern to save. * @param savedPattern The previously saved pattern, converted to byte[] format * @param userId the user whose pattern is to be saved. + * @param allowUntrustedChange whether we want to allow saving a new password if the existing + * password being provided is incorrect. + * + * @return whether this was successful or not. */ - public void saveLockPattern(List<LockPatternView.Cell> pattern, byte[] savedPattern, - int userId) { + public boolean saveLockPattern(List<LockPatternView.Cell> pattern, byte[] savedPattern, + int userId, boolean allowUntrustedChange) { if (!hasSecureLockScreen()) { throw new UnsupportedOperationException( "This operation requires the lock screen feature."); @@ -755,11 +771,11 @@ public class LockPatternUtils { setKeyguardStoredPasswordQuality(PASSWORD_QUALITY_SOMETHING, userId); try { getLockSettings().setLockCredential(bytePattern, CREDENTIAL_TYPE_PATTERN, savedPattern, - PASSWORD_QUALITY_SOMETHING, userId); + PASSWORD_QUALITY_SOMETHING, userId, allowUntrustedChange); } catch (Exception e) { Log.e(TAG, "Couldn't save lock pattern", e); setKeyguardStoredPasswordQuality(currentQuality, userId); - return; + return false; } // Update the device encryption password. if (userId == UserHandle.USER_SYSTEM @@ -773,6 +789,7 @@ public class LockPatternUtils { reportPatternWasChosen(userId); onAfterChangingPassword(userId); + return true; } private void updateCryptoUserInfo(int userId) { @@ -875,17 +892,20 @@ public class LockPatternUtils { * password. * @param password The password to save * @param savedPassword The previously saved lock password, or null if none - * @param requestedQuality {@see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)} + * @param requestedQuality {@see DevicePolicyManager#getPasswordQuality( + * android.content.ComponentName)} * @param userHandle The userId of the user to change the password for * + * @return whether this was successful or not. + * * @deprecated Pass password as a byte array */ @Deprecated - public void saveLockPassword(String password, String savedPassword, int requestedQuality, + public boolean saveLockPassword(String password, String savedPassword, int requestedQuality, int userHandle) { byte[] passwordBytes = password != null ? password.getBytes() : null; byte[] savedPasswordBytes = savedPassword != null ? savedPassword.getBytes() : null; - saveLockPassword(passwordBytes, savedPasswordBytes, requestedQuality, userHandle); + return saveLockPassword(passwordBytes, savedPasswordBytes, requestedQuality, userHandle); } /** @@ -895,11 +915,34 @@ public class LockPatternUtils { * @param password The password to save * @param savedPassword The previously saved lock password, or null if none * @param requestedQuality {@see DevicePolicyManager#getPasswordQuality( - * android.content.ComponentName)} + * android.content.ComponentName)} * @param userHandle The userId of the user to change the password for + * + * @return whether this was successful or not. */ - public void saveLockPassword(byte[] password, byte[] savedPassword, int requestedQuality, + public boolean saveLockPassword(byte[] password, byte[] savedPassword, int requestedQuality, int userHandle) { + return saveLockPassword(password, savedPassword, requestedQuality, + userHandle, false); + } + + /** + * Save a lock password. Does not ensure that the password is as good + * as the requested mode, but will adjust the mode to be as good as the + * password. + * @param password The password to save + * @param savedPassword The previously saved lock password, or null if none + * @param requestedQuality {@see DevicePolicyManager#getPasswordQuality( + * android.content.ComponentName)} + * @param userHandle The userId of the user to change the password for + * @param allowUntrustedChange whether we want to allow saving a new password if the existing + * password being provided is incorrect. + * + * @return whether this method saved the new password successfully or not. This flow will fail + * and return false if the given credential is wrong and allowUntrustedChange is false. + */ + public boolean saveLockPassword(byte[] password, byte[] savedPassword, + int requestedQuality, int userHandle, boolean allowUntrustedChange) { if (!hasSecureLockScreen()) { throw new UnsupportedOperationException( "This operation requires the lock screen feature."); @@ -915,22 +958,36 @@ public class LockPatternUtils { } final int currentQuality = getKeyguardStoredPasswordQuality(userHandle); - setKeyguardStoredPasswordQuality( - computePasswordQuality(CREDENTIAL_TYPE_PASSWORD, password, requestedQuality), - userHandle); + final int passwordQuality = PasswordMetrics.computeForPassword(password).quality; + final int newKeyguardQuality = + computeKeyguardQuality(CREDENTIAL_TYPE_PASSWORD, requestedQuality, passwordQuality); + setKeyguardStoredPasswordQuality(newKeyguardQuality, userHandle); try { getLockSettings().setLockCredential(password, CREDENTIAL_TYPE_PASSWORD, savedPassword, - requestedQuality, userHandle); + requestedQuality, userHandle, allowUntrustedChange); } catch (Exception e) { Log.e(TAG, "Unable to save lock password", e); setKeyguardStoredPasswordQuality(currentQuality, userHandle); - return; + return false; } - updateEncryptionPasswordIfNeeded(password, - PasswordMetrics.computeForPassword(password).quality, userHandle); + updateEncryptionPasswordIfNeeded(password, passwordQuality, userHandle); updatePasswordHistory(password, userHandle); onAfterChangingPassword(userHandle); + return true; + } + + /** + * Compute keyguard credential quality to store in PASSWORD_TYPE_KEY by computing max between + * them so that digit-only password is distinguished from PIN. + * + * TODO: remove this method and make CREDENTIAL_TYPE distinguish between PIN and password, so + * that this quality is no longer needs to be persisted. + */ + private int computeKeyguardQuality( + @CredentialType int credentialType, int requestedQuality, int passwordQuality) { + return credentialType == CREDENTIAL_TYPE_PASSWORD + ? Math.max(passwordQuality, requestedQuality) : passwordQuality; } /** @@ -1033,24 +1090,6 @@ public class LockPatternUtils { } /** - * Returns the password quality of the given credential, promoting it to a higher level - * if DevicePolicyManager has a stronger quality requirement. This value will be written - * to PASSWORD_TYPE_KEY. - */ - private int computePasswordQuality(int type, byte[] credential, int requestedQuality) { - final int quality; - if (type == CREDENTIAL_TYPE_PASSWORD) { - int computedQuality = PasswordMetrics.computeForPassword(credential).quality; - quality = Math.max(requestedQuality, computedQuality); - } else if (type == CREDENTIAL_TYPE_PATTERN) { - quality = PASSWORD_QUALITY_SOMETHING; - } else /* if (type == CREDENTIAL_TYPE_NONE) */ { - quality = PASSWORD_QUALITY_UNSPECIFIED; - } - return quality; - } - - /** * Enables/disables the Separate Profile Challenge for this {@param userHandle}. This is a no-op * for user handles that do not belong to a managed profile. * @@ -1752,9 +1791,10 @@ public class LockPatternUtils { throw new IllegalArgumentException("password must not be null and at least " + "of length " + MIN_LOCK_PASSWORD_SIZE); } - final int quality = computePasswordQuality(type, credential, requestedQuality); + final int quality = PasswordMetrics.computeForCredential(type, credential).quality; + final int keyguardQuality = computeKeyguardQuality(type, quality, requestedQuality); if (!localService.setLockCredentialWithToken(credential, type, tokenHandle, token, - quality, userId)) { + keyguardQuality, userId)) { return false; } setKeyguardStoredPasswordQuality(quality, userId); diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index da27852a3a35..20bed1b34940 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -1126,6 +1126,12 @@ void AndroidRuntime::start(const char* className, const Vector<String8>& options return; } + const char* tzdataRootDir = getenv("ANDROID_TZDATA_ROOT"); + if (tzdataRootDir == NULL) { + LOG_FATAL("No tz data directory specified with ANDROID_TZDATA_ROOT environment variable."); + return; + } + //const char* kernelHack = getenv("LD_ASSUME_KERNEL"); //ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack); diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp index 02dffdc2ca25..342aba024fc5 100644 --- a/core/jni/android_media_AudioRecord.cpp +++ b/core/jni/android_media_AudioRecord.cpp @@ -821,18 +821,18 @@ static jint android_media_AudioRecord_get_active_microphones(JNIEnv *env, return jStatus; } -static int android_media_AudioRecord_set_microphone_direction(JNIEnv *env, jobject thiz, - jint direction) { +static int android_media_AudioRecord_set_preferred_microphone_direction( + JNIEnv *env, jobject thiz, jint direction) { sp<AudioRecord> lpRecorder = getAudioRecord(env, thiz); if (lpRecorder == NULL) { jniThrowException(env, "java/lang/IllegalStateException", - "Unable to retrieve AudioRecord pointer for setMicrophoneDirection()"); + "Unable to retrieve AudioRecord pointer for setPreferredMicrophoneDirection()"); return (jint)AUDIO_JAVA_ERROR; } jint jStatus = AUDIO_JAVA_SUCCESS; - status_t status = - lpRecorder->setMicrophoneDirection(static_cast<audio_microphone_direction_t>(direction)); + status_t status = lpRecorder->setPreferredMicrophoneDirection( + static_cast<audio_microphone_direction_t>(direction)); if (status != NO_ERROR) { jStatus = nativeToJavaStatus(status); } @@ -840,17 +840,17 @@ static int android_media_AudioRecord_set_microphone_direction(JNIEnv *env, jobje return jStatus; } -static int android_media_AudioRecord_set_microphone_field_dimension(JNIEnv *env, jobject thiz, - jfloat zoom) { +static int android_media_AudioRecord_set_preferred_microphone_field_dimension( + JNIEnv *env, jobject thiz, jfloat zoom) { sp<AudioRecord> lpRecorder = getAudioRecord(env, thiz); if (lpRecorder == NULL) { jniThrowException(env, "java/lang/IllegalStateException", - "Unable to retrieve AudioRecord pointer for setMicrophoneFieldDimension()"); + "Unable to retrieve AudioRecord pointer for setPreferredMicrophoneFieldDimension()"); return (jint)AUDIO_JAVA_ERROR; } jint jStatus = AUDIO_JAVA_SUCCESS; - status_t status = lpRecorder->setMicrophoneFieldDimension(zoom); + status_t status = lpRecorder->setPreferredMicrophoneFieldDimension(zoom); if (status != NO_ERROR) { jStatus = nativeToJavaStatus(status); } @@ -913,10 +913,10 @@ static const JNINativeMethod gMethods[] = { {"native_get_active_microphones", "(Ljava/util/ArrayList;)I", (void *)android_media_AudioRecord_get_active_microphones}, {"native_getPortId", "()I", (void *)android_media_AudioRecord_get_port_id}, - {"native_set_microphone_direction", "(I)I", - (void *)android_media_AudioRecord_set_microphone_direction}, - {"native_set_microphone_field_dimension", "(F)I", - (void *)android_media_AudioRecord_set_microphone_field_dimension}, + {"native_set_preferred_microphone_direction", "(I)I", + (void *)android_media_AudioRecord_set_preferred_microphone_direction}, + {"native_set_preferred_microphone_field_dimension", "(F)I", + (void *)android_media_AudioRecord_set_preferred_microphone_field_dimension}, }; // field names found in android/media/AudioRecord.java diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp index 1a90ebfee999..c8f81e2193c8 100644 --- a/core/jni/android_media_AudioSystem.cpp +++ b/core/jni/android_media_AudioSystem.cpp @@ -2038,13 +2038,13 @@ android_media_AudioSystem_getStreamVolumeDB(JNIEnv *env, jobject thiz, static jboolean android_media_AudioSystem_isOffloadSupported(JNIEnv *env, jobject thiz, - jint encoding, jint sampleRate, jint channelMask, jint channelIndexMask) + jint encoding, jint sampleRate, jint channelMask, jint channelIndexMask, jint streamType) { audio_offload_info_t format = AUDIO_INFO_INITIALIZER; format.format = (audio_format_t) audioFormatToNative(encoding); format.sample_rate = (uint32_t) sampleRate; format.channel_mask = nativeChannelMaskFromJavaChannelMasks(channelMask, channelIndexMask); - format.stream_type = AUDIO_STREAM_MUSIC; + format.stream_type = (audio_stream_type_t) streamType; format.has_video = false; format.is_streaming = false; // offload duration unknown at this point: @@ -2292,7 +2292,7 @@ static const JNINativeMethod gMethods[] = { (void *)android_media_AudioSystem_registerRecordingCallback}, {"systemReady", "()I", (void *)android_media_AudioSystem_systemReady}, {"getStreamVolumeDB", "(III)F", (void *)android_media_AudioSystem_getStreamVolumeDB}, - {"native_is_offload_supported", "(IIII)Z", (void *)android_media_AudioSystem_isOffloadSupported}, + {"native_is_offload_supported", "(IIIII)Z", (void *)android_media_AudioSystem_isOffloadSupported}, {"getMicrophones", "(Ljava/util/ArrayList;)I", (void *)android_media_AudioSystem_getMicrophones}, {"getSurroundFormats", "(Ljava/util/Map;Z)I", (void *)android_media_AudioSystem_getSurroundFormats}, {"setSurroundFormatEnabled", "(IZ)I", (void *)android_media_AudioSystem_setSurroundFormatEnabled}, diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp index cfb2dd199f39..d7a981ed3e9d 100644 --- a/core/jni/android_net_NetUtils.cpp +++ b/core/jni/android_net_NetUtils.cpp @@ -487,6 +487,11 @@ static jbyteArray android_net_utils_resNetworkResult(JNIEnv *env, jobject thiz, return answer; } +static void android_net_utils_resNetworkCancel(JNIEnv *env, jobject thiz, jobject javaFd) { + int fd = jniGetFDFromFileDescriptor(env, javaFd); + resNetworkCancel(fd); +} + static jobject android_net_utils_getTcpRepairWindow(JNIEnv *env, jobject thiz, jobject javaFd) { if (javaFd == NULL) { jniThrowNullPointerException(env, NULL); @@ -546,6 +551,7 @@ static const JNINativeMethod gNetworkUtilMethods[] = { { "resNetworkSend", "(I[BII)Ljava/io/FileDescriptor;", (void*) android_net_utils_resNetworkSend }, { "resNetworkQuery", "(ILjava/lang/String;III)Ljava/io/FileDescriptor;", (void*) android_net_utils_resNetworkQuery }, { "resNetworkResult", "(Ljava/io/FileDescriptor;)[B", (void*) android_net_utils_resNetworkResult }, + { "resNetworkCancel", "(Ljava/io/FileDescriptor;)V", (void*) android_net_utils_resNetworkCancel }, }; int register_android_net_NetworkUtils(JNIEnv* env) diff --git a/core/jni/android_view_InputDevice.cpp b/core/jni/android_view_InputDevice.cpp index a698d66965e4..9f4e3e516ada 100644 --- a/core/jni/android_view_InputDevice.cpp +++ b/core/jni/android_view_InputDevice.cpp @@ -68,9 +68,8 @@ jobject android_view_InputDevice_create(JNIEnv* env, const InputDeviceInfo& devi deviceInfo.getKeyboardType(), kcmObj.get(), deviceInfo.hasVibrator(), hasMic, deviceInfo.hasButtonUnderPad())); - const Vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges(); - for (size_t i = 0; i < ranges.size(); i++) { - const InputDeviceInfo::MotionRange& range = ranges.itemAt(i); + const std::vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges(); + for (const InputDeviceInfo::MotionRange& range: ranges) { env->CallVoidMethod(inputDeviceObj.get(), gInputDeviceClassInfo.addMotionRange, range.axis, range.source, range.min, range.max, range.flat, range.fuzz, range.resolution); if (env->ExceptionCheck()) { diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto index f03740725fe1..25caafb2bf65 100644 --- a/core/proto/android/app/settings_enums.proto +++ b/core/proto/android/app/settings_enums.proto @@ -590,6 +590,13 @@ enum Action { // OS: P DIALOG_SWITCH_HFP_DEVICES = 1416; + // OPEN: QS Sensor Privacy Mode tile shown + // ACTION: QS Sensor Privacy Mode tile tapped + // SUBTYPE: 0 is off, 1 is on + // CATEGORY: QUICK_SETTINGS + // OS: Q + QS_SENSOR_PRIVACY = 1598; + // ACTION: Tap & Pay -> Default Application Setting -> Use Forground ACTION_NFC_PAYMENT_FOREGROUND_SETTING = 1622; diff --git a/core/proto/android/stats/connectivity/Android.bp b/core/proto/android/stats/connectivity/Android.bp new file mode 100644 index 000000000000..5aa4ddbdf7f9 --- /dev/null +++ b/core/proto/android/stats/connectivity/Android.bp @@ -0,0 +1,25 @@ +// 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. + +java_library_static { + name: "networkstackprotosnano", + proto: { + type: "nano", + }, + srcs: [ + "network_stack.proto", + ], + sdk_version: "system_current", + no_framework_libs: true, +}
\ No newline at end of file diff --git a/core/proto/android/stats/connectivity/network_stack.proto b/core/proto/android/stats/connectivity/network_stack.proto new file mode 100644 index 000000000000..7d9aa1c6eb23 --- /dev/null +++ b/core/proto/android/stats/connectivity/network_stack.proto @@ -0,0 +1,26 @@ +/* + * 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. + */ + +syntax = "proto2"; + +package android.stats.connectivity; +option java_multiple_files = true; +option java_outer_classname = "NetworkStackProto"; + +message NetworkStackEventData { + +} + diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 5427147aa32a..cb8ece7070be 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -1849,8 +1849,8 @@ <permission android:name="android.permission.HARDWARE_TEST" android:protectionLevel="signature" /> - <!-- @hide Allows an application to manage DynamicAndroid image --> - <permission android:name="android.permission.MANAGE_DYNAMIC_ANDROID" + <!-- @hide Allows an application to manage DynamicSystem image --> + <permission android:name="android.permission.MANAGE_DYNAMIC_SYSTEM" android:protectionLevel="signature" /> <!-- @SystemApi Allows access to Broadcast Radio @@ -1989,6 +1989,12 @@ <permission android:name="android.permission.BIND_INCALL_SERVICE" android:protectionLevel="signature|privileged" /> + <!-- Allows the app to request network scans from telephony. + <p>Not for use by third-party applications. + @SystemApi @hide--> + <permission android:name="android.permission.NETWORK_SCAN" + android:protectionLevel="signature|privileged" /> + <!-- Must be required by a link {@link android.telephony.VisualVoicemailService} to ensure that only the system can bind to it. <p>Protection level: signature|privileged @@ -3927,7 +3933,7 @@ <permission android:name="android.permission.MANAGE_ROLLBACKS" android:protectionLevel="signature|verifier" /> - <!-- @SystemApi @TestApi @hide Allows testing apk level rollbacks. --> + <!-- @TestApi @hide Allows testing apk level rollbacks. --> <permission android:name="android.permission.TEST_MANAGE_ROLLBACKS" android:protectionLevel="signature" /> @@ -4484,6 +4490,11 @@ <permission android:name="android.permission.SUBSTITUTE_SHARE_TARGET_APP_NAME_AND_ICON" android:protectionLevel="signature|privileged" /> + <!-- @SystemApi Allows an application to access shared libraries. + @hide --> + <permission android:name="android.permission.ACCESS_SHARED_LIBRARIES" + android:protectionLevel="signature|installer" /> + <application android:process="system" android:persistent="true" android:hasCode="false" diff --git a/core/res/res/layout/chooser_row.xml b/core/res/res/layout/chooser_row.xml index d4585eb1e6fc..742d7eedaced 100644 --- a/core/res/res/layout/chooser_row.xml +++ b/core/res/res/layout/chooser_row.xml @@ -21,8 +21,8 @@ android:layout_width="match_parent" android:layout_height="100dp" android:gravity="start|top" - android:paddingStart="@dimen/chooser_grid_padding" - android:paddingEnd="@dimen/chooser_grid_padding"> + android:paddingStart="@dimen/chooser_edge_margin_normal" + android:paddingEnd="@dimen/chooser_edge_margin_normal"> <TextView android:id="@+id/chooser_row_text_option" android:layout_width="match_parent" diff --git a/core/res/res/layout/resolve_grid_item.xml b/core/res/res/layout/resolve_grid_item.xml index 71c153fa6021..4a3dfba63c6d 100644 --- a/core/res/res/layout/resolve_grid_item.xml +++ b/core/res/res/layout/resolve_grid_item.xml @@ -18,7 +18,7 @@ --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" - android:layout_width="76dp" + android:layout_width="@dimen/chooser_target_width" android:layout_height="wrap_content" android:minHeight="100dp" android:gravity="center" @@ -27,22 +27,13 @@ android:focusable="true" android:background="?attr/selectableItemBackgroundBorderless"> - <FrameLayout android:layout_width="wrap_content" - android:layout_height="wrap_content"> - <ImageView android:id="@+id/icon" - android:layout_width="48dp" - android:layout_height="48dp" - android:layout_marginLeft="3dp" - android:layout_marginRight="3dp" - android:layout_marginBottom="3dp" - android:scaleType="fitCenter" /> - <ImageView android:id="@+id/target_badge" - android:layout_width="16dp" - android:layout_height="16dp" - android:layout_gravity="end|bottom" - android:visibility="gone" - android:scaleType="fitCenter" /> - </FrameLayout> + <ImageView android:id="@+id/icon" + android:layout_width="@dimen/resolver_icon_size" + android:layout_height="@dimen/resolver_icon_size" + android:layout_marginLeft="3dp" + android:layout_marginRight="3dp" + android:layout_marginBottom="3dp" + android:scaleType="fitCenter" /> <!-- Activity name --> <TextView android:id="@android:id/text1" diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 71e071c14557..14edf6fe1aa3 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -58,6 +58,7 @@ <item><xliff:g id="id">@string/status_bar_mobile</xliff:g></item> <item><xliff:g id="id">@string/status_bar_airplane</xliff:g></item> <item><xliff:g id="id">@string/status_bar_battery</xliff:g></item> + <item><xliff:g id="id">@string/status_bar_sensors_off</xliff:g></item> </string-array> <string translatable="false" name="status_bar_rotate">rotate</string> @@ -92,6 +93,7 @@ <string translatable="false" name="status_bar_microphone">microphone</string> <string translatable="false" name="status_bar_camera">camera</string> <string translatable="false" name="status_bar_airplane">airplane</string> + <string translatable="false" name="status_bar_sensors_off">sensors_off</string> <!-- Flag indicating whether the surface flinger has limited alpha compositing functionality in hardware. If set, the window @@ -914,6 +916,11 @@ case, this can be disabled (set to false). --> <bool name="config_enableCarDockHomeLaunch">true</bool> + <!-- Control whether to force the display of System UI Bars at all times regardless of + System Ui Flags. This can be useful in the Automotive case if there's a requirement for + a UI element to be on screen at all times. --> + <bool name="config_forceShowSystemBars">false</bool> + <!-- HDMI behavior --> <!-- The number of degrees to rotate the display when the device has HDMI connected diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml index 7134eed8dde8..023fbaddfb83 100644 --- a/core/res/res/values/dimens.xml +++ b/core/res/res/values/dimens.xml @@ -578,7 +578,6 @@ <dimen name="default_magnifier_horizontal_offset">0dp</dimen> <item type="dimen" format="float" name="default_magnifier_zoom">1.25</item> - <dimen name="chooser_grid_padding">0dp</dimen> <!-- Spacing around the background change frome service to non-service --> <dimen name="chooser_service_spacing">8dp</dimen> @@ -725,4 +724,5 @@ <dimen name="chooser_preview_width">-1px</dimen> <dimen name="resolver_icon_size">42dp</dimen> <dimen name="resolver_badge_size">18dp</dimen> + <dimen name="chooser_target_width">76dp</dimen> </resources> diff --git a/core/res/res/values/dimens_car.xml b/core/res/res/values/dimens_car.xml index d2cf40a6bc1f..7b3ac2e0e4b5 100644 --- a/core/res/res/values/dimens_car.xml +++ b/core/res/res/values/dimens_car.xml @@ -21,6 +21,7 @@ <dimen name="car_fullscreen_user_pod_height">356dp</dimen> <dimen name="car_fullscreen_user_pod_image_avatar_width">96dp</dimen> <dimen name="car_fullscreen_user_pod_image_avatar_height">96dp</dimen> + <dimen name="car_large_avatar_size">96dp</dimen> <!-- Application Bar --> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 74970e810181..24fd3a8718bb 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -5295,6 +5295,14 @@ <!-- Summary of notification letting users know why battery saver was turned on automatically [CHAR_LIMIT=NONE]--> <string name="dynamic_mode_notification_summary">Battery Saver activated to extend battery life</string> + <!-- Battery saver strings --> + <!-- The user visible name of the notification channel for battery saver notifications [CHAR_LIMIT=80] --> + <string name="battery_saver_notification_channel_name">Battery Saver</string> + <!-- Title of notification letting users know why battery saver didn't turn back on automatically after the device was unplugged [CHAR_LIMIT=NONE] --> + <string name="battery_saver_sticky_disabled_notification_title">Battery Saver won\u2019t reactivate until battery low again</string> + <!-- Summary of notification letting users know why battery saver didn't turn back on automatically after the device was unplugged [CHAR_LIMIT=NONE] --> + <string name="battery_saver_sticky_disabled_notification_summary">Battery has been charged to a sufficient level. Battery Saver won\u2019t reactivate until the battery is low again.</string> + <!-- Description of media type: folder or directory that contains additional files. [CHAR LIMIT=32] --> <string name="mime_type_folder">Folder</string> <!-- Description of media type: application file, such as APK. [CHAR LIMIT=32] --> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 17ccc31179f9..93c845873c85 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1713,6 +1713,7 @@ <java-symbol type="bool" name="config_enableLockScreenRotation" /> <java-symbol type="bool" name="config_enableLockScreenTranslucentDecor" /> <java-symbol type="bool" name="config_enableTranslucentDecor" /> + <java-symbol type="bool" name="config_forceShowSystemBars" /> <java-symbol type="bool" name="config_lidControlsScreenLock" /> <java-symbol type="bool" name="config_lidControlsSleep" /> <java-symbol type="bool" name="config_lockDayNightMode" /> @@ -2761,6 +2762,7 @@ <java-symbol type="string" name="chooser_no_direct_share_targets" /> <java-symbol type="drawable" name="chooser_row_layer_list" /> <java-symbol type="dimen" name="chooser_view_spacing" /> + <java-symbol type="dimen" name="chooser_target_width" /> <java-symbol type="dimen" name="chooser_edge_margin_thin" /> <java-symbol type="dimen" name="chooser_edge_margin_normal" /> <java-symbol type="dimen" name="chooser_preview_image_font_size"/> @@ -2778,7 +2780,6 @@ <java-symbol type="layout" name="chooser_row" /> <java-symbol type="layout" name="chooser_row_direct_share" /> - <java-symbol type="id" name="target_badge" /> <java-symbol type="bool" name="config_supportDoubleTapWake" /> <java-symbol type="drawable" name="ic_perm_device_info" /> <java-symbol type="string" name="config_radio_access_family" /> @@ -2924,6 +2925,7 @@ <java-symbol type="string" name="status_bar_vpn" /> <java-symbol type="string" name="status_bar_microphone" /> <java-symbol type="string" name="status_bar_camera" /> + <java-symbol type="string" name="status_bar_sensors_off" /> <!-- Locale picker --> <java-symbol type="id" name="locale_search_menu" /> @@ -3588,6 +3590,7 @@ <java-symbol type="dimen" name="car_fullscreen_user_pod_icon_text_size" /> <java-symbol type="dimen" name="car_fullscreen_user_pod_image_avatar_height" /> <java-symbol type="dimen" name="car_fullscreen_user_pod_image_avatar_width" /> + <java-symbol type="dimen" name="car_large_avatar_size" /> <java-symbol type="layout" name="car_user_switching_dialog" /> <java-symbol type="id" name="user_loading_avatar" /> <java-symbol type="id" name="user_loading" /> @@ -3643,6 +3646,9 @@ <!-- For Secondary Launcher --> <java-symbol type="string" name="config_secondaryHomeComponent" /> + <java-symbol type="string" name="battery_saver_notification_channel_name" /> + <java-symbol type="string" name="battery_saver_sticky_disabled_notification_title" /> + <java-symbol type="string" name="battery_saver_sticky_disabled_notification_summary" /> <java-symbol type="string" name="dynamic_mode_notification_channel_name" /> <java-symbol type="string" name="dynamic_mode_notification_title" /> <java-symbol type="string" name="dynamic_mode_notification_summary" /> diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java index 7322a5445e86..85947bde5bc4 100644 --- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java +++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java @@ -623,7 +623,6 @@ public class SettingsBackupTest { Settings.Secure.DEFAULT_INPUT_METHOD, Settings.Secure.DEVICE_PAIRED, Settings.Secure.DIALER_DEFAULT_APPLICATION, - Settings.Secure.DISABLE_AIRPLANE_MODE_AFTER_SP_DISABLED, Settings.Secure.DISABLED_PRINT_SERVICES, Settings.Secure.DISABLED_SYSTEM_INPUT_METHODS, Settings.Secure.DISPLAY_DENSITY_FORCED, @@ -647,8 +646,6 @@ public class SettingsBackupTest { Settings.Secure.LOCK_SCREEN_ALLOW_REMOTE_INPUT, // Candidate? Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, Settings.Secure.LOCK_TO_APP_EXIT_LOCKED, - Settings.Secure.MAINTAIN_AIRPLANE_MODE_AFTER_SP_DISABLED, - Settings.Secure.MAINTAIN_LOCATION_AFTER_SP_DISABLED, Settings.Secure.MANAGED_PROFILE_CONTACT_REMOTE_SEARCH, Settings.Secure.MULTI_PRESS_TIMEOUT, Settings.Secure.NFC_PAYMENT_FOREGROUND, @@ -656,12 +653,12 @@ public class SettingsBackupTest { Settings.Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, Settings.Secure.NUM_ROTATION_SUGGESTIONS_ACCEPTED, Settings.Secure.ODI_CAPTIONS_ENABLED, + Settings.Secure.ODI_CAPTIONS_OPTED_OUT, Settings.Secure.PACKAGE_VERIFIER_STATE, Settings.Secure.PACKAGE_VERIFIER_USER_CONSENT, Settings.Secure.PARENTAL_CONTROL_LAST_UPDATE, Settings.Secure.PAYMENT_SERVICE_SEARCH_URI, Settings.Secure.PRINT_SERVICE_SEARCH_URI, - Settings.Secure.REENABLE_LOCATION_AFTER_SP_DISABLED, Settings.Secure.SCREENSAVER_DEFAULT_COMPONENT, // Candidate? Settings.Secure.SEARCH_GLOBAL_SEARCH_ACTIVITY, Settings.Secure.SEARCH_MAX_RESULTS_PER_SOURCE, @@ -685,7 +682,6 @@ public class SettingsBackupTest { Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE, Settings.Secure.SELECTED_SPELL_CHECKER, // Intentionally removed in Q Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE, // Intentionally removed in Q - Settings.Secure.SENSOR_PRIVACY_SENSOR_STATE, Settings.Secure.SETTINGS_CLASSNAME, Settings.Secure.SHOW_NOTE_ABOUT_NOTIFICATION_HIDING, // candidate? Settings.Secure.SHOW_ROTATION_SUGGESTIONS, diff --git a/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java b/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java index 66146c936dca..4266ba9fe86e 100644 --- a/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java +++ b/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java @@ -24,10 +24,16 @@ import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; +import android.app.Instrumentation; +import android.content.Context; import android.graphics.Point; import android.platform.test.annotations.Presubmit; import android.view.SurfaceControl.Transaction; +import android.view.WindowManager.BadTokenException; +import android.view.WindowManager.LayoutParams; +import android.widget.TextView; +import androidx.test.InstrumentationRegistry; import androidx.test.filters.FlakyTest; import androidx.test.runner.AndroidJUnit4; @@ -47,7 +53,6 @@ public class InsetsSourceConsumerTest { private SurfaceSession mSession = new SurfaceSession(); private SurfaceControl mLeash; @Mock Transaction mMockTransaction; - @Mock InsetsController mMockController; @Before public void setup() { @@ -55,8 +60,21 @@ public class InsetsSourceConsumerTest { mLeash = new SurfaceControl.Builder(mSession) .setName("testSurface") .build(); - mConsumer = new InsetsSourceConsumer(TYPE_TOP_BAR, new InsetsState(), - () -> mMockTransaction, mMockController); + final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); + instrumentation.runOnMainSync(() -> { + final Context context = instrumentation.getTargetContext(); + // cannot mock ViewRootImpl since it's final. + final ViewRootImpl viewRootImpl = new ViewRootImpl(context, context.getDisplay()); + try { + viewRootImpl.setView(new TextView(context), new LayoutParams(), null); + } catch (BadTokenException e) { + // activity isn't running, lets ignore BadTokenException. + } + mConsumer = new InsetsSourceConsumer(TYPE_TOP_BAR, new InsetsState(), + () -> mMockTransaction, new InsetsController(viewRootImpl)); + }); + instrumentation.waitForIdleSync(); + mConsumer.setControl(new InsetsSourceControl(TYPE_TOP_BAR, mLeash, new Point())); } diff --git a/core/tests/coretests/src/android/view/textclassifier/ActionsSuggestionsHelperTest.java b/core/tests/coretests/src/android/view/textclassifier/ActionsSuggestionsHelperTest.java index 5c7287f000b7..67423c8402a3 100644 --- a/core/tests/coretests/src/android/view/textclassifier/ActionsSuggestionsHelperTest.java +++ b/core/tests/coretests/src/android/view/textclassifier/ActionsSuggestionsHelperTest.java @@ -215,6 +215,7 @@ public class ActionsSuggestionsHelperTest { ConversationAction.TYPE_OPEN_URL, 1.0f, null, + null, null ); @@ -235,6 +236,7 @@ public class ActionsSuggestionsHelperTest { ConversationAction.TYPE_OPEN_URL, 1.0f, null, + null, new RemoteActionTemplate[0] ); @@ -255,6 +257,7 @@ public class ActionsSuggestionsHelperTest { ConversationAction.TYPE_OPEN_URL, 1.0f, null, + null, new RemoteActionTemplate[]{ new RemoteActionTemplate( "title", diff --git a/core/tests/coretests/src/android/view/textclassifier/intent/LegacyIntentClassificationFactoryTest.java b/core/tests/coretests/src/android/view/textclassifier/intent/LegacyIntentClassificationFactoryTest.java index 19e5b0a250bb..72d1ab1c9d0c 100644 --- a/core/tests/coretests/src/android/view/textclassifier/intent/LegacyIntentClassificationFactoryTest.java +++ b/core/tests/coretests/src/android/view/textclassifier/intent/LegacyIntentClassificationFactoryTest.java @@ -63,6 +63,7 @@ public class LegacyIntentClassificationFactoryTest { null, null, null, + null, null); List<LabeledIntent> intents = mLegacyIntentClassificationFactory.create( @@ -96,6 +97,7 @@ public class LegacyIntentClassificationFactoryTest { null, null, null, + null, null); List<LabeledIntent> intents = mLegacyIntentClassificationFactory.create( diff --git a/core/tests/coretests/src/android/view/textclassifier/intent/TemplateClassificationIntentFactoryTest.java b/core/tests/coretests/src/android/view/textclassifier/intent/TemplateClassificationIntentFactoryTest.java index eaef0a0c42b1..ccf8607b84d9 100644 --- a/core/tests/coretests/src/android/view/textclassifier/intent/TemplateClassificationIntentFactoryTest.java +++ b/core/tests/coretests/src/android/view/textclassifier/intent/TemplateClassificationIntentFactoryTest.java @@ -81,6 +81,7 @@ public class TemplateClassificationIntentFactoryTest { null, null, null, + null, createRemoteActionTemplates()); List<LabeledIntent> intents = @@ -119,6 +120,7 @@ public class TemplateClassificationIntentFactoryTest { null, null, null, + null, createRemoteActionTemplates()); List<LabeledIntent> intents = @@ -153,6 +155,7 @@ public class TemplateClassificationIntentFactoryTest { null, null, null, + null, null); mTemplateClassificationIntentFactory.create( @@ -185,6 +188,7 @@ public class TemplateClassificationIntentFactoryTest { null, null, null, + null, new RemoteActionTemplate[0]); mTemplateClassificationIntentFactory.create( diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsCounterTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsCounterTest.java index 37f818a70ec9..ade3a991b576 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsCounterTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsCounterTest.java @@ -44,8 +44,6 @@ public class BatteryStatsCounterTest extends TestCase { counter.stepAtomic(); counter.stepAtomic(); assertEquals(0, counter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); - assertEquals(0, counter.getCountLocked(BatteryStats.STATS_CURRENT)); - assertEquals(0, counter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED)); // timeBase on (i.e. unplugged) timeBase.setRunning(true, 2, 2); @@ -54,8 +52,6 @@ public class BatteryStatsCounterTest extends TestCase { counter.stepAtomic(); counter.stepAtomic(); assertEquals(4, counter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); - assertEquals(4, counter.getCountLocked(BatteryStats.STATS_CURRENT)); - assertEquals(4, counter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED)); // timeBase off (i.e. plugged in) timeBase.setRunning(false, 3, 3); @@ -63,16 +59,12 @@ public class BatteryStatsCounterTest extends TestCase { counter.stepAtomic(); counter.stepAtomic(); assertEquals(4, counter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); - assertEquals(4, counter.getCountLocked(BatteryStats.STATS_CURRENT)); - assertEquals(4, counter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED)); // timeBase on (i.e. unplugged) timeBase.setRunning(true, 4, 4); counter.stepAtomic(); counter.stepAtomic(); assertEquals(6, counter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); - assertEquals(6, counter.getCountLocked(BatteryStats.STATS_CURRENT)); - assertEquals(2, counter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED)); } @@ -88,8 +80,6 @@ public class BatteryStatsCounterTest extends TestCase { timeBase.setRunning(true, 1, 1); origCounter.stepAtomic(); origCounter.stepAtomic(); origCounter.stepAtomic(); // three times assertEquals(3, origCounter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); - assertEquals(3, origCounter.getCountLocked(BatteryStats.STATS_CURRENT)); - assertEquals(3, origCounter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED)); // Test summary parcelling (from origCounter) final Parcel summaryParcel = Parcel.obtain(); @@ -102,22 +92,16 @@ public class BatteryStatsCounterTest extends TestCase { // timeBase still on (i.e. unplugged) summaryCounter.stepAtomic(); // once assertEquals(4, summaryCounter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); - assertEquals(1, summaryCounter.getCountLocked(BatteryStats.STATS_CURRENT)); - assertEquals(1, summaryCounter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED)); // timeBase off (i.e. plugged in) timeBase.setRunning(false, 3, 3); summaryCounter.stepAtomic(); summaryCounter.stepAtomic(); // twice assertEquals(4, summaryCounter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); - assertEquals(1, summaryCounter.getCountLocked(BatteryStats.STATS_CURRENT)); - assertEquals(1, summaryCounter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED)); // timeBase on (i.e. unplugged) timeBase.setRunning(true, 4, 4); summaryCounter.stepAtomic(); summaryCounter.stepAtomic(); // twice assertEquals(6, summaryCounter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); - assertEquals(3, summaryCounter.getCountLocked(BatteryStats.STATS_CURRENT)); - assertEquals(2, summaryCounter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED)); // Test full parcelling (from summaryCounter) @@ -130,21 +114,15 @@ public class BatteryStatsCounterTest extends TestCase { // timeBase still on (i.e. unplugged) fullParcelCounter.stepAtomic(); // once assertEquals(7, fullParcelCounter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); - assertEquals(4, fullParcelCounter.getCountLocked(BatteryStats.STATS_CURRENT)); - assertEquals(3, fullParcelCounter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED)); // timeBase off (i.e. plugged in) timeBase.setRunning(false, 5, 5); fullParcelCounter.stepAtomic(); fullParcelCounter.stepAtomic(); // twice assertEquals(7, fullParcelCounter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); - assertEquals(4, fullParcelCounter.getCountLocked(BatteryStats.STATS_CURRENT)); - assertEquals(3, fullParcelCounter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED)); // timeBase on (i.e. unplugged) timeBase.setRunning(true, 6, 6); fullParcelCounter.stepAtomic(); fullParcelCounter.stepAtomic(); // twice assertEquals(9, fullParcelCounter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); - assertEquals(6, fullParcelCounter.getCountLocked(BatteryStats.STATS_CURRENT)); - assertEquals(2, fullParcelCounter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED)); } } diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsDurationTimerTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsDurationTimerTest.java index a42286f6882f..78fa3fb734d6 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsDurationTimerTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsDurationTimerTest.java @@ -100,8 +100,70 @@ public class BatteryStatsDurationTimerTest extends TestCase { assertEquals(30802, timer.getTotalDurationMsLocked(220302)); } + /** + * Tests that reset(boolean detachIfReset) clears the correct times if detachIfReset is false. + */ @SmallTest public void testReset() throws Exception { + final MockClocks clocks = new MockClocks(); + + final BatteryStatsImpl.TimeBase timeBase = new BatteryStatsImpl.TimeBase(); + timeBase.init(clocks.uptimeMillis(), clocks.elapsedRealtime()); + + final BatteryStatsImpl.DurationTimer timer = new BatteryStatsImpl.DurationTimer(clocks, + null, BatteryStats.WAKE_TYPE_PARTIAL, null, timeBase); + + timeBase.setRunning(true, /* uptimeUs */ 0, /* realtimeUs */ 100_000); + timer.startRunningLocked(700); + timer.stopRunningLocked(3_100); + assertFalse(timer.isRunningLocked()); + assertEquals(0, timer.getCurrentDurationMsLocked(6_300)); + assertEquals(2_400, timer.getMaxDurationMsLocked(6_301)); + assertEquals(2_400, timer.getTotalDurationMsLocked(6_302)); + + timer.reset(false); + assertEquals(0, timer.getCurrentDurationMsLocked(12_000)); + assertEquals(0, timer.getMaxDurationMsLocked(12_001)); + assertEquals(0, timer.getTotalDurationMsLocked(12_002)); + + assertEquals(true, timeBase.hasObserver(timer)); + + timer.startRunningLocked(24_100); + clocks.uptime = clocks.realtime = 24_200; + timer.reset(false); + assertEquals(34_300, timer.getCurrentDurationMsLocked(58_500)); + assertEquals(34_301, timer.getMaxDurationMsLocked(58_501)); + assertEquals(34_302, timer.getTotalDurationMsLocked(58_502)); + } + + /** + * Tests that reset(boolean detachIfReset) clears the correct times if detachIfReset is true. + */ + @SmallTest + public void testResetAndDetach() throws Exception { + final MockClocks clocks = new MockClocks(); + + final BatteryStatsImpl.TimeBase timeBase = new BatteryStatsImpl.TimeBase(); + timeBase.init(clocks.uptimeMillis(), clocks.elapsedRealtime()); + + final BatteryStatsImpl.DurationTimer timer = new BatteryStatsImpl.DurationTimer(clocks, + null, BatteryStats.WAKE_TYPE_PARTIAL, null, timeBase); + + timeBase.setRunning(true, /* uptimeUs */ 0, /* realtimeUs */ 100_000); + timer.startRunningLocked(700); + timer.stopRunningLocked(3_100); + assertFalse(timer.isRunningLocked()); + assertEquals(0, timer.getCurrentDurationMsLocked(6_300)); + assertEquals(2_400, timer.getMaxDurationMsLocked(6_301)); + assertEquals(2_400, timer.getTotalDurationMsLocked(6_302)); + + timer.reset(true); + clocks.uptime = clocks.realtime = 7_000; + assertEquals(0, timer.getCurrentDurationMsLocked(8_000)); + assertEquals(0, timer.getMaxDurationMsLocked(8_001)); + assertEquals(0, timer.getTotalDurationMsLocked(8_002)); + + assertEquals(false, timeBase.hasObserver(timer)); } @SmallTest diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsImplTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsImplTest.java index 077182921118..4b37dd226e69 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsImplTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsImplTest.java @@ -325,7 +325,7 @@ public class BatteryStatsImplTest { // Get the total acquisition time long totalTime = u.getWifiMulticastTime(currentTimeMs*1000, - BatteryStats.STATS_SINCE_UNPLUGGED); + BatteryStats.STATS_SINCE_CHARGED); assertEquals("Miscalculations of Multicast wakelock acquisition time", (releaseTimeMs - acquireTimeMs) * 1000, totalTime); } @@ -347,7 +347,7 @@ public class BatteryStatsImplTest { // Get the total acquisition time long totalTime = u.getWifiMulticastTime(currentTimeMs*1000, - BatteryStats.STATS_SINCE_UNPLUGGED); + BatteryStats.STATS_SINCE_CHARGED); assertEquals("Miscalculations of Multicast wakelock acquisition time", (currentTimeMs - acquireTimeMs) * 1000, totalTime); } @@ -377,7 +377,7 @@ public class BatteryStatsImplTest { // Get the total acquisition time long totalTime = u.getWifiMulticastTime(currentTimeMs*1000, - BatteryStats.STATS_SINCE_UNPLUGGED); + BatteryStats.STATS_SINCE_CHARGED); assertEquals("Miscalculations of Multicast wakelock acquisition time", (releaseTimeMs_2 - acquireTimeMs_1) * 1000, totalTime); } @@ -407,7 +407,7 @@ public class BatteryStatsImplTest { // Get the total acquisition time long totalTime = u.getWifiMulticastTime(currentTimeMs*1000, - BatteryStats.STATS_SINCE_UNPLUGGED); + BatteryStats.STATS_SINCE_CHARGED); assertEquals("Miscalculations of Multicast wakelock acquisition time", ((releaseTimeMs_1 - acquireTimeMs_1) + (releaseTimeMs_2 - acquireTimeMs_2)) * 1000, totalTime); diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java index 3e33273feddb..8f5dfc5589fe 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java @@ -16,7 +16,6 @@ package com.android.internal.os; -import static android.os.BatteryStats.STATS_CURRENT; import static android.os.BatteryStats.STATS_SINCE_CHARGED; import static android.os.BatteryStats.WAKE_TYPE_PARTIAL; @@ -388,7 +387,7 @@ public class BatteryStatsNoteTest extends TestCase { bi.noteWakupAlarmLocked("com.foo.bar", UID, null, "tag"); Uid.Pkg pkg = bi.getPackageStatsLocked(UID, "com.foo.bar"); - assertEquals(1, pkg.getWakeupAlarmStats().get("tag").getCountLocked(STATS_CURRENT)); + assertEquals(1, pkg.getWakeupAlarmStats().get("tag").getCountLocked(STATS_SINCE_CHARGED)); assertEquals(1, pkg.getWakeupAlarmStats().size()); } diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsServTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsServTest.java index b9995c443f35..df549c5b51c8 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsServTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsServTest.java @@ -44,15 +44,6 @@ public class BatteryStatsServTest extends TestCase { mLaunchedSince = 6064; mLaunched = true; mLaunches = 8085; - mLoadedStartTime = 9096; - mLoadedStarts = 10017; - mLoadedLaunches = 11118; - mLastStartTime = 12219; - mLastStarts = 13310; - mLastLaunches = 14411; - mUnpluggedStartTime = 15512; - mUnpluggedStarts = 16613; - mUnpluggedLaunches = 17714; } long getStartTime() { @@ -94,42 +85,6 @@ public class BatteryStatsServTest extends TestCase { int getLaunches() { return mLaunches; } - - long getLoadedStartTime() { - return mLoadedStartTime; - } - - int getLoadedStarts() { - return mLoadedStarts; - } - - int getLoadedLaunches() { - return mLoadedLaunches; - } - - long getLastStartTime() { - return mLastStartTime; - } - - int getLastStarts() { - return mLastStarts; - } - - int getLastLaunches() { - return mLastLaunches; - } - - long getUnpluggedStartTime() { - return mUnpluggedStartTime; - } - - int getUnpluggedStarts() { - return mUnpluggedStarts; - } - - int getUnpluggedLaunches() { - return mUnpluggedLaunches; - } } /** @@ -147,29 +102,6 @@ public class BatteryStatsServTest extends TestCase { } /** - * Test OnTimeStarted - */ - @SmallTest - public void testOnTimeStarted() throws Exception { - MockBatteryStatsImpl bsi = new MockBatteryStatsImpl(); - TestServ serv = new TestServ(bsi); - - serv.populate(); - serv.setRunning(true); - serv.onTimeStarted(111111, 20000, 222222); - Assert.assertEquals(18989, serv.getUnpluggedStartTime()); - Assert.assertEquals(4042, serv.getUnpluggedStarts()); - Assert.assertEquals(8085, serv.getUnpluggedLaunches()); - - serv.populate(); - serv.setRunning(false); - serv.onTimeStarted(111111, 20000, 222222); - Assert.assertEquals(1010, serv.getUnpluggedStartTime()); - Assert.assertEquals(4042, serv.getUnpluggedStarts()); - Assert.assertEquals(8085, serv.getUnpluggedLaunches()); - } - - /** * Test parceling and unparceling. */ @SmallTest @@ -185,7 +117,7 @@ public class BatteryStatsServTest extends TestCase { TestServ serv = new TestServ(bsi); serv.readFromParcelLocked(parcel); - + Assert.assertEquals(1010, serv.getStartTime()); Assert.assertEquals(2021, serv.getRunningSince()); Assert.assertTrue(serv.getRunning()); @@ -194,15 +126,8 @@ public class BatteryStatsServTest extends TestCase { Assert.assertEquals(6064, serv.getLaunchedSince()); Assert.assertTrue(serv.getLaunched()); Assert.assertEquals(8085, serv.getLaunches()); - Assert.assertEquals(9096, serv.getLoadedStartTime()); - Assert.assertEquals(10017, serv.getLoadedStarts()); - Assert.assertEquals(11118, serv.getLoadedLaunches()); - Assert.assertEquals(0, serv.getLastStartTime()); - Assert.assertEquals(0, serv.getLastStarts()); - Assert.assertEquals(0, serv.getLastLaunches()); - Assert.assertEquals(15512, serv.getUnpluggedStartTime()); - Assert.assertEquals(16613, serv.getUnpluggedStarts()); - Assert.assertEquals(17714, serv.getUnpluggedLaunches()); + + parcel.recycle(); } /** @@ -267,15 +192,6 @@ public class BatteryStatsServTest extends TestCase { Assert.assertEquals(6064, serv.getLaunchedSince()); Assert.assertTrue(serv.getLaunched()); Assert.assertEquals(8085, serv.getLaunches()); - Assert.assertEquals(9096, serv.getLoadedStartTime()); - Assert.assertEquals(10017, serv.getLoadedStarts()); - Assert.assertEquals(11118, serv.getLoadedLaunches()); - Assert.assertEquals(12219, serv.getLastStartTime()); - Assert.assertEquals(13310, serv.getLastStarts()); - Assert.assertEquals(14411, serv.getLastLaunches()); - Assert.assertEquals(15512, serv.getUnpluggedStartTime()); - Assert.assertEquals(16613, serv.getUnpluggedStarts()); - Assert.assertEquals(17714, serv.getUnpluggedLaunches()); } /** @@ -303,15 +219,6 @@ public class BatteryStatsServTest extends TestCase { Assert.assertEquals(777777L, serv.getLaunchedSince()); // <-- changed Assert.assertTrue(serv.getLaunched()); // <-- changed Assert.assertEquals(8086, serv.getLaunches()); // <-- changed - Assert.assertEquals(9096, serv.getLoadedStartTime()); - Assert.assertEquals(10017, serv.getLoadedStarts()); - Assert.assertEquals(11118, serv.getLoadedLaunches()); - Assert.assertEquals(12219, serv.getLastStartTime()); - Assert.assertEquals(13310, serv.getLastStarts()); - Assert.assertEquals(14411, serv.getLastLaunches()); - Assert.assertEquals(15512, serv.getUnpluggedStartTime()); - Assert.assertEquals(16613, serv.getUnpluggedStarts()); - Assert.assertEquals(17714, serv.getUnpluggedLaunches()); } /** @@ -341,15 +248,6 @@ public class BatteryStatsServTest extends TestCase { Assert.assertEquals(6064, serv.getLaunchedSince()); Assert.assertFalse(serv.getLaunched()); Assert.assertEquals(8085, serv.getLaunches()); - Assert.assertEquals(9096, serv.getLoadedStartTime()); - Assert.assertEquals(10017, serv.getLoadedStarts()); - Assert.assertEquals(11118, serv.getLoadedLaunches()); - Assert.assertEquals(12219, serv.getLastStartTime()); - Assert.assertEquals(13310, serv.getLastStarts()); - Assert.assertEquals(14411, serv.getLastLaunches()); - Assert.assertEquals(15512, serv.getUnpluggedStartTime()); - Assert.assertEquals(16613, serv.getUnpluggedStarts()); - Assert.assertEquals(17714, serv.getUnpluggedLaunches()); } /** @@ -375,19 +273,10 @@ public class BatteryStatsServTest extends TestCase { Assert.assertEquals(2021, serv.getRunningSince()); Assert.assertTrue(serv.getRunning()); Assert.assertEquals(4042, serv.getStarts()); - Assert.assertEquals(777777L-6064+5053, serv.getLaunchedTime()); // <-- changed + Assert.assertEquals(777777L-6064+5053, serv.getLaunchedTime()); // <-- changed Assert.assertEquals(6064, serv.getLaunchedSince()); Assert.assertFalse(serv.getLaunched()); Assert.assertEquals(8085, serv.getLaunches()); - Assert.assertEquals(9096, serv.getLoadedStartTime()); - Assert.assertEquals(10017, serv.getLoadedStarts()); - Assert.assertEquals(11118, serv.getLoadedLaunches()); - Assert.assertEquals(12219, serv.getLastStartTime()); - Assert.assertEquals(13310, serv.getLastStarts()); - Assert.assertEquals(14411, serv.getLastLaunches()); - Assert.assertEquals(15512, serv.getUnpluggedStartTime()); - Assert.assertEquals(16613, serv.getUnpluggedStarts()); - Assert.assertEquals(17714, serv.getUnpluggedLaunches()); } /** @@ -416,16 +305,7 @@ public class BatteryStatsServTest extends TestCase { Assert.assertEquals(5053, serv.getLaunchedTime()); Assert.assertEquals(6064, serv.getLaunchedSince()); Assert.assertFalse(serv.getLaunched()); - Assert.assertEquals(8085-1, serv.getLaunches()); // <-- changed - Assert.assertEquals(9096, serv.getLoadedStartTime()); - Assert.assertEquals(10017, serv.getLoadedStarts()); - Assert.assertEquals(11118, serv.getLoadedLaunches()); - Assert.assertEquals(12219, serv.getLastStartTime()); - Assert.assertEquals(13310, serv.getLastStarts()); - Assert.assertEquals(14411, serv.getLastLaunches()); - Assert.assertEquals(15512, serv.getUnpluggedStartTime()); - Assert.assertEquals(16613, serv.getUnpluggedStarts()); - Assert.assertEquals(17714, serv.getUnpluggedLaunches()); + Assert.assertEquals(8085-1, serv.getLaunches()); // <-- changed } /** @@ -455,15 +335,6 @@ public class BatteryStatsServTest extends TestCase { Assert.assertEquals(6064, serv.getLaunchedSince()); Assert.assertTrue(serv.getLaunched()); Assert.assertEquals(8085, serv.getLaunches()); - Assert.assertEquals(9096, serv.getLoadedStartTime()); - Assert.assertEquals(10017, serv.getLoadedStarts()); - Assert.assertEquals(11118, serv.getLoadedLaunches()); - Assert.assertEquals(12219, serv.getLastStartTime()); - Assert.assertEquals(13310, serv.getLastStarts()); - Assert.assertEquals(14411, serv.getLastLaunches()); - Assert.assertEquals(15512, serv.getUnpluggedStartTime()); - Assert.assertEquals(16613, serv.getUnpluggedStarts()); - Assert.assertEquals(17714, serv.getUnpluggedLaunches()); } /** @@ -492,15 +363,6 @@ public class BatteryStatsServTest extends TestCase { Assert.assertEquals(6064, serv.getLaunchedSince()); Assert.assertTrue(serv.getLaunched()); Assert.assertEquals(8085, serv.getLaunches()); - Assert.assertEquals(9096, serv.getLoadedStartTime()); - Assert.assertEquals(10017, serv.getLoadedStarts()); - Assert.assertEquals(11118, serv.getLoadedLaunches()); - Assert.assertEquals(12219, serv.getLastStartTime()); - Assert.assertEquals(13310, serv.getLastStarts()); - Assert.assertEquals(14411, serv.getLastLaunches()); - Assert.assertEquals(15512, serv.getUnpluggedStartTime()); - Assert.assertEquals(16613, serv.getUnpluggedStarts()); - Assert.assertEquals(17714, serv.getUnpluggedLaunches()); } /** @@ -530,15 +392,6 @@ public class BatteryStatsServTest extends TestCase { Assert.assertEquals(6064, serv.getLaunchedSince()); Assert.assertTrue(serv.getLaunched()); Assert.assertEquals(8085, serv.getLaunches()); - Assert.assertEquals(9096, serv.getLoadedStartTime()); - Assert.assertEquals(10017, serv.getLoadedStarts()); - Assert.assertEquals(11118, serv.getLoadedLaunches()); - Assert.assertEquals(12219, serv.getLastStartTime()); - Assert.assertEquals(13310, serv.getLastStarts()); - Assert.assertEquals(14411, serv.getLastLaunches()); - Assert.assertEquals(15512, serv.getUnpluggedStartTime()); - Assert.assertEquals(16613, serv.getUnpluggedStarts()); - Assert.assertEquals(17714, serv.getUnpluggedLaunches()); } /** @@ -568,15 +421,6 @@ public class BatteryStatsServTest extends TestCase { Assert.assertEquals(6064, serv.getLaunchedSince()); Assert.assertTrue(serv.getLaunched()); Assert.assertEquals(8085, serv.getLaunches()); - Assert.assertEquals(9096, serv.getLoadedStartTime()); - Assert.assertEquals(10017, serv.getLoadedStarts()); - Assert.assertEquals(11118, serv.getLoadedLaunches()); - Assert.assertEquals(12219, serv.getLastStartTime()); - Assert.assertEquals(13310, serv.getLastStarts()); - Assert.assertEquals(14411, serv.getLastLaunches()); - Assert.assertEquals(15512, serv.getUnpluggedStartTime()); - Assert.assertEquals(16613, serv.getUnpluggedStarts()); - Assert.assertEquals(17714, serv.getUnpluggedLaunches()); } /** @@ -600,8 +444,6 @@ public class BatteryStatsServTest extends TestCase { serv.populate(); Assert.assertEquals(8085, serv.getLaunches(BatteryStats.STATS_SINCE_CHARGED)); - Assert.assertEquals(8085-11118, serv.getLaunches(BatteryStats.STATS_CURRENT)); - Assert.assertEquals(8085-17714, serv.getLaunches(BatteryStats.STATS_SINCE_UNPLUGGED)); // No change to fields Assert.assertEquals(1010, serv.getStartTime()); @@ -612,15 +454,6 @@ public class BatteryStatsServTest extends TestCase { Assert.assertEquals(6064, serv.getLaunchedSince()); Assert.assertTrue(serv.getLaunched()); Assert.assertEquals(8085, serv.getLaunches()); - Assert.assertEquals(9096, serv.getLoadedStartTime()); - Assert.assertEquals(10017, serv.getLoadedStarts()); - Assert.assertEquals(11118, serv.getLoadedLaunches()); - Assert.assertEquals(12219, serv.getLastStartTime()); - Assert.assertEquals(13310, serv.getLastStarts()); - Assert.assertEquals(14411, serv.getLastLaunches()); - Assert.assertEquals(15512, serv.getUnpluggedStartTime()); - Assert.assertEquals(16613, serv.getUnpluggedStarts()); - Assert.assertEquals(17714, serv.getUnpluggedLaunches()); } /** @@ -637,10 +470,6 @@ public class BatteryStatsServTest extends TestCase { Assert.assertEquals(startTimeToNow, serv.getStartTime(20000, BatteryStats.STATS_SINCE_CHARGED)); - Assert.assertEquals(startTimeToNow-9096, - serv.getStartTime(20000, BatteryStats.STATS_CURRENT)); - Assert.assertEquals(startTimeToNow-15512, - serv.getStartTime(20000, BatteryStats.STATS_SINCE_UNPLUGGED)); // No change to fields Assert.assertEquals(1010, serv.getStartTime()); @@ -651,15 +480,6 @@ public class BatteryStatsServTest extends TestCase { Assert.assertEquals(6064, serv.getLaunchedSince()); Assert.assertTrue(serv.getLaunched()); Assert.assertEquals(8085, serv.getLaunches()); - Assert.assertEquals(9096, serv.getLoadedStartTime()); - Assert.assertEquals(10017, serv.getLoadedStarts()); - Assert.assertEquals(11118, serv.getLoadedLaunches()); - Assert.assertEquals(12219, serv.getLastStartTime()); - Assert.assertEquals(13310, serv.getLastStarts()); - Assert.assertEquals(14411, serv.getLastLaunches()); - Assert.assertEquals(15512, serv.getUnpluggedStartTime()); - Assert.assertEquals(16613, serv.getUnpluggedStarts()); - Assert.assertEquals(17714, serv.getUnpluggedLaunches()); } /** @@ -676,10 +496,6 @@ public class BatteryStatsServTest extends TestCase { Assert.assertEquals(startTimeToNow, serv.getStartTime(20000, BatteryStats.STATS_SINCE_CHARGED)); - Assert.assertEquals(startTimeToNow-9096, - serv.getStartTime(20000, BatteryStats.STATS_CURRENT)); - Assert.assertEquals(startTimeToNow-15512, - serv.getStartTime(20000, BatteryStats.STATS_SINCE_UNPLUGGED)); // No change to fields Assert.assertEquals(1010, serv.getStartTime()); @@ -690,15 +506,6 @@ public class BatteryStatsServTest extends TestCase { Assert.assertEquals(6064, serv.getLaunchedSince()); Assert.assertTrue(serv.getLaunched()); Assert.assertEquals(8085, serv.getLaunches()); - Assert.assertEquals(9096, serv.getLoadedStartTime()); - Assert.assertEquals(10017, serv.getLoadedStarts()); - Assert.assertEquals(11118, serv.getLoadedLaunches()); - Assert.assertEquals(12219, serv.getLastStartTime()); - Assert.assertEquals(13310, serv.getLastStarts()); - Assert.assertEquals(14411, serv.getLastLaunches()); - Assert.assertEquals(15512, serv.getUnpluggedStartTime()); - Assert.assertEquals(16613, serv.getUnpluggedStarts()); - Assert.assertEquals(17714, serv.getUnpluggedLaunches()); } @@ -712,8 +519,6 @@ public class BatteryStatsServTest extends TestCase { serv.populate(); Assert.assertEquals(4042, serv.getStarts(BatteryStats.STATS_SINCE_CHARGED)); - Assert.assertEquals(4042-10017, serv.getStarts(BatteryStats.STATS_CURRENT)); - Assert.assertEquals(4042-16613, serv.getStarts(BatteryStats.STATS_SINCE_UNPLUGGED)); // No change to fields Assert.assertEquals(1010, serv.getStartTime()); @@ -724,15 +529,6 @@ public class BatteryStatsServTest extends TestCase { Assert.assertEquals(6064, serv.getLaunchedSince()); Assert.assertTrue(serv.getLaunched()); Assert.assertEquals(8085, serv.getLaunches()); - Assert.assertEquals(9096, serv.getLoadedStartTime()); - Assert.assertEquals(10017, serv.getLoadedStarts()); - Assert.assertEquals(11118, serv.getLoadedLaunches()); - Assert.assertEquals(12219, serv.getLastStartTime()); - Assert.assertEquals(13310, serv.getLastStarts()); - Assert.assertEquals(14411, serv.getLastLaunches()); - Assert.assertEquals(15512, serv.getUnpluggedStartTime()); - Assert.assertEquals(16613, serv.getUnpluggedStarts()); - Assert.assertEquals(17714, serv.getUnpluggedLaunches()); } } diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimeBaseTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimeBaseTest.java index bce8b40cc31d..e5441c018875 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimeBaseTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimeBaseTest.java @@ -282,12 +282,6 @@ public class BatteryStatsTimeBaseTest extends TestCase { Assert.assertEquals(100+300+666-400, tb.computeUptime(666, BatteryStats.STATS_SINCE_CHARGED)); - Assert.assertEquals(300+666-400, - tb.computeUptime(666, BatteryStats.STATS_CURRENT)); - Assert.assertEquals(300+666-400-50, - tb.computeUptime(666, BatteryStats.STATS_SINCE_UNPLUGGED)); - - Assert.assertEquals(0, tb.computeUptime(666, 6000)); } /** @@ -301,12 +295,6 @@ public class BatteryStatsTimeBaseTest extends TestCase { Assert.assertEquals(200+500+6666-600, tb.computeRealtime(6666, BatteryStats.STATS_SINCE_CHARGED)); - Assert.assertEquals(500+6666-600, - tb.computeRealtime(6666, BatteryStats.STATS_CURRENT)); - Assert.assertEquals(500+6666-600-60, - tb.computeRealtime(6666, BatteryStats.STATS_SINCE_UNPLUGGED)); - - Assert.assertEquals(0, tb.computeUptime(666, 6000)); } /** diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimerTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimerTest.java index 87dc2f3dd43b..40e3a5f55ca5 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimerTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimerTest.java @@ -66,30 +66,6 @@ public class BatteryStatsTimerTest extends TestCase { mCount = val; } - public int getLoadedCount() { - return mLoadedCount; - } - - public void setLoadedCount(int val) { - mLoadedCount = val; - } - - public int getLastCount() { - return mLastCount; - } - - public void setLastCount(int val) { - mLastCount = val; - } - - public int getUnpluggedCount() { - return mUnpluggedCount; - } - - public void setUnpluggedCount(int val) { - mUnpluggedCount = val; - } - public long getTotalTime() { return mTotalTime; } @@ -98,30 +74,6 @@ public class BatteryStatsTimerTest extends TestCase { mTotalTime = val; } - public long getLoadedTime() { - return mLoadedTime; - } - - public void setLoadedTime(long val) { - mLoadedTime = val; - } - - public long getLastTime() { - return mLastTime; - } - - public void setLastTime(long val) { - mLastTime = val; - } - - public long getUnpluggedTime() { - return mUnpluggedTime; - } - - public void setUnpluggedTime(long val) { - mUnpluggedTime = val; - } - public long getTimeBeforeMark() { return mTimeBeforeMark; } @@ -143,16 +95,12 @@ public class BatteryStatsTimerTest extends TestCase { TestTimer timer = new TestTimer(clocks, 0, timeBase); timer.nextComputeCurrentCount = 3000; - // Test that starting the timer counts the unplugged time and counters + // Test that stopping the timer updates mTotalTime and mCount timer.nextComputeRunTime = 4; timer.onTimeStarted(10, 20, 50); - Assert.assertEquals(50, timer.lastComputeRunTimeRealtime); - Assert.assertEquals(4, timer.getUnpluggedTime()); - Assert.assertEquals(3000, timer.getUnpluggedCount()); - - // Test that stopping the timer updates mTotalTime and mCount timer.nextComputeRunTime = 17; timer.onTimeStopped(100, 130, 170); + Assert.assertEquals(170, timer.lastComputeRunTimeRealtime); Assert.assertEquals(17, timer.getTotalTime()); Assert.assertEquals(3000, timer.getCount()); } @@ -168,13 +116,7 @@ public class BatteryStatsTimerTest extends TestCase { // Test write then read TestTimer timer1 = new TestTimer(clocks, 0, timeBase); timer1.setCount(1); - timer1.setLoadedCount(3); - timer1.setLastCount(4); - timer1.setUnpluggedCount(5); timer1.setTotalTime(9223372036854775807L); - timer1.setLoadedTime(9223372036854775806L); - timer1.setLastTime(9223372036854775805L); - timer1.setUnpluggedTime(9223372036854775804L); timer1.setTimeBeforeMark(9223372036854775803L); timer1.nextComputeRunTime = 201; timer1.nextComputeCurrentCount = 2; @@ -187,13 +129,7 @@ public class BatteryStatsTimerTest extends TestCase { TestTimer timer2 = new TestTimer(clocks, 0, timeBase, parcel); Assert.assertEquals(2, timer2.getCount()); // from computeTotalCountLocked() - Assert.assertEquals(3, timer2.getLoadedCount()); - Assert.assertEquals(0, timer2.getLastCount()); // NOT saved - Assert.assertEquals(5, timer2.getUnpluggedCount()); Assert.assertEquals(201, timer2.getTotalTime()); // from computeRunTimeLocked() - Assert.assertEquals(9223372036854775806L, timer2.getLoadedTime()); - Assert.assertEquals(0, timer2.getLastTime()); // NOT saved - Assert.assertEquals(9223372036854775804L, timer2.getUnpluggedTime()); Assert.assertEquals(9223372036854775803L, timer2.getTimeBeforeMark()); parcel.recycle(); @@ -224,25 +160,13 @@ public class BatteryStatsTimerTest extends TestCase { TestTimer timer = new TestTimer(clocks, 0, timeBase); timer.setCount(1); - timer.setLoadedCount(2); - timer.setLastCount(3); - timer.setUnpluggedCount(4); timer.setTotalTime(9223372036854775807L); - timer.setLoadedTime(9223372036854775806L); - timer.setLastTime(9223372036854775805L); - timer.setUnpluggedTime(9223372036854775804L); timer.setTimeBeforeMark(9223372036854775803L); timer.reset(false); Assert.assertEquals(0, timer.getCount()); - Assert.assertEquals(0, timer.getLoadedCount()); - Assert.assertEquals(0, timer.getLastCount()); - Assert.assertEquals(4, timer.getUnpluggedCount()); Assert.assertEquals(0, timer.getTotalTime()); - Assert.assertEquals(0, timer.getLoadedTime()); - Assert.assertEquals(0, timer.getLastTime()); - Assert.assertEquals(9223372036854775804L, timer.getUnpluggedTime()); Assert.assertEquals(0, timer.getTimeBeforeMark()); // reset(false) shouldn't remove it from the list @@ -259,25 +183,13 @@ public class BatteryStatsTimerTest extends TestCase { TestTimer timer = new TestTimer(clocks, 0, timeBase); timer.setCount(1); - timer.setLoadedCount(2); - timer.setLastCount(3); - timer.setUnpluggedCount(4); timer.setTotalTime(9223372036854775807L); - timer.setLoadedTime(9223372036854775806L); - timer.setLastTime(9223372036854775805L); - timer.setUnpluggedTime(9223372036854775804L); timer.setTimeBeforeMark(9223372036854775803L); timer.reset(true); Assert.assertEquals(0, timer.getCount()); - Assert.assertEquals(0, timer.getLoadedCount()); - Assert.assertEquals(0, timer.getLastCount()); - Assert.assertEquals(4, timer.getUnpluggedCount()); Assert.assertEquals(0, timer.getTotalTime()); - Assert.assertEquals(0, timer.getLoadedTime()); - Assert.assertEquals(0, timer.getLastTime()); - Assert.assertEquals(9223372036854775804L, timer.getUnpluggedTime()); Assert.assertEquals(0, timer.getTimeBeforeMark()); // reset(true) should remove it from the list @@ -299,13 +211,7 @@ public class BatteryStatsTimerTest extends TestCase { TestTimer timer1 = new TestTimer(clocks, 0, timeBase); timer1.setCount(1); - timer1.setLoadedCount(2); - timer1.setLastCount(3); - timer1.setUnpluggedCount(4); timer1.setTotalTime(9223372036854775807L); - timer1.setLoadedTime(9223372036854775806L); - timer1.setLastTime(9223372036854775805L); - timer1.setUnpluggedTime(9223372036854775804L); timer1.setTimeBeforeMark(9223372036854775803L); Parcel parcel = Parcel.obtain(); @@ -318,13 +224,7 @@ public class BatteryStatsTimerTest extends TestCase { // Make sure that all the values get touched timer2.setCount(666); - timer2.setLoadedCount(666); - timer2.setLastCount(666); - timer2.setUnpluggedCount(666); timer2.setTotalTime(666); - timer2.setLoadedTime(666); - timer2.setLastTime(666); - timer2.setUnpluggedTime(666); timer2.setTimeBeforeMark(666); parcel.setDataPosition(0); @@ -333,13 +233,7 @@ public class BatteryStatsTimerTest extends TestCase { timer2.readSummaryFromParcelLocked(parcel); Assert.assertEquals(1, timer2.getCount()); - Assert.assertEquals(1, timer2.getLoadedCount()); - Assert.assertEquals(0, timer2.getLastCount()); - Assert.assertEquals(1, timer2.getUnpluggedCount()); Assert.assertEquals(9223372036854775800L, timer2.getTotalTime()); - Assert.assertEquals(9223372036854775800L, timer2.getLoadedTime()); - Assert.assertEquals(0, timer2.getLastTime()); - Assert.assertEquals(9223372036854775800L, timer2.getUnpluggedTime()); Assert.assertEquals(9223372036854775800L, timer2.getTimeBeforeMark()); parcel.recycle(); @@ -359,32 +253,15 @@ public class BatteryStatsTimerTest extends TestCase { TestTimer timer = new TestTimer(clocks, 0, timeBase); timer.setCount(1); - timer.setLoadedCount(2); - timer.setLastCount(3); - timer.setUnpluggedCount(4); timer.setTotalTime(100); - timer.setLoadedTime(200); - timer.setLastTime(300); - timer.setUnpluggedTime(400); timer.setTimeBeforeMark(500); timer.nextComputeRunTime = 10000; - // Timer.getTotalTimeLocked(STATS_SINCE_CHARGED) timer.lastComputeRunTimeRealtime = -1; Assert.assertEquals(10000, timer.getTotalTimeLocked(66, BatteryStats.STATS_SINCE_CHARGED)); Assert.assertEquals(40, timer.lastComputeRunTimeRealtime); - - // Timer.getTotalTimeLocked(STATS_CURRENT) - timer.lastComputeRunTimeRealtime = -1; - Assert.assertEquals(9800, timer.getTotalTimeLocked(66, BatteryStats.STATS_CURRENT)); - Assert.assertEquals(40, timer.lastComputeRunTimeRealtime); - - // Timer.getTotalTimeLocked(STATS_SINCE_UNPLUGGED) - timer.lastComputeRunTimeRealtime = -1; - Assert.assertEquals(9600, timer.getTotalTimeLocked(66, BatteryStats.STATS_SINCE_UNPLUGGED)); - Assert.assertEquals(40, timer.lastComputeRunTimeRealtime); } /** @@ -401,26 +278,11 @@ public class BatteryStatsTimerTest extends TestCase { TestTimer timer = new TestTimer(clocks, 0, timeBase); timer.setCount(1); - timer.setLoadedCount(2); - timer.setLastCount(3); - timer.setUnpluggedCount(4); timer.setTotalTime(100); - timer.setLoadedTime(200); - timer.setLastTime(300); - timer.setUnpluggedTime(400); timer.setTimeBeforeMark(500); - // Timer.getCountLocked(STATS_SINCE_CHARGED) timer.nextComputeCurrentCount = 10000; Assert.assertEquals(10000, timer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); - - // Timer.getCountLocked(STATS_CURRENT) - timer.nextComputeCurrentCount = 10000; - Assert.assertEquals(9998, timer.getCountLocked(BatteryStats.STATS_CURRENT)); - - // Timer.getCountLocked(STATS_SINCE_UNPLUGGED) - timer.nextComputeCurrentCount = 10000; - Assert.assertEquals(9996, timer.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED)); } /** @@ -437,13 +299,7 @@ public class BatteryStatsTimerTest extends TestCase { TestTimer timer = new TestTimer(clocks, 0, timeBase); timer.setCount(1); - timer.setLoadedCount(2); - timer.setLastCount(3); - timer.setUnpluggedCount(4); timer.setTotalTime(100); - timer.setLoadedTime(200); - timer.setLastTime(300); - timer.setUnpluggedTime(400); timer.setTimeBeforeMark(500); timer.nextComputeRunTime = 10000; @@ -460,30 +316,16 @@ public class BatteryStatsTimerTest extends TestCase { TestTimer timer = new TestTimer(clocks, 0, timeBase); timer.setTotalTime(100); - timer.setLoadedTime(200); - timer.setLastTime(300); - timer.setUnpluggedTime(400); timer.setTimeBeforeMark(500); timer.setCount(1); - timer.setLoadedCount(2); - timer.setLastCount(3); - timer.setUnpluggedCount(4); timer.setTotalTime(9223372036854775807L); - timer.setLoadedTime(9223372036854775806L); - timer.setLastTime(9223372036854775805L); - timer.setUnpluggedTime(9223372036854775804L); timer.setTimeBeforeMark(9223372036854775803L); StringBuilder sb = new StringBuilder(); StringBuilderPrinter pw = new StringBuilderPrinter(sb); timer.logState(pw, " "); - - Assert.assertEquals( - " mCount=1 mLoadedCount=2 mLastCount=3 mUnpluggedCount=4\n" - + " mTotalTime=9223372036854775807 mLoadedTime=9223372036854775806\n" - + " mLastTime=9223372036854775805 mUnpluggedTime=9223372036854775804\n", - sb.toString()); + Assert.assertEquals(" mCount=1\n mTotalTime=9223372036854775807\n", sb.toString()); } } diff --git a/core/tests/coretests/src/com/android/internal/os/LongSamplingCounterArrayTest.java b/core/tests/coretests/src/com/android/internal/os/LongSamplingCounterArrayTest.java index 0516bb7f74d7..ee5d2d62f5fd 100644 --- a/core/tests/coretests/src/com/android/internal/os/LongSamplingCounterArrayTest.java +++ b/core/tests/coretests/src/com/android/internal/os/LongSamplingCounterArrayTest.java @@ -16,14 +16,12 @@ package com.android.internal.os; -import static android.os.BatteryStats.STATS_CURRENT; import static android.os.BatteryStats.STATS_SINCE_CHARGED; -import static android.os.BatteryStats.STATS_SINCE_UNPLUGGED; import static com.android.internal.os.BatteryStatsImpl.LongSamplingCounterArray; import static com.android.internal.os.BatteryStatsImpl.TimeBase; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertArrayEquals; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyZeroInteractions; @@ -41,8 +39,6 @@ import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; -import java.util.Arrays; - /** * Test class for {@link BatteryStatsImpl.LongSamplingCounterArray}. * @@ -57,14 +53,15 @@ import java.util.Arrays; * ${ANDROID_PRODUCT_OUT}/data/app/FrameworksCoreTests/FrameworksCoreTests.apk * Run: adb shell am instrument -e class com.android.internal.os.LongSamplingCounterArrayTest -w \ * com.android.frameworks.coretests/androidx.test.runner.AndroidJUnitRunner + * + * or just do + * atest frameworks/base/core/tests/coretests/src/com/android/internal/os/LongSamplingCounterArrayTest.java */ @SmallTest @RunWith(AndroidJUnit4.class) public class LongSamplingCounterArrayTest { private static final long[] COUNTS = {1111, 2222, 3333, 4444}; - private static final long[] LOADED_COUNTS = {5555, 6666, 7777, 8888}; - private static final long[] UNPLUGGED_COUNTS = {44444, 55555, 66666, 77777}; private static final long[] ZEROES = {0, 0, 0, 0}; @Mock private TimeBase mTimeBase; @@ -80,75 +77,54 @@ public class LongSamplingCounterArrayTest { @Test public void testReadWriteParcel() { final Parcel parcel = Parcel.obtain(); - initializeCounterArrayWithDefaultValues(); + updateCounts(COUNTS); LongSamplingCounterArray.writeToParcel(parcel, mCounterArray); parcel.setDataPosition(0); // Now clear counterArray and verify values are read from parcel correctly. - updateCounts(null, null, null); + updateCounts(null); mCounterArray = LongSamplingCounterArray.readFromParcel(parcel, mTimeBase); - assertArrayEquals(COUNTS, mCounterArray.mCounts, "Unexpected counts"); - assertArrayEquals(LOADED_COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts"); - assertArrayEquals(UNPLUGGED_COUNTS, mCounterArray.mUnpluggedCounts, - "Unexpected unpluggedCounts"); + assertArrayEquals(COUNTS, mCounterArray.mCounts); parcel.recycle(); } @Test public void testReadWriteSummaryParcel() { final Parcel parcel = Parcel.obtain(); - initializeCounterArrayWithDefaultValues(); + updateCounts(COUNTS); LongSamplingCounterArray.writeSummaryToParcelLocked(parcel, mCounterArray); parcel.setDataPosition(0); // Now clear counterArray and verify values are read from parcel correctly. - updateCounts(null, null, null); + updateCounts(null); mCounterArray = LongSamplingCounterArray.readSummaryFromParcelLocked(parcel, mTimeBase); - assertArrayEquals(COUNTS, mCounterArray.mCounts, "Unexpected counts"); - assertArrayEquals(COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts"); - assertArrayEquals(COUNTS, mCounterArray.mUnpluggedCounts, "Unexpected unpluggedCounts"); + assertArrayEquals(COUNTS, mCounterArray.mCounts); parcel.recycle(); } @Test public void testOnTimeStarted() { - initializeCounterArrayWithDefaultValues(); + updateCounts(COUNTS); mCounterArray.onTimeStarted(0, 0, 0); - assertArrayEquals(COUNTS, mCounterArray.mCounts, "Unexpected counts"); - assertArrayEquals(LOADED_COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts"); - assertArrayEquals(COUNTS, mCounterArray.mUnpluggedCounts, - "Unexpected unpluggedCounts"); + assertArrayEquals(COUNTS, mCounterArray.mCounts); } @Test public void testOnTimeStopped() { - initializeCounterArrayWithDefaultValues(); + updateCounts(COUNTS); mCounterArray.onTimeStopped(0, 0, 0); - assertArrayEquals(COUNTS, mCounterArray.mCounts, "Unexpected counts"); - assertArrayEquals(LOADED_COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts"); - assertArrayEquals(UNPLUGGED_COUNTS, mCounterArray.mUnpluggedCounts, - "Unexpected unpluggedCounts"); + assertArrayEquals(COUNTS, mCounterArray.mCounts); } @Test public void testGetCountsLocked() { - initializeCounterArrayWithDefaultValues(); + updateCounts(COUNTS); when(mTimeBase.isRunning()).thenReturn(false); - assertArrayEquals(COUNTS, mCounterArray.getCountsLocked(STATS_SINCE_CHARGED), - "Unexpected values"); - assertArrayEquals(subtract(COUNTS, LOADED_COUNTS), - mCounterArray.getCountsLocked(STATS_CURRENT), "Unexpected values"); - assertArrayEquals(subtract(COUNTS, UNPLUGGED_COUNTS), - mCounterArray.getCountsLocked(STATS_SINCE_UNPLUGGED), "Unexpected values"); + assertArrayEquals(COUNTS, mCounterArray.getCountsLocked(STATS_SINCE_CHARGED)); when(mTimeBase.isRunning()).thenReturn(true); - assertArrayEquals(COUNTS, mCounterArray.getCountsLocked(STATS_SINCE_CHARGED), - "Unexpected values"); - assertArrayEquals(subtract(COUNTS, LOADED_COUNTS), - mCounterArray.getCountsLocked(STATS_CURRENT), "Unexpected values"); - assertArrayEquals(subtract(COUNTS, UNPLUGGED_COUNTS), - mCounterArray.getCountsLocked(STATS_SINCE_UNPLUGGED), "Unexpected values"); + assertArrayEquals(COUNTS, mCounterArray.getCountsLocked(STATS_SINCE_CHARGED)); } private long[] subtract(long[] val, long[] toSubtract) { @@ -163,64 +139,45 @@ public class LongSamplingCounterArrayTest { @Test public void testAddCountLocked() { - updateCounts(null, null, null); + updateCounts(null); final long[] deltas = {123, 234, 345, 456}; when(mTimeBase.isRunning()).thenReturn(true); mCounterArray.addCountLocked(deltas); - assertArrayEquals(deltas, mCounterArray.mCounts, "Unexpected counts"); - assertArrayEquals(null, mCounterArray.mLoadedCounts, "Unexpected loadedCounts"); - assertArrayEquals(null, mCounterArray.mUnpluggedCounts, "Unexpected unpluggedCounts"); + assertArrayEquals(deltas, mCounterArray.mCounts); - updateCounts(null, null, null); + updateCounts(null); mCounterArray.addCountLocked(deltas, false); - assertArrayEquals(null, mCounterArray.mCounts, "Unexpected counts"); - assertArrayEquals(null, mCounterArray.mLoadedCounts, "Unexpected loadedCounts"); - assertArrayEquals(null, mCounterArray.mUnpluggedCounts, "Unexpected unpluggedCounts"); + assertArrayEquals(null, mCounterArray.mCounts); mCounterArray.addCountLocked(deltas, true); - assertArrayEquals(deltas, mCounterArray.mCounts, "Unexpected counts"); - assertArrayEquals(null, mCounterArray.mLoadedCounts, "Unexpected loadedCounts"); - assertArrayEquals(null, mCounterArray.mUnpluggedCounts, "Unexpected unpluggedCounts"); + assertArrayEquals(deltas, mCounterArray.mCounts); - initializeCounterArrayWithDefaultValues(); + updateCounts(COUNTS); final long[] newCounts = new long[deltas.length]; for (int i = 0; i < deltas.length; ++i) { newCounts[i] = COUNTS[i] + deltas[i]; } mCounterArray.addCountLocked(deltas); - assertArrayEquals(newCounts, mCounterArray.mCounts, "Unexpected counts"); - assertArrayEquals(LOADED_COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts"); - assertArrayEquals(UNPLUGGED_COUNTS, mCounterArray.mUnpluggedCounts, - "Unexpected unpluggedCounts"); + assertArrayEquals(newCounts, mCounterArray.mCounts); - initializeCounterArrayWithDefaultValues(); + updateCounts(COUNTS); mCounterArray.addCountLocked(deltas, false); - assertArrayEquals(COUNTS, mCounterArray.mCounts, "Unexpected counts"); - assertArrayEquals(LOADED_COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts"); - assertArrayEquals(UNPLUGGED_COUNTS, mCounterArray.mUnpluggedCounts, - "Unexpected unpluggedCounts"); + assertArrayEquals(COUNTS, mCounterArray.mCounts); mCounterArray.addCountLocked(deltas, true); - assertArrayEquals(newCounts, mCounterArray.mCounts, "Unexpected counts"); - assertArrayEquals(LOADED_COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts"); - assertArrayEquals(UNPLUGGED_COUNTS, mCounterArray.mUnpluggedCounts, - "Unexpected unpluggedCounts"); + assertArrayEquals(newCounts, mCounterArray.mCounts); } @Test public void testReset() { - initializeCounterArrayWithDefaultValues(); + updateCounts(COUNTS); // Test with detachIfReset=false mCounterArray.reset(false /* detachIfReset */); - assertArrayEquals(ZEROES, mCounterArray.mCounts, "Unexpected counts"); - assertArrayEquals(ZEROES, mCounterArray.mLoadedCounts, "Unexpected loadedCounts"); - assertArrayEquals(ZEROES, mCounterArray.mUnpluggedCounts, "Unexpected unpluggedCounts"); + assertArrayEquals(ZEROES, mCounterArray.mCounts); verifyZeroInteractions(mTimeBase); - initializeCounterArrayWithDefaultValues(); + updateCounts(COUNTS); // Test with detachIfReset=true mCounterArray.reset(true /* detachIfReset */); - assertArrayEquals(ZEROES, mCounterArray.mCounts, "Unexpected counts"); - assertArrayEquals(ZEROES, mCounterArray.mLoadedCounts, "Unexpected loadedCounts"); - assertArrayEquals(ZEROES, mCounterArray.mUnpluggedCounts, "Unexpected unpluggedCounts"); + assertArrayEquals(ZEROES, mCounterArray.mCounts); verify(mTimeBase).remove(mCounterArray); verifyNoMoreInteractions(mTimeBase); } @@ -232,18 +189,7 @@ public class LongSamplingCounterArrayTest { verifyNoMoreInteractions(mTimeBase); } - private void initializeCounterArrayWithDefaultValues() { - updateCounts(COUNTS, LOADED_COUNTS, UNPLUGGED_COUNTS); - } - - private void assertArrayEquals(long[] expected, long[] actual, String msg) { - assertTrue(msg + ", expected: " + Arrays.toString(expected) - + ", actual: " + Arrays.toString(actual), Arrays.equals(expected, actual)); - } - - private void updateCounts(long[] counts, long[] loadedCounts, long[] unpluggedCounts) { + private void updateCounts(long[] counts) { mCounterArray.mCounts = counts == null ? null : counts.clone(); - mCounterArray.mLoadedCounts = loadedCounts == null ? null : loadedCounts.clone(); - mCounterArray.mUnpluggedCounts = unpluggedCounts == null ? null : unpluggedCounts.clone(); } } diff --git a/core/tests/coretests/src/com/android/internal/os/LongSamplingCounterTest.java b/core/tests/coretests/src/com/android/internal/os/LongSamplingCounterTest.java index d2f5735ce3c1..dccc3d3d76fa 100644 --- a/core/tests/coretests/src/com/android/internal/os/LongSamplingCounterTest.java +++ b/core/tests/coretests/src/com/android/internal/os/LongSamplingCounterTest.java @@ -51,7 +51,6 @@ import org.mockito.MockitoAnnotations; public class LongSamplingCounterTest { private static final long COUNT = 1111; - private static final long CURRENT_COUNT = 5555; @Mock private TimeBase mTimeBase; @@ -67,116 +66,87 @@ public class LongSamplingCounterTest { @Test public void testReadWriteParcel() { final Parcel parcel = Parcel.obtain(); - updateCounts(COUNT, CURRENT_COUNT); + mCounter.addCountLocked(COUNT, true); + assertEquals(COUNT, getCount()); mCounter.writeToParcel(parcel); parcel.setDataPosition(0); - // Now clear counterArray and verify values are read from parcel correctly. - updateCounts(0, 0); + // Now change count but verify values are read from parcel correctly. + mCounter.addCountLocked(7 * COUNT, true); + assertEquals(8 * COUNT, getCount()); mCounter = new LongSamplingCounter(mTimeBase, parcel); - assertEquals(COUNT, mCounter.mCount); - assertEquals(CURRENT_COUNT, mCounter.mCurrentCount); + assertEquals(COUNT, getCount()); parcel.recycle(); } @Test public void testReadWriteSummaryParcel() { final Parcel parcel = Parcel.obtain(); - updateCounts(COUNT, CURRENT_COUNT); + mCounter.addCountLocked(COUNT, true); + assertEquals(COUNT, getCount()); mCounter.writeSummaryFromParcelLocked(parcel); parcel.setDataPosition(0); - // Now clear counterArray and verify values are read from parcel correctly. - updateCounts(0, 0); + // Now change count but verify values are read from parcel correctly. + mCounter.addCountLocked(7 * COUNT, true); + assertEquals(8 * COUNT, getCount()); mCounter.readSummaryFromParcelLocked(parcel); - assertEquals(COUNT, mCounter.mCount); + assertEquals(COUNT, getCount()); parcel.recycle(); } @Test public void testOnTimeStarted() { - updateCounts(COUNT, CURRENT_COUNT); + mCounter.addCountLocked(COUNT, true); + assertEquals(COUNT, getCount()); mCounter.onTimeStarted(0, 0, 0); - assertEquals(COUNT, mCounter.mCount); - assertEquals(COUNT, mCounter.mUnpluggedCount); + assertEquals(COUNT, getCount()); } @Test public void testOnTimeStopped() { - updateCounts(COUNT, CURRENT_COUNT); + mCounter.addCountLocked(COUNT, true); + assertEquals(COUNT, getCount()); mCounter.onTimeStopped(0, 0, 0); - assertEquals(COUNT, mCounter.mCount); + assertEquals(COUNT, getCount()); } @Test public void testAddCountLocked() { - updateCounts(0, 0); - assertEquals(0, mCounter.getCountLocked(0)); + assertEquals(0, getCount()); when(mTimeBase.isRunning()).thenReturn(true); mCounter.addCountLocked(111); assertEquals(111, mCounter.getCountLocked(STATS_SINCE_CHARGED)); - assertEquals(111, mCounter.mCurrentCount); mCounter.addCountLocked(222); assertEquals(333, mCounter.getCountLocked(STATS_SINCE_CHARGED)); - assertEquals(333, mCounter.mCurrentCount); when(mTimeBase.isRunning()).thenReturn(false); mCounter.addCountLocked(456); assertEquals(333, mCounter.getCountLocked(STATS_SINCE_CHARGED)); - assertEquals(789, mCounter.mCurrentCount); mCounter.addCountLocked(444, true); assertEquals(777, mCounter.getCountLocked(STATS_SINCE_CHARGED)); - assertEquals(1233, mCounter.mCurrentCount); mCounter.addCountLocked(567, false); assertEquals(777, mCounter.getCountLocked(STATS_SINCE_CHARGED)); - assertEquals(1800, mCounter.mCurrentCount); } - @Test - public void testUpdate() { - updateCounts(0, 0); - assertEquals(0, mCounter.getCountLocked(0)); - when(mTimeBase.isRunning()).thenReturn(true); - mCounter.update(111); - assertEquals(111, mCounter.getCountLocked(STATS_SINCE_CHARGED)); - assertEquals(111, mCounter.mCurrentCount); - mCounter.update(333); - assertEquals(333, mCounter.getCountLocked(STATS_SINCE_CHARGED)); - assertEquals(333, mCounter.mCurrentCount); - - when(mTimeBase.isRunning()).thenReturn(false); - mCounter.update(789); - assertEquals(333, mCounter.getCountLocked(STATS_SINCE_CHARGED)); - assertEquals(789, mCounter.mCurrentCount); - mCounter.update(100); - assertEquals(333, mCounter.getCountLocked(STATS_SINCE_CHARGED)); - assertEquals(100, mCounter.mCurrentCount); - - mCounter.update(544, true); - assertEquals(777, mCounter.getCountLocked(STATS_SINCE_CHARGED)); - assertEquals(544, mCounter.mCurrentCount); - mCounter.update(1544, false); - assertEquals(777, mCounter.getCountLocked(STATS_SINCE_CHARGED)); - assertEquals(1544, mCounter.mCurrentCount); - } @Test public void testReset() { - updateCounts(COUNT, CURRENT_COUNT); + mCounter.addCountLocked(COUNT, true); + assertEquals(COUNT, getCount()); // Test with detachIfReset=false mCounter.reset(false /* detachIfReset */); - assertEquals(0, mCounter.mCount); - assertEquals(CURRENT_COUNT, mCounter.mCurrentCount); + assertEquals(0, getCount()); verifyZeroInteractions(mTimeBase); - updateCounts(COUNT, CURRENT_COUNT); + mCounter.addCountLocked(COUNT, true); + assertEquals(COUNT, getCount()); // Test with detachIfReset=true mCounter.reset(true /* detachIfReset */); - assertEquals(0, mCounter.mCount); - assertEquals(CURRENT_COUNT, mCounter.mCurrentCount); + assertEquals(0, getCount()); verify(mTimeBase).remove(mCounter); verifyNoMoreInteractions(mTimeBase); } @@ -188,8 +158,7 @@ public class LongSamplingCounterTest { verifyNoMoreInteractions(mTimeBase); } - private void updateCounts(long total, long current) { - mCounter.mCount = total; - mCounter.mCurrentCount = current; + private long getCount() { + return mCounter.getCountLocked(STATS_SINCE_CHARGED); } } diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml index fcd5d566f250..aa1a217e71b6 100644 --- a/data/etc/privapp-permissions-platform.xml +++ b/data/etc/privapp-permissions-platform.xml @@ -112,7 +112,6 @@ applications that come with the platform <permission name="android.permission.MANAGE_USERS"/> <permission name="android.permission.UPDATE_APP_OPS_STATS"/> <permission name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME"/> - <permission name="android.permission.CLEAR_APP_USER_DATA"/> <permission name="android.permission.PACKAGE_USAGE_STATS"/> </privapp-permissions> @@ -124,6 +123,7 @@ applications that come with the platform <permission name="android.permission.UPDATE_APP_OPS_STATS"/> <permission name="android.permission.REQUEST_INCIDENT_REPORT_APPROVAL"/> <permission name="android.permission.APPROVE_INCIDENT_REPORTS"/> + <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE" /> </privapp-permissions> <privapp-permissions package="com.android.phone"> @@ -307,6 +307,7 @@ applications that come with the platform <permission name="android.permission.WRITE_SECURE_SETTINGS"/> <permission name="android.permission.STATUS_BAR_SERVICE"/> <permission name="android.permission.REQUEST_INCIDENT_REPORT_APPROVAL"/> + <permission name="android.permission.CONTROL_KEYGUARD_SECURE_NOTIFICATIONS"/> </privapp-permissions> <privapp-permissions package="com.android.statementservice"> @@ -329,9 +330,9 @@ applications that come with the platform <permission name="android.permission.CONTROL_VPN"/> </privapp-permissions> - <privapp-permissions package="com.android.dynandroid"> + <privapp-permissions package="com.android.dynsystem"> <permission name="android.permission.REBOOT"/> - <permission name="android.permission.MANAGE_DYNAMIC_ANDROID"/> + <permission name="android.permission.MANAGE_DYNAMIC_SYSTEM"/> </privapp-permissions> </permissions> diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java index 346c7ab970dd..c48546103a6f 100644 --- a/graphics/java/android/graphics/Paint.java +++ b/graphics/java/android/graphics/Paint.java @@ -229,7 +229,8 @@ public class Paint { public static final int VERTICAL_TEXT_FLAG = 0x1000; // These flags are always set on a new/reset paint, even if flags 0 is passed. - static final int HIDDEN_DEFAULT_PAINT_FLAGS = DEV_KERN_TEXT_FLAG | EMBEDDED_BITMAP_TEXT_FLAG; + static final int HIDDEN_DEFAULT_PAINT_FLAGS = DEV_KERN_TEXT_FLAG | EMBEDDED_BITMAP_TEXT_FLAG + | FILTER_BITMAP_FLAG; /** * Font hinter option that disables font hinting. diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp index 9916da5d9f10..b8ebf3bb0ca9 100644 --- a/libs/hwui/renderthread/VulkanManager.cpp +++ b/libs/hwui/renderthread/VulkanManager.cpp @@ -439,34 +439,47 @@ Frame VulkanManager::dequeueNextBuffer(VulkanSurface* surface) { LOG_ALWAYS_FATAL_IF(!bufferInfo->dequeued); if (bufferInfo->dequeue_fence != -1) { - int fence_clone = dup(bufferInfo->dequeue_fence); - if (fence_clone == -1) { - ALOGE("dup(fence) failed, stalling until signalled: %s (%d)", strerror(errno), errno); - sync_wait(bufferInfo->dequeue_fence, -1 /* forever */); - } else { - VkSemaphoreCreateInfo semaphoreInfo; - semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; - semaphoreInfo.pNext = nullptr; - semaphoreInfo.flags = 0; - VkSemaphore semaphore; - VkResult err = mCreateSemaphore(mDevice, &semaphoreInfo, nullptr, &semaphore); - LOG_ALWAYS_FATAL_IF(VK_SUCCESS != err, "Failed to create import semaphore, err: %d", - err); - - VkImportSemaphoreFdInfoKHR importInfo; - importInfo.sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR; - importInfo.pNext = nullptr; - importInfo.semaphore = semaphore; - importInfo.flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT; - importInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT; - importInfo.fd = fence_clone; - - err = mImportSemaphoreFdKHR(mDevice, &importInfo); - LOG_ALWAYS_FATAL_IF(VK_SUCCESS != err, "Failed to import semaphore, err: %d", err); - - GrBackendSemaphore backendSemaphore; - backendSemaphore.initVulkan(semaphore); - bufferInfo->skSurface->wait(1, &backendSemaphore); + struct sync_file_info* finfo = sync_file_info(bufferInfo->dequeue_fence); + bool isSignalPending = false; + if (finfo != NULL) { + isSignalPending = finfo->status != 1; + sync_file_info_free(finfo); + } + if (isSignalPending) { + int fence_clone = dup(bufferInfo->dequeue_fence); + if (fence_clone == -1) { + ALOGE("dup(fence) failed, stalling until signalled: %s (%d)", strerror(errno), + errno); + sync_wait(bufferInfo->dequeue_fence, -1 /* forever */); + } else { + VkSemaphoreCreateInfo semaphoreInfo; + semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; + semaphoreInfo.pNext = nullptr; + semaphoreInfo.flags = 0; + VkSemaphore semaphore; + VkResult err = mCreateSemaphore(mDevice, &semaphoreInfo, nullptr, &semaphore); + LOG_ALWAYS_FATAL_IF(VK_SUCCESS != err, "Failed to create import semaphore, err: %d", + err); + + VkImportSemaphoreFdInfoKHR importInfo; + importInfo.sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR; + importInfo.pNext = nullptr; + importInfo.semaphore = semaphore; + importInfo.flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT; + importInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT; + importInfo.fd = fence_clone; + + err = mImportSemaphoreFdKHR(mDevice, &importInfo); + LOG_ALWAYS_FATAL_IF(VK_SUCCESS != err, "Failed to import semaphore, err: %d", err); + + GrBackendSemaphore backendSemaphore; + backendSemaphore.initVulkan(semaphore); + bufferInfo->skSurface->wait(1, &backendSemaphore); + // The following flush blocks the GPU immediately instead of waiting for other + // drawing ops. It seems dequeue_fence is not respected otherwise. + //TODO: remove the flush after finding why backendSemaphore is not working. + bufferInfo->skSurface->flush(); + } } } diff --git a/libs/hwui/renderthread/VulkanSurface.cpp b/libs/hwui/renderthread/VulkanSurface.cpp index c03c3a896e26..a98eb322cfc7 100644 --- a/libs/hwui/renderthread/VulkanSurface.cpp +++ b/libs/hwui/renderthread/VulkanSurface.cpp @@ -256,11 +256,44 @@ VulkanSurface* VulkanSurface::Create(ANativeWindow* window, ColorMode colorMode, vkPixelFormat = VK_FORMAT_R16G16B16A16_SFLOAT; } - uint64_t producerUsage = - AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER | AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE; - uint64_t consumerUsage; - native_window_get_consumer_usage(window, &consumerUsage); - windowInfo.windowUsageFlags = consumerUsage | producerUsage; + if (nullptr != vkManager.mGetPhysicalDeviceImageFormatProperties2) { + VkPhysicalDeviceExternalImageFormatInfo externalImageFormatInfo; + externalImageFormatInfo.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO; + externalImageFormatInfo.pNext = nullptr; + externalImageFormatInfo.handleType = + VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID; + + VkPhysicalDeviceImageFormatInfo2 imageFormatInfo; + imageFormatInfo.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2; + imageFormatInfo.pNext = &externalImageFormatInfo; + imageFormatInfo.format = vkPixelFormat; + imageFormatInfo.type = VK_IMAGE_TYPE_2D; + imageFormatInfo.tiling = VK_IMAGE_TILING_OPTIMAL; + imageFormatInfo.usage = usageFlags; + imageFormatInfo.flags = 0; + + VkAndroidHardwareBufferUsageANDROID hwbUsage; + hwbUsage.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID; + hwbUsage.pNext = nullptr; + + VkImageFormatProperties2 imgFormProps; + imgFormProps.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2; + imgFormProps.pNext = &hwbUsage; + + res = vkManager.mGetPhysicalDeviceImageFormatProperties2(vkManager.mPhysicalDevice, + &imageFormatInfo, &imgFormProps); + if (VK_SUCCESS != res) { + ALOGE("Failed to query GetPhysicalDeviceImageFormatProperties2"); + return nullptr; + } + + windowInfo.windowUsageFlags = hwbUsage.androidHardwareBufferUsage; + + } else { + ALOGE("VulkanSurface::Create() vkmGetPhysicalDeviceImageFormatProperties2 is missing"); + return nullptr; + } /* * Now we attempt to modify the window! diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl index a4582b7ece92..93dc6fa9bf93 100644 --- a/location/java/android/location/ILocationManager.aidl +++ b/location/java/android/location/ILocationManager.aidl @@ -29,6 +29,7 @@ import android.location.IGnssNavigationMessageListener; import android.location.ILocationListener; import android.location.Location; import android.location.LocationRequest; +import android.location.LocationTime; import android.os.Bundle; import com.android.internal.location.ProviderProperties; @@ -104,6 +105,7 @@ interface ILocationManager void setTestProviderLocation(String provider, in Location loc, String opPackageName); void setTestProviderEnabled(String provider, boolean enabled, String opPackageName); List<LocationRequest> getTestProviderCurrentRequests(String provider, String opPackageName); + LocationTime getGnssTimeMillis(); // --- deprecated --- void setTestProviderStatus(String provider, int status, in Bundle extras, long updateTime, diff --git a/location/java/android/location/LocationTime.aidl b/location/java/android/location/LocationTime.aidl new file mode 100644 index 000000000000..f6263637bb33 --- /dev/null +++ b/location/java/android/location/LocationTime.aidl @@ -0,0 +1,19 @@ +/* + * 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.location; + +parcelable LocationTime; diff --git a/location/java/android/location/LocationTime.java b/location/java/android/location/LocationTime.java new file mode 100644 index 000000000000..e5535d192776 --- /dev/null +++ b/location/java/android/location/LocationTime.java @@ -0,0 +1,73 @@ +/* + * 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.location; + +import android.annotation.NonNull; +import android.os.Parcel; +import android.os.Parcelable; + +/** + * Data class for passing location derived time. + * @hide + */ +public final class LocationTime implements Parcelable { + + private final long mTime; + private final long mElapsedRealtimeNanos; + + public LocationTime(long time, long elapsedRealtimeNanos) { + mTime = time; + mElapsedRealtimeNanos = elapsedRealtimeNanos; + } + + /** + * The current time, according to the Gnss location provider. */ + public long getTime() { + return mTime; + } + + /** + * The elapsed nanos since boot {@link #getTime} was computed at. + */ + public long getElapsedRealtimeNanos() { + return mElapsedRealtimeNanos; + } + + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeLong(mTime); + out.writeLong(mElapsedRealtimeNanos); + } + + @Override + public int describeContents() { + return 0; + } + + public static final @NonNull Parcelable.Creator<LocationTime> CREATOR = + new Parcelable.Creator<LocationTime>() { + public LocationTime createFromParcel(Parcel in) { + long time = in.readLong(); + long elapsedRealtimeNanos = in.readLong(); + return new LocationTime(time, elapsedRealtimeNanos); + } + + public LocationTime[] newArray(int size) { + return new LocationTime[size]; + } + }; +} diff --git a/media/Android.bp b/media/Android.bp index 86dc509501a4..34801813ee87 100644 --- a/media/Android.bp +++ b/media/Android.bp @@ -90,7 +90,6 @@ filegroup { "apex/java/android/media/DataSourceDesc.java", "apex/java/android/media/UriDataSourceDesc.java", "apex/java/android/media/FileDataSourceDesc.java", - "apex/java/android/media/CallbackDataSourceDesc.java", "apex/java/android/media/Media2Utils.java", "apex/java/android/media/MediaPlayer2Utils.java", "apex/java/android/media/MediaPlayer2.java", @@ -98,6 +97,7 @@ filegroup { "apex/java/android/media/Media2HTTPConnection.java", "apex/java/android/media/RoutingDelegate.java", "apex/java/android/media/BufferingParams.java", + "apex/java/android/media/ProxyDataSourceCallback.java", ], } diff --git a/media/apex/java/android/media/CallbackDataSourceDesc.java b/media/apex/java/android/media/CallbackDataSourceDesc.java deleted file mode 100644 index 9209ca94897f..000000000000 --- a/media/apex/java/android/media/CallbackDataSourceDesc.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright 2018 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; - -/** - * Structure of data source descriptor for sources using callback. - * - * Used by {@link MediaPlayer2#setDataSource}, {@link MediaPlayer2#setNextDataSource} and - * {@link MediaPlayer2#setNextDataSources} to set data source for playback. - * - * <p>Users should use {@link Builder} to create {@link CallbackDataSourceDesc}. - * - */ -public class CallbackDataSourceDesc extends DataSourceDesc { - private DataSourceCallback mDataSourceCallback; - - private CallbackDataSourceDesc() { - } - - /** - * Return the DataSourceCallback of this data source. - * @return the DataSourceCallback of this data source - */ - public @NonNull DataSourceCallback getDataSourceCallback() { - return mDataSourceCallback; - } - - /** - * Builder class for {@link CallbackDataSourceDesc} objects. - * <p> Here is an example where <code>Builder</code> is used to define the - * {@link CallbackDataSourceDesc} to be used by a {@link MediaPlayer2} instance: - * - * <pre class="prettyprint"> - * CallbackDataSourceDesc newDSD = new CallbackDataSourceDesc.Builder() - * .setDataSource(media2DataSource) - * .setStartPosition(1000) - * .setEndPosition(15000) - * .build(); - * mediaplayer2.setDataSourceDesc(newDSD); - * </pre> - */ - public static class Builder extends BuilderBase<Builder> { - private DataSourceCallback mDataSourceCallback; - - /** - * Constructs a new Builder with the defaults. - */ - public Builder() { - super(); - } - - /** - * Constructs a new Builder from a given {@link CallbackDataSourceDesc} instance - * @param dsd the {@link CallbackDataSourceDesc} object whose data will be reused - * in the new Builder. - */ - public Builder(@Nullable CallbackDataSourceDesc dsd) { - super(dsd); - if (dsd == null) { - return; // use default - } - mDataSourceCallback = dsd.mDataSourceCallback; - } - - /** - * Combines all of the fields that have been set and return a new - * {@link CallbackDataSourceDesc} object. <code>IllegalStateException</code> will be - * thrown if there is conflict between fields. - * - * @return a new {@link CallbackDataSourceDesc} object - */ - public @NonNull CallbackDataSourceDesc build() { - if (mDataSourceCallback == null) { - throw new IllegalStateException( - "DataSourceCallback should not be null"); - } - - CallbackDataSourceDesc dsd = new CallbackDataSourceDesc(); - super.build(dsd); - dsd.mDataSourceCallback = mDataSourceCallback; - - return dsd; - } - - /** - * Sets the data source (DataSourceCallback) to use. - * - * @param dscb the DataSourceCallback for the media to play - * @return the same Builder instance. - * @throws NullPointerException if dscb is null. - */ - public @NonNull Builder setDataSource(@NonNull DataSourceCallback dscb) { - Media2Utils.checkArgument(dscb != null, "data source cannot be null."); - mDataSourceCallback = dscb; - return this; - } - } -} diff --git a/media/apex/java/android/media/DataSourceCallback.java b/media/apex/java/android/media/DataSourceCallback.java index 6515bd6a2c09..c297ecda249c 100644 --- a/media/apex/java/android/media/DataSourceCallback.java +++ b/media/apex/java/android/media/DataSourceCallback.java @@ -32,8 +32,12 @@ import java.io.IOException; * you don't need to do your own synchronization unless you're modifying the * DataSourceCallback from another thread while it's being used by the framework.</p> * + * @hide */ public abstract class DataSourceCallback implements Closeable { + + public static final int END_OF_STREAM = -1; + /** * Called to request data from the given position. * @@ -49,7 +53,7 @@ public abstract class DataSourceCallback implements Closeable { * @param offset the offset within buffer to read the data into. * @param size the number of bytes to read. * @throws IOException on fatal errors. - * @return the number of bytes read, or -1 if end of stream is reached. + * @return the number of bytes read, or {@link #END_OF_STREAM} if end of stream is reached. */ public abstract int readAt(long position, @NonNull byte[] buffer, int offset, int size) throws IOException; diff --git a/media/apex/java/android/media/DataSourceDesc.java b/media/apex/java/android/media/DataSourceDesc.java index e6fd120b6d5b..d00ff2a70955 100644 --- a/media/apex/java/android/media/DataSourceDesc.java +++ b/media/apex/java/android/media/DataSourceDesc.java @@ -18,15 +18,22 @@ package android.media; import android.annotation.NonNull; import android.annotation.Nullable; +import android.net.Uri; +import android.os.ParcelFileDescriptor; + +import java.net.CookieHandler; +import java.net.CookieManager; +import java.net.HttpCookie; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; /** - * Base class of data source descriptor. + * Data source descriptor. * * Used by {@link MediaPlayer2#setDataSource}, {@link MediaPlayer2#setNextDataSource} and * {@link MediaPlayer2#setNextDataSources} to set data source for playback. - * - * <p>Users should use subclasses' builder to change {@link DataSourceDesc}. - * */ public class DataSourceDesc { // intentionally less than long.MAX_VALUE @@ -45,7 +52,10 @@ public class DataSourceDesc { private long mStartPositionMs = 0; private long mEndPositionMs = POSITION_UNKNOWN; - DataSourceDesc() { + DataSourceDesc(String mediaId, long startPositionMs, long endPositionMs) { + mMediaId = mediaId; + mStartPositionMs = startPositionMs; + mEndPositionMs = endPositionMs; } /** @@ -97,17 +107,44 @@ public class DataSourceDesc { } /** - * Base class for Builders in the subclasses of {@link DataSourceDesc}. + * Builder for {@link DataSourceDesc}. + * <p> + * Here is an example where <code>Builder</code> is used to define the + * {@link DataSourceDesc} to be used by a {@link MediaPlayer2} instance: + * + * <pre class="prettyprint"> + * DataSourceDesc newDSD = new DataSourceDesc.Builder() + * .setDataSource(context, uri, headers, cookies) + * .setStartPosition(1000) + * .setEndPosition(15000) + * .build(); + * mediaplayer2.setDataSourceDesc(newDSD); + * </pre> */ - protected static class BuilderBase<T extends BuilderBase> { + public static final class Builder { + private static final int SOURCE_TYPE_UNKNOWN = 0; + private static final int SOURCE_TYPE_URI = 1; + private static final int SOURCE_TYPE_FILE = 2; + + private int mSourceType = SOURCE_TYPE_UNKNOWN; private String mMediaId; private long mStartPositionMs = 0; private long mEndPositionMs = POSITION_UNKNOWN; + // For UriDataSourceDesc + private Uri mUri; + private Map<String, String> mHeader; + private List<HttpCookie> mCookies; + + // For FileDataSourceDesc + private ParcelFileDescriptor mPFD; + private long mOffset = 0; + private long mLength = FileDataSourceDesc.FD_LENGTH_UNKNOWN; + /** * Constructs a new BuilderBase with the defaults. */ - BuilderBase() { + public Builder() { } /** @@ -115,33 +152,55 @@ public class DataSourceDesc { * @param dsd the {@link DataSourceDesc} object whose data will be reused * in the new BuilderBase. */ - BuilderBase(DataSourceDesc dsd) { + public Builder(@Nullable DataSourceDesc dsd) { if (dsd == null) { return; } mMediaId = dsd.mMediaId; mStartPositionMs = dsd.mStartPositionMs; mEndPositionMs = dsd.mEndPositionMs; + if (dsd instanceof FileDataSourceDesc) { + mSourceType = SOURCE_TYPE_FILE; + mPFD = ((FileDataSourceDesc) dsd).getParcelFileDescriptor(); + mOffset = ((FileDataSourceDesc) dsd).getOffset(); + mLength = ((FileDataSourceDesc) dsd).getLength(); + } else if (dsd instanceof UriDataSourceDesc) { + mSourceType = SOURCE_TYPE_URI; + mUri = ((UriDataSourceDesc) dsd).getUri(); + mHeader = ((UriDataSourceDesc) dsd).getHeaders(); + mCookies = ((UriDataSourceDesc) dsd).getCookies(); + } else { + throw new IllegalStateException("Unknown source type:" + mSourceType); + } } /** * Sets all fields that have been set in the {@link DataSourceDesc} object. * <code>IllegalStateException</code> will be thrown if there is conflict between fields. * - * @param dsd an instance of subclass of {@link DataSourceDesc} whose data will be set - * @return the same instance of subclass of {@link DataSourceDesc} + * @return {@link DataSourceDesc} */ - void build(@NonNull DataSourceDesc dsd) { - Media2Utils.checkArgument(dsd != null, "dsd cannot be null."); - + @NonNull + public DataSourceDesc build() { + if (mSourceType == SOURCE_TYPE_UNKNOWN) { + throw new IllegalStateException("Source is not set."); + } if (mStartPositionMs > mEndPositionMs) { throw new IllegalStateException("Illegal start/end position: " + mStartPositionMs + " : " + mEndPositionMs); } - dsd.mMediaId = mMediaId; - dsd.mStartPositionMs = mStartPositionMs; - dsd.mEndPositionMs = mEndPositionMs; + DataSourceDesc desc; + if (mSourceType == SOURCE_TYPE_FILE) { + desc = new FileDataSourceDesc( + mMediaId, mStartPositionMs, mEndPositionMs, mPFD, mOffset, mLength); + } else if (mSourceType == SOURCE_TYPE_URI) { + desc = new UriDataSourceDesc( + mMediaId, mStartPositionMs, mEndPositionMs, mUri, mHeader, mCookies); + } else { + throw new IllegalStateException("Unknown source type:" + mSourceType); + } + return desc; } /** @@ -150,9 +209,10 @@ public class DataSourceDesc { * @param mediaId the media Id of this data source * @return the same Builder instance. */ - public @NonNull T setMediaId(@Nullable String mediaId) { + @NonNull + public Builder setMediaId(@Nullable String mediaId) { mMediaId = mediaId; - return (T) this; + return this; } /** @@ -163,12 +223,13 @@ public class DataSourceDesc { * @return the same Builder instance. * */ - public @NonNull T setStartPosition(long position) { + @NonNull + public Builder setStartPosition(long position) { if (position < 0) { position = 0; } mStartPositionMs = position; - return (T) this; + return this; } /** @@ -179,12 +240,143 @@ public class DataSourceDesc { * @param position the end position in milliseconds at which the playback will end * @return the same Builder instance. */ - public @NonNull T setEndPosition(long position) { + @NonNull + public Builder setEndPosition(long position) { if (position < 0) { position = LONG_MAX_TIME_MS; } mEndPositionMs = position; - return (T) this; + return this; + } + + /** + * Sets the data source as a content Uri. + * + * @param uri the Content URI of the data you want to play + * @return the same Builder instance. + * @throws NullPointerException if context or uri is null. + */ + @NonNull + public Builder setDataSource(@NonNull Uri uri) { + setSourceType(SOURCE_TYPE_URI); + Media2Utils.checkArgument(uri != null, "uri cannot be null"); + mUri = uri; + return this; + } + + /** + * Sets the data source as a content Uri. + * + * To provide cookies for the subsequent HTTP requests, you can install your own default + * cookie handler and use other variants of setDataSource APIs instead. Alternatively, you + * can use this API to pass the cookies as a list of HttpCookie. If the app has not + * installed a CookieHandler already, {@link MediaPlayer2} will create a CookieManager + * and populates its CookieStore with the provided cookies when this data source is passed + * to {@link MediaPlayer2}. If the app has installed its own handler already, the handler + * is required to be of CookieManager type such that {@link MediaPlayer2} can update the + * manager’s CookieStore. + * + * <p><strong>Note</strong> that the cross domain redirection is allowed by default, + * but that can be changed with key/value pairs through the headers parameter with + * "android-allow-cross-domain-redirect" as the key and "0" or "1" as the value to + * disallow or allow cross domain redirection. + * + * @param uri the Content URI of the data you want to play + * @param headers the headers to be sent together with the request for the data + * The headers must not include cookies. Instead, use the cookies param. + * @param cookies the cookies to be sent together with the request + * @return the same Builder instance. + * @throws NullPointerException if context or uri is null. + * @throws IllegalArgumentException if the cookie handler is not of CookieManager type + * when cookies are provided. + */ + @NonNull + public Builder setDataSource(@NonNull Uri uri, @Nullable Map<String, String> headers, + @Nullable List<HttpCookie> cookies) { + setSourceType(SOURCE_TYPE_URI); + Media2Utils.checkArgument(uri != null, "uri cannot be null"); + if (cookies != null) { + CookieHandler cookieHandler = CookieHandler.getDefault(); + if (cookieHandler != null && !(cookieHandler instanceof CookieManager)) { + throw new IllegalArgumentException( + "The cookie handler has to be of CookieManager type " + + "when cookies are provided."); + } + } + + mUri = uri; + if (headers != null) { + mHeader = new HashMap<String, String>(headers); + } + if (cookies != null) { + mCookies = new ArrayList<HttpCookie>(cookies); + } + return this; + } + + /** + * Sets the data source (ParcelFileDescriptor) to use. The ParcelFileDescriptor must be + * seekable (N.B. a LocalSocket is not seekable). When the {@link DataSourceDesc} + * created by this builder is passed to {@link MediaPlayer2} via + * {@link MediaPlayer2#setDataSource}, + * {@link MediaPlayer2#setNextDataSource} or + * {@link MediaPlayer2#setNextDataSources}, MediaPlayer2 will + * close the ParcelFileDescriptor. + * + * @param pfd the ParcelFileDescriptor for the file to play + * @return the same Builder instance. + * @throws NullPointerException if pfd is null. + */ + @NonNull + public Builder setDataSource(@NonNull ParcelFileDescriptor pfd) { + setSourceType(SOURCE_TYPE_FILE); + Media2Utils.checkArgument(pfd != null, "pfd cannot be null."); + mPFD = pfd; + return this; + } + + /** + * Sets the data source (ParcelFileDescriptor) to use. The ParcelFileDescriptor must be + * seekable (N.B. a LocalSocket is not seekable). When the {@link DataSourceDesc} + * created by this builder is passed to {@link MediaPlayer2} via + * {@link MediaPlayer2#setDataSource}, + * {@link MediaPlayer2#setNextDataSource} or + * {@link MediaPlayer2#setNextDataSources}, MediaPlayer2 will + * close the ParcelFileDescriptor. + * + * Any negative number for offset is treated as 0. + * Any negative number for length is treated as maximum length of the data source. + * + * @param pfd the ParcelFileDescriptor for the file to play + * @param offset the offset into the file where the data to be played starts, in bytes + * @param length the length in bytes of the data to be played + * @return the same Builder instance. + * @throws NullPointerException if pfd is null. + */ + @NonNull + public Builder setDataSource( + @NonNull ParcelFileDescriptor pfd, long offset, long length) { + setSourceType(SOURCE_TYPE_FILE); + if (pfd == null) { + throw new NullPointerException("pfd cannot be null."); + } + if (offset < 0) { + offset = 0; + } + if (length < 0) { + length = FileDataSourceDesc.FD_LENGTH_UNKNOWN; + } + mPFD = pfd; + mOffset = offset; + mLength = length; + return this; + } + + private void setSourceType(int type) { + if (mSourceType != SOURCE_TYPE_UNKNOWN) { + throw new IllegalStateException("Source is already set. type=" + mSourceType); + } + mSourceType = type; } } } diff --git a/media/apex/java/android/media/FileDataSourceDesc.java b/media/apex/java/android/media/FileDataSourceDesc.java index 4b703670abf1..feb67e136d9b 100644 --- a/media/apex/java/android/media/FileDataSourceDesc.java +++ b/media/apex/java/android/media/FileDataSourceDesc.java @@ -17,7 +17,7 @@ package android.media; import android.annotation.NonNull; -import android.annotation.Nullable; +import android.annotation.TestApi; import android.os.ParcelFileDescriptor; import android.util.Log; @@ -30,8 +30,9 @@ import java.io.IOException; * {@link MediaPlayer2#setNextDataSources} to set data source for playback. * * <p>Users should use {@link Builder} to create {@link FileDataSourceDesc}. - * + * @hide */ +@TestApi public class FileDataSourceDesc extends DataSourceDesc { private static final String TAG = "FileDataSourceDesc"; @@ -48,8 +49,12 @@ public class FileDataSourceDesc extends DataSourceDesc { private int mCount = 0; private boolean mClosed = false; - private FileDataSourceDesc() { - super(); + FileDataSourceDesc(String mediaId, long startPositionMs, long endPositionMs, + ParcelFileDescriptor pfd, long offset, long length) { + super(mediaId, startPositionMs, endPositionMs); + mPFD = pfd; + mOffset = offset; + mLength = length; } /** @@ -128,133 +133,4 @@ public class FileDataSourceDesc extends DataSourceDesc { public long getLength() { return mLength; } - - /** - * Builder class for {@link FileDataSourceDesc} objects. - * <p> Here is an example where <code>Builder</code> is used to define the - * {@link FileDataSourceDesc} to be used by a {@link MediaPlayer2} instance: - * - * <pre class="prettyprint"> - * FileDataSourceDesc newDSD = new FileDataSourceDesc.Builder() - * .setDataSource(pfd, 0, srcLength) - * .setStartPosition(1000) - * .setEndPosition(15000) - * .build(); - * mediaplayer2.setDataSourceDesc(newDSD); - * </pre> - */ - public static class Builder extends BuilderBase<Builder> { - private ParcelFileDescriptor mPFD; - private long mOffset = 0; - private long mLength = FD_LENGTH_UNKNOWN; - - /** - * Constructs a new Builder with the defaults. - */ - public Builder() { - super(); - } - - /** - * Constructs a new Builder from a given {@link FileDataSourceDesc} instance - * @param dsd the {@link FileDataSourceDesc} object whose data will be reused - * in the new Builder. - */ - public Builder(@Nullable FileDataSourceDesc dsd) { - super(dsd); - if (dsd == null) { - return; // use default - } - mPFD = dsd.mPFD; - mOffset = dsd.mOffset; - mLength = dsd.mLength; - } - - /** - * Combines all of the fields that have been set and return a new - * {@link FileDataSourceDesc} object. <code>IllegalStateException</code> will be - * thrown if there is conflict between fields. - * - * @return a new {@link FileDataSourceDesc} object - */ - public @NonNull FileDataSourceDesc build() { - if (mPFD == null) { - throw new IllegalStateException( - "underline ParcelFileDescriptor should not be null"); - } - try { - mPFD.getFd(); - } catch (IllegalStateException e) { - throw new IllegalStateException("ParcelFileDescriptor has been closed"); - } - - FileDataSourceDesc dsd = new FileDataSourceDesc(); - super.build(dsd); - dsd.mPFD = mPFD; - dsd.mOffset = mOffset; - dsd.mLength = mLength; - - return dsd; - } - - /** - * Sets the data source (ParcelFileDescriptor) to use. The ParcelFileDescriptor must be - * seekable (N.B. a LocalSocket is not seekable). When the {@link FileDataSourceDesc} - * created by this builder is passed to {@link MediaPlayer2} via - * {@link MediaPlayer2#setDataSource}, - * {@link MediaPlayer2#setNextDataSource} or - * {@link MediaPlayer2#setNextDataSources}, MediaPlayer2 will - * close the ParcelFileDescriptor. - * - * @param pfd the ParcelFileDescriptor for the file to play - * @return the same Builder instance. - * @throws NullPointerException if pfd is null. - */ - public @NonNull Builder setDataSource(@NonNull ParcelFileDescriptor pfd) { - Media2Utils.checkArgument(pfd != null, "pfd cannot be null."); - resetDataSource(); - mPFD = pfd; - return this; - } - - /** - * Sets the data source (ParcelFileDescriptor) to use. The ParcelFileDescriptor must be - * seekable (N.B. a LocalSocket is not seekable). When the {@link FileDataSourceDesc} - * created by this builder is passed to {@link MediaPlayer2} via - * {@link MediaPlayer2#setDataSource}, - * {@link MediaPlayer2#setNextDataSource} or - * {@link MediaPlayer2#setNextDataSources}, MediaPlayer2 will - * close the ParcelFileDescriptor. - * - * Any negative number for offset is treated as 0. - * Any negative number for length is treated as maximum length of the data source. - * - * @param pfd the ParcelFileDescriptor for the file to play - * @param offset the offset into the file where the data to be played starts, in bytes - * @param length the length in bytes of the data to be played - * @return the same Builder instance. - * @throws NullPointerException if pfd is null. - */ - public @NonNull Builder setDataSource( - @NonNull ParcelFileDescriptor pfd, long offset, long length) { - Media2Utils.checkArgument(pfd != null, "pfd cannot be null."); - if (offset < 0) { - offset = 0; - } - if (length < 0) { - length = FD_LENGTH_UNKNOWN; - } - resetDataSource(); - mPFD = pfd; - mOffset = offset; - mLength = length; - return this; - } - - private void resetDataSource() { - mPFD = null; - mOffset = 0; - mLength = FD_LENGTH_UNKNOWN; - } - } } diff --git a/media/apex/java/android/media/MediaPlayer2.java b/media/apex/java/android/media/MediaPlayer2.java index fbe184bf144f..19bb2586af35 100644 --- a/media/apex/java/android/media/MediaPlayer2.java +++ b/media/apex/java/android/media/MediaPlayer2.java @@ -274,8 +274,7 @@ import java.util.concurrent.atomic.AtomicLong; * successful transition. Any other value will be an error. Call {@link #getState()} to * determine the current state. </p> */ -public class MediaPlayer2 implements AutoCloseable - , AudioRouting { +public class MediaPlayer2 implements AutoCloseable, AudioRouting { static { System.loadLibrary("media2_jni"); native_init(); @@ -879,27 +878,32 @@ public class MediaPlayer2 implements AutoCloseable throws IOException { Media2Utils.checkArgument(dsd != null, "the DataSourceDesc cannot be null"); - if (dsd instanceof CallbackDataSourceDesc) { - CallbackDataSourceDesc cbDSD = (CallbackDataSourceDesc) dsd; - handleDataSource(isCurrent, - srcId, - cbDSD.getDataSourceCallback(), - cbDSD.getStartPosition(), - cbDSD.getEndPosition()); - } else if (dsd instanceof FileDataSourceDesc) { + if (dsd instanceof FileDataSourceDesc) { FileDataSourceDesc fileDSD = (FileDataSourceDesc) dsd; - handleDataSource(isCurrent, - srcId, - fileDSD.getParcelFileDescriptor(), - fileDSD.getOffset(), - fileDSD.getLength(), - fileDSD.getStartPosition(), - fileDSD.getEndPosition()); + ParcelFileDescriptor pfd = fileDSD.getParcelFileDescriptor(); + if (pfd.getStatSize() == -1) { + // Underlying pipeline doesn't understand '-1' size. Create a wrapper for + // translation. + // TODO: Make native code handle '-1' size. + handleDataSource(isCurrent, + srcId, + new ProxyDataSourceCallback(pfd), + fileDSD.getStartPosition(), + fileDSD.getEndPosition()); + } else { + handleDataSource(isCurrent, + srcId, + pfd, + fileDSD.getOffset(), + fileDSD.getLength(), + fileDSD.getStartPosition(), + fileDSD.getEndPosition()); + } } else if (dsd instanceof UriDataSourceDesc) { UriDataSourceDesc uriDSD = (UriDataSourceDesc) dsd; handleDataSource(isCurrent, srcId, - uriDSD.getContext(), + mContext, uriDSD.getUri(), uriDSD.getHeaders(), uriDSD.getCookies(), @@ -1810,12 +1814,10 @@ public class MediaPlayer2 implements AutoCloseable public MediaTimestamp getTimestamp() { try { // TODO: get the timestamp from native side - return new MediaTimestamp.Builder() - .setMediaTimestamp( - getCurrentPosition() * 1000L, - System.nanoTime(), - getState() == PLAYER_STATE_PLAYING ? getPlaybackParams().getSpeed() : 0.f) - .build(); + return new MediaTimestamp( + getCurrentPosition() * 1000L, + System.nanoTime(), + getState() == PLAYER_STATE_PLAYING ? getPlaybackParams().getSpeed() : 0.f); } catch (IllegalStateException e) { return null; } @@ -1966,6 +1968,17 @@ public class MediaPlayer2 implements AutoCloseable private native byte[] native_invoke(byte[] request); /** + * @hide + */ + @IntDef(flag = false, prefix = "MEDIA_TRACK_TYPE", value = { + TrackInfo.MEDIA_TRACK_TYPE_VIDEO, + TrackInfo.MEDIA_TRACK_TYPE_AUDIO, + TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE + }) + @Retention(RetentionPolicy.SOURCE) + public @interface TrackType {} + + /** * Class for MediaPlayer2 to return each audio/video/subtitle track's metadata. * * @see MediaPlayer2#getTrackInfo @@ -2012,10 +2025,11 @@ public class MediaPlayer2 implements AutoCloseable public static final int MEDIA_TRACK_TYPE_SUBTITLE = 4; public static final int MEDIA_TRACK_TYPE_METADATA = 5; + final int mId; final int mTrackType; final MediaFormat mFormat; - static TrackInfo create(Iterator<Value> in) { + static TrackInfo create(int idx, Iterator<Value> in) { int trackType = in.next().getInt32Value(); // TODO: build the full MediaFormat; currently we are using createSubtitleFormat // even for audio/video tracks, meaning we only set the mime and language. @@ -2028,11 +2042,12 @@ public class MediaPlayer2 implements AutoCloseable format.setInteger(MediaFormat.KEY_IS_DEFAULT, in.next().getInt32Value()); format.setInteger(MediaFormat.KEY_IS_FORCED_SUBTITLE, in.next().getInt32Value()); } - return new TrackInfo(trackType, format); + return new TrackInfo(idx, trackType, format); } /** @hide */ - TrackInfo(int type, MediaFormat format) { + TrackInfo(int id, int type, MediaFormat format) { + mId = id; mTrackType = type; mFormat = format; } @@ -2119,7 +2134,7 @@ public class MediaPlayer2 implements AutoCloseable } TrackInfo[] trackInfo = new TrackInfo[size]; for (int i = 0; i < size; ++i) { - trackInfo[i] = TrackInfo.create(in); + trackInfo[i] = TrackInfo.create(i, in); } return trackInfo; } @@ -2127,54 +2142,56 @@ public class MediaPlayer2 implements AutoCloseable /** * Returns the index of the audio, video, or subtitle track currently selected for playback. * The return value is an index into the array returned by {@link #getTrackInfo}, and can - * be used in calls to {@link #selectTrack(int)} or {@link #deselectTrack(int)}. + * be used in calls to {@link #selectTrack(TrackInfo)} or {@link #deselectTrack(TrackInfo)}. * Same as {@link #getSelectedTrack(DataSourceDesc, int)} with * {@code dsd = getCurrentDataSource()}. * * @param trackType should be one of {@link TrackInfo#MEDIA_TRACK_TYPE_VIDEO}, * {@link TrackInfo#MEDIA_TRACK_TYPE_AUDIO}, or * {@link TrackInfo#MEDIA_TRACK_TYPE_SUBTITLE} - * @return index of the audio, video, or subtitle track currently selected for playback; - * a negative integer is returned when there is no selected track for {@code trackType} or + * @return metadata corresponding to the audio, video, or subtitle track currently selected for + * playback; {@code null} is returned when there is no selected track for {@code trackType} or * when {@code trackType} is not one of audio, video, or subtitle. * @throws IllegalStateException if called after {@link #close()} * @throws NullPointerException if current data source is null * * @see #getTrackInfo() - * @see #selectTrack(int) - * @see #deselectTrack(int) + * @see #selectTrack(TrackInfo) + * @see #deselectTrack(TrackInfo) */ - public int getSelectedTrack(int trackType) { + @Nullable + public TrackInfo getSelectedTrack(@TrackType int trackType) { return getSelectedTrack(getCurrentDataSource(), trackType); } /** * Returns the index of the audio, video, or subtitle track currently selected for playback. * The return value is an index into the array returned by {@link #getTrackInfo}, and can - * be used in calls to {@link #selectTrack(DataSourceDesc, int)} or - * {@link #deselectTrack(DataSourceDesc, int)}. + * be used in calls to {@link #selectTrack(DataSourceDesc, TrackInfo)} or + * {@link #deselectTrack(DataSourceDesc, TrackInfo)}. * * @param dsd the descriptor of data source of which you want to get selected track * @param trackType should be one of {@link TrackInfo#MEDIA_TRACK_TYPE_VIDEO}, * {@link TrackInfo#MEDIA_TRACK_TYPE_AUDIO}, or * {@link TrackInfo#MEDIA_TRACK_TYPE_SUBTITLE} - * @return index of the audio, video, or subtitle track currently selected for playback; - * a negative integer is returned when there is no selected track for {@code trackType} or + * @return metadata corresponding to the audio, video, or subtitle track currently selected for + * playback; {@code null} is returned when there is no selected track for {@code trackType} or * when {@code trackType} is not one of audio, video, or subtitle. * @throws IllegalStateException if called after {@link #close()} * @throws NullPointerException if dsd is null * * @see #getTrackInfo(DataSourceDesc) - * @see #selectTrack(DataSourceDesc, int) - * @see #deselectTrack(DataSourceDesc, int) + * @see #selectTrack(DataSourceDesc, TrackInfo) + * @see #deselectTrack(DataSourceDesc, TrackInfo) */ - public int getSelectedTrack(@NonNull DataSourceDesc dsd, int trackType) { + @Nullable + public TrackInfo getSelectedTrack(@NonNull DataSourceDesc dsd, @TrackType int trackType) { if (dsd == null) { throw new NullPointerException("non-null dsd is expected"); } SourceInfo sourceInfo = getSourceInfo(dsd); if (sourceInfo == null) { - return -1; + return null; } PlayerMessage request = PlayerMessage.newBuilder() @@ -2184,26 +2201,30 @@ public class MediaPlayer2 implements AutoCloseable .build(); PlayerMessage response = invoke(request); if (response == null) { - return -1; + return null; } - return response.getValues(0).getInt32Value(); + // TODO: return full TrackInfo data from native player instead of index + final int idx = response.getValues(0).getInt32Value(); + final List<TrackInfo> trackInfos = getTrackInfo(dsd); + return trackInfos.isEmpty() ? null : trackInfos.get(idx); } /** * Selects a track of current data source. - * Same as {@link #selectTrack(DataSourceDesc, int)} with + * Same as {@link #selectTrack(DataSourceDesc, TrackInfo)} with * {@code dsd = getCurrentDataSource()}. * - * @param index the index of the track to be selected. The valid range of the index - * is 0..total number of track - 1. The total number of tracks as well as the type of - * each individual track can be found by calling {@link #getTrackInfo()} method. + * @param trackInfo metadata corresponding to the track to be selected. A {@code trackInfo} + * object can be obtained from {@link #getTrackInfo()}. * @return a token which can be used to cancel the operation later with {@link #cancelCommand}. * + * This is an asynchronous call. + * * @see MediaPlayer2#getTrackInfo() */ - // This is an asynchronous call. - public @NonNull Object selectTrack(int index) { - return selectTrack(getCurrentDataSource(), index); + @NonNull + public Object selectTrack(@NonNull TrackInfo trackInfo) { + return selectTrack(getCurrentDataSource(), trackInfo); } /** @@ -2228,38 +2249,40 @@ public class MediaPlayer2 implements AutoCloseable * in that an audio track can only be selected in the <em>Prepared</em> state. * </p> * @param dsd the descriptor of data source of which you want to select track - * @param index the index of the track to be selected. The valid range of the index - * is 0..total number of track - 1. The total number of tracks as well as the type of - * each individual track can be found by calling {@link #getTrackInfo(DataSourceDesc)} method. + * @param trackInfo metadata corresponding to the track to be selected. A {@code trackInfo} + * object can be obtained from {@link #getTrackInfo()}. * @return a token which can be used to cancel the operation later with {@link #cancelCommand}. * + * This is an asynchronous call. + * * @see MediaPlayer2#getTrackInfo(DataSourceDesc) */ - // This is an asynchronous call. - public @NonNull Object selectTrack(@NonNull DataSourceDesc dsd, int index) { + @NonNull + public Object selectTrack(@NonNull DataSourceDesc dsd, @NonNull TrackInfo trackInfo) { return addTask(new Task(CALL_COMPLETED_SELECT_TRACK, false) { @Override void process() { - selectOrDeselectTrack(dsd, index, true /* select */); + selectOrDeselectTrack(dsd, trackInfo.mId, true /* select */); } }); } /** * Deselect a track of current data source. - * Same as {@link #deselectTrack(DataSourceDesc, int)} with + * Same as {@link #deselectTrack(DataSourceDesc, TrackInfo)} with * {@code dsd = getCurrentDataSource()}. * - * @param index the index of the track to be deselected. The valid range of the index - * is 0..total number of tracks - 1. The total number of tracks as well as the type of - * each individual track can be found by calling {@link #getTrackInfo()} method. + * @param trackInfo metadata corresponding to the track to be selected. A {@code trackInfo} + * object can be obtained from {@link #getTrackInfo()}. * @return a token which can be used to cancel the operation later with {@link #cancelCommand}. * + * This is an asynchronous call. + * * @see MediaPlayer2#getTrackInfo() */ - // This is an asynchronous call. - public @NonNull Object deselectTrack(int index) { - return deselectTrack(getCurrentDataSource(), index); + @NonNull + public Object deselectTrack(@NonNull TrackInfo trackInfo) { + return deselectTrack(getCurrentDataSource(), trackInfo); } /** @@ -2270,19 +2293,20 @@ public class MediaPlayer2 implements AutoCloseable * selected before, it throws an exception. * </p> * @param dsd the descriptor of data source of which you want to deselect track - * @param index the index of the track to be deselected. The valid range of the index - * is 0..total number of tracks - 1. The total number of tracks as well as the type of - * each individual track can be found by calling {@link #getTrackInfo} method. + * @param trackInfo metadata corresponding to the track to be selected. A {@code trackInfo} + * object can be obtained from {@link #getTrackInfo()}. * @return a token which can be used to cancel the operation later with {@link #cancelCommand}. * + * This is an asynchronous call. + * * @see MediaPlayer2#getTrackInfo(DataSourceDesc) */ - // This is an asynchronous call. - public @NonNull Object deselectTrack(@NonNull DataSourceDesc dsd, int index) { + @NonNull + public Object deselectTrack(@NonNull DataSourceDesc dsd, @NonNull TrackInfo trackInfo) { return addTask(new Task(CALL_COMPLETED_DESELECT_TRACK, false) { @Override void process() { - selectOrDeselectTrack(dsd, index, false /* select */); + selectOrDeselectTrack(dsd, trackInfo.mId, false /* select */); } }); } @@ -2643,13 +2667,13 @@ public class MediaPlayer2 implements AutoCloseable return; } Iterator<Value> in = playerMsg.getValuesList().iterator(); - SubtitleData data = new SubtitleData.Builder() - .setSubtitleData( - in.next().getInt32Value(), // trackIndex - in.next().getInt64Value(), // startTimeUs - in.next().getInt64Value(), // durationUs - in.next().getBytesValue().toByteArray()) // data - .build(); + final int trackIndex = in.next().getInt32Value(); + TrackInfo trackInfo = getTrackInfo(dsd).get(trackIndex); + final long startTimeUs = in.next().getInt64Value(); + final long durationTimeUs = in.next().getInt64Value(); + final byte[] subData = in.next().getBytesValue().toByteArray(); + SubtitleData data = new SubtitleData(trackInfo, + startTimeUs, durationTimeUs, subData); sendEvent(new EventNotifier() { @Override public void notify(EventCallback callback) { @@ -2673,11 +2697,9 @@ public class MediaPlayer2 implements AutoCloseable return; } Iterator<Value> in = playerMsg.getValuesList().iterator(); - data = new TimedMetaData.Builder() - .setTimedMetaData( - in.next().getInt64Value(), // timestampUs - in.next().getBytesValue().toByteArray()) // metaData - .build(); + data = new TimedMetaData( + in.next().getInt64Value(), // timestampUs + in.next().getBytesValue().toByteArray()); // metaData } else { data = null; } @@ -2772,6 +2794,74 @@ public class MediaPlayer2 implements AutoCloseable } /** + * Class encapsulating subtitle data, as received through the + * {@link EventCallback#onSubtitleData} interface. + * <p> + * A {@link SubtitleData} object includes: + * <ul> + * <li> track metadadta in a {@link TrackInfo} object</li> + * <li> the start time (in microseconds) of the data</li> + * <li> the duration (in microseconds) of the data</li> + * <li> the actual data.</li> + * </ul> + * The data is stored in a byte-array, and is encoded in one of the supported in-band + * subtitle formats. The subtitle encoding is determined by the MIME type of the + * {@link TrackInfo} of the subtitle track, one of + * {@link MediaFormat#MIMETYPE_TEXT_CEA_608}, {@link MediaFormat#MIMETYPE_TEXT_CEA_708}, + * {@link MediaFormat#MIMETYPE_TEXT_VTT}. + */ + public static final class SubtitleData { + + private TrackInfo mTrackInfo; + private long mStartTimeUs; + private long mDurationUs; + private byte[] mData; + + private SubtitleData(TrackInfo trackInfo, long startTimeUs, long durationUs, byte[] data) { + mTrackInfo = trackInfo; + mStartTimeUs = startTimeUs; + mDurationUs = durationUs; + mData = (data != null ? data : new byte[0]); + } + + /** + * @return metadata of track which contains this subtitle data + */ + @NonNull + public TrackInfo getTrackInfo() { + return mTrackInfo; + } + + /** + * @return media time at which the subtitle should start to be displayed in microseconds + */ + public long getStartTimeUs() { + return mStartTimeUs; + } + + /** + * @return the duration in microsecond during which the subtitle should be displayed + */ + public long getDurationUs() { + return mDurationUs; + } + + /** + * Returns the encoded data for the subtitle content. + * Encoding format depends on the subtitle type, refer to + * <a href="https://en.wikipedia.org/wiki/CEA-708">CEA 708</a>, + * <a href="https://en.wikipedia.org/wiki/EIA-608">CEA/EIA 608</a> and + * <a href="https://www.w3.org/TR/webvtt1/">WebVTT</a>, defined by the MIME type + * of the subtitle track. + * @return the encoded subtitle data + */ + @NonNull + public byte[] getData() { + return mData; + } + } + + /** * Interface definition for callbacks to be invoked when the player has the corresponding * events. */ @@ -3446,10 +3536,18 @@ public class MediaPlayer2 implements AutoCloseable /** * Mutable builder to create a {@link MediaPlayer2.DrmPreparationInfo} object. + * + * {@link Builder#Builder(UUID) UUID} must not be null; {@link #setKeyType keyType} + * must be one of {@link MediaDrm#KEY_TYPE_STREAMING} or {@link MediaDrm#KEY_TYPE_OFFLINE}. + * <p> + * When {@link #setKeyType keyType} is {@link MediaDrm#KEY_TYPE_STREAMING}, + * {@link #setInitData(byte[]) initData} and {@link #setMimeType(String) mimeType} + * must not be null; When {@link #setKeyType keyType} is {@link MediaDrm#KEY_TYPE_OFFLINE}, + * {@link #setKeySetId(byte[]) keySetId} must not be null. */ public static final class Builder { - private UUID mUUID; + private final UUID mUUID; private byte[] mKeySetId; private byte[] mInitData; private String mMimeType; @@ -3457,15 +3555,11 @@ public class MediaPlayer2 implements AutoCloseable private Map<String, String> mOptionalParameters; /** - * Set UUID of the crypto scheme selected to decrypt content. An UUID can be retrieved - * from the source listening to {@link MediaPlayer2.DrmEventCallback#onDrmInfo}. - * - * @param uuid of selected crypto scheme - * @return this + * @param uuid UUID of the crypto scheme selected to decrypt content. An UUID can be + * retrieved from the source listening to {@link DrmEventCallback#onDrmInfo}. */ - public @NonNull Builder setUuid(@NonNull UUID uuid) { + public Builder(@NonNull UUID uuid) { this.mUUID = uuid; - return this; } /** @@ -3538,12 +3632,16 @@ public class MediaPlayer2 implements AutoCloseable } /** - * @return an immutable {@link MediaPlayer2.DrmPreparationInfo} representing the - * settings of this builder + * @return an immutable {@link DrmPreparationInfo} based on settings of this builder */ - public @NonNull MediaPlayer2.DrmPreparationInfo build() { - return new MediaPlayer2.DrmPreparationInfo(mUUID, mKeySetId, mInitData, mMimeType, - mKeyType, mOptionalParameters); + @NonNull + public DrmPreparationInfo build() { + final DrmPreparationInfo info = new DrmPreparationInfo(mUUID, mKeySetId, mInitData, + mMimeType, mKeyType, mOptionalParameters); + if (!info.isValid()) { + throw new IllegalArgumentException("invalid DrmPreparationInfo"); + } + return info; } } @@ -3579,13 +3677,61 @@ public class MediaPlayer2 implements AutoCloseable } return false; } + + /** + * @return UUID of the crypto scheme selected to decrypt content. + */ + @NonNull + public UUID getUuid() { + return mUUID; + } + + /** + * @return identifier of the persisted offline key. + */ + @Nullable + public byte[] getKeySetId() { + return mKeySetId; + } + + /** + * @return container-specific DRM initialization data. + */ + @Nullable + public byte[] getInitData() { + return mInitData; + } + + /** + * @return mime type of the content + */ + @Nullable + public String getMimeType() { + return mMimeType; + } + + /** + * @return type of the key request. + */ + @MediaPlayer2.MediaDrmKeyType + public int getKeyType() { + return mKeyType; + } + + /** + * @return optional parameters to be included in the {@link MediaDrm.KeyRequest}. + */ + @Nullable + public Map<String, String> getOptionalParameters() { + return mOptionalParameters; + } } /** * Interface definition for callbacks to be invoked when the player has the corresponding * DRM events. */ - public static class DrmEventCallback { + public static abstract class DrmEventCallback { /** * Called to indicate DRM info is available. Return a {@link DrmPreparationInfo} object that @@ -3598,10 +3744,9 @@ public class MediaPlayer2 implements AutoCloseable * @return a {@link DrmPreparationInfo} object to initialize DRM playback, or null to skip * DRM initialization */ - public @Nullable DrmPreparationInfo onDrmInfo(@NonNull MediaPlayer2 mp, - @NonNull DataSourceDesc dsd, @NonNull DrmInfo drmInfo) { - return null; - } + @Nullable + public abstract DrmPreparationInfo onDrmInfo(@NonNull MediaPlayer2 mp, + @NonNull DataSourceDesc dsd, @NonNull DrmInfo drmInfo); /** * Called to give the app the opportunity to configure DRM before the session is created. @@ -3636,10 +3781,9 @@ public class MediaPlayer2 implements AutoCloseable * throwing an {@link RuntimeException} from this callback would trigger an * {@link EventCallback#onError}. */ - public @NonNull byte[] onDrmKeyRequest(@NonNull MediaPlayer2 mp, - @NonNull DataSourceDesc dsd, @NonNull MediaDrm.KeyRequest request) { - return new byte[0]; - } + @NonNull + public abstract byte[] onDrmKeyRequest(@NonNull MediaPlayer2 mp, + @NonNull DataSourceDesc dsd, @NonNull MediaDrm.KeyRequest request); /** * Called to notify the client that {@code mp} is ready to decrypt DRM protected data source @@ -3664,10 +3808,11 @@ public class MediaPlayer2 implements AutoCloseable /** * Registers the callback to be invoked for various DRM events. * + * This is a synchronous call. + * * @param eventCallback the callback that will be run * @param executor the executor through which the callback should be invoked */ - // This is a synchronous call. public void setDrmEventCallback(@NonNull @CallbackExecutor Executor executor, @NonNull DrmEventCallback eventCallback) { if (eventCallback == null) { @@ -3684,8 +3829,9 @@ public class MediaPlayer2 implements AutoCloseable /** * Clear the {@link DrmEventCallback}. + * + * This is a synchronous call. */ - // This is a synchronous call. public void clearDrmEventCallback() { synchronized (mDrmEventCallbackLock) { mDrmEventCallback = null; diff --git a/media/apex/java/android/media/MediaPlayer2Utils.java b/media/apex/java/android/media/MediaPlayer2Utils.java index c6dee22813a0..ac34260f9bcf 100644 --- a/media/apex/java/android/media/MediaPlayer2Utils.java +++ b/media/apex/java/android/media/MediaPlayer2Utils.java @@ -36,6 +36,8 @@ public class MediaPlayer2Utils { .setSampleRate(sampleRate) .setChannelMask(channelMask) .build(); - return AudioManager.isOffloadedPlaybackSupported(format); + //TODO MP2 needs to pass AudioAttributes for this query, instead of using default attr + return AudioManager.isOffloadedPlaybackSupported(format, + (new AudioAttributes.Builder()).build()); } } diff --git a/media/apex/java/android/media/ProxyDataSourceCallback.java b/media/apex/java/android/media/ProxyDataSourceCallback.java new file mode 100644 index 000000000000..14d3ce87f03d --- /dev/null +++ b/media/apex/java/android/media/ProxyDataSourceCallback.java @@ -0,0 +1,68 @@ +/* + * Copyright 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.media; + +import android.os.ParcelFileDescriptor; +import android.system.ErrnoException; +import android.system.Os; +import android.system.OsConstants; +import android.util.Log; + +import java.io.FileDescriptor; +import java.io.IOException; + +/** + * A DataSourceCallback that is backed by a ParcelFileDescriptor. + */ +class ProxyDataSourceCallback extends DataSourceCallback { + private static final String TAG = "TestDataSourceCallback"; + + ParcelFileDescriptor mPFD; + FileDescriptor mFD; + + ProxyDataSourceCallback(ParcelFileDescriptor pfd) throws IOException { + mPFD = pfd.dup(); + mFD = mPFD.getFileDescriptor(); + } + + @Override + public synchronized int readAt(long position, byte[] buffer, int offset, int size) + throws IOException { + try { + Os.lseek(mFD, position, OsConstants.SEEK_SET); + int ret = Os.read(mFD, buffer, offset, size); + return (ret == 0) ? END_OF_STREAM : ret; + } catch (ErrnoException e) { + throw new IOException(e); + } + } + + @Override + public synchronized long getSize() throws IOException { + return mPFD.getStatSize(); + } + + @Override + public synchronized void close() { + try { + mPFD.close(); + } catch (IOException e) { + Log.e(TAG, "Failed to close the PFD.", e); + } + } +} + diff --git a/media/apex/java/android/media/Session2CommandGroup.java b/media/apex/java/android/media/Session2CommandGroup.java index 73a59d00ae34..06ae8737fdc0 100644 --- a/media/apex/java/android/media/Session2CommandGroup.java +++ b/media/apex/java/android/media/Session2CommandGroup.java @@ -167,22 +167,6 @@ public final class Session2CommandGroup implements Parcelable { } /** - * Adds a predefined command with given {@code commandCode} to this command group. - * - * @param commandCode A command code to add. - * Shouldn't be {@link Session2Command#COMMAND_CODE_CUSTOM}. - */ - @NonNull - public Builder addCommand(int commandCode) { - if (commandCode == COMMAND_CODE_CUSTOM) { - throw new IllegalArgumentException( - "Use addCommand(Session2Command) for COMMAND_CODE_CUSTOM."); - } - mCommands.add(new Session2Command(commandCode)); - return this; - } - - /** * Removes a command from this group which matches given {@code command}. * * @param command A command to find. Shouldn't be {@code null}. @@ -197,21 +181,6 @@ public final class Session2CommandGroup implements Parcelable { } /** - * Removes a command from this group which matches given {@code commandCode}. - * - * @param commandCode A command code to find. - * Shouldn't be {@link Session2Command#COMMAND_CODE_CUSTOM}. - */ - @NonNull - public Builder removeCommand(int commandCode) { - if (commandCode == COMMAND_CODE_CUSTOM) { - throw new IllegalArgumentException("commandCode shouldn't be COMMAND_CODE_CUSTOM"); - } - mCommands.remove(new Session2Command(commandCode)); - return this; - } - - /** * Builds {@link Session2CommandGroup}. * * @return a new {@link Session2CommandGroup}. diff --git a/media/apex/java/android/media/UriDataSourceDesc.java b/media/apex/java/android/media/UriDataSourceDesc.java index c0b3c825323c..eaedf1e377e2 100644 --- a/media/apex/java/android/media/UriDataSourceDesc.java +++ b/media/apex/java/android/media/UriDataSourceDesc.java @@ -18,11 +18,9 @@ package android.media; import android.annotation.NonNull; import android.annotation.Nullable; -import android.content.Context; +import android.annotation.TestApi; import android.net.Uri; -import java.net.CookieHandler; -import java.net.CookieManager; import java.net.HttpCookie; import java.util.ArrayList; import java.util.HashMap; @@ -36,15 +34,20 @@ import java.util.Map; * {@link MediaPlayer2#setNextDataSources} to set data source for playback. * * <p>Users should use {@link Builder} to change {@link UriDataSourceDesc}. - * + * @hide */ +@TestApi public class UriDataSourceDesc extends DataSourceDesc { private Uri mUri; private Map<String, String> mHeader; private List<HttpCookie> mCookies; - private Context mContext; - private UriDataSourceDesc() { + UriDataSourceDesc(String mediaId, long startPositionMs, long endPositionMs, + Uri uri, Map<String, String> header, List<HttpCookie> cookies) { + super(mediaId, startPositionMs, endPositionMs); + mUri = uri; + mHeader = header; + mCookies = cookies; } /** @@ -76,155 +79,4 @@ public class UriDataSourceDesc extends DataSourceDesc { } return new ArrayList<HttpCookie>(mCookies); } - - /** - * Return the Context used for resolving the Uri of this data source. - * @return the Context used for resolving the Uri of this data source - */ - public @NonNull Context getContext() { - return mContext; - } - - /** - * Builder class for {@link UriDataSourceDesc} objects. - * <p> Here is an example where <code>Builder</code> is used to define the - * {@link UriDataSourceDesc} to be used by a {@link MediaPlayer2} instance: - * - * <pre class="prettyprint"> - * UriDataSourceDesc newDSD = new UriDataSourceDesc.Builder() - * .setDataSource(context, uri, headers, cookies) - * .setStartPosition(1000) - * .setEndPosition(15000) - * .build(); - * mediaplayer2.setDataSourceDesc(newDSD); - * </pre> - */ - public static class Builder extends BuilderBase<Builder> { - private Uri mUri; - private Map<String, String> mHeader; - private List<HttpCookie> mCookies; - private Context mContext; - - /** - * Constructs a new Builder with the defaults. - */ - public Builder() { - super(); - } - - /** - * Constructs a new Builder from a given {@link UriDataSourceDesc} instance - * @param dsd the {@link UriDataSourceDesc} object whose data will be reused - * in the new Builder. - */ - public Builder(@Nullable UriDataSourceDesc dsd) { - super(dsd); - if (dsd == null) { - return; // use default - } - mUri = dsd.mUri; - mHeader = dsd.mHeader; - mCookies = dsd.mCookies; - mContext = dsd.mContext; - } - - /** - * Combines all of the fields that have been set and return a new - * {@link UriDataSourceDesc} object. <code>IllegalStateException</code> will be - * thrown if there is conflict between fields. - * - * @return a new {@link UriDataSourceDesc} object - */ - public @NonNull UriDataSourceDesc build() { - if (mUri == null || mContext == null) { - throw new IllegalStateException( - "Uri and Context should not be null"); - } - - UriDataSourceDesc dsd = new UriDataSourceDesc(); - super.build(dsd); - dsd.mUri = mUri; - dsd.mHeader = mHeader; - dsd.mCookies = mCookies; - dsd.mContext = mContext; - - return dsd; - } - - /** - * Sets the data source as a content Uri. - * - * @param context the Context to use when resolving the Uri - * @param uri the Content URI of the data you want to play - * @return the same Builder instance. - * @throws NullPointerException if context or uri is null. - */ - public @NonNull Builder setDataSource(@NonNull Context context, @NonNull Uri uri) { - Media2Utils.checkArgument(context != null, "context cannot be null"); - Media2Utils.checkArgument(uri != null, "uri cannot be null"); - resetDataSource(); - mUri = uri; - mContext = context; - return this; - } - - /** - * Sets the data source as a content Uri. - * - * To provide cookies for the subsequent HTTP requests, you can install your own default - * cookie handler and use other variants of setDataSource APIs instead. Alternatively, you - * can use this API to pass the cookies as a list of HttpCookie. If the app has not - * installed a CookieHandler already, {@link MediaPlayer2} will create a CookieManager - * and populates its CookieStore with the provided cookies when this data source is passed - * to {@link MediaPlayer2}. If the app has installed its own handler already, the handler - * is required to be of CookieManager type such that {@link MediaPlayer2} can update the - * manager’s CookieStore. - * - * <p><strong>Note</strong> that the cross domain redirection is allowed by default, - * but that can be changed with key/value pairs through the headers parameter with - * "android-allow-cross-domain-redirect" as the key and "0" or "1" as the value to - * disallow or allow cross domain redirection. - * - * @param context the Context to use when resolving the Uri - * @param uri the Content URI of the data you want to play - * @param headers the headers to be sent together with the request for the data - * The headers must not include cookies. Instead, use the cookies param. - * @param cookies the cookies to be sent together with the request - * @return the same Builder instance. - * @throws NullPointerException if context or uri is null. - * @throws IllegalArgumentException if the cookie handler is not of CookieManager type - * when cookies are provided. - */ - public @NonNull Builder setDataSource(@NonNull Context context, @NonNull Uri uri, - @Nullable Map<String, String> headers, @Nullable List<HttpCookie> cookies) { - Media2Utils.checkArgument(context != null, "context cannot be null"); - Media2Utils.checkArgument(uri != null, "uri cannot be null"); - if (cookies != null) { - CookieHandler cookieHandler = CookieHandler.getDefault(); - if (cookieHandler != null && !(cookieHandler instanceof CookieManager)) { - throw new IllegalArgumentException( - "The cookie handler has to be of CookieManager type " - + "when cookies are provided."); - } - } - - resetDataSource(); - mUri = uri; - if (headers != null) { - mHeader = new HashMap<String, String>(headers); - } - if (cookies != null) { - mCookies = new ArrayList<HttpCookie>(cookies); - } - mContext = context; - return this; - } - - private void resetDataSource() { - mUri = null; - mHeader = null; - mCookies = null; - mContext = null; - } - } } diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index f9080a70206e..7cb5e00e7684 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -44,6 +44,7 @@ import android.media.session.MediaController; import android.media.session.MediaSession; import android.media.session.MediaSessionLegacyHelper; import android.media.session.MediaSessionManager; +import android.net.Uri; import android.os.Binder; import android.os.Build; import android.os.Handler; @@ -1488,13 +1489,18 @@ public class AudioManager { * it does not indicate whether the resources necessary for the offloaded playback are * available at that instant. * @param format the audio format (codec, sample rate, channels) being checked. + * @param attributes the {@link AudioAttributes} to be used for playback * @return true if the given audio format can be offloaded. */ - public static boolean isOffloadedPlaybackSupported(@NonNull AudioFormat format) { + public static boolean isOffloadedPlaybackSupported(@NonNull AudioFormat format, + @NonNull AudioAttributes attributes) { if (format == null) { - throw new IllegalArgumentException("Illegal null AudioFormat"); + throw new NullPointerException("Illegal null AudioFormat"); } - return AudioSystem.isOffloadSupported(format); + if (attributes == null) { + throw new NullPointerException("Illegal null AudioAttributes"); + } + return AudioSystem.isOffloadSupported(format, attributes); } //==================================================================== @@ -3307,7 +3313,8 @@ public class AudioManager { try { MediaProjection projection = policy.getMediaProjection(); String regId = service.registerAudioPolicy(policy.getConfig(), policy.cb(), - policy.hasFocusListener(), policy.isFocusPolicy(), policy.isVolumeController(), + policy.hasFocusListener(), policy.isFocusPolicy(), policy.isTestFocusPolicy(), + policy.isVolumeController(), projection == null ? null : projection.getProjection()); if (regId == null) { return ERROR; @@ -5441,6 +5448,20 @@ public class AudioManager { sAudioAudioVolumeGroupChangedHandler.unregisterListener(callback); } + /** + * Return if an asset contains haptic channels or not. + * @param uri the {@link Uri} of the asset. + * @return true if the assert contains haptic channels. + * @hide + */ + public static boolean hasHapticChannels(Uri uri) { + try { + return getService().hasHapticChannels(uri); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + //--------------------------------------------------------- // Inner classes //-------------------- diff --git a/media/java/android/media/AudioPlaybackCaptureConfiguration.java b/media/java/android/media/AudioPlaybackCaptureConfiguration.java index 333cd2d4f0cf..4aa0b903bcdf 100644 --- a/media/java/android/media/AudioPlaybackCaptureConfiguration.java +++ b/media/java/android/media/AudioPlaybackCaptureConfiguration.java @@ -17,6 +17,7 @@ package android.media; import android.annotation.NonNull; +import android.media.AudioAttributes.AttributeUsage; import android.media.audiopolicy.AudioMix; import android.media.audiopolicy.AudioMixingRule; import android.media.projection.MediaProjection; @@ -41,12 +42,9 @@ import com.android.internal.util.Preconditions; * <pre> * MediaProjection mediaProjection; * // Retrieve a audio capable projection from the MediaProjectionManager - * AudioAttributes mediaAttr = new AudioAttributes.Builder() - * .setUsage(AudioAttributes.USAGE_MEDIA) - * .build(); * AudioPlaybackCaptureConfiguration config = * new AudioPlaybackCaptureConfiguration.Builder(mediaProjection) - * .addMatchingUsage(mediaAttr) + * .addMatchingUsage(AudioAttributes.USAGE_MEDIA) * .build(); * AudioRecord record = new AudioRecord.Builder() * .setAudioPlaybackCaptureConfig(config) @@ -68,6 +66,15 @@ public final class AudioPlaybackCaptureConfiguration { } /** + * @return the {@code MediaProjection} used to build this object. + * @see {@code Builder.Builder} + */ + public @NonNull MediaProjection getMediaProjection() { + return mProjection; + } + + + /** * Returns a mix that routes audio back into the app while still playing it from the speakers. * * @param audioFormat The format in which to capture the audio. @@ -78,9 +85,6 @@ public final class AudioPlaybackCaptureConfiguration { .setRouteFlags(AudioMix.ROUTE_FLAG_LOOP_BACK | AudioMix.ROUTE_FLAG_RENDER) .build(); } - MediaProjection getMediaProjection() { - return mProjection; - } /** Builder for creating {@link AudioPlaybackCaptureConfiguration} instances. */ public static final class Builder { @@ -121,14 +125,13 @@ public final class AudioPlaybackCaptureConfiguration { * attributes. * * @throws IllegalStateException if called in conjunction with - * {@link #excludeUsage(AudioAttributes)}. + * {@link #excludeUsage(int)}. */ - public @NonNull Builder addMatchingUsage(@NonNull AudioAttributes audioAttributes) { - Preconditions.checkNotNull(audioAttributes); + public @NonNull Builder addMatchingUsage(@AttributeUsage int usage) { Preconditions.checkState( mUsageMatchType != MATCH_TYPE_EXCLUSIVE, ERROR_MESSAGE_MISMATCHED_RULES); - mAudioMixingRuleBuilder - .addRule(audioAttributes, AudioMixingRule.RULE_MATCH_ATTRIBUTE_USAGE); + mAudioMixingRuleBuilder.addRule(new AudioAttributes.Builder().setUsage(usage).build(), + AudioMixingRule.RULE_MATCH_ATTRIBUTE_USAGE); mUsageMatchType = MATCH_TYPE_INCLUSIVE; return this; } @@ -156,14 +159,15 @@ public final class AudioPlaybackCaptureConfiguration { * given attributes. * * @throws IllegalStateException if called in conjunction with - * {@link #addMatchingUsage(AudioAttributes)}. + * {@link #addMatchingUsage(int)}. */ - public @NonNull Builder excludeUsage(@NonNull AudioAttributes audioAttributes) { - Preconditions.checkNotNull(audioAttributes); + public @NonNull Builder excludeUsage(@AttributeUsage int usage) { Preconditions.checkState( mUsageMatchType != MATCH_TYPE_INCLUSIVE, ERROR_MESSAGE_MISMATCHED_RULES); - mAudioMixingRuleBuilder.excludeRule(audioAttributes, - AudioMixingRule.RULE_MATCH_ATTRIBUTE_USAGE); + mAudioMixingRuleBuilder.excludeRule(new AudioAttributes.Builder() + .setUsage(usage) + .build(), + AudioMixingRule.RULE_MATCH_ATTRIBUTE_USAGE); mUsageMatchType = MATCH_TYPE_EXCLUSIVE; return this; } diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java index 8051236680aa..a7760a80974d 100644 --- a/media/java/android/media/AudioRecord.java +++ b/media/java/android/media/AudioRecord.java @@ -1798,8 +1798,8 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection, * * @return true if sucessful. */ - public boolean setMicrophoneDirection(@DirectionMode int direction) { - return native_set_microphone_direction(direction) == AudioSystem.SUCCESS; + public boolean setPreferredMicrophoneDirection(@DirectionMode int direction) { + return native_set_preferred_microphone_direction(direction) == AudioSystem.SUCCESS; } /** @@ -1810,10 +1810,11 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection, * though 0 (no zoom) to 1 (maximum zoom). * @return true if sucessful. */ - public boolean setMicrophoneFieldDimension(@FloatRange(from = -1.0, to = 1.0) float zoom) { + public boolean setPreferredMicrophoneFieldDimension( + @FloatRange(from = -1.0, to = 1.0) float zoom) { Preconditions.checkArgument( zoom >= -1 && zoom <= 1, "Argument must fall between -1 & 1 (inclusive)"); - return native_set_microphone_field_dimension(zoom) == AudioSystem.SUCCESS; + return native_set_preferred_microphone_field_dimension(zoom) == AudioSystem.SUCCESS; } //--------------------------------------------------------- @@ -1969,8 +1970,8 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection, private native int native_getPortId(); - private native int native_set_microphone_direction(int direction); - private native int native_set_microphone_field_dimension(float zoom); + private native int native_set_preferred_microphone_direction(int direction); + private native int native_set_preferred_microphone_field_dimension(float zoom); //--------------------------------------------------------- // Utility methods diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java index a976d707f5cb..ad255fe3d5a2 100644 --- a/media/java/android/media/AudioSystem.java +++ b/media/java/android/media/AudioSystem.java @@ -1022,13 +1022,14 @@ public class AudioSystem public static native float getStreamVolumeDB(int stream, int index, int device); - static boolean isOffloadSupported(@NonNull AudioFormat format) { + static boolean isOffloadSupported(@NonNull AudioFormat format, @NonNull AudioAttributes attr) { return native_is_offload_supported(format.getEncoding(), format.getSampleRate(), - format.getChannelMask(), format.getChannelIndexMask()); + format.getChannelMask(), format.getChannelIndexMask(), + attr.getVolumeControlStream()); } private static native boolean native_is_offload_supported(int encoding, int sampleRate, - int channelMask, int channelIndexMask); + int channelMask, int channelIndexMask, int streamType); public static native int getMicrophones(ArrayList<MicrophoneInfo> microphonesInfo); diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java index 41e059bba92d..325e227e6f93 100644 --- a/media/java/android/media/AudioTrack.java +++ b/media/java/android/media/AudioTrack.java @@ -914,8 +914,9 @@ public class AudioTrack extends PlayerBase /** * Sets whether this track will play through the offloaded audio path. * When set to true, at build time, the audio format will be checked against - * {@link AudioManager#isOffloadedPlaybackSupported(AudioFormat)} to verify the audio format - * used by this track is supported on the device's offload path (if any). + * {@link AudioManager#isOffloadedPlaybackSupported(AudioFormat,AudioAttributes)} + * to verify the audio format used by this track is supported on the device's offload + * path (if any). * <br>Offload is only supported for media audio streams, and therefore requires that * the usage be {@link AudioAttributes#USAGE_MEDIA}. * @param offload true to require the offload path for playback. @@ -979,7 +980,7 @@ public class AudioTrack extends PlayerBase throw new UnsupportedOperationException( "Cannot create AudioTrack, offload requires USAGE_MEDIA"); } - if (!AudioSystem.isOffloadSupported(mFormat)) { + if (!AudioSystem.isOffloadSupported(mFormat, mAttributes)) { throw new UnsupportedOperationException( "Cannot create AudioTrack, offload format not supported"); } @@ -3177,7 +3178,8 @@ public class AudioTrack extends PlayerBase * Registers a callback for the notification of stream events. * This callback can only be registered for instances operating in offloaded mode * (see {@link AudioTrack.Builder#setOffloadedPlayback(boolean)} and - * {@link AudioManager#isOffloadedPlaybackSupported(AudioFormat)} for more details). + * {@link AudioManager#isOffloadedPlaybackSupported(AudioFormat,AudioAttributes)} for + * more details). * @param executor {@link Executor} to handle the callbacks. * @param eventCallback the callback to receive the stream event notifications. */ diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl index c29f355181f4..980cb0459821 100644 --- a/media/java/android/media/IAudioService.aidl +++ b/media/java/android/media/IAudioService.aidl @@ -37,6 +37,7 @@ import android.media.audiopolicy.AudioProductStrategies; import android.media.audiopolicy.AudioVolumeGroups; import android.media.audiopolicy.IAudioPolicyCallback; import android.media.projection.IMediaProjection; +import android.net.Uri; /** * {@hide} @@ -195,6 +196,7 @@ interface IAudioService { String registerAudioPolicy(in AudioPolicyConfig policyConfig, in IAudioPolicyCallback pcb, boolean hasFocusListener, boolean isFocusPolicy, + boolean isTestFocusPolicy, boolean isVolumeController, in IMediaProjection projection); oneway void unregisterAudioPolicyAsync(in IAudioPolicyCallback pcb); @@ -250,6 +252,8 @@ interface IAudioService { int removeUidDeviceAffinity(in IAudioPolicyCallback pcb, in int uid); + boolean hasHapticChannels(in Uri uri); + // WARNING: read warning at top of file, new methods that need to be used by native // code via IAudioManager.h need to be added to the top section. } diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java index aeb77cfddbbd..005f2d47367b 100644 --- a/media/java/android/media/MediaDrm.java +++ b/media/java/android/media/MediaDrm.java @@ -304,6 +304,11 @@ public final class MediaDrm implements AutoCloseable { } /** + * The SessionException has an unknown error code. + */ + public static final int ERROR_UNKNOWN = 0; + + /** * This indicates that apps using MediaDrm sessions are * temporarily exceeding the capacity of available crypto * resources. The app should retry the operation later. diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java index 27499c6160d3..a22c8d0a8457 100644 --- a/media/java/android/media/MediaFormat.java +++ b/media/java/android/media/MediaFormat.java @@ -413,7 +413,18 @@ public final class MediaFormat { */ public static final String KEY_INTRA_REFRESH_PERIOD = "intra-refresh-period"; - /** + /** + * An optional key describing whether encoders prepend headers to sync frames (e.g. + * SPS and PPS to IDR frames for H.264). This is an optional parameter that applies only + * to video encoders. A video encoder may not support this feature; check the output + * format to verify that this feature was enabled. + * + * The value is an integer, with 1 indicating to prepend headers to every sync frames, + * or 0 otherwise. The default value is 0. + */ + public static final String KEY_PREPEND_HEADER_TO_SYNC_FRAMES = "prepend-sps-pps-to-idr-frames"; + + /** * A key describing the temporal layering schema. This is an optional parameter * that applies only to video encoders. Use {@link MediaCodec#getOutputFormat} * after {@link MediaCodec#configure configure} to query if the encoder supports @@ -863,6 +874,12 @@ public final class MediaFormat { */ public static final String KEY_IS_FORCED_SUBTITLE = "is-forced-subtitle"; + /** + * A key describing the number of haptic channels in an audio format. + * The associated value is an integer. + */ + public static final String KEY_HAPTIC_CHANNEL_COUNT = "haptic-channel-count"; + /** @hide */ public static final String KEY_IS_TIMED_TEXT = "is-timed-text"; diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java index e7b4752701fb..575a0bb03f7b 100644 --- a/media/java/android/media/MediaRecorder.java +++ b/media/java/android/media/MediaRecorder.java @@ -1537,8 +1537,8 @@ public class MediaRecorder implements AudioRouting, * @param direction Direction constant. * @return true if sucessful. */ - public boolean setMicrophoneDirection(@DirectionMode int direction) { - return native_setMicrophoneDirection(direction) == 0; + public boolean setPreferredMicrophoneDirection(@DirectionMode int direction) { + return native_setPreferredMicrophoneDirection(direction) == 0; } /** @@ -1549,14 +1549,15 @@ public class MediaRecorder implements AudioRouting, * though 0 (no zoom) to 1 (maximum zoom). * @return true if sucessful. */ - public boolean setMicrophoneFieldDimension(@FloatRange(from = -1.0, to = 1.0) float zoom) { + public boolean setPreferredMicrophoneFieldDimension( + @FloatRange(from = -1.0, to = 1.0) float zoom) { Preconditions.checkArgument( zoom >= -1 && zoom <= 1, "Argument must fall between -1 & 1 (inclusive)"); - return native_setMicrophoneFieldDimension(zoom) == 0; + return native_setPreferredMicrophoneFieldDimension(zoom) == 0; } - private native int native_setMicrophoneDirection(int direction); - private native int native_setMicrophoneFieldDimension(float zoom); + private native int native_setPreferredMicrophoneDirection(int direction); + private native int native_setPreferredMicrophoneFieldDimension(float zoom); //-------------------------------------------------------------------------- // Implementation of AudioRecordingMonitor interface diff --git a/media/java/android/media/MediaTimestamp.java b/media/java/android/media/MediaTimestamp.java index da3362a019b9..0777ba3144ea 100644 --- a/media/java/android/media/MediaTimestamp.java +++ b/media/java/android/media/MediaTimestamp.java @@ -16,8 +16,7 @@ package android.media; -import android.annotation.NonNull; -import android.annotation.SystemApi; +import android.annotation.FloatRange; /** * An immutable object that represents the linear correlation between the media time @@ -76,6 +75,7 @@ public final class MediaTimestamp * greater than 1.0 if media clock is faster than the system clock; * less than 1.0 if media clock is slower than the system clock. */ + @FloatRange(from = 0.0f, to = Float.MAX_VALUE) public float getMediaClockRate() { return clockRate; } @@ -87,11 +87,19 @@ public final class MediaTimestamp /** @hide - accessor shorthand */ public final float clockRate; - /** @hide */ - MediaTimestamp(long mediaUs, long systemNs, float rate) { - mediaTimeUs = mediaUs; - nanoTime = systemNs; - clockRate = rate; + /** + * Constructor. + * + * @param mediaTimeUs the media time of the anchor in microseconds + * @param nanoTimeNs the {@link java.lang.System#nanoTime system time} corresponding to the + * media time in nanoseconds. + * @param clockRate the rate of the media clock in relation to the system time. + */ + public MediaTimestamp(long mediaTimeUs, long nanoTimeNs, + @FloatRange(from = 0.0f, to = Float.MAX_VALUE) float clockRate) { + this.mediaTimeUs = mediaTimeUs; + this.nanoTime = nanoTimeNs; + this.clockRate = clockRate; } /** @hide */ @@ -120,71 +128,4 @@ public final class MediaTimestamp + " clockRate=" + clockRate + "}"; } - - /** - * Builder class for {@link MediaTimestamp} objects. - * <p> Here is an example where <code>Builder</code> is used to define the - * {@link MediaTimestamp}: - * - * <pre class="prettyprint"> - * MediaTimestamp mts = new MediaTimestamp.Builder() - * .setMediaTimestamp(mediaTime, systemTime, rate) - * .build(); - * </pre> - * @hide - */ - @SystemApi - public static final class Builder { - long mMediaTimeUs; - long mNanoTime; - float mClockRate = 1.0f; - - /** - * Constructs a new Builder with the defaults. - */ - public Builder() { - } - - /** - * Constructs a new Builder from a given {@link MediaTimestamp} instance - * @param mts the {@link MediaTimestamp} object whose data will be reused - * in the new Builder. - */ - public Builder(@NonNull MediaTimestamp mts) { - if (mts == null) { - throw new IllegalArgumentException("null MediaTimestamp is not allowed"); - } - mMediaTimeUs = mts.mediaTimeUs; - mNanoTime = mts.nanoTime; - mClockRate = mts.clockRate; - } - - /** - * Combines all of the fields that have been set and return a new - * {@link MediaTimestamp} object. - * - * @return a new {@link MediaTimestamp} object - */ - public @NonNull MediaTimestamp build() { - return new MediaTimestamp(mMediaTimeUs, mNanoTime, mClockRate); - } - - /** - * Sets the info of media timestamp. - * - * @param mediaTimeUs the media time of the anchor in microseconds - * @param nanoTime the {@link java.lang.System#nanoTime system time} corresponding to - * the media time in nanoseconds. - * @param clockRate the rate of the media clock in relation to the system time. - * @return the same Builder instance. - */ - public @NonNull Builder setMediaTimestamp( - long mediaTimeUs, long nanoTime, float clockRate) { - mMediaTimeUs = mediaTimeUs; - mNanoTime = nanoTime; - mClockRate = clockRate; - - return this; - } - } } diff --git a/media/java/android/media/MicrophoneDirection.java b/media/java/android/media/MicrophoneDirection.java index 2382da54801c..e4eec446b7bc 100644 --- a/media/java/android/media/MicrophoneDirection.java +++ b/media/java/android/media/MicrophoneDirection.java @@ -32,13 +32,21 @@ public interface MicrophoneDirection { */ int MIC_DIRECTION_UNSPECIFIED = 0; /** - * Optimize capture for audio coming from the screen-side of the device. + * Optimize capture for audio coming from the side of the device facing the user. + * In the typical case, a device with a single screen, screen-side camera/microphone and + * non-screen-side camera/microphone, this will be the screen side (as in a "selfie"). + * For a different device geometry, it is the side for which the expectation is to be + * facing the user. */ - int MIC_DIRECTION_FRONT = 1; + int MIC_DIRECTION_TOWARDS_USER = 1; /** - * Optimize capture for audio coming from the side of the device opposite the screen. + * Optimize capture for audio coming from the side of the device pointing away from the user. + * In the typical case, a device with a single screen, screen-side camera/microphone and + * non-screen-side camera/microphone, this will be the non-screen side. + * For a different device geometry, it is the side for which the expectation is to be + * facing away from the user. This is the "taking a video of something else" case. */ - int MIC_DIRECTION_BACK = 2; + int MIC_DIRECTION_AWAY_FROM_USER = 2; /** * Optimize capture for audio coming from an off-device microphone. */ @@ -47,8 +55,8 @@ public interface MicrophoneDirection { /** @hide */ /*public*/ @IntDef({ MIC_DIRECTION_UNSPECIFIED, - MIC_DIRECTION_FRONT, - MIC_DIRECTION_BACK, + MIC_DIRECTION_TOWARDS_USER, + MIC_DIRECTION_AWAY_FROM_USER, MIC_DIRECTION_EXTERNAL }) @Retention(RetentionPolicy.SOURCE) @@ -58,18 +66,23 @@ public interface MicrophoneDirection { * which side of the device to optimize capture from. Typically used in conjunction with * the camera capturing video. * + * Usage would include specifying the audio capture to follow camera being used to capture + * video. * @param direction Direction constant. * @return true if sucessful. */ - boolean setMicrophoneDirection(@DirectionMode int direction); + boolean setPreferredMicrophoneDirection(@DirectionMode int direction); /** * Specifies the zoom factor (i.e. the field dimension) for the selected microphone * (for processing). The selected microphone is determined by the use-case for the stream. * + * Usage would include specifying the audio focus to follow the zoom specified for the camera + * being used to capture video. + * * @param zoom the desired field dimension of microphone capture. Range is from -1 (wide angle), * though 0 (no zoom) to 1 (maximum zoom). * @return true if sucessful. */ - boolean setMicrophoneFieldDimension(@FloatRange(from = -1.0, to = 1.0) float zoom); + boolean setPreferredMicrophoneFieldDimension(@FloatRange(from = -1.0, to = 1.0) float zoom); } diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java index 9a609236aa30..e0e657bb4474 100644 --- a/media/java/android/media/RingtoneManager.java +++ b/media/java/android/media/RingtoneManager.java @@ -1098,6 +1098,28 @@ public class RingtoneManager { } /** + * Returns if the {@link Ringtone} at the given position in the + * {@link Cursor} contains haptic channels. + * + * @param position The position (in the {@link Cursor}) of the ringtone. + * @return true if the ringtone contains haptic channels. + */ + public boolean hasHapticChannels(int position) { + return hasHapticChannels(getRingtoneUri(position)); + } + + /** + * Returns if the {@link Ringtone} from a given sound URI contains + * haptic channels or not. + * + * @param ringtoneUri The {@link Uri} of a sound or ringtone. + * @return true if the ringtone contains haptic channels. + */ + public static boolean hasHapticChannels(@NonNull Uri ringtoneUri) { + return AudioManager.hasHapticChannels(ringtoneUri); + } + + /** * Creates a {@link android.media.MediaScannerConnection} to scan a ringtone file and add its * information to the internal database. * diff --git a/media/java/android/media/SubtitleData.java b/media/java/android/media/SubtitleData.java index 2c6c61f8df18..2ef69820fb84 100644 --- a/media/java/android/media/SubtitleData.java +++ b/media/java/android/media/SubtitleData.java @@ -17,11 +17,8 @@ package android.media; import android.annotation.NonNull; -import android.annotation.SystemApi; import android.os.Parcel; -import java.util.Arrays; - /** * Class encapsulating subtitle data, as received through the * {@link MediaPlayer.OnSubtitleDataListener} interface. @@ -82,12 +79,23 @@ public final class SubtitleData } } - /** @hide */ + /** + * Constructor. + * + * @param trackIndex the index of the media player track which contains this subtitle data. + * @param startTimeUs the start time in microsecond for the subtitle data + * @param durationUs the duration in microsecond for the subtitle data + * @param data the data array for the subtitle data. It should not be null. + * No data copying is made. + */ public SubtitleData(int trackIndex, long startTimeUs, long durationUs, @NonNull byte[] data) { + if (data == null) { + throw new IllegalArgumentException("null data is not allowed"); + } mTrackIndex = trackIndex; mStartTimeUs = startTimeUs; mDurationUs = durationUs; - mData = (data != null ? data : new byte[0]); + mData = data; } /** @@ -141,80 +149,4 @@ public final class SubtitleData return true; } - - /** - * Builder class for {@link SubtitleData} objects. - * <p> Here is an example where <code>Builder</code> is used to define the - * {@link SubtitleData}: - * - * <pre class="prettyprint"> - * SubtitleData sd = new SubtitleData.Builder() - * .setSubtitleData(trackIndex, startTime, duration, data) - * .build(); - * </pre> - * @hide - */ - @SystemApi - public static final class Builder { - private int mTrackIndex; - private long mStartTimeUs; - private long mDurationUs; - private byte[] mData = new byte[0]; - - /** - * Constructs a new Builder with the defaults. - */ - public Builder() { - } - - /** - * Constructs a new Builder from a given {@link SubtitleData} instance - * @param sd the {@link SubtitleData} object whose data will be reused - * in the new Builder. It should not be null. The data array is copied. - */ - public Builder(@NonNull SubtitleData sd) { - if (sd == null) { - throw new IllegalArgumentException("null SubtitleData is not allowed"); - } - mTrackIndex = sd.mTrackIndex; - mStartTimeUs = sd.mStartTimeUs; - mDurationUs = sd.mDurationUs; - if (sd.mData != null) { - mData = Arrays.copyOf(sd.mData, sd.mData.length); - } - } - - /** - * Combines all of the fields that have been set and return a new - * {@link SubtitleData} object. <code>IllegalStateException</code> will be - * thrown if there is conflict between fields. - * - * @return a new {@link SubtitleData} object - */ - public @NonNull SubtitleData build() { - return new SubtitleData(mTrackIndex, mStartTimeUs, mDurationUs, mData); - } - - /** - * Sets the info of subtitle data. - * - * @param trackIndex the index of the media player track which contains this subtitle data. - * @param startTimeUs the start time in microsecond for the subtile data - * @param durationUs the duration in microsecond for the subtile data - * @param data the data array for the subtile data. It should not be null. - * No data copying is made. - * @return the same Builder instance. - */ - public @NonNull Builder setSubtitleData( - int trackIndex, long startTimeUs, long durationUs, @NonNull byte[] data) { - if (data == null) { - throw new IllegalArgumentException("null data is not allowed"); - } - mTrackIndex = trackIndex; - mStartTimeUs = startTimeUs; - mDurationUs = durationUs; - mData = data; - return this; - } - } } diff --git a/media/java/android/media/TimedMetaData.java b/media/java/android/media/TimedMetaData.java index 990760cf32ae..b99b30c58cf3 100644 --- a/media/java/android/media/TimedMetaData.java +++ b/media/java/android/media/TimedMetaData.java @@ -17,11 +17,8 @@ package android.media; import android.annotation.NonNull; -import android.annotation.SystemApi; import android.os.Parcel; -import java.util.Arrays; - /** * Class that embodies one timed metadata access unit, including * @@ -52,7 +49,11 @@ public final class TimedMetaData { } /** - * @hide + * Constructor. + * + * @param timestampUs the timestamp in microsecond for the timed metadata + * @param metaData the metadata array for the timed metadata. No data copying is made. + * It should not be null. */ public TimedMetaData(long timestampUs, @NonNull byte[] metaData) { if (metaData == null) { @@ -90,71 +91,4 @@ public final class TimedMetaData { return true; } - - /** - * Builder class for {@link TimedMetaData} objects. - * <p> Here is an example where <code>Builder</code> is used to define the - * {@link TimedMetaData}: - * - * <pre class="prettyprint"> - * TimedMetaData tmd = new TimedMetaData.Builder() - * .setTimedMetaData(timestamp, metaData) - * .build(); - * </pre> - * @hide - */ - @SystemApi - public static final class Builder { - private long mTimestampUs; - private byte[] mMetaData = new byte[0]; - - /** - * Constructs a new Builder with the defaults. - */ - public Builder() { - } - - /** - * Constructs a new Builder from a given {@link TimedMetaData} instance - * @param tmd the {@link TimedMetaData} object whose data will be reused - * in the new Builder. It should not be null. The metadata array is copied. - */ - public Builder(@NonNull TimedMetaData tmd) { - if (tmd == null) { - throw new IllegalArgumentException("null TimedMetaData is not allowed"); - } - mTimestampUs = tmd.mTimestampUs; - if (tmd.mMetaData != null) { - mMetaData = Arrays.copyOf(tmd.mMetaData, tmd.mMetaData.length); - } - } - - /** - * Combines all of the fields that have been set and return a new - * {@link TimedMetaData} object. <code>IllegalStateException</code> will be - * thrown if there is conflict between fields. - * - * @return a new {@link TimedMetaData} object - */ - public @NonNull TimedMetaData build() { - return new TimedMetaData(mTimestampUs, mMetaData); - } - - /** - * Sets the info of timed metadata. - * - * @param timestamp the timestamp in microsecond for the timed metadata - * @param metaData the metadata array for the timed metadata. No data copying is made. - * It should not be null. - * @return the same Builder instance. - */ - public @NonNull Builder setTimedMetaData(long timestamp, @NonNull byte[] metaData) { - if (metaData == null) { - throw new IllegalArgumentException("null metaData is not allowed"); - } - mTimestampUs = timestamp; - mMetaData = metaData; - return this; - } - } } diff --git a/media/java/android/media/audiopolicy/AudioMixingRule.java b/media/java/android/media/audiopolicy/AudioMixingRule.java index 6c48cdb7b643..d41f416f3d51 100644 --- a/media/java/android/media/audiopolicy/AudioMixingRule.java +++ b/media/java/android/media/audiopolicy/AudioMixingRule.java @@ -409,6 +409,10 @@ public class AudioMixingRule { final int match_rule = rule & ~RULE_EXCLUSION_MASK; while (crIterator.hasNext()) { final AudioMixMatchCriterion criterion = crIterator.next(); + + if ((criterion.mRule & ~RULE_EXCLUSION_MASK) != match_rule) { + continue; // The two rules are not of the same type + } switch (match_rule) { case RULE_MATCH_ATTRIBUTE_USAGE: // "usage"-based rule diff --git a/media/java/android/media/audiopolicy/AudioPolicy.java b/media/java/android/media/audiopolicy/AudioPolicy.java index 978583e99971..00f601388164 100644 --- a/media/java/android/media/audiopolicy/AudioPolicy.java +++ b/media/java/android/media/audiopolicy/AudioPolicy.java @@ -75,6 +75,7 @@ public class AudioPolicy { private String mRegistrationId; private AudioPolicyStatusListener mStatusListener; private boolean mIsFocusPolicy; + private boolean mIsTestFocusPolicy; /** * The list of AudioTrack instances created to inject audio into the associated mixes @@ -121,6 +122,10 @@ public class AudioPolicy { /** @hide */ public boolean isFocusPolicy() { return mIsFocusPolicy; } /** @hide */ + public boolean isTestFocusPolicy() { + return mIsTestFocusPolicy; + } + /** @hide */ public boolean isVolumeController() { return mVolCb != null; } /** @hide */ public @Nullable MediaProjection getMediaProjection() { @@ -128,10 +133,11 @@ public class AudioPolicy { } /** - * The parameter is guaranteed non-null through the Builder + * The parameters are guaranteed non-null through the Builder */ private AudioPolicy(AudioPolicyConfig config, Context context, Looper looper, - AudioPolicyFocusListener fl, AudioPolicyStatusListener sl, boolean isFocusPolicy, + AudioPolicyFocusListener fl, AudioPolicyStatusListener sl, + boolean isFocusPolicy, boolean isTestFocusPolicy, AudioPolicyVolumeCallback vc, @Nullable MediaProjection projection) { mConfig = config; mStatus = POLICY_STATUS_UNREGISTERED; @@ -148,6 +154,7 @@ public class AudioPolicy { mFocusListener = fl; mStatusListener = sl; mIsFocusPolicy = isFocusPolicy; + mIsTestFocusPolicy = isTestFocusPolicy; mVolCb = vc; mProjection = projection; } @@ -163,6 +170,7 @@ public class AudioPolicy { private AudioPolicyFocusListener mFocusListener; private AudioPolicyStatusListener mStatusListener; private boolean mIsFocusPolicy = false; + private boolean mIsTestFocusPolicy = false; private AudioPolicyVolumeCallback mVolCb; private MediaProjection mProjection; @@ -181,6 +189,7 @@ public class AudioPolicy { * @return the same Builder instance. * @throws IllegalArgumentException */ + @NonNull public Builder addMix(@NonNull AudioMix mix) throws IllegalArgumentException { if (mix == null) { throw new IllegalArgumentException("Illegal null AudioMix argument"); @@ -195,6 +204,7 @@ public class AudioPolicy { * @return the same Builder instance. * @throws IllegalArgumentException */ + @NonNull public Builder setLooper(@NonNull Looper looper) throws IllegalArgumentException { if (looper == null) { throw new IllegalArgumentException("Illegal null Looper argument"); @@ -220,12 +230,28 @@ public class AudioPolicy { * @param enforce true if the policy will govern audio focus decisions. * @return the same Builder instance. */ + @NonNull public Builder setIsAudioFocusPolicy(boolean isFocusPolicy) { mIsFocusPolicy = isFocusPolicy; return this; } /** + * Test method to declare whether this audio focus policy is for test purposes only. + * Having a test policy registered will disable the current focus policy and replace it + * with this test policy. When unregistered, the previous focus policy will be restored. + * <p>A value of <code>true</code> will be ignored if the AudioPolicy is not also + * focus policy. + * @param isTestFocusPolicy true if the focus policy to register is for testing purposes. + * @return the same Builder instance + */ + @NonNull + public Builder setIsTestFocusPolicy(boolean isTestFocusPolicy) { + mIsTestFocusPolicy = isTestFocusPolicy; + return this; + } + + /** * Sets the audio policy status listener. * @param l a {@link AudioPolicy.AudioPolicyStatusListener} */ @@ -240,6 +266,7 @@ public class AudioPolicy { * @param vc * @return the same Builder instance. */ + @NonNull public Builder setAudioPolicyVolumeCallback(@NonNull AudioPolicyVolumeCallback vc) { if (vc == null) { throw new IllegalArgumentException("Invalid null volume callback"); @@ -256,6 +283,7 @@ public class AudioPolicy { * * @hide */ + @NonNull public Builder setMediaProjection(@NonNull MediaProjection projection) { if (projection == null) { throw new IllegalArgumentException("Invalid null volume callback"); @@ -273,6 +301,7 @@ public class AudioPolicy { * {@link AudioPolicy.AudioPolicyStatusListener} but the policy was configured * as an audio focus policy with {@link #setIsAudioFocusPolicy(boolean)}. */ + @NonNull public AudioPolicy build() { if (mStatusListener != null) { // the AudioPolicy status listener includes updates on each mix activity state @@ -285,7 +314,8 @@ public class AudioPolicy { + "an AudioPolicyFocusListener"); } return new AudioPolicy(new AudioPolicyConfig(mMixes), mContext, mLooper, - mFocusListener, mStatusListener, mIsFocusPolicy, mVolCb, mProjection); + mFocusListener, mStatusListener, mIsFocusPolicy, mIsTestFocusPolicy, + mVolCb, mProjection); } } diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java index cbc6c9d6e451..080094cf99d9 100644 --- a/media/java/android/media/session/MediaSession.java +++ b/media/java/android/media/session/MediaSession.java @@ -27,12 +27,15 @@ import android.content.Intent; import android.media.AudioAttributes; import android.media.MediaDescription; import android.media.MediaMetadata; +import android.media.MediaParceledListSlice; import android.media.Rating; import android.media.VolumeProvider; import android.media.session.MediaSessionManager.RemoteUserInfo; import android.net.Uri; import android.os.Bundle; import android.os.Handler; +import android.os.Looper; +import android.os.Message; import android.os.Parcel; import android.os.Parcelable; import android.os.Process; @@ -40,6 +43,10 @@ import android.os.RemoteException; import android.os.ResultReceiver; import android.service.media.MediaBrowserService; import android.text.TextUtils; +import android.util.Log; +import android.util.Pair; +import android.view.KeyEvent; +import android.view.ViewConfiguration; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -116,12 +123,21 @@ public final class MediaSession { FLAG_EXCLUSIVE_GLOBAL_PRIORITY }) public @interface SessionFlags { } - private final MediaSessionEngine mImpl; + private final Object mLock = new Object(); private final int mMaxBitmapSize; + private final Token mSessionToken; + private final MediaController mController; + private final ISession mBinder; + private final SessionCallbackLink mCbStub; + // Do not change the name of mCallback. Support lib accesses this by using reflection. @UnsupportedAppUsage - private Object mCallback; + private CallbackMessageHandler mCallback; + private VolumeProvider mVolumeProvider; + private PlaybackState mPlaybackState; + + private boolean mActive = false; /** * Creates a new session. The session will automatically be registered with @@ -160,14 +176,15 @@ public final class MediaSession { if (TextUtils.isEmpty(tag)) { throw new IllegalArgumentException("tag cannot be null or empty"); } + mMaxBitmapSize = context.getResources().getDimensionPixelSize( + com.android.internal.R.dimen.config_mediaMetadataBitmapMaxSize); + mCbStub = new SessionCallbackLink(context, this); MediaSessionManager manager = (MediaSessionManager) context .getSystemService(Context.MEDIA_SESSION_SERVICE); try { - SessionCallbackLink cbLink = new SessionCallbackLink(context); - ISession binder = manager.createSession(cbLink, tag, sessionInfo); - mImpl = new MediaSessionEngine(context, binder, cbLink); - mMaxBitmapSize = context.getResources().getDimensionPixelSize( - com.android.internal.R.dimen.config_mediaMetadataBitmapMaxSize); + mBinder = manager.createSession(mCbStub, tag, sessionInfo); + mSessionToken = new Token(mBinder.getController()); + mController = new MediaController(context, mSessionToken); } catch (RemoteException e) { throw new RuntimeException("Remote error creating session.", e); } @@ -183,8 +200,7 @@ public final class MediaSession { * @param callback The callback object */ public void setCallback(@Nullable Callback callback) { - mCallback = callback == null ? null : new Object(); - mImpl.setCallback(callback); + setCallback(callback, null); } /** @@ -197,8 +213,24 @@ public final class MediaSession { * @param handler The handler that events should be posted on. */ public void setCallback(@Nullable Callback callback, @Nullable Handler handler) { - mCallback = callback == null ? null : new Object(); - mImpl.setCallback(callback, handler); + synchronized (mLock) { + if (mCallback != null) { + // We're updating the callback, clear the session from the old one. + mCallback.mCallback.mSession = null; + mCallback.removeCallbacksAndMessages(null); + } + if (callback == null) { + mCallback = null; + return; + } + if (handler == null) { + handler = new Handler(); + } + callback.mSession = this; + CallbackMessageHandler msgHandler = new CallbackMessageHandler(handler.getLooper(), + callback); + mCallback = msgHandler; + } } /** @@ -209,7 +241,11 @@ public final class MediaSession { * @param pi The intent to launch to show UI for this Session. */ public void setSessionActivity(@Nullable PendingIntent pi) { - mImpl.setSessionActivity(pi); + try { + mBinder.setLaunchPendingIntent(pi); + } catch (RemoteException e) { + Log.wtf(TAG, "Failure in setLaunchPendingIntent.", e); + } } /** @@ -221,7 +257,11 @@ public final class MediaSession { * @param mbr The {@link PendingIntent} to send the media button event to. */ public void setMediaButtonReceiver(@Nullable PendingIntent mbr) { - mImpl.setMediaButtonReceiver(mbr); + try { + mBinder.setMediaButtonReceiver(mbr); + } catch (RemoteException e) { + Log.wtf(TAG, "Failure in setMediaButtonReceiver.", e); + } } /** @@ -230,7 +270,11 @@ public final class MediaSession { * @param flags The flags to set for this session. */ public void setFlags(@SessionFlags int flags) { - mImpl.setFlags(flags); + try { + mBinder.setFlags(flags); + } catch (RemoteException e) { + Log.wtf(TAG, "Failure in setFlags.", e); + } } /** @@ -245,7 +289,14 @@ public final class MediaSession { * @param attributes The {@link AudioAttributes} for this session's audio. */ public void setPlaybackToLocal(AudioAttributes attributes) { - mImpl.setPlaybackToLocal(attributes); + if (attributes == null) { + throw new IllegalArgumentException("Attributes cannot be null for local playback."); + } + try { + mBinder.setPlaybackToLocal(attributes); + } catch (RemoteException e) { + Log.wtf(TAG, "Failure in setPlaybackToLocal.", e); + } } /** @@ -260,7 +311,26 @@ public final class MediaSession { * not be null. */ public void setPlaybackToRemote(@NonNull VolumeProvider volumeProvider) { - mImpl.setPlaybackToRemote(volumeProvider); + if (volumeProvider == null) { + throw new IllegalArgumentException("volumeProvider may not be null!"); + } + synchronized (mLock) { + mVolumeProvider = volumeProvider; + } + volumeProvider.setCallback(new VolumeProvider.Callback() { + @Override + public void onVolumeChanged(VolumeProvider volumeProvider) { + notifyRemoteVolumeChanged(volumeProvider); + } + }); + + try { + mBinder.setPlaybackToRemote(volumeProvider.getVolumeControl(), + volumeProvider.getMaxVolume()); + mBinder.setCurrentVolume(volumeProvider.getCurrentVolume()); + } catch (RemoteException e) { + Log.wtf(TAG, "Failure in setPlaybackToRemote.", e); + } } /** @@ -272,7 +342,15 @@ public final class MediaSession { * @param active Whether this session is active or not. */ public void setActive(boolean active) { - mImpl.setActive(active); + if (mActive == active) { + return; + } + try { + mBinder.setActive(active); + mActive = active; + } catch (RemoteException e) { + Log.wtf(TAG, "Failure in setActive.", e); + } } /** @@ -281,7 +359,7 @@ public final class MediaSession { * @return True if the session is active, false otherwise. */ public boolean isActive() { - return mImpl.isActive(); + return mActive; } /** @@ -293,7 +371,14 @@ public final class MediaSession { * @param extras Any extras included with the event */ public void sendSessionEvent(@NonNull String event, @Nullable Bundle extras) { - mImpl.sendSessionEvent(event, extras); + if (TextUtils.isEmpty(event)) { + throw new IllegalArgumentException("event cannot be null or empty"); + } + try { + mBinder.sendEvent(event, extras); + } catch (RemoteException e) { + Log.wtf(TAG, "Error sending event", e); + } } /** @@ -302,7 +387,11 @@ public final class MediaSession { * but it must be released if your activity or service is being destroyed. */ public void release() { - mImpl.close(); + try { + mBinder.destroySession(); + } catch (RemoteException e) { + Log.wtf(TAG, "Error releasing session: ", e); + } } /** @@ -314,7 +403,7 @@ public final class MediaSession { * session */ public @NonNull Token getSessionToken() { - return mImpl.getSessionToken(); + return mSessionToken; } /** @@ -324,7 +413,7 @@ public final class MediaSession { * @return A controller for this session. */ public @NonNull MediaController getController() { - return mImpl.getController(); + return mController; } /** @@ -333,7 +422,12 @@ public final class MediaSession { * @param state The current state of playback */ public void setPlaybackState(@Nullable PlaybackState state) { - mImpl.setPlaybackState(state); + mPlaybackState = state; + try { + mBinder.setPlaybackState(state); + } catch (RemoteException e) { + Log.wtf(TAG, "Dead object in setPlaybackState.", e); + } } /** @@ -345,10 +439,24 @@ public final class MediaSession { * @see android.media.MediaMetadata.Builder#putBitmap */ public void setMetadata(@Nullable MediaMetadata metadata) { + long duration = -1; + int fields = 0; + MediaDescription description = null; if (metadata != null) { - metadata = new MediaMetadata.Builder(metadata, mMaxBitmapSize).build(); + metadata = (new MediaMetadata.Builder(metadata, mMaxBitmapSize)).build(); + if (metadata.containsKey(MediaMetadata.METADATA_KEY_DURATION)) { + duration = metadata.getLong(MediaMetadata.METADATA_KEY_DURATION); + } + fields = metadata.size(); + description = metadata.getDescription(); + } + String metadataDescription = "size=" + fields + ", description=" + description; + + try { + mBinder.setMetadata(metadata, duration, metadataDescription); + } catch (RemoteException e) { + Log.wtf(TAG, "Dead object in setPlaybackState.", e); } - mImpl.setMetadata(metadata); } /** @@ -363,7 +471,11 @@ public final class MediaSession { * @param queue A list of items in the play queue. */ public void setQueue(@Nullable List<QueueItem> queue) { - mImpl.setQueue(queue); + try { + mBinder.setQueue(queue == null ? null : new MediaParceledListSlice(queue)); + } catch (RemoteException e) { + Log.wtf("Dead object in setQueue.", e); + } } /** @@ -374,7 +486,11 @@ public final class MediaSession { * @param title The title of the play queue. */ public void setQueueTitle(@Nullable CharSequence title) { - mImpl.setQueueTitle(title); + try { + mBinder.setQueueTitle(title); + } catch (RemoteException e) { + Log.wtf("Dead object in setQueueTitle.", e); + } } /** @@ -391,7 +507,11 @@ public final class MediaSession { * </ul> */ public void setRatingType(@Rating.Style int type) { - mImpl.setRatingType(type); + try { + mBinder.setRatingType(type); + } catch (RemoteException e) { + Log.e(TAG, "Error in setRatingType.", e); + } } /** @@ -402,7 +522,11 @@ public final class MediaSession { * @param extras The extras associated with the {@link MediaSession}. */ public void setExtras(@Nullable Bundle extras) { - mImpl.setExtras(extras); + try { + mBinder.setExtras(extras); + } catch (RemoteException e) { + Log.wtf("Dead object in setExtras.", e); + } } /** @@ -414,7 +538,31 @@ public final class MediaSession { * @see MediaSessionManager#isTrustedForMediaControl(RemoteUserInfo) */ public final @NonNull RemoteUserInfo getCurrentControllerInfo() { - return mImpl.getCurrentControllerInfo(); + if (mCallback == null || mCallback.mCurrentControllerInfo == null) { + throw new IllegalStateException( + "This should be called inside of MediaSession.Callback methods"); + } + return mCallback.mCurrentControllerInfo; + } + + /** + * Notify the system that the remote volume changed. + * + * @param provider The provider that is handling volume changes. + * @hide + */ + public void notifyRemoteVolumeChanged(VolumeProvider provider) { + synchronized (mLock) { + if (provider == null || provider != mVolumeProvider) { + Log.w(TAG, "Received update from stale volume provider"); + return; + } + } + try { + mBinder.setCurrentVolume(provider.getCurrentVolume()); + } catch (RemoteException e) { + Log.e(TAG, "Error in notifyVolumeChanged", e); + } } /** @@ -426,7 +574,10 @@ public final class MediaSession { */ @UnsupportedAppUsage public String getCallingPackage() { - return mImpl.getCallingPackage(); + if (mCallback != null && mCallback.mCurrentControllerInfo != null) { + return mCallback.mCurrentControllerInfo.getPackageName(); + } + return null; } /** @@ -435,7 +586,130 @@ public final class MediaSession { * @hide */ public static boolean isActiveState(int state) { - return MediaSessionEngine.isActiveState(state); + switch (state) { + case PlaybackState.STATE_FAST_FORWARDING: + case PlaybackState.STATE_REWINDING: + case PlaybackState.STATE_SKIPPING_TO_PREVIOUS: + case PlaybackState.STATE_SKIPPING_TO_NEXT: + case PlaybackState.STATE_BUFFERING: + case PlaybackState.STATE_CONNECTING: + case PlaybackState.STATE_PLAYING: + return true; + } + return false; + } + + void dispatchPrepare(RemoteUserInfo caller) { + postToCallback(caller, CallbackMessageHandler.MSG_PREPARE, null, null); + } + + void dispatchPrepareFromMediaId(RemoteUserInfo caller, String mediaId, Bundle extras) { + postToCallback(caller, CallbackMessageHandler.MSG_PREPARE_MEDIA_ID, mediaId, extras); + } + + void dispatchPrepareFromSearch(RemoteUserInfo caller, String query, Bundle extras) { + postToCallback(caller, CallbackMessageHandler.MSG_PREPARE_SEARCH, query, extras); + } + + void dispatchPrepareFromUri(RemoteUserInfo caller, Uri uri, Bundle extras) { + postToCallback(caller, CallbackMessageHandler.MSG_PREPARE_URI, uri, extras); + } + + void dispatchPlay(RemoteUserInfo caller) { + postToCallback(caller, CallbackMessageHandler.MSG_PLAY, null, null); + } + + void dispatchPlayFromMediaId(RemoteUserInfo caller, String mediaId, Bundle extras) { + postToCallback(caller, CallbackMessageHandler.MSG_PLAY_MEDIA_ID, mediaId, extras); + } + + void dispatchPlayFromSearch(RemoteUserInfo caller, String query, Bundle extras) { + postToCallback(caller, CallbackMessageHandler.MSG_PLAY_SEARCH, query, extras); + } + + void dispatchPlayFromUri(RemoteUserInfo caller, Uri uri, Bundle extras) { + postToCallback(caller, CallbackMessageHandler.MSG_PLAY_URI, uri, extras); + } + + void dispatchSkipToItem(RemoteUserInfo caller, long id) { + postToCallback(caller, CallbackMessageHandler.MSG_SKIP_TO_ITEM, id, null); + } + + void dispatchPause(RemoteUserInfo caller) { + postToCallback(caller, CallbackMessageHandler.MSG_PAUSE, null, null); + } + + void dispatchStop(RemoteUserInfo caller) { + postToCallback(caller, CallbackMessageHandler.MSG_STOP, null, null); + } + + void dispatchNext(RemoteUserInfo caller) { + postToCallback(caller, CallbackMessageHandler.MSG_NEXT, null, null); + } + + void dispatchPrevious(RemoteUserInfo caller) { + postToCallback(caller, CallbackMessageHandler.MSG_PREVIOUS, null, null); + } + + void dispatchFastForward(RemoteUserInfo caller) { + postToCallback(caller, CallbackMessageHandler.MSG_FAST_FORWARD, null, null); + } + + void dispatchRewind(RemoteUserInfo caller) { + postToCallback(caller, CallbackMessageHandler.MSG_REWIND, null, null); + } + + void dispatchSeekTo(RemoteUserInfo caller, long pos) { + postToCallback(caller, CallbackMessageHandler.MSG_SEEK_TO, pos, null); + } + + void dispatchRate(RemoteUserInfo caller, Rating rating) { + postToCallback(caller, CallbackMessageHandler.MSG_RATE, rating, null); + } + + void dispatchSetPlaybackSpeed(RemoteUserInfo caller, float speed) { + postToCallback(caller, CallbackMessageHandler.MSG_SET_PLAYBACK_SPEED, speed, null); + } + + void dispatchCustomAction(RemoteUserInfo caller, String action, Bundle args) { + postToCallback(caller, CallbackMessageHandler.MSG_CUSTOM_ACTION, action, args); + } + + void dispatchMediaButton(RemoteUserInfo caller, Intent mediaButtonIntent) { + postToCallback(caller, CallbackMessageHandler.MSG_MEDIA_BUTTON, mediaButtonIntent, null); + } + + void dispatchMediaButtonDelayed(RemoteUserInfo info, Intent mediaButtonIntent, + long delay) { + postToCallbackDelayed(info, CallbackMessageHandler.MSG_PLAY_PAUSE_KEY_DOUBLE_TAP_TIMEOUT, + mediaButtonIntent, null, delay); + } + + void dispatchAdjustVolume(RemoteUserInfo caller, int direction) { + postToCallback(caller, CallbackMessageHandler.MSG_ADJUST_VOLUME, direction, null); + } + + void dispatchSetVolumeTo(RemoteUserInfo caller, int volume) { + postToCallback(caller, CallbackMessageHandler.MSG_SET_VOLUME, volume, null); + } + + void dispatchCommand(RemoteUserInfo caller, String command, Bundle args, + ResultReceiver resultCb) { + Command cmd = new Command(command, args, resultCb); + postToCallback(caller, CallbackMessageHandler.MSG_COMMAND, cmd, null); + } + + void postToCallback(RemoteUserInfo caller, int what, Object obj, Bundle data) { + postToCallbackDelayed(caller, what, obj, data, 0); + } + + void postToCallbackDelayed(RemoteUserInfo caller, int what, Object obj, Bundle data, + long delay) { + synchronized (mLock) { + if (mCallback != null) { + mCallback.post(caller, what, obj, data, delay); + } + } } /** @@ -534,7 +808,9 @@ public final class MediaSession { */ public abstract static class Callback { - MediaSessionEngine.MediaButtonEventDelegate mMediaButtonEventDelegate; + private MediaSession mSession; + private CallbackMessageHandler mHandler; + private boolean mMediaPlayPauseKeyPending; public Callback() { } @@ -566,12 +842,110 @@ public final class MediaSession { * @return True if the event was handled, false otherwise. */ public boolean onMediaButtonEvent(@NonNull Intent mediaButtonIntent) { - if (mMediaButtonEventDelegate != null) { - return mMediaButtonEventDelegate.onMediaButtonIntent(mediaButtonIntent); + if (mSession != null && mHandler != null + && Intent.ACTION_MEDIA_BUTTON.equals(mediaButtonIntent.getAction())) { + KeyEvent ke = mediaButtonIntent.getParcelableExtra(Intent.EXTRA_KEY_EVENT); + if (ke != null && ke.getAction() == KeyEvent.ACTION_DOWN) { + PlaybackState state = mSession.mPlaybackState; + long validActions = state == null ? 0 : state.getActions(); + switch (ke.getKeyCode()) { + case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: + case KeyEvent.KEYCODE_HEADSETHOOK: + if (ke.getRepeatCount() > 0) { + // Consider long-press as a single tap. + handleMediaPlayPauseKeySingleTapIfPending(); + } else if (mMediaPlayPauseKeyPending) { + // Consider double tap as the next. + mHandler.removeMessages(CallbackMessageHandler + .MSG_PLAY_PAUSE_KEY_DOUBLE_TAP_TIMEOUT); + mMediaPlayPauseKeyPending = false; + if ((validActions & PlaybackState.ACTION_SKIP_TO_NEXT) != 0) { + onSkipToNext(); + } + } else { + mMediaPlayPauseKeyPending = true; + mSession.dispatchMediaButtonDelayed( + mSession.getCurrentControllerInfo(), + mediaButtonIntent, ViewConfiguration.getDoubleTapTimeout()); + } + return true; + default: + // If another key is pressed within double tap timeout, consider the + // pending play/pause as a single tap to handle media keys in order. + handleMediaPlayPauseKeySingleTapIfPending(); + break; + } + + switch (ke.getKeyCode()) { + case KeyEvent.KEYCODE_MEDIA_PLAY: + if ((validActions & PlaybackState.ACTION_PLAY) != 0) { + onPlay(); + return true; + } + break; + case KeyEvent.KEYCODE_MEDIA_PAUSE: + if ((validActions & PlaybackState.ACTION_PAUSE) != 0) { + onPause(); + return true; + } + break; + case KeyEvent.KEYCODE_MEDIA_NEXT: + if ((validActions & PlaybackState.ACTION_SKIP_TO_NEXT) != 0) { + onSkipToNext(); + return true; + } + break; + case KeyEvent.KEYCODE_MEDIA_PREVIOUS: + if ((validActions & PlaybackState.ACTION_SKIP_TO_PREVIOUS) != 0) { + onSkipToPrevious(); + return true; + } + break; + case KeyEvent.KEYCODE_MEDIA_STOP: + if ((validActions & PlaybackState.ACTION_STOP) != 0) { + onStop(); + return true; + } + break; + case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: + if ((validActions & PlaybackState.ACTION_FAST_FORWARD) != 0) { + onFastForward(); + return true; + } + break; + case KeyEvent.KEYCODE_MEDIA_REWIND: + if ((validActions & PlaybackState.ACTION_REWIND) != 0) { + onRewind(); + return true; + } + break; + } + } } return false; } + private void handleMediaPlayPauseKeySingleTapIfPending() { + if (!mMediaPlayPauseKeyPending) { + return; + } + mMediaPlayPauseKeyPending = false; + mHandler.removeMessages(CallbackMessageHandler.MSG_PLAY_PAUSE_KEY_DOUBLE_TAP_TIMEOUT); + PlaybackState state = mSession.mPlaybackState; + long validActions = state == null ? 0 : state.getActions(); + boolean isPlaying = state != null + && state.getState() == PlaybackState.STATE_PLAYING; + boolean canPlay = (validActions & (PlaybackState.ACTION_PLAY_PAUSE + | PlaybackState.ACTION_PLAY)) != 0; + boolean canPause = (validActions & (PlaybackState.ACTION_PLAY_PAUSE + | PlaybackState.ACTION_PAUSE)) != 0; + if (isPlaying && canPause) { + onPause(); + } else if (!isPlaying && canPlay) { + onPlay(); + } + } + /** * Override to handle requests to prepare playback. During the preparation, a session should * not hold audio focus in order to allow other sessions play seamlessly. The state of @@ -727,14 +1101,6 @@ public final class MediaSession { */ public void onCustomAction(@NonNull String action, @Nullable Bundle extras) { } - - /** - * @hide - */ - public void onSetMediaButtonEventDelegate( - @NonNull MediaSessionEngine.MediaButtonEventDelegate delegate) { - mMediaButtonEventDelegate = delegate; - } } /** @@ -747,7 +1113,7 @@ public final class MediaSession { */ public static final int UNKNOWN_ID = -1; - private final MediaSessionEngine.QueueItem mImpl; + private final MediaDescription mDescription; @UnsupportedAppUsage private final long mId; @@ -759,32 +1125,39 @@ public final class MediaSession { * play queue and cannot be {@link #UNKNOWN_ID}. */ public QueueItem(MediaDescription description, long id) { - mImpl = new MediaSessionEngine.QueueItem(description, id); + if (description == null) { + throw new IllegalArgumentException("Description cannot be null."); + } + if (id == UNKNOWN_ID) { + throw new IllegalArgumentException("Id cannot be QueueItem.UNKNOWN_ID"); + } + mDescription = description; mId = id; } private QueueItem(Parcel in) { - mImpl = new MediaSessionEngine.QueueItem(in); - mId = mImpl.getQueueId(); + mDescription = MediaDescription.CREATOR.createFromParcel(in); + mId = in.readLong(); } /** * Get the description for this item. */ public MediaDescription getDescription() { - return mImpl.getDescription(); + return mDescription; } /** * Get the queue id for this item. */ public long getQueueId() { - return mImpl.getQueueId(); + return mId; } @Override public void writeToParcel(Parcel dest, int flags) { - mImpl.writeToParcel(dest, flags); + mDescription.writeToParcel(dest, flags); + dest.writeLong(mId); } @Override @@ -795,20 +1168,21 @@ public final class MediaSession { public static final @android.annotation.NonNull Creator<MediaSession.QueueItem> CREATOR = new Creator<MediaSession.QueueItem>() { - @Override - public MediaSession.QueueItem createFromParcel(Parcel p) { - return new MediaSession.QueueItem(p); - } + @Override + public MediaSession.QueueItem createFromParcel(Parcel p) { + return new MediaSession.QueueItem(p); + } - @Override - public MediaSession.QueueItem[] newArray(int size) { - return new MediaSession.QueueItem[size]; - } - }; + @Override + public MediaSession.QueueItem[] newArray(int size) { + return new MediaSession.QueueItem[size]; + } + }; @Override public String toString() { - return mImpl.toString(); + return "MediaSession.QueueItem {" + "Description=" + mDescription + ", Id=" + mId + + " }"; } @Override @@ -821,7 +1195,171 @@ public final class MediaSession { return false; } - return mImpl.equals(((QueueItem) o).mImpl); + final QueueItem item = (QueueItem) o; + if (mId != item.mId) { + return false; + } + + if (!Objects.equals(mDescription, item.mDescription)) { + return false; + } + + return true; + } + } + + private static final class Command { + public final String command; + public final Bundle extras; + public final ResultReceiver stub; + + Command(String command, Bundle extras, ResultReceiver stub) { + this.command = command; + this.extras = extras; + this.stub = stub; + } + } + + private class CallbackMessageHandler extends Handler { + private static final int MSG_COMMAND = 1; + private static final int MSG_MEDIA_BUTTON = 2; + private static final int MSG_PREPARE = 3; + private static final int MSG_PREPARE_MEDIA_ID = 4; + private static final int MSG_PREPARE_SEARCH = 5; + private static final int MSG_PREPARE_URI = 6; + private static final int MSG_PLAY = 7; + private static final int MSG_PLAY_MEDIA_ID = 8; + private static final int MSG_PLAY_SEARCH = 9; + private static final int MSG_PLAY_URI = 10; + private static final int MSG_SKIP_TO_ITEM = 11; + private static final int MSG_PAUSE = 12; + private static final int MSG_STOP = 13; + private static final int MSG_NEXT = 14; + private static final int MSG_PREVIOUS = 15; + private static final int MSG_FAST_FORWARD = 16; + private static final int MSG_REWIND = 17; + private static final int MSG_SEEK_TO = 18; + private static final int MSG_RATE = 19; + private static final int MSG_SET_PLAYBACK_SPEED = 20; + private static final int MSG_CUSTOM_ACTION = 21; + private static final int MSG_ADJUST_VOLUME = 22; + private static final int MSG_SET_VOLUME = 23; + private static final int MSG_PLAY_PAUSE_KEY_DOUBLE_TAP_TIMEOUT = 24; + + private MediaSession.Callback mCallback; + private RemoteUserInfo mCurrentControllerInfo; + + CallbackMessageHandler(Looper looper, MediaSession.Callback callback) { + super(looper); + mCallback = callback; + mCallback.mHandler = this; + } + + void post(RemoteUserInfo caller, int what, Object obj, Bundle data, long delayMs) { + Pair<RemoteUserInfo, Object> objWithCaller = Pair.create(caller, obj); + Message msg = obtainMessage(what, objWithCaller); + msg.setAsynchronous(true); + msg.setData(data); + if (delayMs > 0) { + sendMessageDelayed(msg, delayMs); + } else { + sendMessage(msg); + } + } + + @Override + public void handleMessage(Message msg) { + mCurrentControllerInfo = ((Pair<RemoteUserInfo, Object>) msg.obj).first; + + VolumeProvider vp; + Object obj = ((Pair<RemoteUserInfo, Object>) msg.obj).second; + + switch (msg.what) { + case MSG_COMMAND: + Command cmd = (Command) obj; + mCallback.onCommand(cmd.command, cmd.extras, cmd.stub); + break; + case MSG_MEDIA_BUTTON: + mCallback.onMediaButtonEvent((Intent) obj); + break; + case MSG_PREPARE: + mCallback.onPrepare(); + break; + case MSG_PREPARE_MEDIA_ID: + mCallback.onPrepareFromMediaId((String) obj, msg.getData()); + break; + case MSG_PREPARE_SEARCH: + mCallback.onPrepareFromSearch((String) obj, msg.getData()); + break; + case MSG_PREPARE_URI: + mCallback.onPrepareFromUri((Uri) obj, msg.getData()); + break; + case MSG_PLAY: + mCallback.onPlay(); + break; + case MSG_PLAY_MEDIA_ID: + mCallback.onPlayFromMediaId((String) obj, msg.getData()); + break; + case MSG_PLAY_SEARCH: + mCallback.onPlayFromSearch((String) obj, msg.getData()); + break; + case MSG_PLAY_URI: + mCallback.onPlayFromUri((Uri) obj, msg.getData()); + break; + case MSG_SKIP_TO_ITEM: + mCallback.onSkipToQueueItem((Long) obj); + break; + case MSG_PAUSE: + mCallback.onPause(); + break; + case MSG_STOP: + mCallback.onStop(); + break; + case MSG_NEXT: + mCallback.onSkipToNext(); + break; + case MSG_PREVIOUS: + mCallback.onSkipToPrevious(); + break; + case MSG_FAST_FORWARD: + mCallback.onFastForward(); + break; + case MSG_REWIND: + mCallback.onRewind(); + break; + case MSG_SEEK_TO: + mCallback.onSeekTo((Long) obj); + break; + case MSG_RATE: + mCallback.onSetRating((Rating) obj); + break; + case MSG_SET_PLAYBACK_SPEED: + mCallback.onSetPlaybackSpeed((Float) obj); + break; + case MSG_CUSTOM_ACTION: + mCallback.onCustomAction((String) obj, msg.getData()); + break; + case MSG_ADJUST_VOLUME: + synchronized (mLock) { + vp = mVolumeProvider; + } + if (vp != null) { + vp.onAdjustVolume((int) obj); + } + break; + case MSG_SET_VOLUME: + synchronized (mLock) { + vp = mVolumeProvider; + } + if (vp != null) { + vp.onSetVolumeTo((int) obj); + } + break; + case MSG_PLAY_PAUSE_KEY_DOUBLE_TAP_TIMEOUT: + mCallback.handleMediaPlayPauseKeySingleTapIfPending(); + break; + } + mCurrentControllerInfo = null; } } } diff --git a/media/java/android/media/session/MediaSessionEngine.java b/media/java/android/media/session/MediaSessionEngine.java deleted file mode 100644 index 7c5243ac31cd..000000000000 --- a/media/java/android/media/session/MediaSessionEngine.java +++ /dev/null @@ -1,1236 +0,0 @@ -/* - * Copyright 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.media.session; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.app.Activity; -import android.app.PendingIntent; -import android.content.Context; -import android.content.Intent; -import android.media.AudioAttributes; -import android.media.MediaDescription; -import android.media.MediaMetadata; -import android.media.MediaParceledListSlice; -import android.media.Rating; -import android.media.VolumeProvider; -import android.media.session.MediaSessionManager.RemoteUserInfo; -import android.net.Uri; -import android.os.Bundle; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import android.os.Parcel; -import android.os.RemoteException; -import android.os.ResultReceiver; -import android.service.media.MediaBrowserService; -import android.text.TextUtils; -import android.util.Log; -import android.util.Pair; -import android.view.KeyEvent; -import android.view.ViewConfiguration; - -import java.util.List; -import java.util.Objects; - -/** - * @hide - */ -public final class MediaSessionEngine implements AutoCloseable { - private static final String TAG = "MediaSession"; - - private final Object mLock = new Object(); - - private final MediaSession.Token mSessionToken; - private final MediaController mController; - private final ISession mBinder; - - private CallbackMessageHandler mCallbackHandler; - private VolumeProvider mVolumeProvider; - private PlaybackState mPlaybackState; - - private boolean mActive = false; - - /** - * Creates a new session. The session will automatically be registered with - * the system but will not be published until {@link #setActive(boolean) - * setActive(true)} is called. You must call {@link #close()} when - * finished with the session. - * - * @param context The context to use to create the session. - * @param binder A session binder - */ - public MediaSessionEngine(@NonNull Context context, @NonNull ISession binder, - @NonNull SessionCallbackLink cbLink) throws RemoteException { - mBinder = binder; - - cbLink.setSessionEngine(this); - mSessionToken = new MediaSession.Token(mBinder.getController()); - mController = new MediaController(context, mSessionToken); - } - - /** - * Set the callback to receive updates for the MediaSession. This includes - * media button events and transport controls. The caller's thread will be - * used to post updates. - * <p> - * Set the callback to null to stop receiving updates. - * - * @param callback The callback object - */ - public void setCallback(@Nullable MediaSession.Callback callback) { - setCallback(callback, new Handler()); - } - - /** - * Set the callback to receive updates for the MediaSession. This includes - * media button events and transport controls. - * <p> - * Set the callback to null to stop receiving updates. - * - * @param callback The callback to receive updates on. - * @param handler The handler that events should be posted on. - */ - public void setCallback(@Nullable MediaSession.Callback callback, @NonNull Handler handler) { - setCallbackInternal(callback == null ? null : new CallbackWrapper(callback), handler); - } - - private void setCallbackInternal(CallbackWrapper callback, Handler handler) { - synchronized (mLock) { - if (mCallbackHandler != null) { - // We're updating the callback, clear the session from the old one. - mCallbackHandler.mCallbackWrapper.mSessionImpl = null; - mCallbackHandler.removeCallbacksAndMessages(null); - } - if (callback == null) { - mCallbackHandler = null; - return; - } - callback.mSessionImpl = this; - CallbackMessageHandler msgHandler = new CallbackMessageHandler(handler.getLooper(), - callback); - mCallbackHandler = msgHandler; - } - } - - /** - * Set an intent for launching UI for this Session. This can be used as a - * quick link to an ongoing media screen. The intent should be for an - * activity that may be started using {@link Activity#startActivity(Intent)}. - * - * @param pi The intent to launch to show UI for this Session. - */ - public void setSessionActivity(@Nullable PendingIntent pi) { - try { - mBinder.setLaunchPendingIntent(pi); - } catch (RemoteException e) { - Log.wtf(TAG, "Failure in setLaunchPendingIntent.", e); - } - } - - /** - * Set a pending intent for your media button receiver to allow restarting - * playback after the session has been stopped. If your app is started in - * this way an {@link Intent#ACTION_MEDIA_BUTTON} intent will be sent via - * the pending intent. - * - * @param mbr The {@link PendingIntent} to send the media button event to. - */ - public void setMediaButtonReceiver(@Nullable PendingIntent mbr) { - try { - mBinder.setMediaButtonReceiver(mbr); - } catch (RemoteException e) { - Log.wtf(TAG, "Failure in setMediaButtonReceiver.", e); - } - } - - /** - * Set any flags for the session. - * - * @param flags The flags to set for this session. - */ - public void setFlags(int flags) { - try { - mBinder.setFlags(flags); - } catch (RemoteException e) { - Log.wtf(TAG, "Failure in setFlags.", e); - } - } - - /** - * Set the attributes for this session's audio. This will affect the - * system's volume handling for this session. If - * {@link #setPlaybackToRemote} was previously called it will stop receiving - * volume commands and the system will begin sending volume changes to the - * appropriate stream. - * <p> - * By default sessions use attributes for media. - * - * @param attributes The {@link AudioAttributes} for this session's audio. - */ - public void setPlaybackToLocal(AudioAttributes attributes) { - if (attributes == null) { - throw new IllegalArgumentException("Attributes cannot be null for local playback."); - } - try { - mBinder.setPlaybackToLocal(attributes); - } catch (RemoteException e) { - Log.wtf(TAG, "Failure in setPlaybackToLocal.", e); - } - } - - /** - * Configure this session to use remote volume handling. This must be called - * to receive volume button events, otherwise the system will adjust the - * appropriate stream volume for this session. If - * {@link #setPlaybackToLocal} was previously called the system will stop - * handling volume changes for this session and pass them to the volume - * provider instead. - * - * @param volumeProvider The provider that will handle volume changes. May - * not be null. - */ - public void setPlaybackToRemote(@NonNull VolumeProvider volumeProvider) { - if (volumeProvider == null) { - throw new IllegalArgumentException("volumeProvider may not be null!"); - } - synchronized (mLock) { - mVolumeProvider = volumeProvider; - } - volumeProvider.setCallback(new VolumeProvider.Callback() { - @Override - public void onVolumeChanged(VolumeProvider volumeProvider) { - notifyRemoteVolumeChanged(volumeProvider); - } - }); - - try { - mBinder.setPlaybackToRemote(volumeProvider.getVolumeControl(), - volumeProvider.getMaxVolume()); - mBinder.setCurrentVolume(volumeProvider.getCurrentVolume()); - } catch (RemoteException e) { - Log.wtf(TAG, "Failure in setPlaybackToRemote.", e); - } - } - - /** - * Set if this session is currently active and ready to receive commands. If - * set to false your session's controller may not be discoverable. You must - * set the session to active before it can start receiving media button - * events or transport commands. - * - * @param active Whether this session is active or not. - */ - public void setActive(boolean active) { - if (mActive == active) { - return; - } - try { - mBinder.setActive(active); - mActive = active; - } catch (RemoteException e) { - Log.wtf(TAG, "Failure in setActive.", e); - } - } - - /** - * Get the current active state of this session. - * - * @return True if the session is active, false otherwise. - */ - public boolean isActive() { - return mActive; - } - - /** - * Send a proprietary event to all MediaControllers listening to this - * Session. It's up to the Controller/Session owner to determine the meaning - * of any events. - * - * @param event The name of the event to send - * @param extras Any extras included with the event - */ - public void sendSessionEvent(@NonNull String event, @Nullable Bundle extras) { - if (TextUtils.isEmpty(event)) { - throw new IllegalArgumentException("event cannot be null or empty"); - } - try { - mBinder.sendEvent(event, extras); - } catch (RemoteException e) { - Log.wtf(TAG, "Error sending event", e); - } - } - - /** - * This must be called when an app has finished performing playback. If - * playback is expected to start again shortly the session can be left open, - * but it must be released if your activity or service is being destroyed. - */ - public void close() { - try { - mBinder.destroySession(); - } catch (RemoteException e) { - Log.wtf(TAG, "Error releasing session: ", e); - } - } - - /** - * Retrieve a token object that can be used by apps to create a - * {@link MediaController} for interacting with this session. The owner of - * the session is responsible for deciding how to distribute these tokens. - * - * @return A token that can be used to create a MediaController for this - * session - */ - public @NonNull MediaSession.Token getSessionToken() { - return mSessionToken; - } - - /** - * Get a controller for this session. This is a convenience method to avoid - * having to cache your own controller in process. - * - * @return A controller for this session. - */ - public @NonNull MediaController getController() { - return mController; - } - - /** - * Update the current playback state. - * - * @param state The current state of playback - */ - public void setPlaybackState(@Nullable PlaybackState state) { - mPlaybackState = state; - try { - mBinder.setPlaybackState(state); - } catch (RemoteException e) { - Log.wtf(TAG, "Dead object in setPlaybackState.", e); - } - } - - /** - * Update the current metadata. New metadata can be created using - * {@link android.media.MediaMetadata.Builder}. This operation may take time proportional to - * the size of the bitmap to replace large bitmaps with a scaled down copy. - * - * @param metadata The new metadata - * @see android.media.MediaMetadata.Builder#putBitmap - */ - public void setMetadata(@Nullable MediaMetadata metadata) { - long duration = -1; - int fields = 0; - MediaDescription description = null; - if (metadata != null) { - if (metadata.containsKey(MediaMetadata.METADATA_KEY_DURATION)) { - duration = metadata.getLong(MediaMetadata.METADATA_KEY_DURATION); - } - fields = metadata.size(); - description = metadata.getDescription(); - } - String metadataDescription = "size=" + fields + ", description=" + description; - - try { - mBinder.setMetadata(metadata, duration, metadataDescription); - } catch (RemoteException e) { - Log.wtf(TAG, "Dead object in setPlaybackState.", e); - } - } - - /** - * Update the list of items in the play queue. It is an ordered list and - * should contain the current item, and previous or upcoming items if they - * exist. Specify null if there is no current play queue. - * <p> - * The queue should be of reasonable size. If the play queue is unbounded - * within your app, it is better to send a reasonable amount in a sliding - * window instead. - * - * @param queue A list of items in the play queue. - */ - public void setQueue(@Nullable List<MediaSession.QueueItem> queue) { - try { - mBinder.setQueue(queue == null ? null : new MediaParceledListSlice(queue)); - } catch (RemoteException e) { - Log.wtf("Dead object in setQueue.", e); - } - } - - /** - * Set the title of the play queue. The UI should display this title along - * with the play queue itself. - * e.g. "Play Queue", "Now Playing", or an album name. - * - * @param title The title of the play queue. - */ - public void setQueueTitle(@Nullable CharSequence title) { - try { - mBinder.setQueueTitle(title); - } catch (RemoteException e) { - Log.wtf("Dead object in setQueueTitle.", e); - } - } - - /** - * Set the style of rating used by this session. Apps trying to set the - * rating should use this style. Must be one of the following: - * <ul> - * <li>{@link Rating#RATING_NONE}</li> - * <li>{@link Rating#RATING_3_STARS}</li> - * <li>{@link Rating#RATING_4_STARS}</li> - * <li>{@link Rating#RATING_5_STARS}</li> - * <li>{@link Rating#RATING_HEART}</li> - * <li>{@link Rating#RATING_PERCENTAGE}</li> - * <li>{@link Rating#RATING_THUMB_UP_DOWN}</li> - * </ul> - */ - public void setRatingType(int type) { - try { - mBinder.setRatingType(type); - } catch (RemoteException e) { - Log.e(TAG, "Error in setRatingType.", e); - } - } - - /** - * Set some extras that can be associated with the {@link MediaSession}. No assumptions should - * be made as to how a {@link MediaController} will handle these extras. - * Keys should be fully qualified (e.g. com.example.MY_EXTRA) to avoid conflicts. - * - * @param extras The extras associated with the {@link MediaSession}. - */ - public void setExtras(@Nullable Bundle extras) { - try { - mBinder.setExtras(extras); - } catch (RemoteException e) { - Log.wtf("Dead object in setExtras.", e); - } - } - - /** - * Gets the controller information who sent the current request. - * <p> - * Note: This is only valid while in a request callback, such as - * {@link MediaSession.Callback#onPlay}. - * - * @throws IllegalStateException If this method is called outside of - * {@link MediaSession.Callback} methods. - * @see MediaSessionManager#isTrustedForMediaControl(RemoteUserInfo) - */ - public @NonNull RemoteUserInfo getCurrentControllerInfo() { - if (mCallbackHandler == null || mCallbackHandler.mCurrentControllerInfo == null) { - throw new IllegalStateException( - "This should be called inside of MediaSession.Callback methods"); - } - return mCallbackHandler.mCurrentControllerInfo; - } - - /** - * Returns the name of the package that sent the last media button, transport control, or - * command from controllers and the system. This is only valid while in a request callback, such - * as {@link MediaSession.Callback#onPlay}. - */ - public String getCallingPackage() { - if (mCallbackHandler != null && mCallbackHandler.mCurrentControllerInfo != null) { - return mCallbackHandler.mCurrentControllerInfo.getPackageName(); - } - return null; - } - - - /** - * Notify the system that the remote volume changed. - * - * @param provider The provider that is handling volume changes. - */ - private void notifyRemoteVolumeChanged(VolumeProvider provider) { - synchronized (mLock) { - if (provider == null || provider != mVolumeProvider) { - Log.w(TAG, "Received update from stale volume provider"); - return; - } - } - try { - mBinder.setCurrentVolume(provider.getCurrentVolume()); - } catch (RemoteException e) { - Log.e(TAG, "Error in notifyVolumeChanged", e); - } - } - - void dispatchPrepare(RemoteUserInfo caller) { - postToCallback(caller, CallbackMessageHandler.MSG_PREPARE, null, null); - } - - void dispatchPrepareFromMediaId(RemoteUserInfo caller, String mediaId, Bundle extras) { - postToCallback(caller, CallbackMessageHandler.MSG_PREPARE_MEDIA_ID, mediaId, extras); - } - - void dispatchPrepareFromSearch(RemoteUserInfo caller, String query, Bundle extras) { - postToCallback(caller, CallbackMessageHandler.MSG_PREPARE_SEARCH, query, extras); - } - - void dispatchPrepareFromUri(RemoteUserInfo caller, Uri uri, Bundle extras) { - postToCallback(caller, CallbackMessageHandler.MSG_PREPARE_URI, uri, extras); - } - - void dispatchPlay(RemoteUserInfo caller) { - postToCallback(caller, CallbackMessageHandler.MSG_PLAY, null, null); - } - - void dispatchPlayFromMediaId(RemoteUserInfo caller, String mediaId, Bundle extras) { - postToCallback(caller, CallbackMessageHandler.MSG_PLAY_MEDIA_ID, mediaId, extras); - } - - void dispatchPlayFromSearch(RemoteUserInfo caller, String query, Bundle extras) { - postToCallback(caller, CallbackMessageHandler.MSG_PLAY_SEARCH, query, extras); - } - - void dispatchPlayFromUri(RemoteUserInfo caller, Uri uri, Bundle extras) { - postToCallback(caller, CallbackMessageHandler.MSG_PLAY_URI, uri, extras); - } - - void dispatchSkipToItem(RemoteUserInfo caller, long id) { - postToCallback(caller, CallbackMessageHandler.MSG_SKIP_TO_ITEM, id, null); - } - - void dispatchPause(RemoteUserInfo caller) { - postToCallback(caller, CallbackMessageHandler.MSG_PAUSE, null, null); - } - - void dispatchStop(RemoteUserInfo caller) { - postToCallback(caller, CallbackMessageHandler.MSG_STOP, null, null); - } - - void dispatchNext(RemoteUserInfo caller) { - postToCallback(caller, CallbackMessageHandler.MSG_NEXT, null, null); - } - - void dispatchPrevious(RemoteUserInfo caller) { - postToCallback(caller, CallbackMessageHandler.MSG_PREVIOUS, null, null); - } - - void dispatchFastForward(RemoteUserInfo caller) { - postToCallback(caller, CallbackMessageHandler.MSG_FAST_FORWARD, null, null); - } - - void dispatchRewind(RemoteUserInfo caller) { - postToCallback(caller, CallbackMessageHandler.MSG_REWIND, null, null); - } - - void dispatchSeekTo(RemoteUserInfo caller, long pos) { - postToCallback(caller, CallbackMessageHandler.MSG_SEEK_TO, pos, null); - } - - void dispatchRate(RemoteUserInfo caller, Rating rating) { - postToCallback(caller, CallbackMessageHandler.MSG_RATE, rating, null); - } - - void dispatchSetPlaybackSpeed(RemoteUserInfo caller, float speed) { - postToCallback(caller, CallbackMessageHandler.MSG_SET_PLAYBACK_SPEED, speed, null); - } - - void dispatchCustomAction(RemoteUserInfo caller, String action, Bundle args) { - postToCallback(caller, CallbackMessageHandler.MSG_CUSTOM_ACTION, action, args); - } - - void dispatchMediaButton(RemoteUserInfo caller, Intent mediaButtonIntent) { - postToCallback(caller, CallbackMessageHandler.MSG_MEDIA_BUTTON, mediaButtonIntent, null); - } - - void dispatchMediaButtonDelayed(RemoteUserInfo info, Intent mediaButtonIntent, - long delay) { - postToCallbackDelayed(info, CallbackMessageHandler.MSG_PLAY_PAUSE_KEY_DOUBLE_TAP_TIMEOUT, - mediaButtonIntent, null, delay); - } - - void dispatchAdjustVolume(RemoteUserInfo caller, int direction) { - postToCallback(caller, CallbackMessageHandler.MSG_ADJUST_VOLUME, direction, null); - } - - void dispatchSetVolumeTo(RemoteUserInfo caller, int volume) { - postToCallback(caller, CallbackMessageHandler.MSG_SET_VOLUME, volume, null); - } - - void dispatchCommand(RemoteUserInfo caller, String command, Bundle args, - ResultReceiver resultCb) { - Command cmd = new Command(command, args, resultCb); - postToCallback(caller, CallbackMessageHandler.MSG_COMMAND, cmd, null); - } - - private void postToCallback(RemoteUserInfo caller, int what, Object obj, Bundle data) { - postToCallbackDelayed(caller, what, obj, data, 0); - } - - private void postToCallbackDelayed(RemoteUserInfo caller, int what, Object obj, Bundle data, - long delay) { - synchronized (mLock) { - if (mCallbackHandler != null) { - mCallbackHandler.post(caller, what, obj, data, delay); - } - } - } - - /** - * Return true if this is considered an active playback state. - */ - public static boolean isActiveState(int state) { - switch (state) { - case PlaybackState.STATE_FAST_FORWARDING: - case PlaybackState.STATE_REWINDING: - case PlaybackState.STATE_SKIPPING_TO_PREVIOUS: - case PlaybackState.STATE_SKIPPING_TO_NEXT: - case PlaybackState.STATE_BUFFERING: - case PlaybackState.STATE_CONNECTING: - case PlaybackState.STATE_PLAYING: - return true; - } - return false; - } - - /** - * Interface for handling MediaButtoneEvent - */ - public interface MediaButtonEventDelegate { - /** - * Called when a media button is pressed and this session has the - * highest priority or a controller sends a media button event to the - * session. - * - * @param mediaButtonIntent an intent containing the KeyEvent as an extra - * @return True if the event was handled, false otherwise. - */ - boolean onMediaButtonIntent(Intent mediaButtonIntent); - } - - /** - * Receives media buttons, transport controls, and commands from controllers - * and the system. A callback may be set using {@link #setCallback}. - * @hide - */ - public static class CallbackWrapper implements MediaButtonEventDelegate { - - private final MediaSession.Callback mCallback; - - @SuppressWarnings("WeakerAccess") /* synthetic access */ - MediaSessionEngine mSessionImpl; - @SuppressWarnings("WeakerAccess") /* synthetic access */ - CallbackMessageHandler mHandler; - private boolean mMediaPlayPauseKeyPending; - - public CallbackWrapper(MediaSession.Callback callback) { - mCallback = callback; - if (mCallback != null) { - mCallback.onSetMediaButtonEventDelegate(this); - } - } - - /** - * Called when a controller has sent a command to this session. - * The owner of the session may handle custom commands but is not - * required to. - * - * @param command The command name. - * @param args Optional parameters for the command, may be null. - * @param cb A result receiver to which a result may be sent by the command, may be null. - */ - public void onCommand(@NonNull String command, @Nullable Bundle args, - @Nullable ResultReceiver cb) { - if (mCallback != null) { - mCallback.onCommand(command, args, cb); - } - } - - /** - * Called when a media button is pressed and this session has the - * highest priority or a controller sends a media button event to the - * session. The default behavior will call the relevant method if the - * action for it was set. - * <p> - * The intent will be of type {@link Intent#ACTION_MEDIA_BUTTON} with a - * KeyEvent in {@link Intent#EXTRA_KEY_EVENT} - * - * @param mediaButtonIntent an intent containing the KeyEvent as an - * extra - * @return True if the event was handled, false otherwise. - */ - public boolean onMediaButtonEvent(@NonNull Intent mediaButtonIntent) { - return mCallback == null ? false : mCallback.onMediaButtonEvent(mediaButtonIntent); - } - - private void handleMediaPlayPauseKeySingleTapIfPending() { - if (!mMediaPlayPauseKeyPending) { - return; - } - mMediaPlayPauseKeyPending = false; - mHandler.removeMessages(CallbackMessageHandler.MSG_PLAY_PAUSE_KEY_DOUBLE_TAP_TIMEOUT); - PlaybackState state = mSessionImpl.mPlaybackState; - long validActions = state == null ? 0 : state.getActions(); - boolean isPlaying = state != null - && state.getState() == PlaybackState.STATE_PLAYING; - boolean canPlay = (validActions & (PlaybackState.ACTION_PLAY_PAUSE - | PlaybackState.ACTION_PLAY)) != 0; - boolean canPause = (validActions & (PlaybackState.ACTION_PLAY_PAUSE - | PlaybackState.ACTION_PAUSE)) != 0; - if (isPlaying && canPause) { - onPause(); - } else if (!isPlaying && canPlay) { - onPlay(); - } - } - - /** - * Override to handle requests to prepare playback. During the preparation, a session should - * not hold audio focus in order to allow other sessions play seamlessly. The state of - * playback should be updated to {@link PlaybackState#STATE_PAUSED} after the preparation is - * done. - */ - public void onPrepare() { - if (mCallback != null) { - mCallback.onPrepare(); - } - } - - /** - * Override to handle requests to prepare for playing a specific mediaId that was provided - * by your app's {@link MediaBrowserService}. During the preparation, a session should not - * hold audio focus in order to allow other sessions play seamlessly. The state of playback - * should be updated to {@link PlaybackState#STATE_PAUSED} after the preparation is done. - * The playback of the prepared content should start in the implementation of - * {@link #onPlay}. Override {@link #onPlayFromMediaId} to handle requests for starting - * playback without preparation. - */ - public void onPrepareFromMediaId(String mediaId, Bundle extras) { - if (mCallback != null) { - mCallback.onPrepareFromMediaId(mediaId, extras); - } - } - - /** - * Override to handle requests to prepare playback from a search query. An empty query - * indicates that the app may prepare any music. The implementation should attempt to make a - * smart choice about what to play. During the preparation, a session should not hold audio - * focus in order to allow other sessions play seamlessly. The state of playback should be - * updated to {@link PlaybackState#STATE_PAUSED} after the preparation is done. The playback - * of the prepared content should start in the implementation of {@link #onPlay}. Override - * {@link #onPlayFromSearch} to handle requests for starting playback without preparation. - */ - public void onPrepareFromSearch(String query, Bundle extras) { - if (mCallback != null) { - mCallback.onPrepareFromSearch(query, extras); - } - } - - /** - * Override to handle requests to prepare a specific media item represented by a URI. - * During the preparation, a session should not hold audio focus in order to allow - * other sessions play seamlessly. The state of playback should be updated to - * {@link PlaybackState#STATE_PAUSED} after the preparation is done. - * The playback of the prepared content should start in the implementation of - * {@link #onPlay}. Override {@link #onPlayFromUri} to handle requests - * for starting playback without preparation. - */ - public void onPrepareFromUri(Uri uri, Bundle extras) { - if (mCallback != null) { - mCallback.onPrepareFromUri(uri, extras); - } - } - - /** - * Override to handle requests to begin playback. - */ - public void onPlay() { - if (mCallback != null) { - mCallback.onPlay(); - } - } - - /** - * Override to handle requests to begin playback from a search query. An - * empty query indicates that the app may play any music. The - * implementation should attempt to make a smart choice about what to - * play. - */ - public void onPlayFromSearch(String query, Bundle extras) { - if (mCallback != null) { - mCallback.onPlayFromSearch(query, extras); - } - } - - /** - * Override to handle requests to play a specific mediaId that was - * provided by your app's {@link MediaBrowserService}. - */ - public void onPlayFromMediaId(String mediaId, Bundle extras) { - if (mCallback != null) { - mCallback.onPlayFromMediaId(mediaId, extras); - } - } - - /** - * Override to handle requests to play a specific media item represented by a URI. - */ - public void onPlayFromUri(Uri uri, Bundle extras) { - if (mCallback != null) { - mCallback.onPlayFromUri(uri, extras); - } - } - - /** - * Override to handle requests to play an item with a given id from the - * play queue. - */ - public void onSkipToQueueItem(long id) { - if (mCallback != null) { - mCallback.onSkipToQueueItem(id); - } - } - - /** - * Override to handle requests to pause playback. - */ - public void onPause() { - if (mCallback != null) { - mCallback.onPause(); - } - } - - /** - * Override to handle requests to skip to the next media item. - */ - public void onSkipToNext() { - if (mCallback != null) { - mCallback.onSkipToNext(); - } - } - - /** - * Override to handle requests to skip to the previous media item. - */ - public void onSkipToPrevious() { - if (mCallback != null) { - mCallback.onSkipToPrevious(); - } - } - - /** - * Override to handle requests to fast forward. - */ - public void onFastForward() { - if (mCallback != null) { - mCallback.onFastForward(); - } - } - - /** - * Override to handle requests to rewind. - */ - public void onRewind() { - if (mCallback != null) { - mCallback.onRewind(); - } - } - - /** - * Override to handle requests to stop playback. - */ - public void onStop() { - if (mCallback != null) { - mCallback.onStop(); - } - } - - /** - * Override to handle requests to seek to a specific position in ms. - * - * @param pos New position to move to, in milliseconds. - */ - public void onSeekTo(long pos) { - if (mCallback != null) { - mCallback.onSeekTo(pos); - } - } - - /** - * Override to handle the item being rated. - * - * @param rating - */ - public void onSetRating(@NonNull Rating rating) { - if (mCallback != null) { - mCallback.onSetRating(rating); - } - } - - /** - * Override to handle the playback speed change. - * - * @param speed the playback speed - */ - public void onSetPlaybackSpeed(float speed) { - if (mCallback != null) { - mCallback.onSetPlaybackSpeed(speed); - } - } - - /** - * Called when a {@link MediaController} wants a {@link PlaybackState.CustomAction} to be - * performed. - * - * @param action The action that was originally sent in the - * {@link PlaybackState.CustomAction}. - * @param extras Optional extras specified by the {@link MediaController}. - */ - public void onCustomAction(@NonNull String action, @Nullable Bundle extras) { - if (mCallback != null) { - mCallback.onCustomAction(action, extras); - } - } - - @Override - public boolean onMediaButtonIntent(Intent mediaButtonIntent) { - if (mSessionImpl != null && mHandler != null - && Intent.ACTION_MEDIA_BUTTON.equals(mediaButtonIntent.getAction())) { - KeyEvent ke = mediaButtonIntent.getParcelableExtra(Intent.EXTRA_KEY_EVENT); - if (ke != null && ke.getAction() == KeyEvent.ACTION_DOWN) { - PlaybackState state = mSessionImpl.mPlaybackState; - long validActions = state == null ? 0 : state.getActions(); - switch (ke.getKeyCode()) { - case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: - case KeyEvent.KEYCODE_HEADSETHOOK: - if (ke.getRepeatCount() > 0) { - // Consider long-press as a single tap. - handleMediaPlayPauseKeySingleTapIfPending(); - } else if (mMediaPlayPauseKeyPending) { - // Consider double tap as the next. - mHandler.removeMessages(CallbackMessageHandler - .MSG_PLAY_PAUSE_KEY_DOUBLE_TAP_TIMEOUT); - mMediaPlayPauseKeyPending = false; - if ((validActions & PlaybackState.ACTION_SKIP_TO_NEXT) != 0) { - onSkipToNext(); - } - } else { - mMediaPlayPauseKeyPending = true; - mSessionImpl.dispatchMediaButtonDelayed( - mSessionImpl.getCurrentControllerInfo(), - mediaButtonIntent, ViewConfiguration.getDoubleTapTimeout()); - } - return true; - default: - // If another key is pressed within double tap timeout, consider the - // pending play/pause as a single tap to handle media keys in order. - handleMediaPlayPauseKeySingleTapIfPending(); - break; - } - - switch (ke.getKeyCode()) { - case KeyEvent.KEYCODE_MEDIA_PLAY: - if ((validActions & PlaybackState.ACTION_PLAY) != 0) { - onPlay(); - return true; - } - break; - case KeyEvent.KEYCODE_MEDIA_PAUSE: - if ((validActions & PlaybackState.ACTION_PAUSE) != 0) { - onPause(); - return true; - } - break; - case KeyEvent.KEYCODE_MEDIA_NEXT: - if ((validActions & PlaybackState.ACTION_SKIP_TO_NEXT) != 0) { - onSkipToNext(); - return true; - } - break; - case KeyEvent.KEYCODE_MEDIA_PREVIOUS: - if ((validActions & PlaybackState.ACTION_SKIP_TO_PREVIOUS) != 0) { - onSkipToPrevious(); - return true; - } - break; - case KeyEvent.KEYCODE_MEDIA_STOP: - if ((validActions & PlaybackState.ACTION_STOP) != 0) { - onStop(); - return true; - } - break; - case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: - if ((validActions & PlaybackState.ACTION_FAST_FORWARD) != 0) { - onFastForward(); - return true; - } - break; - case KeyEvent.KEYCODE_MEDIA_REWIND: - if ((validActions & PlaybackState.ACTION_REWIND) != 0) { - onRewind(); - return true; - } - break; - } - } - } - return false; - } - } - - /** - * A single item that is part of the play queue. It contains a description - * of the item and its id in the queue. - */ - public static final class QueueItem { - /** - * This id is reserved. No items can be explicitly assigned this id. - */ - public static final int UNKNOWN_ID = -1; - - private final MediaDescription mDescription; - private final long mId; - - /** - * Create a new {@link MediaSession.QueueItem}. - * - * @param description The {@link MediaDescription} for this item. - * @param id An identifier for this item. It must be unique within the - * play queue and cannot be {@link #UNKNOWN_ID}. - */ - public QueueItem(MediaDescription description, long id) { - if (description == null) { - throw new IllegalArgumentException("Description cannot be null."); - } - if (id == UNKNOWN_ID) { - throw new IllegalArgumentException("Id cannot be QueueItem.UNKNOWN_ID"); - } - mDescription = description; - mId = id; - } - - public QueueItem(Parcel in) { - mDescription = MediaDescription.CREATOR.createFromParcel(in); - mId = in.readLong(); - } - - /** - * Get the description for this item. - */ - public MediaDescription getDescription() { - return mDescription; - } - - /** - * Get the queue id for this item. - */ - public long getQueueId() { - return mId; - } - - /** - * Flatten this object in to a Parcel. - * - * @param dest The Parcel in which the object should be written. - * @param flags Additional flags about how the object should be written. - */ - public void writeToParcel(Parcel dest, int flags) { - mDescription.writeToParcel(dest, flags); - dest.writeLong(mId); - } - - @Override - public String toString() { - return "MediaSession.QueueItem {" + "Description=" + mDescription + ", Id=" + mId - + " }"; - } - - @Override - public boolean equals(Object o) { - if (o == null) { - return false; - } - - if (!(o instanceof QueueItem)) { - return false; - } - - final QueueItem item = (QueueItem) o; - if (mId != item.mId) { - return false; - } - - if (!Objects.equals(mDescription, item.mDescription)) { - return false; - } - - return true; - } - } - - private static final class Command { - public final String command; - public final Bundle extras; - public final ResultReceiver stub; - - Command(String command, Bundle extras, ResultReceiver stub) { - this.command = command; - this.extras = extras; - this.stub = stub; - } - } - - private class CallbackMessageHandler extends Handler { - private static final int MSG_COMMAND = 1; - private static final int MSG_MEDIA_BUTTON = 2; - private static final int MSG_PREPARE = 3; - private static final int MSG_PREPARE_MEDIA_ID = 4; - private static final int MSG_PREPARE_SEARCH = 5; - private static final int MSG_PREPARE_URI = 6; - private static final int MSG_PLAY = 7; - private static final int MSG_PLAY_MEDIA_ID = 8; - private static final int MSG_PLAY_SEARCH = 9; - private static final int MSG_PLAY_URI = 10; - private static final int MSG_SKIP_TO_ITEM = 11; - private static final int MSG_PAUSE = 12; - private static final int MSG_STOP = 13; - private static final int MSG_NEXT = 14; - private static final int MSG_PREVIOUS = 15; - private static final int MSG_FAST_FORWARD = 16; - private static final int MSG_REWIND = 17; - private static final int MSG_SEEK_TO = 18; - private static final int MSG_RATE = 19; - private static final int MSG_SET_PLAYBACK_SPEED = 20; - private static final int MSG_CUSTOM_ACTION = 21; - private static final int MSG_ADJUST_VOLUME = 22; - private static final int MSG_SET_VOLUME = 23; - private static final int MSG_PLAY_PAUSE_KEY_DOUBLE_TAP_TIMEOUT = 24; - - @SuppressWarnings("WeakerAccess") /* synthetic access */ - CallbackWrapper mCallbackWrapper; - @SuppressWarnings("WeakerAccess") /* synthetic access */ - RemoteUserInfo mCurrentControllerInfo; - - CallbackMessageHandler(Looper looper, CallbackWrapper callbackWrapper) { - super(looper); - mCallbackWrapper = callbackWrapper; - mCallbackWrapper.mHandler = this; - } - - void post(RemoteUserInfo caller, int what, Object obj, Bundle data, long delayMs) { - Pair<RemoteUserInfo, Object> objWithCaller = Pair.create(caller, obj); - Message msg = obtainMessage(what, objWithCaller); - msg.setAsynchronous(true); - msg.setData(data); - if (delayMs > 0) { - sendMessageDelayed(msg, delayMs); - } else { - sendMessage(msg); - } - } - - @Override - public void handleMessage(Message msg) { - mCurrentControllerInfo = ((Pair<RemoteUserInfo, Object>) msg.obj).first; - - VolumeProvider vp; - Object obj = ((Pair<RemoteUserInfo, Object>) msg.obj).second; - - switch (msg.what) { - case MSG_COMMAND: - Command cmd = (Command) obj; - mCallbackWrapper.onCommand(cmd.command, cmd.extras, cmd.stub); - break; - case MSG_MEDIA_BUTTON: - mCallbackWrapper.onMediaButtonEvent((Intent) obj); - break; - case MSG_PREPARE: - mCallbackWrapper.onPrepare(); - break; - case MSG_PREPARE_MEDIA_ID: - mCallbackWrapper.onPrepareFromMediaId((String) obj, msg.getData()); - break; - case MSG_PREPARE_SEARCH: - mCallbackWrapper.onPrepareFromSearch((String) obj, msg.getData()); - break; - case MSG_PREPARE_URI: - mCallbackWrapper.onPrepareFromUri((Uri) obj, msg.getData()); - break; - case MSG_PLAY: - mCallbackWrapper.onPlay(); - break; - case MSG_PLAY_MEDIA_ID: - mCallbackWrapper.onPlayFromMediaId((String) obj, msg.getData()); - break; - case MSG_PLAY_SEARCH: - mCallbackWrapper.onPlayFromSearch((String) obj, msg.getData()); - break; - case MSG_PLAY_URI: - mCallbackWrapper.onPlayFromUri((Uri) obj, msg.getData()); - break; - case MSG_SKIP_TO_ITEM: - mCallbackWrapper.onSkipToQueueItem((Long) obj); - break; - case MSG_PAUSE: - mCallbackWrapper.onPause(); - break; - case MSG_STOP: - mCallbackWrapper.onStop(); - break; - case MSG_NEXT: - mCallbackWrapper.onSkipToNext(); - break; - case MSG_PREVIOUS: - mCallbackWrapper.onSkipToPrevious(); - break; - case MSG_FAST_FORWARD: - mCallbackWrapper.onFastForward(); - break; - case MSG_REWIND: - mCallbackWrapper.onRewind(); - break; - case MSG_SEEK_TO: - mCallbackWrapper.onSeekTo((Long) obj); - break; - case MSG_RATE: - mCallbackWrapper.onSetRating((Rating) obj); - break; - case MSG_SET_PLAYBACK_SPEED: - mCallbackWrapper.onSetPlaybackSpeed((Float) obj); - break; - case MSG_CUSTOM_ACTION: - mCallbackWrapper.onCustomAction((String) obj, msg.getData()); - break; - case MSG_ADJUST_VOLUME: - synchronized (mLock) { - vp = mVolumeProvider; - } - if (vp != null) { - vp.onAdjustVolume((int) obj); - } - break; - case MSG_SET_VOLUME: - synchronized (mLock) { - vp = mVolumeProvider; - } - if (vp != null) { - vp.onSetVolumeTo((int) obj); - } - break; - case MSG_PLAY_PAUSE_KEY_DOUBLE_TAP_TIMEOUT: - mCallbackWrapper.handleMediaPlayPauseKeySingleTapIfPending(); - break; - } - mCurrentControllerInfo = null; - } - } -} diff --git a/media/java/android/media/session/SessionCallbackLink.java b/media/java/android/media/session/SessionCallbackLink.java index 6ffdc2bace18..c858a60ea5d7 100644 --- a/media/java/android/media/session/SessionCallbackLink.java +++ b/media/java/android/media/session/SessionCallbackLink.java @@ -49,9 +49,9 @@ public final class SessionCallbackLink implements Parcelable { * Constructor for stub (Callee) * @hide */ - public SessionCallbackLink(@NonNull Context context) { + public SessionCallbackLink(@NonNull Context context, MediaSession session) { mContext = context; - mISessionCallback = new CallbackStub(); + mISessionCallback = new CallbackStub(session); } /** @@ -63,15 +63,6 @@ public final class SessionCallbackLink implements Parcelable { } /** - * Set {@link MediaSessionEngine} which will be used by {@link CallbackStub}. - */ - void setSessionEngine(@Nullable MediaSessionEngine sessionImpl) { - if (mISessionCallback instanceof CallbackStub) { - ((CallbackStub) mISessionCallback).mSessionImpl = new WeakReference<>(sessionImpl); - } - } - - /** * Notify session that a controller sends a command. * * @param packageName the package name of the controller @@ -568,7 +559,11 @@ public final class SessionCallbackLink implements Parcelable { }; private class CallbackStub extends ISessionCallback.Stub { - private WeakReference<MediaSessionEngine> mSessionImpl; + private WeakReference<MediaSession> mMediaSession; + + private CallbackStub(MediaSession session) { + mMediaSession = new WeakReference<>(session); + } private RemoteUserInfo createRemoteUserInfo(String packageName, int pid, int uid) { return new RemoteUserInfo(packageName, pid, uid); @@ -580,9 +575,9 @@ public final class SessionCallbackLink implements Parcelable { ensureMediaControlPermission(); final long token = Binder.clearCallingIdentity(); try { - MediaSessionEngine sessionImpl = mSessionImpl.get(); - if (sessionImpl != null) { - sessionImpl.dispatchCommand(createRemoteUserInfo(packageName, pid, uid), + MediaSession session = mMediaSession.get(); + if (session != null) { + session.dispatchCommand(createRemoteUserInfo(packageName, pid, uid), command, args, cb); } } finally { @@ -596,9 +591,9 @@ public final class SessionCallbackLink implements Parcelable { ensureMediaControlPermission(); final long token = Binder.clearCallingIdentity(); try { - MediaSessionEngine sessionImpl = mSessionImpl.get(); - if (sessionImpl != null) { - sessionImpl.dispatchMediaButton( + MediaSession session = mMediaSession.get(); + if (session != null) { + session.dispatchMediaButton( createRemoteUserInfo(packageName, pid, uid), mediaButtonIntent); } } finally { @@ -615,9 +610,9 @@ public final class SessionCallbackLink implements Parcelable { ensureMediaControlPermission(); final long token = Binder.clearCallingIdentity(); try { - MediaSessionEngine sessionImpl = mSessionImpl.get(); - if (sessionImpl != null) { - sessionImpl.dispatchMediaButton(createRemoteUserInfo(packageName, pid, uid), + MediaSession session = mMediaSession.get(); + if (session != null) { + session.dispatchMediaButton(createRemoteUserInfo(packageName, pid, uid), mediaButtonIntent); } } finally { @@ -631,9 +626,9 @@ public final class SessionCallbackLink implements Parcelable { ensureMediaControlPermission(); final long token = Binder.clearCallingIdentity(); try { - MediaSessionEngine sessionImpl = mSessionImpl.get(); - if (sessionImpl != null) { - sessionImpl.dispatchPrepare(createRemoteUserInfo(packageName, pid, uid)); + MediaSession session = mMediaSession.get(); + if (session != null) { + session.dispatchPrepare(createRemoteUserInfo(packageName, pid, uid)); } } finally { Binder.restoreCallingIdentity(token); @@ -646,9 +641,9 @@ public final class SessionCallbackLink implements Parcelable { ensureMediaControlPermission(); final long token = Binder.clearCallingIdentity(); try { - MediaSessionEngine sessionImpl = mSessionImpl.get(); - if (sessionImpl != null) { - sessionImpl.dispatchPrepareFromMediaId( + MediaSession session = mMediaSession.get(); + if (session != null) { + session.dispatchPrepareFromMediaId( createRemoteUserInfo(packageName, pid, uid), mediaId, extras); } } finally { @@ -662,9 +657,9 @@ public final class SessionCallbackLink implements Parcelable { ensureMediaControlPermission(); final long token = Binder.clearCallingIdentity(); try { - MediaSessionEngine sessionImpl = mSessionImpl.get(); - if (sessionImpl != null) { - sessionImpl.dispatchPrepareFromSearch( + MediaSession session = mMediaSession.get(); + if (session != null) { + session.dispatchPrepareFromSearch( createRemoteUserInfo(packageName, pid, uid), query, extras); } } finally { @@ -678,9 +673,9 @@ public final class SessionCallbackLink implements Parcelable { ensureMediaControlPermission(); final long token = Binder.clearCallingIdentity(); try { - MediaSessionEngine sessionImpl = mSessionImpl.get(); - if (sessionImpl != null) { - sessionImpl.dispatchPrepareFromUri( + MediaSession session = mMediaSession.get(); + if (session != null) { + session.dispatchPrepareFromUri( createRemoteUserInfo(packageName, pid, uid), uri, extras); } } finally { @@ -694,9 +689,9 @@ public final class SessionCallbackLink implements Parcelable { ensureMediaControlPermission(); final long token = Binder.clearCallingIdentity(); try { - MediaSessionEngine sessionImpl = mSessionImpl.get(); - if (sessionImpl != null) { - sessionImpl.dispatchPlay(createRemoteUserInfo(packageName, pid, uid)); + MediaSession session = mMediaSession.get(); + if (session != null) { + session.dispatchPlay(createRemoteUserInfo(packageName, pid, uid)); } } finally { Binder.restoreCallingIdentity(token); @@ -709,9 +704,9 @@ public final class SessionCallbackLink implements Parcelable { ensureMediaControlPermission(); final long token = Binder.clearCallingIdentity(); try { - MediaSessionEngine sessionImpl = mSessionImpl.get(); - if (sessionImpl != null) { - sessionImpl.dispatchPlayFromMediaId( + MediaSession session = mMediaSession.get(); + if (session != null) { + session.dispatchPlayFromMediaId( createRemoteUserInfo(packageName, pid, uid), mediaId, extras); } } finally { @@ -725,9 +720,9 @@ public final class SessionCallbackLink implements Parcelable { ensureMediaControlPermission(); final long token = Binder.clearCallingIdentity(); try { - MediaSessionEngine sessionImpl = mSessionImpl.get(); - if (sessionImpl != null) { - sessionImpl.dispatchPlayFromSearch( + MediaSession session = mMediaSession.get(); + if (session != null) { + session.dispatchPlayFromSearch( createRemoteUserInfo(packageName, pid, uid), query, extras); } } finally { @@ -741,9 +736,9 @@ public final class SessionCallbackLink implements Parcelable { ensureMediaControlPermission(); final long token = Binder.clearCallingIdentity(); try { - MediaSessionEngine sessionImpl = mSessionImpl.get(); - if (sessionImpl != null) { - sessionImpl.dispatchPlayFromUri( + MediaSession session = mMediaSession.get(); + if (session != null) { + session.dispatchPlayFromUri( createRemoteUserInfo(packageName, pid, uid), uri, extras); } } finally { @@ -757,9 +752,9 @@ public final class SessionCallbackLink implements Parcelable { ensureMediaControlPermission(); final long token = Binder.clearCallingIdentity(); try { - MediaSessionEngine sessionImpl = mSessionImpl.get(); - if (sessionImpl != null) { - sessionImpl.dispatchSkipToItem( + MediaSession session = mMediaSession.get(); + if (session != null) { + session.dispatchSkipToItem( createRemoteUserInfo(packageName, pid, uid), id); } } finally { @@ -773,9 +768,9 @@ public final class SessionCallbackLink implements Parcelable { ensureMediaControlPermission(); final long token = Binder.clearCallingIdentity(); try { - MediaSessionEngine sessionImpl = mSessionImpl.get(); - if (sessionImpl != null) { - sessionImpl.dispatchPause(createRemoteUserInfo(packageName, pid, uid)); + MediaSession session = mMediaSession.get(); + if (session != null) { + session.dispatchPause(createRemoteUserInfo(packageName, pid, uid)); } } finally { Binder.restoreCallingIdentity(token); @@ -788,9 +783,9 @@ public final class SessionCallbackLink implements Parcelable { ensureMediaControlPermission(); final long token = Binder.clearCallingIdentity(); try { - MediaSessionEngine sessionImpl = mSessionImpl.get(); - if (sessionImpl != null) { - sessionImpl.dispatchStop(createRemoteUserInfo(packageName, pid, uid)); + MediaSession session = mMediaSession.get(); + if (session != null) { + session.dispatchStop(createRemoteUserInfo(packageName, pid, uid)); } } finally { Binder.restoreCallingIdentity(token); @@ -803,9 +798,9 @@ public final class SessionCallbackLink implements Parcelable { ensureMediaControlPermission(); final long token = Binder.clearCallingIdentity(); try { - MediaSessionEngine sessionImpl = mSessionImpl.get(); - if (sessionImpl != null) { - sessionImpl.dispatchNext(createRemoteUserInfo(packageName, pid, uid)); + MediaSession session = mMediaSession.get(); + if (session != null) { + session.dispatchNext(createRemoteUserInfo(packageName, pid, uid)); } } finally { Binder.restoreCallingIdentity(token); @@ -818,9 +813,9 @@ public final class SessionCallbackLink implements Parcelable { ensureMediaControlPermission(); final long token = Binder.clearCallingIdentity(); try { - MediaSessionEngine sessionImpl = mSessionImpl.get(); - if (sessionImpl != null) { - sessionImpl.dispatchPrevious(createRemoteUserInfo(packageName, pid, uid)); + MediaSession session = mMediaSession.get(); + if (session != null) { + session.dispatchPrevious(createRemoteUserInfo(packageName, pid, uid)); } } finally { Binder.restoreCallingIdentity(token); @@ -833,9 +828,9 @@ public final class SessionCallbackLink implements Parcelable { ensureMediaControlPermission(); final long token = Binder.clearCallingIdentity(); try { - MediaSessionEngine sessionImpl = mSessionImpl.get(); - if (sessionImpl != null) { - sessionImpl.dispatchFastForward( + MediaSession session = mMediaSession.get(); + if (session != null) { + session.dispatchFastForward( createRemoteUserInfo(packageName, pid, uid)); } } finally { @@ -849,9 +844,9 @@ public final class SessionCallbackLink implements Parcelable { ensureMediaControlPermission(); final long token = Binder.clearCallingIdentity(); try { - MediaSessionEngine sessionImpl = mSessionImpl.get(); - if (sessionImpl != null) { - sessionImpl.dispatchRewind(createRemoteUserInfo(packageName, pid, uid)); + MediaSession session = mMediaSession.get(); + if (session != null) { + session.dispatchRewind(createRemoteUserInfo(packageName, pid, uid)); } } finally { Binder.restoreCallingIdentity(token); @@ -864,9 +859,9 @@ public final class SessionCallbackLink implements Parcelable { ensureMediaControlPermission(); final long token = Binder.clearCallingIdentity(); try { - MediaSessionEngine sessionImpl = mSessionImpl.get(); - if (sessionImpl != null) { - sessionImpl.dispatchSeekTo( + MediaSession session = mMediaSession.get(); + if (session != null) { + session.dispatchSeekTo( createRemoteUserInfo(packageName, pid, uid), pos); } } finally { @@ -880,9 +875,9 @@ public final class SessionCallbackLink implements Parcelable { ensureMediaControlPermission(); final long token = Binder.clearCallingIdentity(); try { - MediaSessionEngine sessionImpl = mSessionImpl.get(); - if (sessionImpl != null) { - sessionImpl.dispatchRate( + MediaSession session = mMediaSession.get(); + if (session != null) { + session.dispatchRate( createRemoteUserInfo(packageName, pid, uid), rating); } } finally { @@ -896,9 +891,9 @@ public final class SessionCallbackLink implements Parcelable { ensureMediaControlPermission(); final long token = Binder.clearCallingIdentity(); try { - MediaSessionEngine sessionImpl = mSessionImpl.get(); - if (sessionImpl != null) { - sessionImpl.dispatchSetPlaybackSpeed( + MediaSession session = mMediaSession.get(); + if (session != null) { + session.dispatchSetPlaybackSpeed( createRemoteUserInfo(packageName, pid, uid), speed); } } finally { @@ -912,9 +907,9 @@ public final class SessionCallbackLink implements Parcelable { ensureMediaControlPermission(); final long token = Binder.clearCallingIdentity(); try { - MediaSessionEngine sessionImpl = mSessionImpl.get(); - if (sessionImpl != null) { - sessionImpl.dispatchCustomAction( + MediaSession session = mMediaSession.get(); + if (session != null) { + session.dispatchCustomAction( createRemoteUserInfo(packageName, pid, uid), action, args); } } finally { @@ -928,9 +923,9 @@ public final class SessionCallbackLink implements Parcelable { ensureMediaControlPermission(); final long token = Binder.clearCallingIdentity(); try { - MediaSessionEngine sessionImpl = mSessionImpl.get(); - if (sessionImpl != null) { - sessionImpl.dispatchAdjustVolume( + MediaSession session = mMediaSession.get(); + if (session != null) { + session.dispatchAdjustVolume( createRemoteUserInfo(packageName, pid, uid), direction); } } finally { @@ -944,9 +939,9 @@ public final class SessionCallbackLink implements Parcelable { ensureMediaControlPermission(); final long token = Binder.clearCallingIdentity(); try { - MediaSessionEngine sessionImpl = mSessionImpl.get(); - if (sessionImpl != null) { - sessionImpl.dispatchSetVolumeTo( + MediaSession session = mMediaSession.get(); + if (session != null) { + session.dispatchSetVolumeTo( createRemoteUserInfo(packageName, pid, uid), value); } } finally { diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp index d7ab854d63ba..f412161f418a 100644 --- a/media/jni/android_media_MediaDrm.cpp +++ b/media/jni/android_media_MediaDrm.cpp @@ -149,6 +149,7 @@ struct SessionExceptionFields { }; struct SessionExceptionErrorCodes { + jint kErrorUnknown; jint kResourceContention; } gSessionExceptionErrorCodes; @@ -888,6 +889,8 @@ static void android_media_MediaDrm_native_init(JNIEnv *env) { gFields.sessionException.classId = static_cast<jclass>(env->NewGlobalRef(clazz)); GET_FIELD_ID(gFields.sessionException.errorCode, clazz, "mErrorCode", "I"); + GET_STATIC_FIELD_ID(field, clazz, "ERROR_UNKNOWN", "I"); + gSessionExceptionErrorCodes.kErrorUnknown = env->GetStaticIntField(clazz, field); GET_STATIC_FIELD_ID(field, clazz, "ERROR_RESOURCE_CONTENTION", "I"); gSessionExceptionErrorCodes.kResourceContention = env->GetStaticIntField(clazz, field); } diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp index 3ec0903472bc..24fff0635238 100644 --- a/media/jni/android_media_MediaRecorder.cpp +++ b/media/jni/android_media_MediaRecorder.cpp @@ -760,9 +760,9 @@ android_media_MediaRecord_getActiveMicrophones(JNIEnv *env, return jStatus; } -static jint android_media_MediaRecord_setMicrophoneDirection( +static jint android_media_MediaRecord_setPreferredMicrophoneDirection( JNIEnv *env, jobject thiz, jint direction) { - ALOGV("setMicrophoneDirection(%d)", direction); + ALOGV("setPreferredMicrophoneDirection(%d)", direction); sp<MediaRecorder> mr = getMediaRecorder(env, thiz); if (mr == NULL) { jniThrowException(env, "java/lang/IllegalStateException", NULL); @@ -771,7 +771,7 @@ static jint android_media_MediaRecord_setMicrophoneDirection( jint jStatus = AUDIO_JAVA_SUCCESS; status_t status = - mr->setMicrophoneDirection(static_cast<audio_microphone_direction_t>(direction)); + mr->setPreferredMicrophoneDirection(static_cast<audio_microphone_direction_t>(direction)); if (status != NO_ERROR) { jStatus = nativeToJavaStatus(status); } @@ -779,9 +779,9 @@ static jint android_media_MediaRecord_setMicrophoneDirection( return jStatus; } -static jint android_media_MediaRecord_setMicrophoneFieldDimension( +static jint android_media_MediaRecord_setPreferredMicrophoneFieldDimension( JNIEnv *env, jobject thiz, jfloat zoom) { - ALOGV("setMicrophoneFieldDimension(%f)", zoom); + ALOGV("setPreferredMicrophoneFieldDimension(%f)", zoom); sp<MediaRecorder> mr = getMediaRecorder(env, thiz); if (mr == NULL) { jniThrowException(env, "java/lang/IllegalStateException", NULL); @@ -789,7 +789,7 @@ static jint android_media_MediaRecord_setMicrophoneFieldDimension( } jint jStatus = AUDIO_JAVA_SUCCESS; - status_t status = mr->setMicrophoneFieldDimension(zoom); + status_t status = mr->setPreferredMicrophoneFieldDimension(zoom); if (status != NO_ERROR) { jStatus = nativeToJavaStatus(status); } @@ -850,8 +850,10 @@ static const JNINativeMethod gMethods[] = { {"native_getActiveMicrophones", "(Ljava/util/ArrayList;)I", (void *)android_media_MediaRecord_getActiveMicrophones}, {"native_getPortId", "()I", (void *)android_media_MediaRecord_getPortId}, - {"native_setMicrophoneDirection", "(I)I", (void *)android_media_MediaRecord_setMicrophoneDirection}, - {"native_setMicrophoneFieldDimension", "(F)I", (void *)android_media_MediaRecord_setMicrophoneFieldDimension}, + {"native_setPreferredMicrophoneDirection", "(I)I", + (void *)android_media_MediaRecord_setPreferredMicrophoneDirection}, + {"native_setPreferredMicrophoneFieldDimension", "(F)I", + (void *)android_media_MediaRecord_setPreferredMicrophoneFieldDimension}, }; // This function only registers the native methods, and is called from diff --git a/media/mca/effect/java/android/media/effect/SingleFilterEffect.java b/media/mca/effect/java/android/media/effect/SingleFilterEffect.java index 47900dfcfd5a..dfbf5d20e074 100644 --- a/media/mca/effect/java/android/media/effect/SingleFilterEffect.java +++ b/media/mca/effect/java/android/media/effect/SingleFilterEffect.java @@ -17,6 +17,7 @@ package android.media.effect; +import android.annotation.UnsupportedAppUsage; import android.filterfw.core.Filter; import android.filterfw.core.FilterFactory; import android.filterfw.core.FilterFunction; @@ -44,6 +45,7 @@ public class SingleFilterEffect extends FilterEffect { * @param outputName The name of the output image port. * @param finalParameters Key-value pairs of final input port assignments. */ + @UnsupportedAppUsage public SingleFilterEffect(EffectContext context, String name, Class filterClass, diff --git a/media/mca/filterfw/java/android/filterfw/GraphEnvironment.java b/media/mca/filterfw/java/android/filterfw/GraphEnvironment.java index 7c90b2731ff8..52615bf09faa 100644 --- a/media/mca/filterfw/java/android/filterfw/GraphEnvironment.java +++ b/media/mca/filterfw/java/android/filterfw/GraphEnvironment.java @@ -119,6 +119,7 @@ public class GraphEnvironment extends MffEnvironment { * * @param references An alternating argument list of keys (Strings) and values. */ + @UnsupportedAppUsage public void addReferences(Object... references) { getGraphReader().addReferencesByKeysAndValues(references); } diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt index e1dc40636ca5..1f2480ba0b47 100644 --- a/native/android/libandroid.map.txt +++ b/native/android/libandroid.map.txt @@ -148,6 +148,7 @@ LIBANDROID { AHardwareBuffer_getNativeHandle; # introduced=26 AHardwareBuffer_isSupported; # introduced=29 AHardwareBuffer_lock; # introduced=26 + AHardwareBuffer_lockAndGetInfo; # introduced=29 AHardwareBuffer_lockPlanes; # introduced=29 AHardwareBuffer_recvHandleFromUnixSocket; # introduced=26 AHardwareBuffer_release; # introduced=26 diff --git a/packages/CarSystemUI/Android.bp b/packages/CarSystemUI/Android.bp index 4c9629def113..589623b0d6cd 100644 --- a/packages/CarSystemUI/Android.bp +++ b/packages/CarSystemUI/Android.bp @@ -32,7 +32,6 @@ android_app { "SystemUISharedLib", "SettingsLib", "android.car.userlib", - "androidx.car_car", "androidx.legacy_legacy-support-v4", "androidx.recyclerview_recyclerview", "androidx.preference_preference", @@ -46,7 +45,6 @@ android_app { "androidx.slice_slice-builders", "androidx.arch.core_core-runtime", "androidx.lifecycle_lifecycle-extensions", - "car-theme-lib-bp", "SystemUI-tags", "SystemUI-proto", ], diff --git a/packages/CarSystemUI/res-keyguard/drawable/keyguard_button_background.xml b/packages/CarSystemUI/res-keyguard/drawable/keyguard_button_background.xml index b428931670f5..8b2779d10481 100644 --- a/packages/CarSystemUI/res-keyguard/drawable/keyguard_button_background.xml +++ b/packages/CarSystemUI/res-keyguard/drawable/keyguard_button_background.xml @@ -18,13 +18,13 @@ <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="true"> <shape android:shape="rectangle"> - <corners android:radius="@dimen/car_button_radius"/> + <corners android:radius="@*android:dimen/car_button_radius"/> <solid android:color="#131315"/> </shape> </item> <item> <shape android:shape="rectangle"> - <corners android:radius="@dimen/car_button_radius"/> + <corners android:radius="@*android:dimen/car_button_radius"/> <solid android:color="@color/button_background"/> </shape> </item> diff --git a/packages/CarSystemUI/res-keyguard/layout-land/keyguard_pattern_view.xml b/packages/CarSystemUI/res-keyguard/layout-land/keyguard_pattern_view.xml index b115a1f3c131..a465254afebb 100644 --- a/packages/CarSystemUI/res-keyguard/layout-land/keyguard_pattern_view.xml +++ b/packages/CarSystemUI/res-keyguard/layout-land/keyguard_pattern_view.xml @@ -28,7 +28,7 @@ android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent" - android:paddingHorizontal="@dimen/car_margin"> + android:paddingHorizontal="@*android:dimen/car_margin"> <FrameLayout android:layout_height="match_parent" @@ -53,10 +53,10 @@ <TextView android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_margin="@dimen/car_padding_2" + android:layout_margin="@*android:dimen/car_padding_2" android:gravity="center" android:textColor="@android:color/white" - android:textSize="@dimen/car_body1_size" + android:textSize="@*android:dimen/car_body1_size" android:text="@string/keyguard_enter_your_pattern" /> <include layout="@layout/keyguard_message_area" /> diff --git a/packages/CarSystemUI/res-keyguard/layout-land/keyguard_pin_view.xml b/packages/CarSystemUI/res-keyguard/layout-land/keyguard_pin_view.xml index ed88c6235d58..5746102f5f27 100644 --- a/packages/CarSystemUI/res-keyguard/layout-land/keyguard_pin_view.xml +++ b/packages/CarSystemUI/res-keyguard/layout-land/keyguard_pin_view.xml @@ -29,7 +29,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" - android:paddingHorizontal="@dimen/car_margin"> + android:paddingHorizontal="@*android:dimen/car_margin"> <FrameLayout android:layout_width="0dp" @@ -72,10 +72,10 @@ <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_margin="@dimen/car_padding_2" + android:layout_margin="@*android:dimen/car_padding_2" android:gravity="center" android:textColor="@android:color/white" - android:textSize="@dimen/car_body1_size" + android:textSize="@*android:dimen/car_body1_size" android:text="@string/keyguard_enter_your_pin" /> <include layout="@layout/keyguard_message_area" /> diff --git a/packages/CarSystemUI/res-keyguard/layout/keyguard_message_area.xml b/packages/CarSystemUI/res-keyguard/layout/keyguard_message_area.xml index c2304147982a..09cf4722dae0 100644 --- a/packages/CarSystemUI/res-keyguard/layout/keyguard_message_area.xml +++ b/packages/CarSystemUI/res-keyguard/layout/keyguard_message_area.xml @@ -27,5 +27,5 @@ android:singleLine="true" android:ellipsize="marquee" android:focusable="true" - android:layout_marginBottom="@dimen/car_padding_4" - android:textSize="@dimen/car_body2_size" /> + android:layout_marginBottom="@*android:dimen/car_padding_4" + android:textSize="@*android:dimen/car_body2_size" /> diff --git a/packages/CarSystemUI/res-keyguard/layout/keyguard_password_view.xml b/packages/CarSystemUI/res-keyguard/layout/keyguard_password_view.xml index e701fdb956f5..7004fb64ba06 100644 --- a/packages/CarSystemUI/res-keyguard/layout/keyguard_password_view.xml +++ b/packages/CarSystemUI/res-keyguard/layout/keyguard_password_view.xml @@ -51,7 +51,7 @@ android:singleLine="true" android:textStyle="normal" android:inputType="textPassword" - android:textSize="@dimen/car_body1_size" + android:textSize="@*android:dimen/car_body1_size" android:textColor="?attr/wallpaperTextColor" android:textAppearance="?android:attr/textAppearanceMedium" android:imeOptions="flagForceAscii|actionDone" @@ -61,10 +61,10 @@ <TextView android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_margin="@dimen/car_padding_2" + android:layout_margin="@*android:dimen/car_padding_2" android:gravity="center" android:textColor="@android:color/white" - android:textSize="@dimen/car_body1_size" + android:textSize="@*android:dimen/car_body1_size" android:text="@string/keyguard_enter_your_password" /> <Button diff --git a/packages/CarSystemUI/res-keyguard/layout/keyguard_pattern_view.xml b/packages/CarSystemUI/res-keyguard/layout/keyguard_pattern_view.xml index 00333a8a826e..bb69d44a3ac7 100644 --- a/packages/CarSystemUI/res-keyguard/layout/keyguard_pattern_view.xml +++ b/packages/CarSystemUI/res-keyguard/layout/keyguard_pattern_view.xml @@ -46,10 +46,10 @@ <TextView android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_margin="@dimen/car_padding_2" + android:layout_margin="@*android:dimen/car_padding_2" android:gravity="center" android:textColor="@android:color/white" - android:textSize="@dimen/car_body1_size" + android:textSize="@*android:dimen/car_body1_size" android:text="@string/keyguard_enter_your_pattern" /> <include layout="@layout/keyguard_message_area" /> diff --git a/packages/CarSystemUI/res-keyguard/layout/keyguard_pin_view.xml b/packages/CarSystemUI/res-keyguard/layout/keyguard_pin_view.xml index 16622518c36f..815e67d1e278 100644 --- a/packages/CarSystemUI/res-keyguard/layout/keyguard_pin_view.xml +++ b/packages/CarSystemUI/res-keyguard/layout/keyguard_pin_view.xml @@ -59,10 +59,10 @@ <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_margin="@dimen/car_padding_2" + android:layout_margin="@*android:dimen/car_padding_2" android:gravity="center" android:textColor="@android:color/white" - android:textSize="@dimen/car_body1_size" + android:textSize="@*android:dimen/car_body1_size" android:text="@string/keyguard_enter_your_pin" /> <include layout="@layout/keyguard_message_area" /> diff --git a/packages/CarSystemUI/res-keyguard/values-land/dimens.xml b/packages/CarSystemUI/res-keyguard/values-land/dimens.xml index 805a13497f6f..c39e0e4731e8 100644 --- a/packages/CarSystemUI/res-keyguard/values-land/dimens.xml +++ b/packages/CarSystemUI/res-keyguard/values-land/dimens.xml @@ -15,6 +15,6 @@ limitations under the License. --> <resources> - <dimen name="num_pad_key_margin_horizontal">@dimen/car_padding_5</dimen> - <dimen name="num_pad_key_margin_bottom">@dimen/car_padding_4</dimen> + <dimen name="num_pad_key_margin_horizontal">@*android:dimen/car_padding_5</dimen> + <dimen name="num_pad_key_margin_bottom">@*android:dimen/car_padding_4</dimen> </resources> diff --git a/packages/CarSystemUI/res-keyguard/values/colors.xml b/packages/CarSystemUI/res-keyguard/values/colors.xml index e6edbea3f80e..ba9f060fab88 100644 --- a/packages/CarSystemUI/res-keyguard/values/colors.xml +++ b/packages/CarSystemUI/res-keyguard/values/colors.xml @@ -16,6 +16,6 @@ --> <resources> - <color name="button_background">@color/car_dark_blue_grey_600</color> - <color name="button_text">@color/car_action1_light</color> + <color name="button_background">@*android:color/car_dark_blue_grey_600</color> + <color name="button_text">@android:color/white</color> </resources>
\ No newline at end of file diff --git a/packages/CarSystemUI/res-keyguard/values/dimens.xml b/packages/CarSystemUI/res-keyguard/values/dimens.xml index 9424dc3870ba..8dfe1716ef54 100644 --- a/packages/CarSystemUI/res-keyguard/values/dimens.xml +++ b/packages/CarSystemUI/res-keyguard/values/dimens.xml @@ -19,8 +19,8 @@ <dimen name="num_pad_margin_right">144dp</dimen> <dimen name="num_pad_key_width">80dp</dimen> <dimen name="num_pad_key_height">80dp</dimen> - <dimen name="num_pad_key_margin_horizontal">@dimen/car_padding_6</dimen> - <dimen name="num_pad_key_margin_bottom">@dimen/car_padding_5</dimen> + <dimen name="num_pad_key_margin_horizontal">@*android:dimen/car_padding_5</dimen> + <dimen name="num_pad_key_margin_bottom">@*android:dimen/car_padding_5</dimen> <dimen name="pin_entry_height">@dimen/num_pad_key_height</dimen> <dimen name="divider_height">1dp</dimen> <dimen name="key_enter_margin_top">128dp</dimen> diff --git a/packages/CarSystemUI/res-keyguard/values/styles.xml b/packages/CarSystemUI/res-keyguard/values/styles.xml index b39e6e64316e..ecea30a13ced 100644 --- a/packages/CarSystemUI/res-keyguard/values/styles.xml +++ b/packages/CarSystemUI/res-keyguard/values/styles.xml @@ -40,7 +40,7 @@ <item name="android:layout_marginEnd">@dimen/num_pad_key_margin_horizontal</item> </style> - <style name="KeyguardButton" parent="Widget.Car.Button"> + <style name="KeyguardButton" parent="@android:style/Widget.DeviceDefault.Button"> <item name="android:background">@drawable/keyguard_button_background</item> <item name="android:textColor">@color/button_text</item> <item name="android:textAllCaps">false</item> @@ -48,6 +48,6 @@ <style name="Widget.TextView.NumPadKey" parent="@android:style/Widget.TextView"> <!-- Only replaces the text size. --> - <item name="android:textSize">@dimen/car_body1_size</item> + <item name="android:textSize">@*android:dimen/car_body1_size</item> </style> </resources> diff --git a/packages/CarSystemUI/res/drawable/car_ic_add_white.xml b/packages/CarSystemUI/res/drawable/car_ic_add_white.xml index d6818607ec08..9d5ca264cdfa 100644 --- a/packages/CarSystemUI/res/drawable/car_ic_add_white.xml +++ b/packages/CarSystemUI/res/drawable/car_ic_add_white.xml @@ -13,8 +13,8 @@ limitations under the License. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="@dimen/car_touch_target_size" - android:height="@dimen/car_touch_target_size" + android:width="@*android:dimen/car_touch_target_size" + android:height="@*android:dimen/car_touch_target_size" android:viewportWidth="24.0" android:viewportHeight="24.0"> <path diff --git a/packages/CarSystemUI/res/drawable/car_rounded_bg_bottom.xml b/packages/CarSystemUI/res/drawable/car_rounded_bg_bottom.xml index eb501e5c26eb..07227fbeb0d8 100644 --- a/packages/CarSystemUI/res/drawable/car_rounded_bg_bottom.xml +++ b/packages/CarSystemUI/res/drawable/car_rounded_bg_bottom.xml @@ -19,9 +19,9 @@ android:shape="rectangle"> <solid android:color="?android:attr/colorBackgroundFloating" /> <corners - android:bottomLeftRadius="@dimen/car_radius_3" + android:bottomLeftRadius="@*android:dimen/car_radius_3" android:topLeftRadius="0dp" - android:bottomRightRadius="@dimen/car_radius_3" + android:bottomRightRadius="@*android:dimen/car_radius_3" android:topRightRadius="0dp" /> </shape> diff --git a/packages/CarSystemUI/res/drawable/car_seekbar_thumb.xml b/packages/CarSystemUI/res/drawable/car_seekbar_thumb.xml index 1a9b8a521d78..2649a005a971 100644 --- a/packages/CarSystemUI/res/drawable/car_seekbar_thumb.xml +++ b/packages/CarSystemUI/res/drawable/car_seekbar_thumb.xml @@ -19,19 +19,19 @@ <item> <shape android:shape="oval"> <padding - android:bottom="@dimen/car_padding_1" - android:left="@dimen/car_padding_1" - android:right="@dimen/car_padding_1" - android:top="@dimen/car_padding_1"/> + android:bottom="@*android:dimen/car_padding_1" + android:left="@*android:dimen/car_padding_1" + android:right="@*android:dimen/car_padding_1" + android:top="@*android:dimen/car_padding_1"/> <solid android:color="@android:color/black"/> </shape> </item> <item> <shape android:shape="oval"> - <solid android:color="@color/car_accent"/> + <solid android:color="@*android:color/car_accent"/> <size - android:width="@dimen/car_seekbar_thumb_size" - android:height="@dimen/car_seekbar_thumb_size"/> + android:width="@*android:dimen/car_seekbar_thumb_size" + android:height="@*android:dimen/car_seekbar_thumb_size"/> </shape> </item> </layer-list> diff --git a/packages/CarSystemUI/res/layout/car_fullscreen_user_switcher.xml b/packages/CarSystemUI/res/layout/car_fullscreen_user_switcher.xml index e8c5134cd180..395eac1d2ccb 100644 --- a/packages/CarSystemUI/res/layout/car_fullscreen_user_switcher.xml +++ b/packages/CarSystemUI/res/layout/car_fullscreen_user_switcher.xml @@ -14,12 +14,12 @@ See the License for the specific language governing permissions and limitations under the License. --> -<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto" - android:fitsSystemWindows="true" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:visibility="gone"> +<FrameLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:fitsSystemWindows="true" + android:visibility="gone"> <LinearLayout android:id="@+id/container" @@ -27,20 +27,21 @@ android:layout_height="match_parent" android:orientation="vertical"> - <include layout="@layout/car_status_bar_header" - android:theme="@android:style/Theme" - android:layout_alignParentTop="true"/> + <include + layout="@layout/car_status_bar_header" + android:layout_alignParentTop="true" + android:theme="@android:style/Theme"/> - <com.android.systemui.statusbar.car.UserGridRecyclerView - android:id="@+id/user_grid" + <FrameLayout android:layout_width="match_parent" - android:layout_height="match_parent" - android:layout_marginTop="@dimen/car_user_switcher_margin_top" - android:theme="@style/PagedListTheme" - app:verticallyCenterListContent="true" - app:showPagedListViewDivider="false" - app:gutter="both" - app:itemSpacing="@dimen/car_user_switcher_vertical_spacing_between_users"/> + android:layout_height="match_parent"> + <com.android.systemui.statusbar.car.UserGridRecyclerView + android:id="@+id/user_grid" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" + android:layout_marginTop="@dimen/car_user_switcher_margin_top"/> + </FrameLayout> </LinearLayout> </FrameLayout> diff --git a/packages/CarSystemUI/res/layout/car_navigation_bar.xml b/packages/CarSystemUI/res/layout/car_navigation_bar.xml index 93d2b67dcda2..34fd70332cd0 100644 --- a/packages/CarSystemUI/res/layout/car_navigation_bar.xml +++ b/packages/CarSystemUI/res/layout/car_navigation_bar.xml @@ -137,8 +137,8 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" - android:paddingStart="@dimen/car_keyline_1" - android:paddingEnd="@dimen/car_keyline_1" + android:paddingStart="@*android:dimen/car_keyline_1" + android:paddingEnd="@*android:dimen/car_keyline_1" android:gravity="center" android:visibility="gone"> </LinearLayout> diff --git a/packages/CarSystemUI/res/layout/car_navigation_bar_unprovisioned.xml b/packages/CarSystemUI/res/layout/car_navigation_bar_unprovisioned.xml index 4fa877ff37dc..28eba6ceade1 100644 --- a/packages/CarSystemUI/res/layout/car_navigation_bar_unprovisioned.xml +++ b/packages/CarSystemUI/res/layout/car_navigation_bar_unprovisioned.xml @@ -28,12 +28,12 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" - android:paddingStart="@dimen/car_padding_5" - android:paddingEnd="@dimen/car_padding_5"> + android:paddingStart="@*android:dimen/car_padding_5" + android:paddingEnd="@*android:dimen/car_padding_5"> <com.android.systemui.statusbar.car.CarNavigationButton android:id="@+id/home" - android:layout_width="@dimen/car_touch_target_size" + android:layout_width="@*android:dimen/car_touch_target_size" android:layout_height="match_parent" android:background="?android:attr/selectableItemBackground" android:src="@drawable/car_ic_overview" diff --git a/packages/CarSystemUI/res/layout/car_qs_panel.xml b/packages/CarSystemUI/res/layout/car_qs_panel.xml index d923e0fbb20b..9c598d71bd22 100644 --- a/packages/CarSystemUI/res/layout/car_qs_panel.xml +++ b/packages/CarSystemUI/res/layout/car_qs_panel.xml @@ -28,7 +28,6 @@ <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/user_switcher_container" android:clipChildren="false" android:layout_width="match_parent" @@ -37,11 +36,7 @@ <com.android.systemui.statusbar.car.UserGridRecyclerView android:id="@+id/user_grid" android:layout_width="match_parent" - android:layout_height="match_parent" - android:theme="@style/PagedListTheme" - app:showPagedListViewDivider="false" - app:gutter="both" - app:itemSpacing="@dimen/car_user_switcher_vertical_spacing_between_users"/> + android:layout_height="match_parent"/> </RelativeLayout> diff --git a/packages/CarSystemUI/res/layout/car_top_navigation_bar.xml b/packages/CarSystemUI/res/layout/car_top_navigation_bar.xml index 2fe740d51e8f..925ccb4a162a 100644 --- a/packages/CarSystemUI/res/layout/car_top_navigation_bar.xml +++ b/packages/CarSystemUI/res/layout/car_top_navigation_bar.xml @@ -49,11 +49,11 @@ android:id="@+id/lefttext" android:layout_width="wrap_content" android:layout_height="match_parent" - android:paddingStart="@dimen/car_padding_4" + android:paddingStart="@*android:dimen/car_padding_4" android:paddingEnd="16dp" android:gravity="center_vertical|start" android:minEms="4" - android:textAppearance="@style/TextAppearance.Car.Status" + android:textAppearance="@style/TextAppearance.CarStatus" systemui:hvacAreaId="49" systemui:hvacMaxText="@string/hvac_max_text" systemui:hvacMaxValue="@dimen/hvac_max_value" @@ -96,7 +96,7 @@ android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:layout_toEndOf="@+id/clock_container" - android:paddingStart="@dimen/car_padding_1" + android:paddingStart="@*android:dimen/car_padding_1" android:gravity="center_vertical" android:orientation="horizontal" > @@ -132,10 +132,10 @@ android:layout_width="wrap_content" android:layout_height="match_parent" android:paddingStart="16dp" - android:paddingEnd="@dimen/car_padding_4" + android:paddingEnd="@*android:dimen/car_padding_4" android:gravity="center_vertical|end" android:minEms="4" - android:textAppearance="@style/TextAppearance.Car.Status" + android:textAppearance="@style/TextAppearance.CarStatus" systemui:hvacAreaId="68" systemui:hvacMaxText="@string/hvac_max_text" systemui:hvacMaxValue="@dimen/hvac_max_value" diff --git a/packages/CarSystemUI/res/layout/car_volume_dialog.xml b/packages/CarSystemUI/res/layout/car_volume_dialog.xml index 709797d41060..35551eabfaed 100644 --- a/packages/CarSystemUI/res/layout/car_volume_dialog.xml +++ b/packages/CarSystemUI/res/layout/car_volume_dialog.xml @@ -14,15 +14,9 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License --> -<androidx.car.widget.PagedListView +<androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/volume_list" android:layout_width="match_parent" android:layout_height="wrap_content" - android:minWidth="@dimen/volume_dialog_panel_width" - android:theme="@style/PagedListViewTheme" - app:gutter="none" - app:scrollBarEnabled="false" - app:listDividerColor="@color/list_divider_color" - app:showPagedListViewDivider="true"/> + android:minWidth="@dimen/volume_dialog_panel_width"/> diff --git a/packages/CarSystemUI/res/layout/car_volume_item.xml b/packages/CarSystemUI/res/layout/car_volume_item.xml new file mode 100644 index 000000000000..2275ca6329e2 --- /dev/null +++ b/packages/CarSystemUI/res/layout/car_volume_item.xml @@ -0,0 +1,71 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + 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. +--> + +<RelativeLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:minHeight="@dimen/car_volume_item_height"> + + <!-- Primary Action. --> + <ImageView + android:id="@+id/primary_icon" + android:layout_width="@dimen/car_primary_icon_size" + android:layout_centerVertical="true" + android:layout_marginStart="@dimen/car_volume_item_margin_horizontal" + android:layout_alignParentStart="true" + android:layout_height="@dimen/car_primary_icon_size"/> + + <!-- Note: the horizontal padding and offset are set to 0 so that the track and thumb + aligns with the proper keylines. --> + <SeekBar + android:id="@+id/seek_bar" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginBottom="@dimen/car_volume_item_seekbar_margin_vertical" + android:layout_marginTop="@dimen/car_volume_item_seekbar_margin_vertical" + android:min="0" + android:paddingBottom="@dimen/car_volume_item_seekbar_padding_vertical" + android:layout_centerVertical="true" + android:paddingEnd="0dp" + android:paddingStart="0dp" + android:paddingTop="@dimen/car_volume_item_seekbar_padding_vertical" + android:splitTrack="false" + android:layout_toStartOf="@id/supplemental_icon_divider" + android:layout_marginStart="@dimen/car_volume_item_seekbar_margin_start" + android:layout_marginEnd="@dimen/car_volume_item_seekbar_margin_end" + android:thumbOffset="0dp"/> + + <!-- Supplemental action. --> + <View + android:id="@+id/supplemental_icon_divider" + android:layout_width="@dimen/car_volume_item_divider_width" + android:layout_height="@dimen/car_volume_item_divider_height" + android:layout_marginEnd="@dimen/car_volume_item_divider_margin_end" + android:layout_centerVertical="true" + android:layout_toStartOf="@id/supplemental_icon" + android:background="@color/car_volume_item_divider_color"/> + <ImageView + android:id="@+id/supplemental_icon" + android:layout_width="@dimen/car_primary_icon_size" + android:layout_height="@dimen/car_primary_icon_size" + android:background="?android:attr/selectableItemBackground" + android:layout_centerVertical="true" + android:layout_alignParentEnd="true" + android:layout_marginEnd="@dimen/car_volume_item_margin_horizontal" + android:scaleType="fitCenter"/> +</RelativeLayout> diff --git a/packages/CarSystemUI/res/layout/notification_center_activity.xml b/packages/CarSystemUI/res/layout/notification_center_activity.xml index 7c833035d57c..383aba4e400a 100644 --- a/packages/CarSystemUI/res/layout/notification_center_activity.xml +++ b/packages/CarSystemUI/res/layout/notification_center_activity.xml @@ -32,19 +32,14 @@ android:translationZ="2dp" /> - <androidx.car.widget.PagedListView + <androidx.recyclerview.widget.RecyclerView android:id="@+id/notifications" android:layout_width="0dp" android:layout_height="0dp" android:orientation="vertical" - android:theme="@style/PagedListTheme" - app:gutter="none" - app:itemSpacing="@dimen/item_spacing" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" - app:layout_constraintEnd_toEndOf="parent" - app:scrollBarEnabled="false" - app:showPagedListViewDivider="false"/> + app:layout_constraintEnd_toEndOf="parent"/> </com.android.car.notification.CarNotificationView> diff --git a/packages/CarSystemUI/res/values/colors.xml b/packages/CarSystemUI/res/values/colors.xml index 7b4e32b407ae..83ec3514c01a 100644 --- a/packages/CarSystemUI/res/values/colors.xml +++ b/packages/CarSystemUI/res/values/colors.xml @@ -45,4 +45,6 @@ <color name="keyguard_button_text_color">@android:color/black</color> <color name="list_divider_color">@*android:color/car_list_divider_light</color> + <color name="car_volume_item_divider_color">@*android:color/car_list_divider</color> + <color name="car_volume_item_background_color">@*android:color/car_card_dark</color> </resources> diff --git a/packages/CarSystemUI/res/values/colors_car.xml b/packages/CarSystemUI/res/values/colors_car.xml index 08e16cdbe3b3..69ab3f3cf957 100644 --- a/packages/CarSystemUI/res/values/colors_car.xml +++ b/packages/CarSystemUI/res/values/colors_car.xml @@ -18,12 +18,12 @@ --> <resources> <color name="car_qs_background_primary">#263238</color> <!-- Blue Gray 900 --> - <color name="car_qs_footer_user_name_color">@color/car_grey_50</color> + <color name="car_qs_footer_user_name_color">@*android:color/car_grey_50</color> <!-- colors for user switcher --> - <color name="car_user_switcher_background_color">@color/car_card_dark</color> - <color name="car_user_switcher_name_text_color">@color/car_body1_light</color> - <color name="car_user_switcher_add_user_background_color">@color/car_dark_blue_grey_600</color> - <color name="car_user_switcher_add_user_add_sign_color">@color/car_body1_light</color> + <color name="car_user_switcher_background_color">@*android:color/car_card_dark</color> + <color name="car_user_switcher_name_text_color">@*android:color/car_body1_light</color> + <color name="car_user_switcher_add_user_background_color">@*android:color/car_dark_blue_grey_600</color> + <color name="car_user_switcher_add_user_add_sign_color">@*android:color/car_body1_light</color> </resources> diff --git a/packages/CarSystemUI/res/values/dimens.xml b/packages/CarSystemUI/res/values/dimens.xml index 07ecca201c12..8789c8a924b3 100644 --- a/packages/CarSystemUI/res/values/dimens.xml +++ b/packages/CarSystemUI/res/values/dimens.xml @@ -26,7 +26,7 @@ <!-- The amount by which to scale up the status bar icons. --> <item name="status_bar_icon_scale_factor" format="float" type="dimen">1.75</item> - <dimen name="car_primary_icon_size">36dp</dimen> + <dimen name="car_primary_icon_size">@*android:dimen/car_primary_icon_size</dimen> <!-- dimensions for the car user switcher --> <dimen name="car_user_switcher_name_text_size">@dimen/car_body1_size</dimen> @@ -49,7 +49,7 @@ <dimen name="volume_dialog_elevation">6dp</dimen> - <dimen name="volume_dialog_row_margin_end">@dimen/car_keyline_3</dimen> + <dimen name="volume_dialog_row_margin_end">@*android:dimen/car_keyline_3</dimen> <dimen name="volume_dialog_row_padding_end">0dp</dimen> @@ -59,4 +59,33 @@ <dimen name="car_keyline_1">24dp</dimen> <dimen name="car_keyline_2">96dp</dimen> <dimen name="car_keyline_3">128dp</dimen> + + <dimen name="privacy_chip_icon_max_height">100dp</dimen> + + <!-- Height of icons in Ongoing App Ops dialog. Both App Op icon and application icon --> + <dimen name="ongoing_appops_dialog_icon_height">48dp</dimen> + <!-- Margin between text lines in Ongoing App Ops dialog --> + <dimen name="ongoing_appops_dialog_text_margin">15dp</dimen> + <!-- Padding around Ongoing App Ops dialog content --> + <dimen name="ongoing_appops_dialog_content_padding">24dp</dimen> + <!-- Margins around the Ongoing App Ops chip. In landscape, the side margins are 0 --> + <dimen name="ongoing_appops_chip_margin">12dp</dimen> + <!-- Start and End padding for Ongoing App Ops chip --> + <dimen name="ongoing_appops_chip_side_padding">6dp</dimen> + <!-- Padding between background of Ongoing App Ops chip and content --> + <dimen name="ongoing_appops_chip_bg_padding">4dp</dimen> + <!-- Radius of Ongoing App Ops chip corners --> + <dimen name="ongoing_appops_chip_bg_corner_radius">12dp</dimen> + + <!-- Car volume dimens. --> + <dimen name="car_volume_item_height">@*android:dimen/car_single_line_list_item_height</dimen> + <dimen name="car_volume_item_margin_horizontal">@*android:dimen/car_keyline_1</dimen> + <dimen name="car_volume_item_seekbar_margin_vertical">@*android:dimen/car_padding_1</dimen> + <dimen name="car_volume_item_seekbar_margin_start">@*android:dimen/car_keyline_3</dimen> + <dimen name="car_volume_item_seekbar_margin_end">@*android:dimen/car_padding_4</dimen> + <dimen name="car_volume_item_seekbar_padding_vertical">@*android:dimen/car_seekbar_padding</dimen> + <dimen name="car_volume_item_divider_height">60dp</dimen> + <dimen name="car_volume_item_divider_width">1dp</dimen> + <dimen name="car_volume_item_divider_margin_end">@*android:dimen/car_padding_4</dimen> + <dimen name="car_volume_item_corner_radius">@*android:dimen/car_radius_3</dimen> </resources> diff --git a/packages/CarSystemUI/res/values/dimens_car.xml b/packages/CarSystemUI/res/values/dimens_car.xml index c027f81eb8bd..42a764959545 100644 --- a/packages/CarSystemUI/res/values/dimens_car.xml +++ b/packages/CarSystemUI/res/values/dimens_car.xml @@ -17,11 +17,11 @@ --> <resources> <!-- dimensions for the car user switcher --> - <dimen name="car_user_switcher_name_text_size">@dimen/car_body1_size</dimen> - <dimen name="car_user_switcher_image_avatar_size">@dimen/car_large_avatar_size</dimen> - <dimen name="car_user_switcher_vertical_spacing_between_users">@dimen/car_padding_5</dimen> - <dimen name="car_user_switcher_vertical_spacing_between_name_and_avatar">@dimen/car_padding_4</dimen> - <dimen name="car_user_switcher_margin_top">@dimen/car_padding_4</dimen> + <dimen name="car_user_switcher_name_text_size">@*android:dimen/car_body1_size</dimen> + <dimen name="car_user_switcher_image_avatar_size">@*android:dimen/car_large_avatar_size</dimen> + <dimen name="car_user_switcher_vertical_spacing_between_users">@*android:dimen/car_padding_5</dimen> + <dimen name="car_user_switcher_vertical_spacing_between_name_and_avatar">@*android:dimen/car_padding_4</dimen> + <dimen name="car_user_switcher_margin_top">@*android:dimen/car_padding_4</dimen> <dimen name="car_navigation_button_width">64dp</dimen> <dimen name="car_navigation_bar_width">760dp</dimen> @@ -37,7 +37,7 @@ <dimen name="car_qs_footer_icon_height">56dp</dimen> <dimen name="car_qs_footer_user_switch_icon_margin">5dp</dimen> <dimen name="car_qs_footer_user_switch_icon_width">36dp</dimen> - <dimen name="car_qs_footer_user_name_text_size">@dimen/car_body2_size</dimen> + <dimen name="car_qs_footer_user_name_text_size">@*android:dimen/car_body2_size</dimen> <dimen name="car_user_switcher_container_height">420dp</dimen> <!-- This must be the negative of car_user_switcher_container_height for the animation. --> diff --git a/packages/CarSystemUI/res/values/styles.xml b/packages/CarSystemUI/res/values/styles.xml index 0d95d308f48b..371bebdebc86 100644 --- a/packages/CarSystemUI/res/values/styles.xml +++ b/packages/CarSystemUI/res/values/styles.xml @@ -29,12 +29,12 @@ parent="@*android:style/TextAppearance.StatusBar.Icon"> <item name="android:textSize">42sp</item> <item name="android:fontFamily">sans-serif-regular</item> - <item name="android:textColor">@color/car_grey_50</item> + <item name="android:textColor">@*android:color/car_grey_50</item> </style> - <style name="TextAppearance.Car.Status"> - <item name="android:textSize">@dimen/car_body2_size</item> - <item name="android:textColor">@color/car_grey_50</item> + <style name="TextAppearance.CarStatus" parent="@android:style/TextAppearance.DeviceDefault"> + <item name="android:textSize">@*android:dimen/car_body2_size</item> + <item name="android:textColor">@*android:color/car_grey_50</item> </style> <style name="CarNavigationBarButtonTheme"> @@ -46,11 +46,4 @@ <item name="android:layout_width">96dp</item> <item name="android:background">@drawable/nav_button_background</item> </style> - - <style name="PagedListViewTheme" parent="@style/Theme.CarSupportWrapper.NoActionBar"> - <item name="android:background">@*android:color/car_background</item> - <item name="listItemBackgroundColor">@*android:color/car_background</item> - <item name="dividerEndMargin">@dimen/car_keyline_1</item> - <item name="dividerStartMargin">@dimen/car_keyline_1</item> - </style> </resources>
\ No newline at end of file diff --git a/packages/CarSystemUI/res/values/themes.xml b/packages/CarSystemUI/res/values/themes.xml index 8d1a4d7c08c4..f82be3c0e529 100644 --- a/packages/CarSystemUI/res/values/themes.xml +++ b/packages/CarSystemUI/res/values/themes.xml @@ -18,10 +18,6 @@ --> <resources> - <!--This Theme contains attributes required for components from the car support lib --> - <style name="PagedListTheme" parent="Theme.CarSupportWrapper.NoActionBar"> - </style> - <style name="Theme.Notification" parent="Theme.DeviceDefault.NoActionBar.Notification"> </style> </resources> diff --git a/packages/CarSystemUI/src/com/android/systemui/notifications/NotificationsUI.java b/packages/CarSystemUI/src/com/android/systemui/notifications/NotificationsUI.java index 4a2d2fbc30cf..48cb55b3d90e 100644 --- a/packages/CarSystemUI/src/com/android/systemui/notifications/NotificationsUI.java +++ b/packages/CarSystemUI/src/com/android/systemui/notifications/NotificationsUI.java @@ -16,11 +16,11 @@ package com.android.systemui.notifications; -import android.app.ActivityManager; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.annotation.SuppressLint; +import android.app.ActivityManager; import android.car.Car; import android.car.CarNotConnectedException; import android.car.drivingstate.CarUxRestrictionsManager; @@ -113,7 +113,7 @@ public class NotificationsUI extends SystemUI ServiceManager.getService(Context.STATUS_BAR_SERVICE)), launchResult -> { if (launchResult == ActivityManager.START_TASK_TO_FRONT - || launchResult == ActivityManager.START_SUCCESS){ + || launchResult == ActivityManager.START_SUCCESS) { closeCarNotifications(DEFAULT_FLING_VELOCITY); } }); @@ -179,8 +179,7 @@ public class NotificationsUI extends SystemUI } }); - RecyclerView notificationList = mCarNotificationWindow - .findViewById(com.android.car.notification.R.id.recycler_view); + RecyclerView notificationList = mCarNotificationWindow.findViewById(R.id.notifications); // register a scroll listener so we can figure out if we are at the bottom of the // list of notifications notificationList.addOnScrollListener(new RecyclerView.OnScrollListener() { @@ -202,7 +201,7 @@ public class NotificationsUI extends SystemUI // There's a view installed at a higher z-order such that we can intercept the ACTION_DOWN // to set the initial click state. mCarNotificationWindow.findViewById(R.id.glass_pane).setOnTouchListener((v, event) -> { - if (event.getActionMasked() == MotionEvent.ACTION_UP ) { + if (event.getActionMasked() == MotionEvent.ACTION_UP) { mNotificationListAtBottomAtTimeOfTouch = false; } if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { @@ -259,7 +258,7 @@ public class NotificationsUI extends SystemUI public boolean onTouch(View v, MotionEvent event) { // reset mNotificationListAtBottomAtTimeOfTouch here since the "glass pane" will not // get the up event - if (event.getActionMasked() == MotionEvent.ACTION_UP ) { + if (event.getActionMasked() == MotionEvent.ACTION_UP) { mNotificationListAtBottomAtTimeOfTouch = false; } boolean wasScrolledUp = mScrollUpDetector.onTouchEvent(event); @@ -351,7 +350,7 @@ public class NotificationsUI extends SystemUI public boolean onFling(MotionEvent event1, MotionEvent event2, float velocityX, float velocityY) { if (Math.abs(event1.getX() - event2.getX()) > SWIPE_MAX_OFF_PATH - || Math.abs(velocityY) < SWIPE_THRESHOLD_VELOCITY){ + || Math.abs(velocityY) < SWIPE_THRESHOLD_VELOCITY) { // swipe was not vertical or was not fast enough return false; } @@ -435,8 +434,7 @@ public class NotificationsUI extends SystemUI mNotificationViewController.disable(); mIsShowing = false; mIsTracking = false; - RecyclerView notificationListView = mCarNotificationWindow.findViewById( - com.android.car.notification.R.id.recycler_view); + RecyclerView notificationListView = mCarNotificationWindow.findViewById(R.id.notifications); notificationListView.scrollToPosition(0); } diff --git a/packages/CarSystemUI/src/com/android/systemui/qs/car/CarQSFragment.java b/packages/CarSystemUI/src/com/android/systemui/qs/car/CarQSFragment.java index 41c37d3bbc19..769fc52a574c 100644 --- a/packages/CarSystemUI/src/com/android/systemui/qs/car/CarQSFragment.java +++ b/packages/CarSystemUI/src/com/android/systemui/qs/car/CarQSFragment.java @@ -79,7 +79,7 @@ public class CarQSFragment extends Fragment implements QS { mUserGridView = mUserSwitcherContainer.findViewById(R.id.user_grid); GridLayoutManager layoutManager = new GridLayoutManager(context, context.getResources().getInteger(R.integer.user_fullscreen_switcher_num_col)); - mUserGridView.getRecyclerView().setLayoutManager(layoutManager); + mUserGridView.setLayoutManager(layoutManager); mUserGridView.buildAdapter(); mUserSwitchCallback = new UserSwitchCallback(); diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java index 23fe5944573e..f896cf1bf10c 100644 --- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java +++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java @@ -45,7 +45,7 @@ public class FullscreenUserSwitcher { mUserGridView = container.findViewById(R.id.user_grid); GridLayoutManager layoutManager = new GridLayoutManager(context, context.getResources().getInteger(R.integer.user_fullscreen_switcher_num_col)); - mUserGridView.getRecyclerView().setLayoutManager(layoutManager); + mUserGridView.setLayoutManager(layoutManager); mUserGridView.buildAdapter(); mUserGridView.setUserSelectionListener(this::onUserSelected); diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java index fb2b57b6d490..827a59eddf56 100644 --- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java +++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java @@ -28,6 +28,7 @@ import android.content.DialogInterface; import android.content.pm.UserInfo; import android.content.res.Resources; import android.graphics.Bitmap; +import android.graphics.Rect; import android.os.AsyncTask; import android.util.AttributeSet; import android.view.LayoutInflater; @@ -36,9 +37,9 @@ import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; -import androidx.car.widget.PagedListView; import androidx.core.graphics.drawable.RoundedBitmapDrawable; import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory; +import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.android.internal.util.UserIcons; @@ -52,7 +53,7 @@ import java.util.List; * Displays a GridLayout with icons for the users in the system to allow switching between users. * One of the uses of this is for the lock screen in auto. */ -public class UserGridRecyclerView extends PagedListView implements +public class UserGridRecyclerView extends RecyclerView implements CarUserManagerHelper.OnUsersUpdateListener { private UserSelectionListener mUserSelectionListener; private UserAdapter mAdapter; @@ -63,6 +64,9 @@ public class UserGridRecyclerView extends PagedListView implements super(context, attrs); mContext = context; mCarUserManagerHelper = new CarUserManagerHelper(mContext); + + addItemDecoration(new ItemSpacingDecoration(context.getResources().getDimensionPixelSize( + R.dimen.car_user_switcher_vertical_spacing_between_users))); } /** @@ -253,7 +257,8 @@ public class UserGridRecyclerView extends PagedListView implements } private void showMaxUserLimitReachedDialog() { - AlertDialog maxUsersDialog = new Builder(mContext, R.style.Theme_Car_Dark_Dialog_Alert) + AlertDialog maxUsersDialog = new Builder(mContext, + com.android.internal.R.style.Theme_DeviceDefault_Dialog_Alert) .setTitle(R.string.user_limit_reached_title) .setMessage(getResources().getQuantityString( R.plurals.user_limit_reached_message, @@ -272,7 +277,8 @@ public class UserGridRecyclerView extends PagedListView implements .concat(System.getProperty("line.separator")) .concat(mRes.getString(R.string.user_add_user_message_update)); - AlertDialog addUserDialog = new Builder(mContext, R.style.Theme_Car_Dark_Dialog_Alert) + AlertDialog addUserDialog = new Builder(mContext, + com.android.internal.R.style.Theme_DeviceDefault_Dialog_Alert) .setTitle(R.string.user_add_user_title) .setMessage(message) .setNegativeButton(android.R.string.cancel, this) @@ -391,4 +397,31 @@ public class UserGridRecyclerView extends PagedListView implements void onUserSelected(UserRecord record); } + + /** + * A {@link RecyclerView.ItemDecoration} that will add spacing between each item in the + * RecyclerView that it is added to. + */ + private static class ItemSpacingDecoration extends RecyclerView.ItemDecoration { + private int mItemSpacing; + + private ItemSpacingDecoration(int itemSpacing) { + mItemSpacing = itemSpacing; + } + + @Override + public void getItemOffsets(Rect outRect, View view, RecyclerView parent, + RecyclerView.State state) { + super.getItemOffsets(outRect, view, parent, state); + int position = parent.getChildAdapterPosition(view); + + // Skip offset for last item except for GridLayoutManager. + if (position == state.getItemCount() - 1 + && !(parent.getLayoutManager() instanceof GridLayoutManager)) { + return; + } + + outRect.bottom = mItemSpacing; + } + } } diff --git a/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java b/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java index 10a0ae5a924c..512210be0a46 100644 --- a/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java +++ b/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java @@ -32,9 +32,7 @@ import android.content.DialogInterface; import android.content.ServiceConnection; import android.content.res.TypedArray; import android.content.res.XmlResourceParser; -import android.graphics.Color; import android.graphics.PixelFormat; -import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.media.AudioManager; import android.os.Debug; @@ -46,7 +44,6 @@ import android.util.AttributeSet; import android.util.Log; import android.util.SparseArray; import android.util.Xml; -import android.view.ContextThemeWrapper; import android.view.Gravity; import android.view.MotionEvent; import android.view.View; @@ -56,12 +53,8 @@ import android.view.WindowManager; import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; -import androidx.car.widget.ListItem; -import androidx.car.widget.ListItemAdapter; -import androidx.car.widget.ListItemAdapter.BackgroundStyle; -import androidx.car.widget.ListItemProvider.ListProvider; -import androidx.car.widget.PagedListView; -import androidx.car.widget.SeekbarListItem; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; import com.android.systemui.R; import com.android.systemui.plugins.VolumeDialog; @@ -96,13 +89,13 @@ public class CarVolumeDialogImpl implements VolumeDialog { private final SparseArray<VolumeItem> mVolumeItems = new SparseArray<>(); // Available volume items in car audio manager. private final List<VolumeItem> mAvailableVolumeItems = new ArrayList<>(); - // Volume items in the PagedListView. - private final List<ListItem> mVolumeLineItems = new ArrayList<>(); + // Volume items in the RecyclerView. + private final List<CarVolumeItem> mCarVolumeLineItems = new ArrayList<>(); private final KeyguardManager mKeyguard; private Window mWindow; private CustomDialog mDialog; - private PagedListView mListView; - private ListItemAdapter mPagedListAdapter; + private RecyclerView mListView; + private CarVolumeItemAdapter mVolumeItemsAdapter; private Car mCar; private CarAudioManager mCarAudioManager; private final CarAudioManager.CarVolumeCallback mVolumeChangeCallback = @@ -126,7 +119,7 @@ public class CarVolumeDialogImpl implements VolumeDialog { // callback. Updating the seekbar at the same time could block the continuous // seeking. if (value != volumeItem.progress) { - volumeItem.listItem.setProgress(value); + volumeItem.carVolumeItem.setProgress(value); volumeItem.progress = value; } if ((flags & AudioManager.FLAG_SHOW_UI) != 0) { @@ -160,13 +153,13 @@ public class CarVolumeDialogImpl implements VolumeDialog { // The first one is the default item. if (groupId == 0) { mDefaultVolumeItem = volumeItem; - setupDefaultListItem(); + setupDefaultCarVolumeItem(); } } // If list is already initiated, update its content. - if (mPagedListAdapter != null) { - mPagedListAdapter.notifyDataSetChanged(); + if (mVolumeItemsAdapter != null) { + mVolumeItemsAdapter.notifyDataSetChanged(); } mCarAudioManager.registerCarVolumeCallback(mVolumeChangeCallback); } catch (CarNotConnectedException e) { @@ -184,15 +177,15 @@ public class CarVolumeDialogImpl implements VolumeDialog { } }; - private void setupDefaultListItem() { + private void setupDefaultCarVolumeItem() { mDefaultVolumeItem.defaultItem = true; - addSeekbarListItem(mDefaultVolumeItem, /* volumeGroupId = */0, + addCarVolumeListItem(mDefaultVolumeItem, /* volumeGroupId = */0, R.drawable.car_ic_keyboard_arrow_down, new ExpandIconListener() ); } public CarVolumeDialogImpl(Context context) { - mContext = new ContextThemeWrapper(context, com.android.systemui.R.style.qs_theme); + mContext = context; mKeyguard = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE); mCar = Car.createCar(mContext, mServiceConnection); } @@ -238,7 +231,7 @@ public class CarVolumeDialogImpl implements VolumeDialog { private void initDialog() { loadAudioUsageItems(); - mVolumeLineItems.clear(); + mCarVolumeLineItems.clear(); mDialog = new CustomDialog(mContext); mHovering = false; @@ -246,7 +239,6 @@ public class CarVolumeDialogImpl implements VolumeDialog { mExpanded = false; mWindow = mDialog.getWindow(); mWindow.requestFeature(Window.FEATURE_NO_TITLE); - mWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); mWindow.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR); mWindow.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE @@ -263,10 +255,11 @@ public class CarVolumeDialogImpl implements VolumeDialog { lp.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL; lp.windowAnimations = -1; mWindow.setAttributes(lp); - mWindow.setLayout(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); - mDialog.setCanceledOnTouchOutside(true); mDialog.setContentView(R.layout.car_volume_dialog); + mWindow.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); + + mDialog.setCanceledOnTouchOutside(true); mDialog.setOnShowListener(dialog -> { mListView.setTranslationY(-mListView.getHeight()); mListView.setAlpha(0); @@ -277,7 +270,7 @@ public class CarVolumeDialogImpl implements VolumeDialog { .setInterpolator(new SystemUIInterpolators.LogDecelerateInterpolator()) .start(); }); - mListView = (PagedListView) mWindow.findViewById(R.id.volume_list); + mListView = mWindow.findViewById(R.id.volume_list); mListView.setOnHoverListener((v, event) -> { int action = event.getActionMasked(); mHovering = (action == MotionEvent.ACTION_HOVER_ENTER) @@ -286,10 +279,9 @@ public class CarVolumeDialogImpl implements VolumeDialog { return true; }); - mPagedListAdapter = new ListItemAdapter(mContext, new ListProvider(mVolumeLineItems), - BackgroundStyle.PANEL); - mListView.setAdapter(mPagedListAdapter); - mListView.setMaxPages(PagedListView.UNLIMITED_PAGES); + mVolumeItemsAdapter = new CarVolumeItemAdapter(mContext, mCarVolumeLineItems); + mListView.setAdapter(mVolumeItemsAdapter); + mListView.setLayoutManager(new LinearLayoutManager(mContext)); } @@ -302,13 +294,13 @@ public class CarVolumeDialogImpl implements VolumeDialog { mHandler.removeMessages(H.DISMISS); rescheduleTimeoutH(); // Refresh the data set before showing. - mPagedListAdapter.notifyDataSetChanged(); + mVolumeItemsAdapter.notifyDataSetChanged(); if (mShowing) { return; } mShowing = true; - if (mVolumeLineItems.isEmpty()) { - setupDefaultListItem(); + if (mCarVolumeLineItems.isEmpty()) { + setupDefaultCarVolumeItem(); } mDialog.show(); Events.writeEvent(mContext, Events.EVENT_SHOW_DIALOG, reason, mKeyguard.isKeyguardLocked()); @@ -421,40 +413,41 @@ public class CarVolumeDialogImpl implements VolumeDialog { return result; } - private SeekbarListItem addSeekbarListItem(VolumeItem volumeItem, - int volumeGroupId, + private CarVolumeItem addCarVolumeListItem(VolumeItem volumeItem, int volumeGroupId, int supplementalIconId, @Nullable View.OnClickListener supplementalIconOnClickListener) { - SeekbarListItem listItem = new SeekbarListItem(mContext); - listItem.setMax(getMaxSeekbarValue(mCarAudioManager, volumeGroupId)); + CarVolumeItem carVolumeItem = new CarVolumeItem(); + carVolumeItem.setMax(getMaxSeekbarValue(mCarAudioManager, volumeGroupId)); int color = mContext.getResources().getColor(R.color.car_volume_dialog_tint); int progress = getSeekbarValue(mCarAudioManager, volumeGroupId); - listItem.setProgress(progress); - listItem.setOnSeekBarChangeListener(new CarVolumeDialogImpl - .VolumeSeekBarChangeListener(volumeGroupId, mCarAudioManager)); + carVolumeItem.setProgress(progress); + carVolumeItem.setOnSeekBarChangeListener( + new CarVolumeDialogImpl.VolumeSeekBarChangeListener(volumeGroupId, + mCarAudioManager)); Drawable primaryIcon = mContext.getResources().getDrawable(volumeItem.icon); primaryIcon.mutate().setTint(color); - listItem.setPrimaryActionIcon(primaryIcon); + carVolumeItem.setPrimaryIcon(primaryIcon); if (supplementalIconId != 0) { Drawable supplementalIcon = mContext.getResources().getDrawable(supplementalIconId); supplementalIcon.mutate().setTint(color); - listItem.setSupplementalIcon(supplementalIcon, true); - listItem.setSupplementalIconListener(supplementalIconOnClickListener); + carVolumeItem.setSupplementalIcon(supplementalIcon, + /* showSupplementalIconDivider= */ true); + carVolumeItem.setSupplementalIconListener(supplementalIconOnClickListener); } else { - listItem.setSupplementalEmptyIcon(true); - listItem.setSupplementalIconListener(null); + carVolumeItem.setSupplementalIcon(/* drawable= */ null, + /* showSupplementalIconDivider= */ false); } - mVolumeLineItems.add(listItem); - volumeItem.listItem = listItem; + mCarVolumeLineItems.add(carVolumeItem); + volumeItem.carVolumeItem = carVolumeItem; volumeItem.progress = progress; - return listItem; + return carVolumeItem; } - private VolumeItem findVolumeItem(SeekbarListItem targetItem) { + private VolumeItem findVolumeItem(CarVolumeItem targetItem) { for (int i = 0; i < mVolumeItems.size(); ++i) { VolumeItem volumeItem = mVolumeItems.valueAt(i); - if (volumeItem.listItem == targetItem) { + if (volumeItem.carVolumeItem == targetItem) { return volumeItem; } } @@ -463,7 +456,7 @@ public class CarVolumeDialogImpl implements VolumeDialog { private void cleanupAudioManager() { mCarAudioManager.unregisterCarVolumeCallback(mVolumeChangeCallback); - mVolumeLineItems.clear(); + mCarVolumeLineItems.clear(); mCarAudioManager = null; } @@ -474,8 +467,9 @@ public class CarVolumeDialogImpl implements VolumeDialog { private int rank; private boolean defaultItem = false; - private @DrawableRes int icon; - private SeekbarListItem listItem; + @DrawableRes + private int icon; + private CarVolumeItem carVolumeItem; private int progress; } @@ -554,9 +548,9 @@ public class CarVolumeDialogImpl implements VolumeDialog { // Adding the items which are not coming from the default item. VolumeItem volumeItem = mAvailableVolumeItems.get(groupId); if (volumeItem.defaultItem) { - updateDefaultVolumeItem(volumeItem.listItem); + updateDefaultVolumeItem(volumeItem.carVolumeItem); } else { - addSeekbarListItem(volumeItem, groupId, 0, null); + addCarVolumeListItem(volumeItem, groupId, 0, null); } } inAnimator = AnimatorInflater.loadAnimator( @@ -564,14 +558,14 @@ public class CarVolumeDialogImpl implements VolumeDialog { } else { // Only keeping the default stream if it is not expended. - Iterator itr = mVolumeLineItems.iterator(); + Iterator itr = mCarVolumeLineItems.iterator(); while (itr.hasNext()) { - SeekbarListItem seekbarListItem = (SeekbarListItem) itr.next(); - VolumeItem volumeItem = findVolumeItem(seekbarListItem); + CarVolumeItem carVolumeItem = (CarVolumeItem) itr.next(); + VolumeItem volumeItem = findVolumeItem(carVolumeItem); if (!volumeItem.defaultItem) { itr.remove(); } else { - updateDefaultVolumeItem(seekbarListItem); + updateDefaultVolumeItem(carVolumeItem); } } inAnimator = AnimatorInflater.loadAnimator( @@ -590,22 +584,22 @@ public class CarVolumeDialogImpl implements VolumeDialog { } animators.setTarget(mExpandIcon); animators.start(); - mPagedListAdapter.notifyDataSetChanged(); + mVolumeItemsAdapter.notifyDataSetChanged(); } - private void updateDefaultVolumeItem(SeekbarListItem seekbarListItem){ - VolumeItem volumeItem = findVolumeItem(seekbarListItem); + private void updateDefaultVolumeItem(CarVolumeItem carVolumeItem) { + VolumeItem volumeItem = findVolumeItem(carVolumeItem); // When volume dialog is expanded or collapsed the default list item is never // reset. Whereas all other list items are removed when the dialog is collapsed and then - // added when the dialog is expanded using {@link CarVolumeDialogImpl#addSeekbarListItem}. + // added when the dialog is expanded using {@link CarVolumeDialogImpl#addCarVolumeListItem}. // This sets the progressbar and the tint color of icons for all items other than default // if they were changed. For default list item it should be done manually here. int color = mContext.getResources().getColor(R.color.car_volume_dialog_tint); Drawable primaryIcon = mContext.getResources().getDrawable(volumeItem.icon); primaryIcon.mutate().setTint(color); - volumeItem.listItem.setPrimaryActionIcon(primaryIcon); - volumeItem.listItem.setProgress(volumeItem.progress); + volumeItem.carVolumeItem.setPrimaryIcon(primaryIcon); + volumeItem.carVolumeItem.setProgress(volumeItem.progress); } private final class VolumeSeekBarChangeListener implements OnSeekBarChangeListener { @@ -646,4 +640,4 @@ public class CarVolumeDialogImpl implements VolumeDialog { public void onStopTrackingTouch(SeekBar seekBar) { } } -}
\ No newline at end of file +} diff --git a/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeItem.java b/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeItem.java new file mode 100644 index 000000000000..9613de1bfaaa --- /dev/null +++ b/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeItem.java @@ -0,0 +1,135 @@ +/* + * 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 com.android.systemui.volume; + +import android.graphics.drawable.Drawable; +import android.view.View; +import android.widget.ImageView; +import android.widget.SeekBar; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import com.android.systemui.R; + +/** Holds all related data to represent a volume group. */ +public class CarVolumeItem { + + private boolean mIsDirty; + + private Drawable mPrimaryIcon; + private Drawable mSupplementalIcon; + private View.OnClickListener mSupplementalIconOnClickListener; + private boolean mShowSupplementalIconDivider; + + private int mMax; + private int mProgress; + private SeekBar.OnSeekBarChangeListener mOnSeekBarChangeListener; + + public CarVolumeItem() { + mIsDirty = true; + } + + /** + * Called when {@link CarVolumeItem} is bound to its ViewHolder. + */ + void bind(CarVolumeItemViewHolder viewHolder) { + if (mIsDirty) { + viewHolder.bind(/* carVolumeItem= */ this); + mIsDirty = false; + } + } + + /** Sets progress of seekbar. */ + public void setProgress(int progress) { + mProgress = progress; + mIsDirty = true; + } + + /** Sets max value of seekbar. */ + public void setMax(int max) { + mMax = max; + mIsDirty = true; + } + + /** Sets {@link SeekBar.OnSeekBarChangeListener}. */ + public void setOnSeekBarChangeListener(SeekBar.OnSeekBarChangeListener listener) { + mOnSeekBarChangeListener = listener; + mIsDirty = true; + } + + /** Sets the primary icon. */ + public void setPrimaryIcon(Drawable drawable) { + mPrimaryIcon = drawable; + mIsDirty = true; + } + + /** Sets the supplemental icon and the visibility of the supplemental icon divider. */ + public void setSupplementalIcon(Drawable drawable, boolean showSupplementalIconDivider) { + mSupplementalIcon = drawable; + mShowSupplementalIconDivider = showSupplementalIconDivider; + mIsDirty = true; + } + + /** Sets {@code OnClickListener} for the supplemental icon. */ + public void setSupplementalIconListener(View.OnClickListener listener) { + mSupplementalIconOnClickListener = listener; + mIsDirty = true; + } + + /** Defines the view holder which shows the information held by {@link CarVolumeItem}. */ + public static class CarVolumeItemViewHolder extends RecyclerView.ViewHolder { + + private SeekBar mSeekBar; + private ImageView mPrimaryIcon; + private View mSupplementalIconDivider; + private ImageView mSupplementalIcon; + + public CarVolumeItemViewHolder(@NonNull View itemView) { + super(itemView); + + mSeekBar = itemView.findViewById(R.id.seek_bar); + mPrimaryIcon = itemView.findViewById(R.id.primary_icon); + mSupplementalIcon = itemView.findViewById(R.id.supplemental_icon); + mSupplementalIconDivider = itemView.findViewById(R.id.supplemental_icon_divider); + } + + /** + * Binds {@link CarVolumeItem} to the {@link CarVolumeItemViewHolder}. + */ + void bind(CarVolumeItem carVolumeItem) { + // Progress bar + mSeekBar.setMax(carVolumeItem.mMax); + mSeekBar.setProgress(carVolumeItem.mProgress); + mSeekBar.setOnSeekBarChangeListener(carVolumeItem.mOnSeekBarChangeListener); + + // Primary icon + mPrimaryIcon.setVisibility(View.VISIBLE); + mPrimaryIcon.setImageDrawable(carVolumeItem.mPrimaryIcon); + + // Supplemental icon + mSupplementalIcon.setVisibility(View.VISIBLE); + mSupplementalIconDivider.setVisibility( + carVolumeItem.mShowSupplementalIconDivider ? View.VISIBLE : View.INVISIBLE); + mSupplementalIcon.setImageDrawable(carVolumeItem.mSupplementalIcon); + mSupplementalIcon.setOnClickListener( + carVolumeItem.mSupplementalIconOnClickListener); + mSupplementalIcon.setClickable( + carVolumeItem.mSupplementalIconOnClickListener != null); + } + } +} diff --git a/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeItemAdapter.java b/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeItemAdapter.java new file mode 100644 index 000000000000..5c1f8170afc4 --- /dev/null +++ b/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeItemAdapter.java @@ -0,0 +1,59 @@ +/* + * 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 com.android.systemui.volume; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.recyclerview.widget.RecyclerView; + +import com.android.systemui.R; + +import java.util.List; + +/** The {@link RecyclerView.Adapter} to show the volume items in the sysUI volume dialog. */ +public class CarVolumeItemAdapter extends + RecyclerView.Adapter<CarVolumeItem.CarVolumeItemViewHolder> { + + private final Context mContext; + private final List<CarVolumeItem> mItems; + + public CarVolumeItemAdapter(Context context, List<CarVolumeItem> items) { + mContext = context; + mItems = items; + } + + @Override + public CarVolumeItem.CarVolumeItemViewHolder onCreateViewHolder(ViewGroup parent, + int viewType) { + LayoutInflater inflater = LayoutInflater.from(mContext); + View view = inflater.inflate(R.layout.car_volume_item, parent, false); + return new CarVolumeItem.CarVolumeItemViewHolder(view); + } + + @Override + public void onBindViewHolder(CarVolumeItem.CarVolumeItemViewHolder holder, int position) { + mItems.get(position).bind(holder); + } + + @Override + public int getItemCount() { + return mItems.size(); + } +} diff --git a/packages/DynamicAndroidInstallationService/Android.mk b/packages/DynamicSystemInstallationService/Android.mk index 13d96ac3906e..16aca1bd07c5 100644 --- a/packages/DynamicAndroidInstallationService/Android.mk +++ b/packages/DynamicSystemInstallationService/Android.mk @@ -8,7 +8,7 @@ LOCAL_RESOURCE_DIR := $(addprefix $(LOCAL_PATH)/, res) LOCAL_USE_AAPT2 := true -LOCAL_PACKAGE_NAME := DynamicAndroidInstallationService +LOCAL_PACKAGE_NAME := DynamicSystemInstallationService LOCAL_CERTIFICATE := platform LOCAL_PRIVILEGED_MODULE := true LOCAL_PRIVATE_PLATFORM_APIS := true diff --git a/packages/DynamicAndroidInstallationService/AndroidManifest.xml b/packages/DynamicSystemInstallationService/AndroidManifest.xml index 32acad4d5ab0..291111713977 100644 --- a/packages/DynamicAndroidInstallationService/AndroidManifest.xml +++ b/packages/DynamicSystemInstallationService/AndroidManifest.xml @@ -1,10 +1,10 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.dynandroid" + package="com.android.dynsystem" android:sharedUserId="android.uid.system"> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.INTERNET" /> - <uses-permission android:name="android.permission.MANAGE_DYNAMIC_ANDROID" /> + <uses-permission android:name="android.permission.MANAGE_DYNAMIC_SYSTEM" /> <uses-permission android:name="android.permission.REBOOT" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> @@ -13,24 +13,24 @@ android:label="@string/app_name"> <service - android:name=".DynamicAndroidInstallationService" + android:name=".DynamicSystemInstallationService" android:enabled="true" android:exported="true" - android:permission="android.permission.MANAGE_DYNAMIC_ANDROID" - android:process=":dynandroid"> + android:permission="android.permission.MANAGE_DYNAMIC_SYSTEM" + android:process=":dynsystem"> <intent-filter> - <action android:name="android.content.action.NOTIFY_IF_IN_USE" /> + <action android:name="android.os.image.action.NOTIFY_IF_IN_USE" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </service> <activity android:name=".VerificationActivity" android:exported="true" - android:permission="android.permission.MANAGE_DYNAMIC_ANDROID" + android:permission="android.permission.MANAGE_DYNAMIC_SYSTEM" android:theme="@android:style/Theme.Material.Light.Dialog.NoActionBar" - android:process=":dynandroid"> + android:process=":dynsystem"> <intent-filter> - <action android:name="android.content.action.START_INSTALL" /> + <action android:name="android.os.image.action.START_INSTALL" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> diff --git a/packages/DynamicAndroidInstallationService/MODULE_LICENSE_APACHE2 b/packages/DynamicSystemInstallationService/MODULE_LICENSE_APACHE2 index e69de29bb2d1..e69de29bb2d1 100644 --- a/packages/DynamicAndroidInstallationService/MODULE_LICENSE_APACHE2 +++ b/packages/DynamicSystemInstallationService/MODULE_LICENSE_APACHE2 diff --git a/packages/DynamicAndroidInstallationService/NOTICE b/packages/DynamicSystemInstallationService/NOTICE index c5b1efa7aac7..c5b1efa7aac7 100644 --- a/packages/DynamicAndroidInstallationService/NOTICE +++ b/packages/DynamicSystemInstallationService/NOTICE diff --git a/packages/DynamicAndroidInstallationService/res/drawable/ic_system_update_googblue_24dp.xml b/packages/DynamicSystemInstallationService/res/drawable/ic_system_update_googblue_24dp.xml index acf1567ab7fe..acf1567ab7fe 100644 --- a/packages/DynamicAndroidInstallationService/res/drawable/ic_system_update_googblue_24dp.xml +++ b/packages/DynamicSystemInstallationService/res/drawable/ic_system_update_googblue_24dp.xml diff --git a/packages/DynamicAndroidInstallationService/res/values/strings.xml b/packages/DynamicSystemInstallationService/res/values/strings.xml index 03c7c28c7036..a72e4e2c1b74 100644 --- a/packages/DynamicAndroidInstallationService/res/values/strings.xml +++ b/packages/DynamicSystemInstallationService/res/values/strings.xml @@ -12,14 +12,14 @@ <!-- password page description [CHAR LIMIT=128] --> <string name="keyguard_description">Please enter your password and continue to AndroidOnTap installation</string> - <!-- Displayed on notification: DynAndroid installation is completed [CHAR LIMIT=128] --> + <!-- Displayed on notification: AndroidOnTap installation is completed [CHAR LIMIT=128] --> <string name="notification_install_completed">New system is ready, you can reboot into it or discard it.</string> - <!-- Displayed on notification: DynAndroid installation is in progress [CHAR LIMIT=128] --> + <!-- Displayed on notification: AndroidOnTap installation is in progress [CHAR LIMIT=128] --> <string name="notification_install_inprogress">Installation is in progress.</string> - <!-- Displayed on notification: DynAndroid installation is in progress [CHAR LIMIT=128] --> + <!-- Displayed on notification: AndroidOnTap installation is in progress [CHAR LIMIT=128] --> <string name="notification_install_failed">Installation Failed.</string> <!-- Displayed on notification: We are running in AndroidOnTap [CHAR LIMIT=128] --> - <string name="notification_dynandroid_in_use">We are running in AndroidOnTap.</string> + <string name="notification_dynsystem_in_use">We are running in AndroidOnTap.</string> <!-- Action on notification: Cancel installation [CHAR LIMIT=16] --> <string name="notification_action_cancel">Cancel</string> @@ -28,11 +28,11 @@ <!-- Action on notification: Uninstall AndroidOnTap [CHAR LIMIT=16] --> <string name="notification_action_uninstall">Uninstall</string> <!-- Action on notification: Reboot to AndroidOnTap [CHAR LIMIT=16] --> - <string name="notification_action_reboot_to_dynandroid">Reboot</string> + <string name="notification_action_reboot_to_dynsystem">Reboot</string> - <!-- Toast when installed DynamicAndroid is discarded [CHAR LIMIT=64] --> - <string name="toast_dynandroid_discarded">Installed AndroidOnTap is discarded.</string> - <!-- Toast when we fail to launch into DynamicAndroid [CHAR LIMIT=64] --> - <string name="toast_failed_to_reboot_to_dynandroid">Failed to reboot into AndroidOnTap.</string> + <!-- Toast when installed AndroidOnTap is discarded [CHAR LIMIT=64] --> + <string name="toast_dynsystem_discarded">Installed AndroidOnTap is discarded.</string> + <!-- Toast when we fail to launch into AndroidOnTap [CHAR LIMIT=64] --> + <string name="toast_failed_to_reboot_to_dynsystem">Failed to reboot into AndroidOnTap.</string> </resources> diff --git a/packages/DynamicAndroidInstallationService/src/com/android/dynandroid/BootCompletedReceiver.java b/packages/DynamicSystemInstallationService/src/com/android/dynandroid/BootCompletedReceiver.java index dd1be897b2ea..38576ee47283 100644 --- a/packages/DynamicAndroidInstallationService/src/com/android/dynandroid/BootCompletedReceiver.java +++ b/packages/DynamicSystemInstallationService/src/com/android/dynandroid/BootCompletedReceiver.java @@ -14,20 +14,20 @@ * limitations under the License. */ -package com.android.dynandroid; +package com.android.dynsystem; import android.content.BroadcastReceiver; import android.content.Context; -import android.content.DynamicAndroidClient; import android.content.Intent; import android.os.UserHandle; +import android.os.image.DynamicSystemClient; import android.util.Log; /** * A BoardcastReceiver waiting for ACTION_BOOT_COMPLETED and ask * the service to display a notification if we are currently running - * in DynamicAndroid. + * in DynamicSystem. */ public class BootCompletedReceiver extends BroadcastReceiver { @@ -41,9 +41,9 @@ public class BootCompletedReceiver extends BroadcastReceiver { if (Intent.ACTION_BOOT_COMPLETED.equals(action)) { Intent startServiceIntent = new Intent( - context, DynamicAndroidInstallationService.class); + context, DynamicSystemInstallationService.class); - startServiceIntent.setAction(DynamicAndroidClient.ACTION_NOTIFY_IF_IN_USE); + startServiceIntent.setAction(DynamicSystemClient.ACTION_NOTIFY_IF_IN_USE); context.startServiceAsUser(startServiceIntent, UserHandle.SYSTEM); } } diff --git a/packages/DynamicAndroidInstallationService/src/com/android/dynandroid/DynamicAndroidInstallationService.java b/packages/DynamicSystemInstallationService/src/com/android/dynandroid/DynamicSystemInstallationService.java index d942babf78a6..df2c57181904 100644 --- a/packages/DynamicAndroidInstallationService/src/com/android/dynandroid/DynamicAndroidInstallationService.java +++ b/packages/DynamicSystemInstallationService/src/com/android/dynandroid/DynamicSystemInstallationService.java @@ -14,28 +14,28 @@ * limitations under the License. */ -package com.android.dynandroid; - -import static android.content.DynamicAndroidClient.ACTION_NOTIFY_IF_IN_USE; -import static android.content.DynamicAndroidClient.ACTION_START_INSTALL; -import static android.content.DynamicAndroidClient.CAUSE_ERROR_EXCEPTION; -import static android.content.DynamicAndroidClient.CAUSE_ERROR_INVALID_URL; -import static android.content.DynamicAndroidClient.CAUSE_ERROR_IO; -import static android.content.DynamicAndroidClient.CAUSE_INSTALL_CANCELLED; -import static android.content.DynamicAndroidClient.CAUSE_INSTALL_COMPLETED; -import static android.content.DynamicAndroidClient.CAUSE_NOT_SPECIFIED; -import static android.content.DynamicAndroidClient.STATUS_IN_PROGRESS; -import static android.content.DynamicAndroidClient.STATUS_IN_USE; -import static android.content.DynamicAndroidClient.STATUS_NOT_STARTED; -import static android.content.DynamicAndroidClient.STATUS_READY; +package com.android.dynsystem; + import static android.os.AsyncTask.Status.FINISHED; import static android.os.AsyncTask.Status.PENDING; import static android.os.AsyncTask.Status.RUNNING; - -import static com.android.dynandroid.InstallationAsyncTask.RESULT_ERROR_EXCEPTION; -import static com.android.dynandroid.InstallationAsyncTask.RESULT_ERROR_INVALID_URL; -import static com.android.dynandroid.InstallationAsyncTask.RESULT_ERROR_IO; -import static com.android.dynandroid.InstallationAsyncTask.RESULT_OK; +import static android.os.image.DynamicSystemClient.ACTION_NOTIFY_IF_IN_USE; +import static android.os.image.DynamicSystemClient.ACTION_START_INSTALL; +import static android.os.image.DynamicSystemClient.CAUSE_ERROR_EXCEPTION; +import static android.os.image.DynamicSystemClient.CAUSE_ERROR_INVALID_URL; +import static android.os.image.DynamicSystemClient.CAUSE_ERROR_IO; +import static android.os.image.DynamicSystemClient.CAUSE_INSTALL_CANCELLED; +import static android.os.image.DynamicSystemClient.CAUSE_INSTALL_COMPLETED; +import static android.os.image.DynamicSystemClient.CAUSE_NOT_SPECIFIED; +import static android.os.image.DynamicSystemClient.STATUS_IN_PROGRESS; +import static android.os.image.DynamicSystemClient.STATUS_IN_USE; +import static android.os.image.DynamicSystemClient.STATUS_NOT_STARTED; +import static android.os.image.DynamicSystemClient.STATUS_READY; + +import static com.android.dynsystem.InstallationAsyncTask.RESULT_ERROR_EXCEPTION; +import static com.android.dynsystem.InstallationAsyncTask.RESULT_ERROR_INVALID_URL; +import static com.android.dynsystem.InstallationAsyncTask.RESULT_ERROR_IO; +import static com.android.dynsystem.InstallationAsyncTask.RESULT_OK; import android.app.Notification; import android.app.NotificationChannel; @@ -43,16 +43,16 @@ import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.content.Context; -import android.content.DynamicAndroidClient; import android.content.Intent; import android.os.Bundle; -import android.os.DynamicAndroidManager; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.os.Messenger; import android.os.PowerManager; import android.os.RemoteException; +import android.os.image.DynamicSystemClient; +import android.os.image.DynamicSystemManager; import android.util.Log; import android.widget.Toast; @@ -60,31 +60,31 @@ import java.lang.ref.WeakReference; import java.util.ArrayList; /** - * This class is the service in charge of DynamicAndroid installation. + * This class is the service in charge of DynamicSystem installation. * It also posts status to notification bar and wait for user's * cancel and confirm commnands. */ -public class DynamicAndroidInstallationService extends Service +public class DynamicSystemInstallationService extends Service implements InstallationAsyncTask.InstallStatusListener { - private static final String TAG = "DynAndroidInstallationService"; + private static final String TAG = "DynSystemInstallationService"; /* * Intent actions */ private static final String ACTION_CANCEL_INSTALL = - "com.android.dynandroid.ACTION_CANCEL_INSTALL"; + "com.android.dynsystem.ACTION_CANCEL_INSTALL"; private static final String ACTION_DISCARD_INSTALL = - "com.android.dynandroid.ACTION_DISCARD_INSTALL"; - private static final String ACTION_REBOOT_TO_DYN_ANDROID = - "com.android.dynandroid.ACTION_REBOOT_TO_DYN_ANDROID"; + "com.android.dynsystem.ACTION_DISCARD_INSTALL"; + private static final String ACTION_REBOOT_TO_DYN_SYSTEM = + "com.android.dynsystem.ACTION_REBOOT_TO_DYN_SYSTEM"; private static final String ACTION_REBOOT_TO_NORMAL = - "com.android.dynandroid.ACTION_REBOOT_TO_NORMAL"; + "com.android.dynsystem.ACTION_REBOOT_TO_NORMAL"; /* * For notification */ - private static final String NOTIFICATION_CHANNEL_ID = "com.android.dynandroid"; + private static final String NOTIFICATION_CHANNEL_ID = "com.android.dynsystem"; private static final int NOTIFICATION_ID = 1; /* @@ -97,15 +97,15 @@ public class DynamicAndroidInstallationService extends Service final Messenger mMessenger = new Messenger(new IncomingHandler(this)); static class IncomingHandler extends Handler { - private final WeakReference<DynamicAndroidInstallationService> mWeakService; + private final WeakReference<DynamicSystemInstallationService> mWeakService; - IncomingHandler(DynamicAndroidInstallationService service) { + IncomingHandler(DynamicSystemInstallationService service) { mWeakService = new WeakReference<>(service); } @Override public void handleMessage(Message msg) { - DynamicAndroidInstallationService service = mWeakService.get(); + DynamicSystemInstallationService service = mWeakService.get(); if (service != null) { service.handleMessage(msg); @@ -113,7 +113,7 @@ public class DynamicAndroidInstallationService extends Service } } - private DynamicAndroidManager mDynAndroid; + private DynamicSystemManager mDynSystem; private NotificationManager mNM; private long mSystemSize; @@ -130,7 +130,7 @@ public class DynamicAndroidInstallationService extends Service prepareNotification(); - mDynAndroid = (DynamicAndroidManager) getSystemService(Context.DYNAMIC_ANDROID_SERVICE); + mDynSystem = (DynamicSystemManager) getSystemService(Context.DYNAMIC_SYSTEM_SERVICE); } @Override @@ -156,8 +156,8 @@ public class DynamicAndroidInstallationService extends Service executeCancelCommand(); } else if (ACTION_DISCARD_INSTALL.equals(action)) { executeDiscardCommand(); - } else if (ACTION_REBOOT_TO_DYN_ANDROID.equals(action)) { - executeRebootToDynAndroidCommand(); + } else if (ACTION_REBOOT_TO_DYN_SYSTEM.equals(action)) { + executeRebootToDynSystemCommand(); } else if (ACTION_REBOOT_TO_NORMAL.equals(action)) { executeRebootToNormalCommand(); } else if (ACTION_NOTIFY_IF_IN_USE.equals(action)) { @@ -215,17 +215,17 @@ public class DynamicAndroidInstallationService extends Service return; } - if (isInDynamicAndroid()) { - Log.e(TAG, "We are already running in DynamicAndroid"); + if (isInDynamicSystem()) { + Log.e(TAG, "We are already running in DynamicSystem"); return; } - String url = intent.getStringExtra(DynamicAndroidClient.KEY_SYSTEM_URL); - mSystemSize = intent.getLongExtra(DynamicAndroidClient.KEY_SYSTEM_SIZE, 0); - mUserdataSize = intent.getLongExtra(DynamicAndroidClient.KEY_USERDATA_SIZE, 0); + String url = intent.getStringExtra(DynamicSystemClient.KEY_SYSTEM_URL); + mSystemSize = intent.getLongExtra(DynamicSystemClient.KEY_SYSTEM_SIZE, 0); + mUserdataSize = intent.getLongExtra(DynamicSystemClient.KEY_USERDATA_SIZE, 0); mInstallTask = new InstallationAsyncTask( - url, mSystemSize, mUserdataSize, mDynAndroid, this); + url, mSystemSize, mUserdataSize, mDynSystem, this); mInstallTask.execute(); @@ -251,7 +251,7 @@ public class DynamicAndroidInstallationService extends Service } private void executeDiscardCommand() { - if (isInDynamicAndroid()) { + if (isInDynamicSystem()) { Log.e(TAG, "We are now running in AOT, please reboot to normal system first"); return; } @@ -262,16 +262,16 @@ public class DynamicAndroidInstallationService extends Service } Toast.makeText(this, - getString(R.string.toast_dynandroid_discarded), + getString(R.string.toast_dynsystem_discarded), Toast.LENGTH_LONG).show(); resetTaskAndStop(); postStatus(STATUS_NOT_STARTED, CAUSE_INSTALL_CANCELLED); - mDynAndroid.remove(); + mDynSystem.remove(); } - private void executeRebootToDynAndroidCommand() { + private void executeRebootToDynSystemCommand() { if (mInstallTask == null || mInstallTask.getStatus() != FINISHED) { Log.e(TAG, "Trying to reboot to AOT while there is no complete installation"); return; @@ -282,10 +282,10 @@ public class DynamicAndroidInstallationService extends Service mNM.cancel(NOTIFICATION_ID); Toast.makeText(this, - getString(R.string.toast_failed_to_reboot_to_dynandroid), + getString(R.string.toast_failed_to_reboot_to_dynsystem), Toast.LENGTH_LONG).show(); - mDynAndroid.remove(); + mDynSystem.remove(); return; } @@ -293,12 +293,12 @@ public class DynamicAndroidInstallationService extends Service PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE); if (powerManager != null) { - powerManager.reboot("dynandroid"); + powerManager.reboot("dynsystem"); } } private void executeRebootToNormalCommand() { - if (!isInDynamicAndroid()) { + if (!isInDynamicSystem()) { Log.e(TAG, "It's already running in normal system."); return; } @@ -346,7 +346,7 @@ public class DynamicAndroidInstallationService extends Service } private PendingIntent createPendingIntent(String action) { - Intent intent = new Intent(this, DynamicAndroidInstallationService.class); + Intent intent = new Intent(this, DynamicSystemInstallationService.class); intent.setAction(action); return PendingIntent.getService(this, 0, intent, 0); } @@ -375,8 +375,8 @@ public class DynamicAndroidInstallationService extends Service builder.setContentText(getString(R.string.notification_install_completed)); builder.addAction(new Notification.Action.Builder( - null, getString(R.string.notification_action_reboot_to_dynandroid), - createPendingIntent(ACTION_REBOOT_TO_DYN_ANDROID)).build()); + null, getString(R.string.notification_action_reboot_to_dynsystem), + createPendingIntent(ACTION_REBOOT_TO_DYN_SYSTEM)).build()); builder.addAction(new Notification.Action.Builder( null, getString(R.string.notification_action_discard), @@ -385,7 +385,7 @@ public class DynamicAndroidInstallationService extends Service break; case STATUS_IN_USE: - builder.setContentText(getString(R.string.notification_dynandroid_in_use)); + builder.setContentText(getString(R.string.notification_dynsystem_in_use)); builder.addAction(new Notification.Action.Builder( null, getString(R.string.notification_action_uninstall), @@ -409,7 +409,7 @@ public class DynamicAndroidInstallationService extends Service } private boolean verifyRequest(Intent intent) { - String url = intent.getStringExtra(DynamicAndroidClient.KEY_SYSTEM_URL); + String url = intent.getStringExtra(DynamicSystemClient.KEY_SYSTEM_URL); return VerificationActivity.isVerified(url); } @@ -443,16 +443,16 @@ public class DynamicAndroidInstallationService extends Service private void notifyOneClient(Messenger client, int status, int cause) throws RemoteException { Bundle bundle = new Bundle(); - bundle.putLong(DynamicAndroidClient.KEY_INSTALLED_SIZE, mInstalledSize); + bundle.putLong(DynamicSystemClient.KEY_INSTALLED_SIZE, mInstalledSize); client.send(Message.obtain(null, - DynamicAndroidClient.MSG_POST_STATUS, status, cause, bundle)); + DynamicSystemClient.MSG_POST_STATUS, status, cause, bundle)); } private int getStatus() { - if (isInDynamicAndroid()) { + if (isInDynamicSystem()) { return STATUS_IN_USE; - } else if (isDynamicAndroidInstalled()) { + } else if (isDynamicSystemInstalled()) { return STATUS_READY; } else if (mInstallTask == null) { return STATUS_NOT_STARTED; @@ -479,17 +479,17 @@ public class DynamicAndroidInstallationService extends Service } } - private boolean isInDynamicAndroid() { - return mDynAndroid.isInUse(); + private boolean isInDynamicSystem() { + return mDynSystem.isInUse(); } - private boolean isDynamicAndroidInstalled() { - return mDynAndroid.isInstalled(); + private boolean isDynamicSystemInstalled() { + return mDynSystem.isInstalled(); } void handleMessage(Message msg) { switch (msg.what) { - case DynamicAndroidClient.MSG_REGISTER_LISTENER: + case DynamicSystemClient.MSG_REGISTER_LISTENER: try { Messenger client = msg.replyTo; @@ -505,7 +505,7 @@ public class DynamicAndroidInstallationService extends Service } break; - case DynamicAndroidClient.MSG_UNREGISTER_LISTENER: + case DynamicSystemClient.MSG_UNREGISTER_LISTENER: mClients.remove(msg.replyTo); break; default: diff --git a/packages/DynamicAndroidInstallationService/src/com/android/dynandroid/InstallationAsyncTask.java b/packages/DynamicSystemInstallationService/src/com/android/dynandroid/InstallationAsyncTask.java index 03fc7739fcce..052fc0a109b3 100644 --- a/packages/DynamicAndroidInstallationService/src/com/android/dynandroid/InstallationAsyncTask.java +++ b/packages/DynamicSystemInstallationService/src/com/android/dynandroid/InstallationAsyncTask.java @@ -14,11 +14,11 @@ * limitations under the License. */ -package com.android.dynandroid; +package com.android.dynsystem; import android.gsi.GsiProgress; import android.os.AsyncTask; -import android.os.DynamicAndroidManager; +import android.os.image.DynamicSystemManager; import android.util.Log; import android.webkit.URLUtil; @@ -60,9 +60,9 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Integer> { private final String mUrl; private final long mSystemSize; private final long mUserdataSize; - private final DynamicAndroidManager mDynamicAndroid; + private final DynamicSystemManager mDynSystem; private final InstallStatusListener mListener; - private DynamicAndroidManager.Session mInstallationSession; + private DynamicSystemManager.Session mInstallationSession; private int mResult = NO_RESULT; @@ -70,11 +70,11 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Integer> { InstallationAsyncTask(String url, long systemSize, long userdataSize, - DynamicAndroidManager dynAndroid, InstallStatusListener listener) { + DynamicSystemManager dynSystem, InstallStatusListener listener) { mUrl = url; mSystemSize = systemSize; mUserdataSize = userdataSize; - mDynamicAndroid = dynAndroid; + mDynSystem = dynSystem; mListener = listener; } @@ -98,7 +98,7 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Integer> { Thread thread = new Thread(() -> { mInstallationSession = - mDynamicAndroid.startInstallation(mSystemSize, mUserdataSize); + mDynSystem.startInstallation(mSystemSize, mUserdataSize); }); @@ -106,12 +106,12 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Integer> { while (thread.isAlive()) { if (isCancelled()) { - boolean aborted = mDynamicAndroid.abort(); - Log.d(TAG, "Called DynamicAndroidManager.abort(), result = " + aborted); + boolean aborted = mDynSystem.abort(); + Log.d(TAG, "Called DynamicSystemManager.abort(), result = " + aborted); return RESULT_OK; } - GsiProgress progress = mDynamicAndroid.getInstallationProgress(); + GsiProgress progress = mDynSystem.getInstallationProgress(); installedSize = progress.bytes_processed; if (installedSize > reportedInstalledSize + minStepToReport) { @@ -146,7 +146,7 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Integer> { ? bytes : Arrays.copyOf(bytes, numBytesRead); if (!mInstallationSession.write(writeBuffer)) { - throw new IOException("Failed write() to DynamicAndroid"); + throw new IOException("Failed write() to DynamicSystem"); } installedSize += numBytesRead; diff --git a/packages/DynamicAndroidInstallationService/src/com/android/dynandroid/VerificationActivity.java b/packages/DynamicSystemInstallationService/src/com/android/dynandroid/VerificationActivity.java index c18c4fe689c9..f05930f8ec07 100644 --- a/packages/DynamicAndroidInstallationService/src/com/android/dynandroid/VerificationActivity.java +++ b/packages/DynamicSystemInstallationService/src/com/android/dynandroid/VerificationActivity.java @@ -14,19 +14,19 @@ * limitations under the License. */ -package com.android.dynandroid; +package com.android.dynsystem; -import static android.content.DynamicAndroidClient.KEY_SYSTEM_SIZE; -import static android.content.DynamicAndroidClient.KEY_SYSTEM_URL; -import static android.content.DynamicAndroidClient.KEY_USERDATA_SIZE; +import static android.os.image.DynamicSystemClient.KEY_SYSTEM_SIZE; +import static android.os.image.DynamicSystemClient.KEY_SYSTEM_URL; +import static android.os.image.DynamicSystemClient.KEY_USERDATA_SIZE; import android.app.Activity; import android.app.KeyguardManager; import android.content.Context; -import android.content.DynamicAndroidClient; import android.content.Intent; import android.os.Bundle; import android.os.UserHandle; +import android.os.image.DynamicSystemClient; import android.util.Log; @@ -88,8 +88,8 @@ public class VerificationActivity extends Activity { sVerifiedUrl = url; // start service - Intent intent = new Intent(this, DynamicAndroidInstallationService.class); - intent.setAction(DynamicAndroidClient.ACTION_START_INSTALL); + Intent intent = new Intent(this, DynamicSystemInstallationService.class); + intent.setAction(DynamicSystemClient.ACTION_START_INSTALL); intent.putExtra(KEY_SYSTEM_URL, url); intent.putExtra(KEY_SYSTEM_SIZE, systemSize); intent.putExtra(KEY_USERDATA_SIZE, userdataSize); diff --git a/packages/NetworkStack/Android.bp b/packages/NetworkStack/Android.bp index 8872147b65ed..01cd00a4814d 100644 --- a/packages/NetworkStack/Android.bp +++ b/packages/NetworkStack/Android.bp @@ -29,6 +29,7 @@ android_library { "netd_aidl_interface-java", "networkstack-aidl-interfaces-java", "datastallprotosnano", + "networkstackprotosnano", ], manifest: "AndroidManifestBase.xml", } diff --git a/packages/NetworkStack/AndroidManifest.xml b/packages/NetworkStack/AndroidManifest.xml index a90db11df016..b0a7923d65f4 100644 --- a/packages/NetworkStack/AndroidManifest.xml +++ b/packages/NetworkStack/AndroidManifest.xml @@ -19,6 +19,7 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.networkstack" android:sharedUserId="android.uid.networkstack"> + <uses-sdk android:minSdkVersion="28" android:targetSdkVersion="28" /> <!-- Signature permission defined in NetworkStackStub --> <uses-permission android:name="android.permission.MAINLINE_NETWORK_STACK" /> <application> @@ -28,4 +29,4 @@ </intent-filter> </service> </application> -</manifest>
\ No newline at end of file +</manifest> diff --git a/packages/NetworkStack/AndroidManifestBase.xml b/packages/NetworkStack/AndroidManifestBase.xml index 621d30c31f98..f69e4b2bb795 100644 --- a/packages/NetworkStack/AndroidManifestBase.xml +++ b/packages/NetworkStack/AndroidManifestBase.xml @@ -20,7 +20,6 @@ package="com.android.networkstack" android:versionCode="11" android:versionName="Q-initial"> - <uses-sdk android:minSdkVersion="28" android:targetSdkVersion="28" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> diff --git a/packages/NetworkStack/AndroidManifest_InProcess.xml b/packages/NetworkStack/AndroidManifest_InProcess.xml index 48fcecd2f06d..275cd02a6cc0 100644 --- a/packages/NetworkStack/AndroidManifest_InProcess.xml +++ b/packages/NetworkStack/AndroidManifest_InProcess.xml @@ -20,6 +20,7 @@ package="com.android.networkstack.inprocess" android:sharedUserId="android.uid.system" android:process="system"> + <uses-sdk android:minSdkVersion="28" android:targetSdkVersion="28" /> <application> <service android:name="com.android.server.NetworkStackService" android:process="system"> <intent-filter> @@ -27,4 +28,4 @@ </intent-filter> </service> </application> -</manifest>
\ No newline at end of file +</manifest> diff --git a/packages/NetworkStack/src/android/net/dhcp/DhcpServingParams.java b/packages/NetworkStack/src/android/net/dhcp/DhcpServingParams.java index 3cd2aa40dfb2..230b693a809a 100644 --- a/packages/NetworkStack/src/android/net/dhcp/DhcpServingParams.java +++ b/packages/NetworkStack/src/android/net/dhcp/DhcpServingParams.java @@ -329,7 +329,7 @@ public class DhcpServingParams { if (mLinkMtu != MTU_UNSET && (mLinkMtu < IPV4_MIN_MTU || mLinkMtu > IPV4_MAX_MTU)) { throw new InvalidParameterException("Invalid link MTU: " + mLinkMtu); } - if (!mServerAddr.isIPv4()) { + if (!mServerAddr.isIpv4()) { throw new InvalidParameterException("serverAddr must be IPv4"); } if (mServerAddr.getPrefixLength() < MIN_PREFIX_LENGTH diff --git a/packages/NetworkStack/src/android/net/ip/IpClient.java b/packages/NetworkStack/src/android/net/ip/IpClient.java index b68fe235647a..346ac68407de 100644 --- a/packages/NetworkStack/src/android/net/ip/IpClient.java +++ b/packages/NetworkStack/src/android/net/ip/IpClient.java @@ -834,7 +834,7 @@ public class IpClient extends StateMachine { static boolean isProvisioned(LinkProperties lp, InitialConfiguration config) { // For historical reasons, we should connect even if all we have is // an IPv4 address and nothing else. - if (lp.hasIPv4Address() || lp.isProvisioned()) { + if (lp.hasIpv4Address() || lp.isProvisioned()) { return true; } if (config == null) { @@ -878,9 +878,9 @@ public class IpClient extends StateMachine { delta = PROV_CHANGE_LOST_PROVISIONING; } - final boolean lostIPv6 = oldLp.isIPv6Provisioned() && !newLp.isIPv6Provisioned(); - final boolean lostIPv4Address = oldLp.hasIPv4Address() && !newLp.hasIPv4Address(); - final boolean lostIPv6Router = oldLp.hasIPv6DefaultRoute() && !newLp.hasIPv6DefaultRoute(); + final boolean lostIPv6 = oldLp.isIpv6Provisioned() && !newLp.isIpv6Provisioned(); + final boolean lostIPv4Address = oldLp.hasIpv4Address() && !newLp.hasIpv4Address(); + final boolean lostIPv6Router = oldLp.hasIpv6DefaultRoute() && !newLp.hasIpv6DefaultRoute(); // If bad wifi avoidance is disabled, then ignore IPv6 loss of // provisioning. Otherwise, when a hotspot that loses Internet @@ -897,7 +897,7 @@ public class IpClient extends StateMachine { // accompanying code in IpReachabilityMonitor) is unreachable. final boolean ignoreIPv6ProvisioningLoss = mConfiguration != null && mConfiguration.mUsingMultinetworkPolicyTracker - && mCm.getAvoidBadWifi(); + && mCm.shouldAvoidBadWifi(); // Additionally: // @@ -920,7 +920,7 @@ public class IpClient extends StateMachine { // If the previous link properties had a global IPv6 address and an // IPv6 default route then also consider the loss of that default route // to be a loss of provisioning. See b/27962810. - if (oldLp.hasGlobalIPv6Address() && (lostIPv6Router && !ignoreIPv6ProvisioningLoss)) { + if (oldLp.hasGlobalIpv6Address() && (lostIPv6Router && !ignoreIPv6ProvisioningLoss)) { delta = PROV_CHANGE_LOST_PROVISIONING; } @@ -1156,7 +1156,7 @@ public class IpClient extends StateMachine { private boolean applyInitialConfig(InitialConfiguration config) { // TODO: also support specifying a static IPv4 configuration in InitialConfiguration. - for (LinkAddress addr : findAll(config.ipAddresses, LinkAddress::isIPv6)) { + for (LinkAddress addr : findAll(config.ipAddresses, LinkAddress::isIpv6)) { if (!mInterfaceCtrl.addAddress(addr)) return false; } @@ -1374,7 +1374,7 @@ public class IpClient extends StateMachine { } private boolean readyToProceed() { - return (!mLinkProperties.hasIPv4Address() && !mLinkProperties.hasGlobalIPv6Address()); + return (!mLinkProperties.hasIpv4Address() && !mLinkProperties.hasGlobalIpv6Address()); } } diff --git a/packages/NetworkStack/src/android/net/ip/IpReachabilityMonitor.java b/packages/NetworkStack/src/android/net/ip/IpReachabilityMonitor.java index 76a03387a12d..3aa6933fe8f2 100644 --- a/packages/NetworkStack/src/android/net/ip/IpReachabilityMonitor.java +++ b/packages/NetworkStack/src/android/net/ip/IpReachabilityMonitor.java @@ -316,8 +316,8 @@ public class IpReachabilityMonitor { } final boolean lostProvisioning = - (mLinkProperties.isIPv4Provisioned() && !whatIfLp.isIPv4Provisioned()) - || (mLinkProperties.isIPv6Provisioned() && !whatIfLp.isIPv6Provisioned()); + (mLinkProperties.isIpv4Provisioned() && !whatIfLp.isIpv4Provisioned()) + || (mLinkProperties.isIpv6Provisioned() && !whatIfLp.isIpv6Provisioned()); if (lostProvisioning) { final String logMsg = "FAILURE: LOST_PROVISIONING, " + event; @@ -332,7 +332,7 @@ public class IpReachabilityMonitor { } private boolean avoidingBadLinks() { - return !mUsingMultinetworkPolicyTracker || mCm.getAvoidBadWifi(); + return !mUsingMultinetworkPolicyTracker || mCm.shouldAvoidBadWifi(); } public void probeAll() { diff --git a/packages/NetworkStack/src/com/android/server/NetworkStackService.java b/packages/NetworkStack/src/com/android/server/NetworkStackService.java index 335d9513bddb..19e9108d2fc8 100644 --- a/packages/NetworkStack/src/com/android/server/NetworkStackService.java +++ b/packages/NetworkStack/src/com/android/server/NetworkStackService.java @@ -277,9 +277,9 @@ public class NetworkStackService extends Service { } @Override - public void notifyAcceptPartialConnectivity() { + public void setAcceptPartialConnectivity() { checkNetworkStackCallingPermission(); - mNm.notifyAcceptPartialConnectivity(); + mNm.setAcceptPartialConnectivity(); } @Override diff --git a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java index 9d91487fec82..73b203c3df49 100644 --- a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java +++ b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java @@ -319,7 +319,8 @@ public class NetworkMonitor extends StateMachine { private final DnsStallDetector mDnsStallDetector; private long mLastProbeTime; // Set to true if data stall is suspected and reset to false after metrics are sent to statsd. - private boolean mCollectDataStallMetrics = false; + private boolean mCollectDataStallMetrics; + private boolean mAcceptPartialConnectivity; public NetworkMonitor(Context context, INetworkMonitorCallbacks cb, Network network, SharedLog validationLog) { @@ -386,10 +387,11 @@ public class NetworkMonitor extends StateMachine { } /** - * ConnectivityService notifies NetworkMonitor that the user accepts partial connectivity and - * NetworkMonitor should ignore the https probe. + * ConnectivityService notifies NetworkMonitor that the user already accepted partial + * connectivity previously, so NetworkMonitor can validate the network even if it has partial + * connectivity. */ - public void notifyAcceptPartialConnectivity() { + public void setAcceptPartialConnectivity() { sendMessage(EVENT_ACCEPT_PARTIAL_CONNECTIVITY); } @@ -651,9 +653,11 @@ public class NetworkMonitor extends StateMachine { case EVENT_DNS_NOTIFICATION: mDnsStallDetector.accumulateConsecutiveDnsTimeoutCount(message.arg1); break; + // Set mAcceptPartialConnectivity to true and if network start evaluating or + // re-evaluating and get the result of partial connectivity, ProbingState will + // disable HTTPS probe and transition to EvaluatingPrivateDnsState. case EVENT_ACCEPT_PARTIAL_CONNECTIVITY: - mUseHttps = false; - transitionTo(mEvaluatingPrivateDnsState); + mAcceptPartialConnectivity = true; break; default: break; @@ -849,6 +853,14 @@ public class NetworkMonitor extends StateMachine { // ignore any re-evaluation requests. After, restart the // evaluation process via EvaluatingState#enter. return (mEvaluateAttempts < IGNORE_REEVALUATE_ATTEMPTS) ? HANDLED : NOT_HANDLED; + // Disable HTTPS probe and transition to EvaluatingPrivateDnsState because: + // 1. Network is connected and finish the network validation. + // 2. NetworkMonitor detects network is partial connectivity and user accepts it. + case EVENT_ACCEPT_PARTIAL_CONNECTIVITY: + mAcceptPartialConnectivity = true; + mUseHttps = false; + transitionTo(mEvaluatingPrivateDnsState); + return HANDLED; default: return NOT_HANDLED; } @@ -1081,7 +1093,12 @@ public class NetworkMonitor extends StateMachine { logNetworkEvent(NetworkEvent.NETWORK_PARTIAL_CONNECTIVITY); notifyNetworkTested(NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY, probeResult.redirectUrl); - transitionTo(mWaitingForNextProbeState); + if (mAcceptPartialConnectivity) { + mUseHttps = false; + transitionTo(mEvaluatingPrivateDnsState); + } else { + transitionTo(mWaitingForNextProbeState); + } } else { logNetworkEvent(NetworkEvent.NETWORK_VALIDATION_FAILED); notifyNetworkTested(NETWORK_TEST_RESULT_INVALID, probeResult.redirectUrl); diff --git a/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java b/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java index d93aef2b73f6..d732c4e81d83 100644 --- a/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java +++ b/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java @@ -583,7 +583,7 @@ public class NetworkMonitorTest { verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1)) .notifyNetworkTested(NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY, null); - nm.notifyAcceptPartialConnectivity(); + nm.setAcceptPartialConnectivity(); verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1)) .notifyNetworkTested(NETWORK_TEST_RESULT_VALID, null); } diff --git a/packages/PackageInstaller/AndroidManifest.xml b/packages/PackageInstaller/AndroidManifest.xml index a69b41258974..62535b635e44 100644 --- a/packages/PackageInstaller/AndroidManifest.xml +++ b/packages/PackageInstaller/AndroidManifest.xml @@ -15,7 +15,6 @@ <uses-permission android:name="android.permission.MANAGE_APP_OPS_MODES" /> <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" /> <uses-permission android:name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME" /> - <uses-permission android:name="android.permission.CLEAR_APP_USER_DATA" /> <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" /> <uses-permission android:name="com.google.android.permission.INSTALL_WEARABLE_PACKAGES" /> diff --git a/packages/PackageInstaller/res/layout/uninstall_content_view.xml b/packages/PackageInstaller/res/layout/uninstall_content_view.xml index 2f8966c0461b..5666c0e44e0b 100644 --- a/packages/PackageInstaller/res/layout/uninstall_content_view.xml +++ b/packages/PackageInstaller/res/layout/uninstall_content_view.xml @@ -36,16 +36,6 @@ style="@android:style/TextAppearance.Material.Subhead" /> <CheckBox - android:id="@+id/clearContributedFiles" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginTop="8dp" - android:layout_marginStart="-8dp" - android:paddingLeft="8sp" - android:visibility="gone" - style="@android:style/TextAppearance.Material.Subhead" /> - - <CheckBox android:id="@+id/keepData" android:layout_width="wrap_content" android:layout_height="wrap_content" diff --git a/packages/PackageInstaller/res/values/strings.xml b/packages/PackageInstaller/res/values/strings.xml index a05a219b917b..797656ef62f4 100644 --- a/packages/PackageInstaller/res/values/strings.xml +++ b/packages/PackageInstaller/res/values/strings.xml @@ -119,8 +119,6 @@ <string name="uninstall_update_text">Replace this app with the factory version? All data will be removed.</string> <!-- [CHAR LIMIT=none] --> <string name="uninstall_update_text_multiuser">Replace this app with the factory version? All data will be removed. This affects all users of this device, including those with work profiles.</string> - <!-- Label of a checkbox that allows to remove the files contributed by app during uninstall [CHAR LIMIT=none] --> - <string name="uninstall_remove_contributed_files">Also remove <xliff:g id="size" example="1.5MB">%1$s</xliff:g> of associated media files.</string> <!-- Label of a checkbox that allows to keep the data (e.g. files, settings) of the app on uninstall [CHAR LIMIT=none] --> <string name="uninstall_keep_data">Keep <xliff:g id="size" example="1.5MB">%1$s</xliff:g> of app data.</string> diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/UninstallUninstalling.java b/packages/PackageInstaller/src/com/android/packageinstaller/UninstallUninstalling.java index 63d8c5a82519..c4dceb4fe079 100644 --- a/packages/PackageInstaller/src/com/android/packageinstaller/UninstallUninstalling.java +++ b/packages/PackageInstaller/src/com/android/packageinstaller/UninstallUninstalling.java @@ -50,8 +50,6 @@ public class UninstallUninstalling extends Activity implements "com.android.packageinstaller.ACTION_UNINSTALL_COMMIT"; static final String EXTRA_APP_LABEL = "com.android.packageinstaller.extra.APP_LABEL"; - static final String EXTRA_CLEAR_CONTRIBUTED_FILES = - "com.android.packageinstaller.extra.CLEAR_CONTRIBUTED_FILES"; static final String EXTRA_KEEP_DATA = "com.android.packageinstaller.extra.KEEP_DATA"; private int mUninstallId; @@ -75,8 +73,6 @@ public class UninstallUninstalling extends Activity implements if (savedInstanceState == null) { boolean allUsers = getIntent().getBooleanExtra(Intent.EXTRA_UNINSTALL_ALL_USERS, false); - boolean clearContributedFiles = getIntent().getBooleanExtra( - EXTRA_CLEAR_CONTRIBUTED_FILES, false); boolean keepData = getIntent().getBooleanExtra(EXTRA_KEEP_DATA, false); UserHandle user = getIntent().getParcelableExtra(Intent.EXTRA_USER); @@ -102,7 +98,6 @@ public class UninstallUninstalling extends Activity implements broadcastIntent, PendingIntent.FLAG_UPDATE_CURRENT); int flags = allUsers ? PackageManager.DELETE_ALL_USERS : 0; - flags |= clearContributedFiles ? PackageManager.DELETE_CONTRIBUTED_MEDIA : 0; flags |= keepData ? PackageManager.DELETE_KEEP_DATA : 0; try { diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/UninstallerActivity.java b/packages/PackageInstaller/src/com/android/packageinstaller/UninstallerActivity.java index 54194491d140..be778e92787e 100755 --- a/packages/PackageInstaller/src/com/android/packageinstaller/UninstallerActivity.java +++ b/packages/PackageInstaller/src/com/android/packageinstaller/UninstallerActivity.java @@ -285,7 +285,7 @@ public class UninstallerActivity extends Activity { fragment.show(ft, "dialog"); } - public void startUninstallProgress(boolean clearContributedFiles, boolean keepData) { + public void startUninstallProgress(boolean keepData) { boolean returnResult = getIntent().getBooleanExtra(Intent.EXTRA_RETURN_RESULT, false); CharSequence label = mDialogInfo.appInfo.loadSafeLabel(getPackageManager()); @@ -310,8 +310,6 @@ public class UninstallerActivity extends Activity { newIntent.putExtra(Intent.EXTRA_UNINSTALL_ALL_USERS, mDialogInfo.allUsers); newIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO, mDialogInfo.appInfo); newIntent.putExtra(UninstallUninstalling.EXTRA_APP_LABEL, label); - newIntent.putExtra(UninstallUninstalling.EXTRA_CLEAR_CONTRIBUTED_FILES, - clearContributedFiles); newIntent.putExtra(UninstallUninstalling.EXTRA_KEEP_DATA, keepData); newIntent.putExtra(PackageInstaller.EXTRA_CALLBACK, mDialogInfo.callback); @@ -362,7 +360,6 @@ public class UninstallerActivity extends Activity { Log.i(TAG, "Uninstalling extras=" + broadcastIntent.getExtras()); int flags = mDialogInfo.allUsers ? PackageManager.DELETE_ALL_USERS : 0; - flags |= clearContributedFiles ? PackageManager.DELETE_CONTRIBUTED_MEDIA : 0; flags |= keepData ? PackageManager.DELETE_KEEP_DATA : 0; ActivityThread.getPackageManager().getPackageInstaller().uninstall( diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/handheld/UninstallAlertDialogFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/handheld/UninstallAlertDialogFragment.java index 499da758739e..0a37cc6cb6ca 100644 --- a/packages/PackageInstaller/src/com/android/packageinstaller/handheld/UninstallAlertDialogFragment.java +++ b/packages/PackageInstaller/src/com/android/packageinstaller/handheld/UninstallAlertDialogFragment.java @@ -36,7 +36,6 @@ import android.os.UserHandle; import android.os.UserManager; import android.os.storage.StorageManager; import android.os.storage.StorageVolume; -import android.provider.MediaStore; import android.util.Log; import android.view.LayoutInflater; import android.view.View; @@ -54,57 +53,9 @@ public class UninstallAlertDialogFragment extends DialogFragment implements DialogInterface.OnClickListener { private static final String LOG_TAG = UninstallAlertDialogFragment.class.getSimpleName(); - private @Nullable CheckBox mClearContributedFiles; private @Nullable CheckBox mKeepData; /** - * Get number of bytes of the files contributed by the package. - * - * @param pkg The package that might have contributed files. - * @param user The user the package belongs to. - * - * @return The number of bytes. - */ - private long getContributedMediaSizeForUser(@NonNull String pkg, @NonNull UserHandle user) { - try { - return MediaStore.getContributedMediaSize(getContext(), pkg, user); - } catch (IOException e) { - Log.e(LOG_TAG, "Cannot determine amount of contributes files for " + pkg - + " (user " + user + ")", e); - return 0; - } - } - - /** - * Get number of bytes of the files contributed by the package. - * - * @param pkg The package that might have contributed files. - * @param user The user the package belongs to or {@code null} if files of all users should be - * counted. - * - * @return The number of bytes. - */ - private long getContributedMediaSize(@NonNull String pkg, @Nullable UserHandle user) { - UserManager userManager = getContext().getSystemService(UserManager.class); - - long contributedFileSize = 0; - - if (user == null) { - List<UserInfo> users = userManager.getUsers(); - - int numUsers = users.size(); - for (int i = 0; i < numUsers; i++) { - contributedFileSize += getContributedMediaSizeForUser(pkg, - UserHandle.of(users.get(i).id)); - } - } else { - contributedFileSize = getContributedMediaSizeForUser(pkg, user); - } - - return contributedFileSize; - } - - /** * Get number of bytes of the app data of the package. * * @param pkg The package that might have app data. @@ -212,8 +163,6 @@ public class UninstallAlertDialogFragment extends DialogFragment implements dialogBuilder.setNegativeButton(android.R.string.cancel, this); String pkg = dialogInfo.appInfo.packageName; - long contributedFileSize = getContributedMediaSize(pkg, - dialogInfo.allUsers ? null : dialogInfo.user); boolean suggestToKeepAppData; try { @@ -230,28 +179,17 @@ public class UninstallAlertDialogFragment extends DialogFragment implements appDataSize = getAppDataSize(pkg, dialogInfo.allUsers ? null : dialogInfo.user); } - if (contributedFileSize == 0 && appDataSize == 0) { + if (appDataSize == 0) { dialogBuilder.setMessage(messageBuilder.toString()); } else { LayoutInflater inflater = getContext().getSystemService(LayoutInflater.class); ViewGroup content = (ViewGroup) inflater.inflate(R.layout.uninstall_content_view, null); ((TextView) content.requireViewById(R.id.message)).setText(messageBuilder.toString()); - - if (contributedFileSize != 0) { - mClearContributedFiles = content.requireViewById(R.id.clearContributedFiles); - mClearContributedFiles.setVisibility(View.VISIBLE); - mClearContributedFiles.setText( - getString(R.string.uninstall_remove_contributed_files, - formatFileSize(getContext(), contributedFileSize))); - } - - if (appDataSize != 0) { - mKeepData = content.requireViewById(R.id.keepData); - mKeepData.setVisibility(View.VISIBLE); - mKeepData.setText(getString(R.string.uninstall_keep_data, - formatFileSize(getContext(), appDataSize))); - } + mKeepData = content.requireViewById(R.id.keepData); + mKeepData.setVisibility(View.VISIBLE); + mKeepData.setText(getString(R.string.uninstall_keep_data, + formatFileSize(getContext(), appDataSize))); dialogBuilder.setView(content); } @@ -263,7 +201,6 @@ public class UninstallAlertDialogFragment extends DialogFragment implements public void onClick(DialogInterface dialog, int which) { if (which == Dialog.BUTTON_POSITIVE) { ((UninstallerActivity) getActivity()).startUninstallProgress( - mClearContributedFiles != null && mClearContributedFiles.isChecked(), mKeepData != null && mKeepData.isChecked()); } else { ((UninstallerActivity) getActivity()).dispatchAborted(); diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/television/UninstallAlertFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/television/UninstallAlertFragment.java index ac5fd76f5bda..21d25f5b030f 100644 --- a/packages/PackageInstaller/src/com/android/packageinstaller/television/UninstallAlertFragment.java +++ b/packages/PackageInstaller/src/com/android/packageinstaller/television/UninstallAlertFragment.java @@ -99,7 +99,7 @@ public class UninstallAlertFragment extends GuidedStepFragment { public void onGuidedActionClicked(GuidedAction action) { if (isAdded()) { if (action.getId() == GuidedAction.ACTION_ID_OK) { - ((UninstallerActivity) getActivity()).startUninstallProgress(false, false); + ((UninstallerActivity) getActivity()).startUninstallProgress(false); getActivity().finish(); } else { ((UninstallerActivity) getActivity()).dispatchAborted(); diff --git a/packages/SettingsLib/AppPreference/res/layout/preference_app.xml b/packages/SettingsLib/AppPreference/res/layout/preference_app.xml index b198f5a35630..711dad4b5b55 100644 --- a/packages/SettingsLib/AppPreference/res/layout/preference_app.xml +++ b/packages/SettingsLib/AppPreference/res/layout/preference_app.xml @@ -48,37 +48,32 @@ android:paddingTop="16dp" android:paddingBottom="16dp"> - <TextView android:id="@android:id/title" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:singleLine="true" - android:textAppearance="?android:attr/textAppearanceListItem" - android:ellipsize="marquee" - android:fadingEdge="horizontal"/> + <TextView + android:id="@android:id/title" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:ellipsize="marquee" + android:fadingEdge="horizontal" + android:singleLine="true" + android:textAppearance="?android:attr/textAppearanceListItem"/> - <LinearLayout - android:id="@+id/summary_container" + <TextView + android:id="@android:id/summary" android:layout_width="match_parent" android:layout_height="wrap_content" - android:visibility="gone"> - <TextView android:id="@android:id/summary" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_weight="1" - android:textAppearance="?android:attr/textAppearanceSmall" - android:textAlignment="viewStart" - android:textColor="?android:attr/textColorSecondary"/> + android:textAppearance="?android:attr/textAppearanceSmall" + android:textColor="?android:attr/textColorSecondary"/> + + <TextView + android:id="@+id/appendix" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:ellipsize="end" + android:maxLines="1" + android:textAppearance="?android:attr/textAppearanceSmall" + android:textColor="?android:attr/textColorSecondary" + android:visibility="gone"/> - <TextView android:id="@+id/appendix" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_weight="1" - android:textAppearance="?android:attr/textAppearanceSmall" - android:textAlignment="viewEnd" - android:textColor="?android:attr/textColorSecondary" - android:maxLines="1" - android:ellipsize="end"/> - </LinearLayout> <ProgressBar android:id="@android:id/progress" style="?android:attr/progressBarStyleHorizontal" diff --git a/packages/SettingsLib/AppPreference/src/com/android/settingslib/widget/apppreference/AppPreference.java b/packages/SettingsLib/AppPreference/src/com/android/settingslib/widget/apppreference/AppPreference.java index ab51a346dc6f..e88ac565913c 100644 --- a/packages/SettingsLib/AppPreference/src/com/android/settingslib/widget/apppreference/AppPreference.java +++ b/packages/SettingsLib/AppPreference/src/com/android/settingslib/widget/apppreference/AppPreference.java @@ -17,7 +17,6 @@ package com.android.settingslib.widget.apppreference; import android.content.Context; -import android.text.TextUtils; import android.util.AttributeSet; import android.view.View; import android.widget.ProgressBar; @@ -52,8 +51,6 @@ public class AppPreference extends Preference { public void onBindViewHolder(PreferenceViewHolder view) { super.onBindViewHolder(view); - view.findViewById(R.id.summary_container) - .setVisibility(TextUtils.isEmpty(getSummary()) ? View.GONE : View.VISIBLE); final ProgressBar progress = (ProgressBar) view.findViewById(android.R.id.progress); if (mProgressVisible) { progress.setProgress(mProgress); diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/apppreference/AppPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/apppreference/AppPreferenceTest.java index 042616aa2015..284888888589 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/apppreference/AppPreferenceTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/apppreference/AppPreferenceTest.java @@ -57,24 +57,6 @@ public class AppPreferenceTest { } @Test - public void setSummary_showSummaryContainer() { - mPref.setSummary("test"); - mPref.onBindViewHolder(mHolder); - - assertThat(mHolder.findViewById(R.id.summary_container).getVisibility()) - .isEqualTo(View.VISIBLE); - } - - @Test - public void noSummary_hideSummaryContainer() { - mPref.setSummary(null); - mPref.onBindViewHolder(mHolder); - - assertThat(mHolder.findViewById(R.id.summary_container).getVisibility()) - .isEqualTo(View.GONE); - } - - @Test public void foobar_testName() { float iconSize = mContext.getResources().getDimension(R.dimen.secondary_app_icon_size); assertThat(Float.floatToIntBits(iconSize)).isEqualTo(Float.floatToIntBits(32)); diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java index ff25ad9f037b..9e46ad6061eb 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java @@ -3235,7 +3235,7 @@ public class SettingsProvider extends ContentProvider { } private final class UpgradeController { - private static final int SETTINGS_VERSION = 175; + private static final int SETTINGS_VERSION = 176; private final int mUserId; @@ -4286,6 +4286,31 @@ public class SettingsProvider extends ContentProvider { currentVersion = 175; } + if (currentVersion == 175) { + // Version 175: Set the default value for System Settings: + // RING_VIBRATION_INTENSITY. If the notification vibration intensity has been + // set and ring vibration intensity hasn't, the ring vibration intensity should + // followed notification vibration intensity. + + final SettingsState systemSettings = getSystemSettingsLocked(userId); + + Setting notificationVibrationIntensity = systemSettings.getSettingLocked( + Settings.System.NOTIFICATION_VIBRATION_INTENSITY); + + Setting ringVibrationIntensity = systemSettings.getSettingLocked( + Settings.System.RING_VIBRATION_INTENSITY); + + if (!notificationVibrationIntensity.isNull() + && ringVibrationIntensity.isNull()) { + systemSettings.insertSettingLocked( + Settings.System.RING_VIBRATION_INTENSITY, + notificationVibrationIntensity.getValue(), + null , true, SettingsState.SYSTEM_PACKAGE_NAME); + } + + currentVersion = 176; + } + // vXXX: Add new settings above this point. if (currentVersion != newVersion) { diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/DeviceConfigServiceTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/DeviceConfigServiceTest.java index df4656a6deeb..e588b3d594ca 100644 --- a/packages/SettingsProvider/test/src/com/android/providers/settings/DeviceConfigServiceTest.java +++ b/packages/SettingsProvider/test/src/com/android/providers/settings/DeviceConfigServiceTest.java @@ -147,7 +147,7 @@ public class DeviceConfigServiceTest { // make sValue the default value executeShellCommand( "device_config put " + sNamespace + " " + sKey + " " + sValue + " default"); - // make newValue the current value (as set by a trusted package) + // make newValue the current value (as set by a untrusted package) executeShellCommand( "device_config put " + sNamespace + " " + sKey + " " + newValue); String result = getFromContentProvider(mContentResolver, sNamespace, sKey); @@ -156,13 +156,7 @@ public class DeviceConfigServiceTest { // reset values that were set by untrusted packages executeShellCommand("device_config reset untrusted_defaults " + sNamespace); result = getFromContentProvider(mContentResolver, sNamespace, sKey); - // the current value was set by a trusted package, so it's not reset - assertEquals(newValue, result); - - // reset values that were set by untrusted or trusted packages - executeShellCommand("device_config reset trusted_defaults " + sNamespace); - result = getFromContentProvider(mContentResolver, sNamespace, sKey); - // the default value has been restored + // the current value was set by a untrusted package, so it's reset assertEquals(sValue, result); } diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index f0399c569cbf..441f88c193d6 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -179,6 +179,9 @@ <!-- Permission needed to run network tests in CTS --> <uses-permission android:name="android.permission.MANAGE_TEST_NETWORKS" /> + <!-- Permission needed to run keyguard manager tests in CTS --> + <uses-permission android:name="android.permission.CONTROL_KEYGUARD_SECURE_NOTIFICATIONS" /> + <application android:label="@string/app_label" android:defaultToDeviceProtectedStorage="true" android:directBootAware="true"> diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java index a9ff21fef99c..1060c7b7ce79 100644 --- a/packages/Shell/src/com/android/shell/BugreportProgressService.java +++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java @@ -1095,6 +1095,7 @@ public class BugreportProgressService extends Service { new AsyncTask<Void, Void, Void>() { @Override protected Void doInBackground(Void... params) { + Looper.prepare(); zipBugreport(info); sendBugreportNotification(info, takingScreenshot); return null; diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index 6df6c7355e3b..d654f5aa23e0 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -438,7 +438,7 @@ <activity android:name=".media.MediaProjectionPermissionActivity" android:exported="true" - android:theme="@style/Theme.AlertDialogHost" + android:theme="@style/Theme.MediaProjectionAlertDialog" android:finishOnCloseSystemDialogs="true" android:launchMode="singleTop" android:excludeFromRecents="true" diff --git a/packages/SystemUI/docs/physics-animation-layout-control-methods.png b/packages/SystemUI/docs/physics-animation-layout-control-methods.png Binary files differdeleted file mode 100644 index e77c676bc13f..000000000000 --- a/packages/SystemUI/docs/physics-animation-layout-control-methods.png +++ /dev/null diff --git a/packages/SystemUI/docs/physics-animation-layout.md b/packages/SystemUI/docs/physics-animation-layout.md index 300f63a3d285..488c4657333f 100644 --- a/packages/SystemUI/docs/physics-animation-layout.md +++ b/packages/SystemUI/docs/physics-animation-layout.md @@ -25,22 +25,74 @@ Value to add every time chained animations update the subsequent animation in th Returns a SpringForce instance to use for animations of the given property. This allows the controller to configure stiffness and bounciness values. Since the physics animations internally use SpringForce instances to hold inflight animation values, this method needs to return a new SpringForce instance each time - no constants allowed. ### Animation Control Methods - Once the layout has used the controller’s configuration properties to build the animations, the controller can use them to actually run animations. This is done for two reasons - reacting to a view being added or removed, or responding to another class (such as a touch handler or broadcast receiver) requesting an animation. ```onChildAdded```, ```onChildRemoved```, and ```setChildVisibility``` are called automatically by the layout, giving the controller the opportunity to animate the child in/out/visible/gone. Custom methods are called by anyone with access to the controller instance to do things like expand, collapse, or move the child views. -In either case, the controller has access to the layout’s protected ```animateValueForChildAtIndex(ViewProperty property, int index, float value)``` method. This method is used to actually run an animation. +In either case, the controller can use `super.animationForChild` to retrieve a `PhysicsPropertyAnimator` instance. This object behaves similarly to the `ViewPropertyAnimator` object you would receive from `View.animate()`. -For example, moving the first child view to *(100, 200)*: +#### PhysicsPropertyAnimator + +Like `ViewPropertyAnimator`, `PhysicsPropertyAnimator` provides the following methods for animating properties: +- `alpha(float)` +- `translationX/Y/Z(float)` +- `scaleX/Y(float)` + +It also provides the following configuration methods: +- `withStartDelay(int)`, for starting the animation after a given delay. +- `withStartVelocity(float)`, for starting the animation with the given start velocity. +- `withPositionStartVelocities(float, float)`, for setting specific start velocities for TRANSLATION_X and TRANSLATION_Y, since these typically differ. +- `start(Runnable)`, to start the animation, with an optional end action to call when the animations for every property (including chained animations) have completed. + +For example, moving the first child view: ``` -animateValueForChildAtIndex(TRANSLATION_X, 0, 100); -animateValueForChildAtIndex(TRANSLATION_Y, 0, 200); +animationForChild(getChildAt(0)) + .translationX(100) + .translationY(200) + .setStartDelay(500) + .start(); ``` -This would use the physics animations constructed by the layout to spring the view to *(100, 200)*. +This would use the physics animations constructed by the layout to spring the view to *(100, 200)* after 500ms. If the controller’s ```getNextAnimationInChain``` method set up the first child’s TRANSLATION_X/Y animations to be chained to the second child’s, this would result in the second child also springing towards (100, 200), plus any offset returned by ```getOffsetForChainedPropertyAnimation```. +##### Advanced Usage +The animator has additional functionality to reduce the amount of boilerplate required for typical physics animation use cases. + +- Often, animations will set starting values for properties before the animation begins. Property methods like `translationX` have an overloaded variant: `translationX(from, to)`. When `start()` is called, the animation will set the view's translationX property to `from` before beginning the animation to `to`. +- We may want to use different end actions for each property. For example, if we're animating a view to the bottom of the screen, and also fading it out, we might want to perform an action as soon as the fade out is complete. We can use `alpha(to, endAction)`, which will call endAction as soon as the alpha animation is finished. A special case is `position(x, y, endAction)`, where the endAction is called when both translationX and translationY animations have completed. + +`PhysicsAnimationController` also provides `animationsForChildrenFromIndex(int, ChildAnimationConfigurator)`. This is a convenience method for starting animations on multiple child views, starting at the given index. The `ChildAnimationConfigurator` is called with a `PhysicsPropertyAnimator` for each child, where calls to methods like `translationX` and `withStartVelocity` can be made. `animationsForChildrenFromIndex` returns a `MultiAnimationStarter` with a single method, `startAll(endAction)`, which starts all of the animations and calls the end action when they have all completed. + +##### Examples +Spring the stack of bubbles (whose animations are chained) to the bottom of the screen, shrinking them to 50% size. Once the first bubble is done shrinking, begin fading them out, and then remove them all from the parent once all bubbles have faded out: + +``` +animationForChild(leadBubble) + .position(screenCenter, screenBottom) + .scaleX(0.5f) + .scaleY(0.5f, () -> animationForChild(leadBubble).alpha(0).start(removeAllFromParent)) + .start(); +``` + +'Drop in' a child view that was just added to the layout: + +``` +animationForChild(newView) + .scaleX(1.15f /* from */, 1f /* to */) + .scaleY(1.15f /* from */, 1f /* to */) + .alpha(0f /* from */, 1f /* to */) + .position(posX, posY) + .start(); +``` + +Move every view except for the first to x = (index - 1) * 50, then remove the first view. + +``` +animationsForChildrenFromIndex(1, (index, anim) -> anim.translationX((index - 1) * 50)) + .startAll(removeFirstView); +``` + ## PhysicsAnimationLayout The layout itself is a FrameLayout descendant with a few extra methods: diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/VolumeDialogController.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/VolumeDialogController.java index 2b10ccb4ac1a..3d2f570bde87 100644 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/VolumeDialogController.java +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/VolumeDialogController.java @@ -60,7 +60,8 @@ public interface VolumeDialogController { boolean areCaptionsEnabled(); void setCaptionsEnabled(boolean isEnabled); - void getCaptionsComponentState(); + + void getCaptionsComponentState(boolean fromTooltip); @ProvidesInterface(version = StreamState.VERSION) public static final class StreamState { @@ -190,6 +191,6 @@ public interface VolumeDialogController { void onScreenOff(); void onShowSafetyWarning(int flags); void onAccessibilityModeChanged(Boolean showA11yStream); - void onCaptionComponentStateChanged(Boolean isComponentEnabled); + void onCaptionComponentStateChanged(Boolean isComponentEnabled, Boolean fromTooltip); } } diff --git a/packages/SystemUI/res/drawable/ic_remove_no_shadow.xml b/packages/SystemUI/res/drawable/ic_remove_no_shadow.xml new file mode 100644 index 000000000000..bed06b58e823 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_remove_no_shadow.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0" + android:tint="?android:attr/textColorPrimary" > + <path + android:fillColor="#FFFFFFFF" + android:pathData="M13.41,12l5.29-5.29c0.39-0.39,0.39-1.02,0-1.41c-0.39-0.39-1.02-0.39-1.41,0L12,10.59L6.71, + 5.29c-0.39-0.39-1.02-0.39-1.41,0c-0.39,0.39-0.39,1.02,0,1.41L10.59,12l-5.29,5.29c-0.39,0.39-0.39,1.02, + 0,1.41c0.39,0.39,1.02,0.39,1.41,0L12,13.41l5.29,5.29c0.39,0.39,1.02,0.39,1.41,0c0.39-0.39,0.39-1.02,0-1.41L13.41,12z"/> +</vector>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/ic_signal_sensors.xml b/packages/SystemUI/res/drawable/ic_signal_sensors.xml deleted file mode 100644 index faaddf6473c4..000000000000 --- a/packages/SystemUI/res/drawable/ic_signal_sensors.xml +++ /dev/null @@ -1,28 +0,0 @@ -<!-- - Copyright (C) 2018 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. ---> - -<vector android:height="48dp" android:viewportHeight="5" - android:viewportWidth="5" android:width="48dp" xmlns:android="http://schemas.android.com/apk/res/android"> - <path android:fillColor="#00000000" - android:pathData="m4.762,0.661 l-4.233,4.233" - android:strokeAlpha="1" android:strokeColor="#000000" - android:strokeLineCap="round" android:strokeLineJoin="miter" android:strokeWidth=".5"/> - <path android:fillColor="#00000000" - android:pathData="M0.265,2.778L1.058,2.778l0.529,-1.323 0.529,2.646 0.529,-3.175 0.529,2.646 0.529,-1.587 0.265,0.794h1.058" - android:strokeAlpha="1" android:strokeColor="#000000" - android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth=".33"/> -</vector> - diff --git a/packages/SystemUI/res/drawable/ic_volume_odi_captions.xml b/packages/SystemUI/res/drawable/ic_volume_odi_captions.xml index 9b907290d0e9..675aee9cd1dd 100644 --- a/packages/SystemUI/res/drawable/ic_volume_odi_captions.xml +++ b/packages/SystemUI/res/drawable/ic_volume_odi_captions.xml @@ -19,6 +19,23 @@ android:viewportWidth="24" android:viewportHeight="24"> <path - android:fillColor="#FF000000" - android:pathData="M20,4C21.1,4 22,4.9 22,6L22,18C22,19.1 21.1,20 20,20L4,20C2.9,20 2,19.1 2,18L2,6C2,4.9 2.9,4 4,4L20,4ZM20,18L20,6L4,6L4,18L20,18ZM6,10L8,10L8,12L6,12L6,10ZM6,14L14,14L14,16L6,16L6,14ZM16,14L18,14L18,16L16,16L16,14ZM10,10L18,10L18,12L10,12L10,10Z"/> + android:pathData="M16,12h2v2h-2z" + android:fillColor="#1A73E8" + android:fillType="nonZero"/> + <path + android:pathData="M6,12h8v2h-8z" + android:fillColor="#1A73E8" + android:fillType="nonZero"/> + <path + android:pathData="M20,2C21.1046,2 22,2.8954 22,4L22,16C22,17.1046 21.1046,18 20,18L6,18L2,22L2,4C2,2.8954 2.8954,2 4,2L20,2ZM20,16L20,4L4,4L4,16L20,16Z" + android:fillColor="#1A73E8" + android:fillType="nonZero"/> + <path + android:pathData="M6,8h2v2h-2z" + android:fillColor="#1A73E8" + android:fillType="nonZero"/> + <path + android:pathData="M10,8h8v2h-8z" + android:fillColor="#1A73E8" + android:fillType="nonZero"/> </vector> diff --git a/packages/SystemUI/res/drawable/ic_volume_odi_captions_disabled.xml b/packages/SystemUI/res/drawable/ic_volume_odi_captions_disabled.xml index f3d8d3b9c2e2..e818455950de 100644 --- a/packages/SystemUI/res/drawable/ic_volume_odi_captions_disabled.xml +++ b/packages/SystemUI/res/drawable/ic_volume_odi_captions_disabled.xml @@ -19,6 +19,19 @@ android:viewportWidth="24" android:viewportHeight="24"> <path - android:fillColor="#FF000000" - android:pathData="M16.9675,14L18,14L18,15.0275L16.9675,14ZM20,17.0176L20,6L8.9281,6L6.9182,4L20,4C21.1,4 22,4.9 22,6L22,18C22,18.2949 21.9353,18.5755 21.8194,18.8281L20,17.0176ZM12.9478,10L18,10L18,12L14.9576,12L12.9478,10ZM1.2823,0.8824L22.8489,22.4489L21.6337,23.6641L17.9696,20L4,20C2.9,20 2,19.1 2,18L2,6C2,5.4577 2.2188,4.964 2.5724,4.6028L0.0672,2.0975L1.2823,0.8824ZM13.9696,16L6,16L6,14L11.9696,14L8,10.0304L8,12L6,12L6,10L7.9696,10L4,6.0304L4,18L15.9696,18L13.9696,16Z"/> + android:pathData="M2.07,0.64L22,20.59L20.6,22L16.6,18L6,18L2,22L2,4C2.0006,3.8236 2.0276,3.6484 2.08,3.48L0.66,2.05L2.07,0.64ZM5.17,16L14.6,16L12.6,14L6,14L6,12L10.6,12L8,9.4L8,10L6,10L6,8L6.6,8L4,5.4L4,16L5.17,16Z" + android:fillColor="#1A73E8" + android:fillType="nonZero"/> + <path + android:pathData="M18,12l-1.74,0l1.74,1.74z" + android:fillColor="#1A73E8" + android:fillType="nonZero"/> + <path + android:pathData="M18,8l-5.74,0l2,2l3.74,0z" + android:fillColor="#1A73E8" + android:fillType="nonZero"/> + <path + android:pathData="M20,4L20,15.74L21.53,17.27C21.8296,16.9142 21.9958,16.4651 22,16L22,4C22,2.8954 21.1046,2 20,2L6.26,2L8.26,4L20,4Z" + android:fillColor="#1A73E8" + android:fillType="nonZero"/> </vector> diff --git a/packages/SystemUI/res/drawable/stat_sys_sensors_off.xml b/packages/SystemUI/res/drawable/stat_sys_sensors_off.xml new file mode 100644 index 000000000000..ca8f9931f148 --- /dev/null +++ b/packages/SystemUI/res/drawable/stat_sys_sensors_off.xml @@ -0,0 +1,41 @@ +<!-- + 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. +--> + +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:insetLeft="3dp" + android:insetRight="3dp" + android:width="17dp" + android:height="17dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + <path + android:pathData="M21.966,2 L2,22" + android:strokeLineCap="round" + android:strokeColor="#000000" + android:fillColor="#00000000" + android:strokeWidth="1.6521436" + android:strokeLineJoin="miter" + android:strokeAlpha="1"/> + <path + android:pathData="M0.752,12L4.496,12l2.496,-6.25 2.496,12.5 2.496,-15 2.496,12.5 2.496,-7.5 1.248,3.75h4.992" + android:strokeLineCap="round" + android:strokeColor="#000000" + android:fillColor="#00000000" + android:strokeWidth="1.25090861" + android:strokeLineJoin="round" + android:strokeAlpha="1"/> +</vector> + diff --git a/packages/SystemUI/res/drawable/volume_tool_tip_rounded_bg.xml b/packages/SystemUI/res/drawable/volume_tool_tip_rounded_bg.xml new file mode 100644 index 000000000000..22e8c48b6e6e --- /dev/null +++ b/packages/SystemUI/res/drawable/volume_tool_tip_rounded_bg.xml @@ -0,0 +1,19 @@ +<!-- + ~ 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 + --> +<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> + <solid android:color="?android:attr/colorAccent" /> + <corners android:radius="8dp" /> +</shape>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout-land/volume_dialog.xml b/packages/SystemUI/res/layout-land/volume_dialog.xml new file mode 100644 index 000000000000..c1e74ef02623 --- /dev/null +++ b/packages/SystemUI/res/layout-land/volume_dialog.xml @@ -0,0 +1,143 @@ +<!-- + ~ 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 + --> +<FrameLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/volume_dialog_container" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:gravity="right" + android:layout_gravity="right" + android:background="@android:color/transparent" + android:theme="@style/volume_dialog_theme"> + + <FrameLayout + android:id="@+id/volume_dialog" + android:minWidth="@dimen/volume_dialog_panel_width" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:gravity="right" + android:layout_gravity="right" + android:background="@android:color/transparent" + android:paddingRight="@dimen/volume_dialog_panel_transparent_padding_right" + android:paddingTop="@dimen/volume_dialog_panel_transparent_padding" + android:paddingBottom="@dimen/volume_dialog_panel_transparent_padding" + android:paddingLeft="@dimen/volume_dialog_panel_transparent_padding" + android:clipToPadding="false"> + + <FrameLayout + android:id="@+id/ringer" + android:layout_width="@dimen/volume_dialog_ringer_size" + android:layout_height="@dimen/volume_dialog_ringer_size" + android:layout_marginBottom="@dimen/volume_dialog_spacer" + android:gravity="right" + android:layout_gravity="right" + android:translationZ="@dimen/volume_dialog_elevation" + android:clipToPadding="false" + android:background="@drawable/rounded_bg_full"> + <com.android.keyguard.AlphaOptimizedImageButton + android:id="@+id/ringer_icon" + style="@style/VolumeButtons" + android:background="@drawable/rounded_ripple" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:tint="@color/accent_tint_color_selector" + android:layout_gravity="center" + android:soundEffectsEnabled="false" /> + + <include layout="@layout/volume_dnd_icon" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginRight="@dimen/volume_dialog_stream_padding" + android:layout_marginTop="6dp"/> + </FrameLayout> + + <LinearLayout + android:id="@+id/main" + android:layout_width="wrap_content" + android:minWidth="@dimen/volume_dialog_panel_width" + android:layout_height="wrap_content" + android:layout_marginTop="68dp" + android:gravity="right" + android:layout_gravity="right" + android:orientation="vertical" + android:translationZ="@dimen/volume_dialog_elevation" + android:clipChildren="false" + android:clipToPadding="false" + android:background="@drawable/rounded_bg_full" > + <LinearLayout + android:id="@+id/volume_dialog_rows" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:minWidth="@dimen/volume_dialog_panel_width" + android:gravity="center" + android:orientation="horizontal" + android:paddingRight="@dimen/volume_dialog_stream_padding" + android:paddingLeft="@dimen/volume_dialog_stream_padding"> + <!-- volume rows added and removed here! :-) --> + </LinearLayout> + <FrameLayout + android:id="@+id/settings_container" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:background="@drawable/rounded_bg_bottom_background"> + <com.android.keyguard.AlphaOptimizedImageButton + android:id="@+id/settings" + android:src="@drawable/ic_tune_black_16dp" + android:layout_width="@dimen/volume_dialog_tap_target_size" + android:layout_height="@dimen/volume_dialog_tap_target_size" + android:layout_gravity="center" + android:contentDescription="@string/accessibility_volume_settings" + android:background="@drawable/ripple_drawable_20dp" + android:tint="?android:attr/textColorSecondary" + android:soundEffectsEnabled="false" /> + </FrameLayout> + </LinearLayout> + + <FrameLayout + android:id="@+id/odi_captions" + android:layout_width="@dimen/volume_dialog_caption_size" + android:layout_height="@dimen/volume_dialog_caption_size" + android:layout_marginRight="68dp" + android:gravity="right" + android:layout_gravity="right" + android:clipToPadding="false" + android:translationZ="@dimen/volume_dialog_elevation" + android:background="@drawable/rounded_bg_full"> + <com.android.keyguard.AlphaOptimizedImageButton + android:id="@+id/odi_captions_icon" + android:src="@drawable/ic_volume_odi_captions_disabled" + style="@style/VolumeButtons" + android:background="@drawable/rounded_ripple" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:tint="@color/accent_tint_color_selector" + android:layout_gravity="center" + android:soundEffectsEnabled="false" /> + </FrameLayout> + + <ViewStub + android:id="@+id/odi_captions_tooltip_stub" + android:inflatedId="@+id/odi_captions_tooltip_view" + android:layout="@layout/volume_tool_tip_view" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginRight="@dimen/volume_tool_tip_right_margin" + android:layout_marginTop="@dimen/volume_tool_tip_top_margin" + android:layout_gravity="right"/> + + </FrameLayout> + +</FrameLayout>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/biometric_dialog.xml b/packages/SystemUI/res/layout/biometric_dialog.xml index 83557f266da0..8f7a45f02c46 100644 --- a/packages/SystemUI/res/layout/biometric_dialog.xml +++ b/packages/SystemUI/res/layout/biometric_dialog.xml @@ -128,7 +128,6 @@ android:textSize="12sp" android:gravity="center_horizontal" android:accessibilityLiveRegion="polite" - android:contentDescription="@string/accessibility_biometric_dialog_help_area" android:textColor="?android:attr/textColorSecondary"/> <LinearLayout diff --git a/packages/SystemUI/res/layout/bubble_permission_view.xml b/packages/SystemUI/res/layout/bubble_permission_view.xml index c9d8a9128d7c..df5264cc7706 100644 --- a/packages/SystemUI/res/layout/bubble_permission_view.xml +++ b/packages/SystemUI/res/layout/bubble_permission_view.xml @@ -58,7 +58,7 @@ android:layout_height="wrap_content" android:layout_marginTop="8dp" android:text="@string/bubbles_prompt" - style="@*android:style/TextAppearance.Material.Body1" /> + style="@*android:style/TextAppearance.DeviceDefault.Notification.Title"/> <!-- Buttons --> <LinearLayout diff --git a/packages/SystemUI/res/layout/media_projection_dialog_title.xml b/packages/SystemUI/res/layout/media_projection_dialog_title.xml new file mode 100644 index 000000000000..c4d784ba23f7 --- /dev/null +++ b/packages/SystemUI/res/layout/media_projection_dialog_title.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright 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. +--> + +<RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" + xmlns:android="http://schemas.android.com/apk/res/android" + android:theme="@style/Theme.MediaProjectionAlertDialog" + android:paddingStart="?android:attr/dialogPreferredPadding" + android:paddingEnd="?android:attr/dialogPreferredPadding" + android:paddingTop="?android:attr/dialogPreferredPadding"> + <ImageView + android:id="@+id/dialog_icon" + android:src="@drawable/ic_media_projection_permission" + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:layout_marginBottom="20dp" + android:layout_centerInParent="true"/> + <TextView + android:id="@+id/dialog_title" + android:gravity="center" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_below="@id/dialog_icon" + android:textColor="?android:attr/colorPrimary" + android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Title" /> +</RelativeLayout> diff --git a/packages/SystemUI/res/layout/qs_carrier.xml b/packages/SystemUI/res/layout/qs_carrier.xml index 6edccbabb823..b94a3163804f 100644 --- a/packages/SystemUI/res/layout/qs_carrier.xml +++ b/packages/SystemUI/res/layout/qs_carrier.xml @@ -24,7 +24,8 @@ android:background="@android:color/transparent" android:clickable="false" android:clipChildren="false" - android:clipToPadding="false" > + android:clipToPadding="false" + android:focusable="true" > <include layout="@layout/mobile_signal_group" diff --git a/packages/SystemUI/res/layout/qs_carrier_group.xml b/packages/SystemUI/res/layout/qs_carrier_group.xml index 20190b7fff0d..36f382b19f4a 100644 --- a/packages/SystemUI/res/layout/qs_carrier_group.xml +++ b/packages/SystemUI/res/layout/qs_carrier_group.xml @@ -34,7 +34,8 @@ android:id="@+id/qs_carrier_divider1" android:layout_width="@dimen/qs_header_carrier_separator_width" android:layout_height="match_parent" - android:visibility="gone" /> + android:visibility="gone" + android:importantForAccessibility="no"/> <include layout="@layout/qs_carrier" @@ -47,7 +48,8 @@ android:layout_width="@dimen/qs_header_carrier_separator_width" android:layout_height="match_parent" android:layout_weight="1" - android:visibility="gone" /> + android:visibility="gone" + android:importantForAccessibility="no"/> <include layout="@layout/qs_carrier" diff --git a/packages/SystemUI/res/layout/qs_footer_impl.xml b/packages/SystemUI/res/layout/qs_footer_impl.xml index 669d53bfdc60..6c8110b31c17 100644 --- a/packages/SystemUI/res/layout/qs_footer_impl.xml +++ b/packages/SystemUI/res/layout/qs_footer_impl.xml @@ -30,13 +30,6 @@ android:clipChildren="false" android:clipToPadding="false"> - <View - android:id="@+id/qs_footer_divider" - android:layout_width="match_parent" - android:layout_height="1dp" - android:layout_gravity="top" - android:background="?android:attr/dividerHorizontal"/> - <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" diff --git a/packages/SystemUI/res/layout/quick_qs_status_icons.xml b/packages/SystemUI/res/layout/quick_qs_status_icons.xml index 74002ac38c02..dc31b70cd091 100644 --- a/packages/SystemUI/res/layout/quick_qs_status_icons.xml +++ b/packages/SystemUI/res/layout/quick_qs_status_icons.xml @@ -19,14 +19,16 @@ android:id="@+id/quick_qs_status_icons" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginTop="8dp" + android:layout_marginTop="@dimen/qs_header_top_margin" android:layout_marginBottom="14dp" android:layout_marginStart="@dimen/status_bar_padding_start" android:layout_marginEnd="@dimen/status_bar_padding_end" android:layout_below="@id/quick_status_bar_system_icons" android:clipChildren="false" android:clipToPadding="false" - android:minHeight="20dp" > + android:minHeight="20dp" + android:clickable="false" + android:focusable="true"> <com.android.systemui.statusbar.policy.DateView android:id="@+id/date" diff --git a/packages/SystemUI/res/layout/quick_settings_header_info.xml b/packages/SystemUI/res/layout/quick_settings_header_info.xml index 075f51d2e17a..da640fd1e164 100644 --- a/packages/SystemUI/res/layout/quick_settings_header_info.xml +++ b/packages/SystemUI/res/layout/quick_settings_header_info.xml @@ -19,7 +19,9 @@ android:layout_width="match_parent" android:layout_height="@dimen/qs_header_tooltip_height" android:layout_below="@id/quick_status_bar_system_icons" - android:layout_marginTop="12dp"> + android:layout_marginTop="@dimen/qs_header_top_margin" + android:paddingStart="@dimen/status_bar_padding_start" + android:paddingEnd="@dimen/status_bar_padding_end"> <TextView android:id="@+id/long_press_tooltip" diff --git a/packages/SystemUI/res/layout/volume_dialog.xml b/packages/SystemUI/res/layout/volume_dialog.xml index 130be89914a8..1d0a24274b12 100644 --- a/packages/SystemUI/res/layout/volume_dialog.xml +++ b/packages/SystemUI/res/layout/volume_dialog.xml @@ -15,32 +15,38 @@ --> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/volume_dialog_container" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:gravity="right" + android:layout_gravity="right" android:background="@android:color/transparent" - android:theme="@style/qs_theme"> + android:theme="@style/volume_dialog_theme"> + <!-- right-aligned to be physically near volume button --> <LinearLayout android:id="@+id/volume_dialog" android:minWidth="@dimen/volume_dialog_panel_width" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_gravity="center_vertical|right" + android:gravity="right" + android:layout_gravity="right" android:background="@android:color/transparent" android:paddingRight="@dimen/volume_dialog_panel_transparent_padding_right" android:paddingTop="@dimen/volume_dialog_panel_transparent_padding" android:paddingBottom="@dimen/volume_dialog_panel_transparent_padding" android:paddingLeft="@dimen/volume_dialog_panel_transparent_padding" android:orientation="vertical" - android:clipToPadding="false" > + android:clipToPadding="false"> <FrameLayout android:id="@+id/ringer" android:layout_width="@dimen/volume_dialog_ringer_size" android:layout_height="@dimen/volume_dialog_ringer_size" android:layout_marginBottom="@dimen/volume_dialog_spacer" - android:translationZ="@dimen/volume_dialog_elevation" + android:gravity="right" android:layout_gravity="right" + android:translationZ="@dimen/volume_dialog_elevation" android:clipToPadding="false" android:background="@drawable/rounded_bg_full"> <com.android.keyguard.AlphaOptimizedImageButton @@ -62,11 +68,14 @@ <LinearLayout android:id="@+id/main" - android:layout_width="wrap_content" android:minWidth="@dimen/volume_dialog_panel_width" + android:layout_width="wrap_content" android:layout_height="wrap_content" + android:gravity="right" + android:layout_gravity="right" android:orientation="vertical" android:translationZ="@dimen/volume_dialog_elevation" + android:clipChildren="false" android:clipToPadding="false" android:background="@drawable/rounded_bg_full" > <LinearLayout @@ -103,10 +112,10 @@ android:layout_width="@dimen/volume_dialog_caption_size" android:layout_height="@dimen/volume_dialog_caption_size" android:layout_marginTop="@dimen/volume_dialog_spacer" - android:translationZ="@dimen/volume_dialog_elevation" + android:gravity="right" android:layout_gravity="right" android:clipToPadding="false" - android:visibility="gone" + android:translationZ="@dimen/volume_dialog_elevation" android:background="@drawable/rounded_bg_full"> <com.android.keyguard.AlphaOptimizedImageButton android:id="@+id/odi_captions_icon" @@ -121,4 +130,15 @@ </FrameLayout> </LinearLayout> + + <ViewStub + android:id="@+id/odi_captions_tooltip_stub" + android:inflatedId="@+id/odi_captions_tooltip_view" + android:layout="@layout/volume_tool_tip_view" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="bottom | right" + android:layout_marginRight="@dimen/volume_tool_tip_right_margin" + android:layout_marginBottom="@dimen/volume_tool_tip_bottom_margin"/> + </FrameLayout>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/volume_dialog_row.xml b/packages/SystemUI/res/layout/volume_dialog_row.xml index 6128da8627a9..b9efc5be70c1 100644 --- a/packages/SystemUI/res/layout/volume_dialog_row.xml +++ b/packages/SystemUI/res/layout/volume_dialog_row.xml @@ -20,7 +20,7 @@ android:layout_width="@dimen/volume_dialog_panel_width" android:clipChildren="false" android:clipToPadding="false" - android:theme="@style/qs_theme"> + android:theme="@style/volume_dialog_theme"> <LinearLayout android:layout_height="wrap_content" diff --git a/packages/SystemUI/res/layout/volume_tool_tip_view.xml b/packages/SystemUI/res/layout/volume_tool_tip_view.xml new file mode 100644 index 000000000000..9fe885ebefc7 --- /dev/null +++ b/packages/SystemUI/res/layout/volume_tool_tip_view.xml @@ -0,0 +1,63 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> + +<com.android.systemui.volume.VolumeToolTipView + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/tooltip_view" + android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:orientation="horizontal"> + + <LinearLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:paddingStart="16dp" + android:paddingEnd="4dp" + android:background="@drawable/volume_tool_tip_rounded_bg" + android:orientation="horizontal"> + + <TextView + android:id="@+id/text" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" + android:textColor="@android:color/white" + android:text="@string/volume_odi_captions_tip" + android:textSize="14sp"/> + <ImageView + android:id="@+id/dismiss" + android:layout_width="40dp" + android:layout_height="40dp" + android:layout_gravity="center_vertical" + android:padding="12dp" + android:layout_marginStart="2dp" + android:layout_marginEnd="2dp" + android:alpha="0.7" + android:src="@drawable/ic_remove_no_shadow" + android:tint="@android:color/white" + android:background="?android:attr/selectableItemBackgroundBorderless" + android:contentDescription="@string/accessibility_volume_close_odi_captions_tip"/> + </LinearLayout> + + <View + android:id="@+id/arrow" + android:layout_width="8dp" + android:layout_height="10dp" + android:layout_marginLeft="-2dp" + android:layout_gravity="center_vertical"/> + +</com.android.systemui.volume.VolumeToolTipView>
\ No newline at end of file diff --git a/packages/SystemUI/res/values-land/dimens.xml b/packages/SystemUI/res/values-land/dimens.xml index bb0c6f6acb06..e7689399f507 100644 --- a/packages/SystemUI/res/values-land/dimens.xml +++ b/packages/SystemUI/res/values-land/dimens.xml @@ -33,5 +33,7 @@ <integer name="quick_settings_num_columns">4</integer> <bool name="quick_settings_wide">true</bool> <dimen name="qs_detail_margin_top">0dp</dimen> - <dimen name="qs_paged_tile_layout_padding_bottom">0dp</dimen> + + <dimen name="volume_tool_tip_right_margin">136dp</dimen> + <dimen name="volume_tool_tip_top_margin">12dp</dimen> </resources> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 30cbaaad33df..1da1405f469a 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -206,10 +206,10 @@ <dimen name="status_bar_icon_padding">0dp</dimen> <!-- the padding on the start of the statusbar --> - <dimen name="status_bar_padding_start">6dp</dimen> + <dimen name="status_bar_padding_start">8dp</dimen> <!-- the padding on the end of the statusbar --> - <dimen name="status_bar_padding_end">6dp</dimen> + <dimen name="status_bar_padding_end">8dp</dimen> <!-- the radius of the overflow dot in the status bar --> <dimen name="overflow_dot_radius">2dp</dimen> @@ -351,6 +351,12 @@ <dimen name="volume_dialog_elevation">9dp</dimen> + <dimen name="volume_tool_tip_right_margin">76dp</dimen> + + <dimen name="volume_tool_tip_bottom_margin">32dp</dimen> + + <dimen name="volume_tool_tip_arrow_corner_radius">2dp</dimen> + <!-- Gravity for the notification panel --> <integer name="notification_panel_layout_gravity">0x31</integer><!-- center_horizontal|top --> @@ -427,7 +433,7 @@ <dimen name="qs_detail_item_icon_marginEnd">20dp</dimen> <dimen name="qs_header_tooltip_height">18dp</dimen> <dimen name="qs_header_alarm_icon_size">18dp</dimen> - <dimen name="qs_header_mobile_icon_size">18dp</dimen> + <dimen name="qs_header_mobile_icon_size">@dimen/status_bar_icon_drawing_size</dimen> <dimen name="qs_header_alarm_text_margin_start">6dp</dimen> <dimen name="qs_header_separator_width">8dp</dimen> <dimen name="qs_header_carrier_separator_width">6dp</dimen> @@ -436,7 +442,8 @@ <dimen name="qs_footer_padding_start">16dp</dimen> <dimen name="qs_footer_padding_end">16dp</dimen> <dimen name="qs_footer_icon_size">16dp</dimen> - <dimen name="qs_paged_tile_layout_padding_bottom">16dp</dimen> + <dimen name="qs_paged_tile_layout_padding_bottom">0dp</dimen> + <dimen name="qs_header_top_margin">12dp</dimen> <dimen name="qs_notif_collapsed_space">64dp</dimen> diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml index 05cf040a3772..501b1b56a848 100644 --- a/packages/SystemUI/res/values/ids.xml +++ b/packages/SystemUI/res/values/ids.xml @@ -111,13 +111,14 @@ <!-- Optional cancel button on Keyguard --> <item type="id" name="cancel_button"/> - <!-- For saving DynamicAnimation physics animations as view tags. --> + <!-- For saving PhysicsAnimationLayout animations/animators as view tags. --> <item type="id" name="translation_x_dynamicanimation_tag"/> <item type="id" name="translation_y_dynamicanimation_tag"/> <item type="id" name="translation_z_dynamicanimation_tag"/> <item type="id" name="alpha_dynamicanimation_tag"/> <item type="id" name="scale_x_dynamicanimation_tag"/> <item type="id" name="scale_y_dynamicanimation_tag"/> + <item type="id" name="physics_animator_tag"/> <!-- Global Actions Menu --> <item type="id" name="global_actions_view" /> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index c6c2763f7801..265c62012250 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -279,8 +279,6 @@ <!-- Button name for "Cancel". [CHAR LIMIT=NONE] --> <string name="cancel">Cancel</string> - <!-- Content description for the error/help message are when the system-provided fingerprint dialog is showing, for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> - <string name="accessibility_biometric_dialog_help_area">Help message area</string> <!-- Message shown when a biometric is authenticated, asking the user to confirm authentication [CHAR LIMIT=30] --> <string name="biometric_dialog_confirm">Confirm</string> <!-- Button name on BiometricPrompt shown when a biometric is detected but not authenticated. Tapping the button resumes authentication [CHAR_LIMIT=30] --> @@ -447,6 +445,9 @@ <!-- Content description of the cell data being disabled. [CHAR LIMIT=NONE] --> <string name="cell_data_off_content_description">Mobile data off</string> + <!-- Content description of the cell data for not default subscription. [CHAR LIMIT=NONE] --> + <string name="not_default_data_content_description">Not set to use data</string> + <!-- Content description of the cell data being disabled but shortened. [CHAR LIMIT=20] --> <string name="cell_data_off">Off</string> @@ -1069,10 +1070,10 @@ <string name="battery_saver_notification_action_text">Turn off Battery Saver</string> <!-- Media projection permission dialog warning text. [CHAR LIMIT=NONE] --> - <string name="media_projection_dialog_text"><xliff:g id="app_seeking_permission" example="Hangouts">%s</xliff:g> will start capturing the played audio and everything on your screen including notifications, passwords, photos, messages and payment information.</string> + <string name="media_projection_dialog_text">While recording or casting, <xliff:g id="app_seeking_permission" example="Hangouts">%s</xliff:g> can capture any sensitive information, such as audio that you play and your passwords, payment info, photos, and messages.</string> <!-- Media projection permission dialog warning title. [CHAR LIMIT=NONE] --> - <string name="media_projection_dialog_title">Allow <xliff:g id="app_seeking_permission" example="Hangouts">%s</xliff:g> to record or cast your screen and played audio?</string> + <string name="media_projection_dialog_title">Exposing sensitive info during casting/recording </string> <!-- Media projection permission dialog permanent grant check box. [CHAR LIMIT=NONE] --> <string name="media_projection_remember_text">Don\'t show again</string> @@ -1307,6 +1308,12 @@ <!-- Content description for accessibility (not shown on the screen): volume dialog collapse button. [CHAR LIMIT=NONE] --> <string name="accessibility_volume_collapse">Collapse</string> + <!-- Label for the odi caption initial tool tip. [CHAR LIMIT=28] --> + <string name="volume_odi_captions_tip">Automatically caption media</string> + + <!-- Content description for accessibility: Clear the odi caption tool tip. [CHAR LIMIT=NONE] --> + <string name="accessibility_volume_close_odi_captions_tip">Close captions tip</string> + <!-- content description for audio output chooser [CHAR LIMIT=NONE]--> <string name="accessibility_output_chooser">Switch output device</string> @@ -2370,12 +2377,29 @@ <string name="bubbles_deep_link_button_description">Open <xliff:g id="app_name" example="YouTube">%1$s</xliff:g></string> <!-- Text used for content description of settings button in the header of expanded bubble view. [CHAR_LIMIT=NONE] --> - <string name="bubbles_settings_button_description">Open notification settings for <xliff:g id="app_name" example="YouTube">%1$s</xliff:g></string> + <string name="bubbles_settings_button_description">Settings for <xliff:g id="app_name" example="YouTube">%1$s</xliff:g> bubbles</string> <!-- Text for asking the user whether bubbles (floating app content) should be enabled for an app. [CHAR LIMIT=NONE] --> - <string name="bubbles_prompt">Allow bubbles from this app?</string> + <string name="bubbles_prompt">Allow bubbles from <xliff:g id="app_name" example="YouTube">%1$s</xliff:g>?</string> <!-- Text used for button allowing user to opt out of bubbles [CHAR LIMIT=20] --> - <string name="no_bubbles">Block</string> + <string name="no_bubbles">Deny</string> <!-- Text used for button allowing user to approve / enable bubbles [CHAR LIMIT=20] --> <string name="yes_bubbles">Allow</string> + <!-- Text used for the button allowing users to postpone their decision to allow or deny bubbles [CHAR LIMIT=40] --> + <string name="ask_me_later_bubbles">Ask me later</string> + <!-- Content description when a bubble is focused. [CHAR LIMIT=NONE] --> + <string name="bubble_content_description_single"><xliff:g id="notification_title" example="some title">%1$s</xliff:g> from <xliff:g id="app_name" example="YouTube">%2$s</xliff:g></string> + <!-- Content description when the stack of bubbles is focused. [CHAR LIMIT=NONE] --> + <string name="bubble_content_description_stack"><xliff:g id="notification_title" example="some title">%1$s</xliff:g> from <xliff:g id="app_name" example="YouTube">%2$s</xliff:g> and <xliff:g id="bubble_count" example="4">%3$d</xliff:g> more</string> + <!-- Action in accessibility menu to move the stack of bubbles [CHAR LIMIT=20] --> + <string name="bubble_accessibility_action_move">Move</string> + <!-- Action in accessibility menu to move the stack of bubbles to the top left of the screen. [CHAR LIMIT=30] --> + <string name="bubble_accessibility_action_move_top_left">Move top left</string> + <!-- Action in accessibility menu to move the stack of bubbles to the top right of the screen. [CHAR LIMIT=30] --> + <string name="bubble_accessibility_action_move_top_right">Move top right</string> + <!-- Action in accessibility menu to move the stack of bubbles to the bottom left of the screen. [CHAR LIMIT=30]--> + <string name="bubble_accessibility_action_move_bottom_left">Move bottom left</string> + <!-- Action in accessibility menu to move the stack of bubbles to the bottom right of the screen. [CHAR LIMIT=30]--> + <string name="bubble_accessibility_action_move_bottom_right">Move bottom right</string> + </resources> diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml index 0f5df45a0eff..a6a6e6b6fea2 100644 --- a/packages/SystemUI/res/values/styles.xml +++ b/packages/SystemUI/res/values/styles.xml @@ -319,6 +319,10 @@ <item name="android:windowIsFloating">true</item> </style> + <style name="volume_dialog_theme" parent="qs_theme"> + <item name="android:windowIsFloating">false</item> + </style> + <style name="systemui_theme_remote_input" parent="@android:style/Theme.DeviceDefault.Light"> <item name="android:colorAccent">@color/remote_input_accent</item> </style> @@ -349,13 +353,13 @@ <style name="AutoSizingList"> <item name="enableAutoSizing">true</item> </style> - <style name="Theme.AlertDialogHost" parent="android:Theme.DeviceDefault"> + <style name="Theme.MediaProjectionAlertDialog" parent="android:Theme.DeviceDefault"> <item name="android:windowIsTranslucent">true</item> <item name="android:windowBackground">@android:color/transparent</item> <item name="android:windowContentOverlay">@null</item> <item name="android:windowNoTitle">true</item> <item name="android:windowIsFloating">true</item> - <item name="android:backgroundDimEnabled">false</item> + <item name="android:backgroundDimEnabled">true</item> <item name="android:alertDialogTheme">@style/Theme.SystemUI.Dialog.Alert</item> </style> diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java index 0f71ffb34938..6b07ed8e8edc 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java @@ -219,6 +219,7 @@ public class ActivityManagerWrapper { IRecentsAnimationRunner runner = null; if (animationHandler != null) { runner = new IRecentsAnimationRunner.Stub() { + @Override public void onAnimationStart(IRecentsAnimationController controller, RemoteAnimationTarget[] apps, Rect homeContentInsets, Rect minimizedHomeBounds) { @@ -230,8 +231,9 @@ public class ActivityManagerWrapper { homeContentInsets, minimizedHomeBounds); } - public void onAnimationCanceled() { - animationHandler.onAnimationCanceled(); + @Override + public void onAnimationCanceled(boolean deferredWithScreenshot) { + animationHandler.onAnimationCanceled(deferredWithScreenshot); } }; } diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java index 9bebb14dabf0..1d9105c35ac5 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java @@ -84,4 +84,20 @@ public class RecentsAnimationControllerCompat { Log.e(TAG, "Failed to finish recents animation", e); } } + + public void setCancelWithDeferredScreenshot(boolean screenshot) { + try { + mAnimationController.setCancelWithDeferredScreenshot(screenshot); + } catch (RemoteException e) { + Log.e(TAG, "Failed to set cancel with deferred screenshot", e); + } + } + + public void cleanupScreenshot() { + try { + mAnimationController.cleanupScreenshot(); + } catch (RemoteException e) { + Log.e(TAG, "Failed to clean up screenshot of recents animation", e); + } + } }
\ No newline at end of file diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationListener.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationListener.java index a473db1a7a14..5850fda617fc 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationListener.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationListener.java @@ -29,5 +29,5 @@ public interface RecentsAnimationListener { /** * Called when the animation into Recents was canceled. This call is made on the binder thread. */ - void onAnimationCanceled(); -}
\ No newline at end of file + void onAnimationCanceled(boolean deferredWithScreenshot); +} diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java index ce65b5a3a3a3..6ae2b4523c2a 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java @@ -271,14 +271,11 @@ public class KeyguardClockSwitch extends RelativeLayout { return mClockView.getTextSize(); } - public void refresh() { - mClockView.refresh(); - } - /** - * Notifies that time tick alarm from doze service fired. + * Refresh the time of the clock, due to either time tick broadcast or doze time tick alarm. */ - public void dozeTimeTick() { + public void refresh() { + mClockView.refresh(); if (mClockPlugin != null) { mClockPlugin.onTimeTick(); } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java index cf22286c1614..14ead0427478 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java @@ -157,6 +157,10 @@ public class KeyguardHostView extends FrameLayout implements SecurityCallback { mSecurityContainer.showPrimarySecurityScreen(false); } + public KeyguardSecurityView getCurrentSecurityView() { + return mSecurityContainer != null ? mSecurityContainer.getCurrentSecurityView() : null; + } + /** * Show a string explaining why the security view needs to be solved. * diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java index 14df70cb623e..52b766de5ec4 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java @@ -47,12 +47,24 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe private static final int USER_TYPE_WORK_PROFILE = 2; private static final int USER_TYPE_SECONDARY_USER = 3; + // Bouncer is dismissed due to no security. + private static final int BOUNCER_DISMISS_NONE_SECURITY = 0; + // Bouncer is dismissed due to pin, password or pattern entered. + private static final int BOUNCER_DISMISS_PASSWORD = 1; + // Bouncer is dismissed due to biometric (face, fingerprint or iris) authenticated. + private static final int BOUNCER_DISMISS_BIOMETRIC = 2; + // Bouncer is dismissed due to extended access granted. + private static final int BOUNCER_DISMISS_EXTENDED_ACCESS = 3; + // Bouncer is dismissed due to sim card unlock code entered. + private static final int BOUNCER_DISMISS_SIM = 4; + private KeyguardSecurityModel mSecurityModel; private LockPatternUtils mLockPatternUtils; private KeyguardSecurityViewFlipper mSecurityViewFlipper; private boolean mIsVerifyUnlockOnly; private SecurityMode mCurrentSecuritySelection = SecurityMode.Invalid; + private KeyguardSecurityView mCurrentSecurityView; private SecurityCallback mSecurityCallback; private AlertDialog mAlertDialog; @@ -327,12 +339,18 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe if (DEBUG) Log.d(TAG, "showNextSecurityScreenOrFinish(" + authenticated + ")"); boolean finish = false; boolean strongAuth = false; - if (mUpdateMonitor.getUserCanSkipBouncer(targetUserId)) { + int eventSubtype = -1; + if (mUpdateMonitor.getUserHasTrust(targetUserId)) { + finish = true; + eventSubtype = BOUNCER_DISMISS_EXTENDED_ACCESS; + } else if (mUpdateMonitor.getUserUnlockedWithBiometric(targetUserId)) { finish = true; + eventSubtype = BOUNCER_DISMISS_BIOMETRIC; } else if (SecurityMode.None == mCurrentSecuritySelection) { SecurityMode securityMode = mSecurityModel.getSecurityMode(targetUserId); if (SecurityMode.None == securityMode) { finish = true; // no security required + eventSubtype = BOUNCER_DISMISS_NONE_SECURITY; } else { showSecurityScreen(securityMode); // switch to the alternate security view } @@ -343,6 +361,7 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe case PIN: strongAuth = true; finish = true; + eventSubtype = BOUNCER_DISMISS_PASSWORD; break; case SimPin: @@ -352,6 +371,7 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe if (securityMode == SecurityMode.None || mLockPatternUtils.isLockScreenDisabled( KeyguardUpdateMonitor.getCurrentUser())) { finish = true; + eventSubtype = BOUNCER_DISMISS_SIM; } else { showSecurityScreen(securityMode); } @@ -363,6 +383,10 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe break; } } + if (eventSubtype != -1) { + mMetricsLogger.write(new LogMaker(MetricsEvent.BOUNCER) + .setType(MetricsEvent.TYPE_DISMISS).setSubtype(eventSubtype)); + } if (finish) { mSecurityCallback.finish(strongAuth, targetUserId); } @@ -405,6 +429,7 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe } mCurrentSecuritySelection = securityMode; + mCurrentSecurityView = newView; mSecurityCallback.onSecurityModeChanged(securityMode, securityMode != SecurityMode.None && newView.needsInput()); } @@ -506,6 +531,10 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe return mCurrentSecuritySelection; } + public KeyguardSecurityView getCurrentSecurityView() { + return mCurrentSecurityView; + } + public void verifyUnlock() { mIsVerifyUnlockOnly = true; showSecurityScreen(getSecurityMode()); diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java index 808e264258da..0369e4c0aea6 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java @@ -214,7 +214,6 @@ public class KeyguardStatusView extends GridLayout implements public void dozeTimeTick() { refreshTime(); mKeyguardSlice.refresh(); - mClockView.dozeTimeTick(); } private void refreshTime() { diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index 63f8cd6d2025..fa39ccd28ff1 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -886,15 +886,22 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { public boolean getUserCanSkipBouncer(int userId) { - boolean fingerprintOrFace = mUserFingerprintAuthenticated.get(userId) - || mUserFaceAuthenticated.get(userId); - return getUserHasTrust(userId) || (fingerprintOrFace && isUnlockingWithBiometricAllowed()); + return getUserHasTrust(userId) || getUserUnlockedWithBiometric(userId); } public boolean getUserHasTrust(int userId) { return !isTrustDisabled(userId) && mUserHasTrust.get(userId); } + /** + * Returns whether the user is unlocked with biometrics. + */ + public boolean getUserUnlockedWithBiometric(int userId) { + boolean fingerprintOrFace = mUserFingerprintAuthenticated.get(userId) + || mUserFaceAuthenticated.get(userId); + return fingerprintOrFace && isUnlockingWithBiometricAllowed(); + } + public boolean getUserTrustIsManaged(int userId) { return mUserTrustIsManaged.get(userId) && !isTrustDisabled(userId); } diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java index b7d19007cac2..70f2ccee7d60 100644 --- a/packages/SystemUI/src/com/android/systemui/Dependency.java +++ b/packages/SystemUI/src/com/android/systemui/Dependency.java @@ -97,6 +97,7 @@ import com.android.systemui.statusbar.policy.NextAlarmController; import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler; import com.android.systemui.statusbar.policy.RotationLockController; import com.android.systemui.statusbar.policy.SecurityController; +import com.android.systemui.statusbar.policy.SensorPrivacyController; import com.android.systemui.statusbar.policy.SmartReplyConstants; import com.android.systemui.statusbar.policy.UserInfoController; import com.android.systemui.statusbar.policy.UserSwitcherController; @@ -291,6 +292,7 @@ public class Dependency extends SystemUI { @Inject Lazy<ActivityManagerWrapper> mActivityManagerWrapper; @Inject Lazy<DevicePolicyManagerWrapper> mDevicePolicyManagerWrapper; @Inject Lazy<PackageManagerWrapper> mPackageManagerWrapper; + @Inject Lazy<SensorPrivacyController> mSensorPrivacyController; @Inject public Dependency() { @@ -461,6 +463,7 @@ public class Dependency extends SystemUI { mProviders.put(ActivityManagerWrapper.class, mActivityManagerWrapper::get); mProviders.put(DevicePolicyManagerWrapper.class, mDevicePolicyManagerWrapper::get); mProviders.put(PackageManagerWrapper.class, mPackageManagerWrapper::get); + mProviders.put(SensorPrivacyController.class, mSensorPrivacyController::get); // TODO(b/118592525): to support multi-display , we start to add something which is diff --git a/packages/SystemUI/src/com/android/systemui/DependencyBinder.java b/packages/SystemUI/src/com/android/systemui/DependencyBinder.java index 3c6f081d0373..53050bf2dc3e 100644 --- a/packages/SystemUI/src/com/android/systemui/DependencyBinder.java +++ b/packages/SystemUI/src/com/android/systemui/DependencyBinder.java @@ -60,6 +60,8 @@ import com.android.systemui.statusbar.policy.RotationLockController; import com.android.systemui.statusbar.policy.RotationLockControllerImpl; import com.android.systemui.statusbar.policy.SecurityController; import com.android.systemui.statusbar.policy.SecurityControllerImpl; +import com.android.systemui.statusbar.policy.SensorPrivacyController; +import com.android.systemui.statusbar.policy.SensorPrivacyControllerImpl; import com.android.systemui.statusbar.policy.UserInfoController; import com.android.systemui.statusbar.policy.UserInfoControllerImpl; import com.android.systemui.statusbar.policy.ZenModeController; @@ -225,5 +227,11 @@ public abstract class DependencyBinder { /** */ @Binds + public abstract SensorPrivacyController provideSensorPrivacyControllerImpl( + SensorPrivacyControllerImpl controllerImpl); + + /** + */ + @Binds public abstract QSHost provideQsHost(QSTileHost controllerImpl); } diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java index 0113d0560764..ed2a6b59d153 100644 --- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java +++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java @@ -19,9 +19,7 @@ package com.android.systemui; import android.content.Context; import android.graphics.Rect; import android.opengl.GLSurfaceView; -import android.os.Build; import android.service.wallpaper.WallpaperService; -import android.util.Log; import android.view.SurfaceHolder; import com.android.systemui.glwallpaper.ImageWallpaperRenderer; @@ -34,15 +32,7 @@ public class ImageWallpaper extends WallpaperService { private static final String TAG = ImageWallpaper.class.getSimpleName(); @Override - public void onCreate() { - super.onCreate(); - } - - @Override public Engine onCreateEngine() { - if (Build.IS_DEBUGGABLE) { - Log.v(TAG, "We are using GLEngine"); - } return new GLEngine(this); } @@ -72,8 +62,15 @@ public class ImageWallpaper extends WallpaperService { } } + @Override + public void onDestroy() { + if (mWallpaperSurfaceView != null) { + mWallpaperSurfaceView.onPause(); + } + } + private class GLWallpaperSurfaceView extends GLSurfaceView implements ImageGLView { - private WallpaperStatusListener mWallpaperChangedListener; + private WallpaperStatusListener mWallpaperStatusListener; GLWallpaperSurfaceView(Context context) { super(context); @@ -88,18 +85,18 @@ public class ImageWallpaper extends WallpaperService { @Override public void setRenderer(Renderer renderer) { super.setRenderer(renderer); - mWallpaperChangedListener = (WallpaperStatusListener) renderer; + mWallpaperStatusListener = (WallpaperStatusListener) renderer; } private void notifyAmbientModeChanged(boolean inAmbient, long duration) { - if (mWallpaperChangedListener != null) { - mWallpaperChangedListener.onAmbientModeChanged(inAmbient, duration); + if (mWallpaperStatusListener != null) { + mWallpaperStatusListener.onAmbientModeChanged(inAmbient, duration); } } private void notifyOffsetsChanged(float xOffset, float yOffset) { - if (mWallpaperChangedListener != null) { - mWallpaperChangedListener.onOffsetsChanged( + if (mWallpaperStatusListener != null) { + mWallpaperStatusListener.onOffsetsChanged( xOffset, yOffset, getHolder().getSurfaceFrame()); } } diff --git a/packages/SystemUI/src/com/android/systemui/Prefs.java b/packages/SystemUI/src/com/android/systemui/Prefs.java index d437555c62a4..27975707bd8d 100644 --- a/packages/SystemUI/src/com/android/systemui/Prefs.java +++ b/packages/SystemUI/src/com/android/systemui/Prefs.java @@ -57,7 +57,8 @@ public final class Prefs { Key.SEEN_RINGER_GUIDANCE_COUNT, Key.QS_HAS_TURNED_OFF_MOBILE_DATA, Key.TOUCHED_RINGER_TOGGLE, - Key.QUICK_STEP_INTERACTION_FLAGS + Key.QUICK_STEP_INTERACTION_FLAGS, + Key.HAS_SEEN_ODI_CAPTIONS_TOOLTIP }) public @interface Key { @Deprecated @@ -103,6 +104,7 @@ public final class Prefs { String QS_HAS_TURNED_OFF_MOBILE_DATA = "QsHasTurnedOffMobileData"; String TOUCHED_RINGER_TOGGLE = "TouchedRingerToggle"; String QUICK_STEP_INTERACTION_FLAGS = "QuickStepInteractionFlags"; + String HAS_SEEN_ODI_CAPTIONS_TOOLTIP = "HasSeenODICaptionsTooltip"; } public static boolean getBoolean(Context context, @Key String key, boolean defaultValue) { diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java index 89bcea461ce4..8e3afd8bcae0 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java @@ -411,6 +411,8 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList mPermissionView.setVisibility(VISIBLE); ((ImageView) mPermissionView.findViewById(R.id.pkgicon)).setImageDrawable(mAppIcon); ((TextView) mPermissionView.findViewById(R.id.pkgname)).setText(mAppName); + ((TextView) mPermissionView.findViewById(R.id.prompt)).setText( + getResources().getString(R.string.bubbles_prompt, mAppName)); logBubbleClickEvent(mEntry.notification, StatsLog.BUBBLE_UICHANGED__ACTION__PERMISSION_DIALOG_SHOWN); } diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java index b409a3181e2b..7a68be494cf9 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java @@ -193,11 +193,19 @@ public class BubbleView extends FrameLayout { if (mEntry == null) { return; } + Notification.BubbleMetadata metadata = mEntry.getBubbleMetadata(); Notification n = mEntry.notification.getNotification(); - boolean isLarge = n.getLargeIcon() != null; - Icon ic = isLarge ? n.getLargeIcon() : n.getSmallIcon(); + Icon ic; + boolean needsTint; + if (metadata != null) { + ic = metadata.getIcon(); + needsTint = ic.getType() != Icon.TYPE_ADAPTIVE_BITMAP; + } else { + needsTint = n.getLargeIcon() == null; + ic = needsTint ? n.getSmallIcon() : n.getLargeIcon(); + } Drawable iconDrawable = ic.loadDrawable(mContext); - if (!isLarge) { + if (needsTint) { // Center icon on coloured background iconDrawable.setTint(Color.WHITE); // TODO: dark mode Drawable bg = new ColorDrawable(n.color); diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java index 40e08bed8352..d601e633137d 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java @@ -104,16 +104,23 @@ public class ExpandedAnimationController * @return The y-value to which the bubbles were expanded, in case that's useful. */ public float expandFromStack(PointF collapseTo, Runnable after) { - mCollapseToPoint = collapseTo; + animationsForChildrenFromIndex( + 0, /* startIndex */ + new ChildAnimationConfigurator() { + // How much to translate the next bubble, so that it is not overlapping the + // previous one. + float mTranslateNextBubbleXBy = mBubblePaddingPx; - // How much to translate the next bubble, so that it is not overlapping the previous one. - float translateNextBubbleXBy = mBubblePaddingPx; - for (int i = 0; i < mLayout.getChildCount(); i++) { - mLayout.animatePositionForChildAtIndex(i, translateNextBubbleXBy, getExpandedY()); - translateNextBubbleXBy += mBubbleSizePx + mBubblePaddingPx; - } + @Override + public void configureAnimationForChildAtIndex( + int index, PhysicsAnimationLayout.PhysicsPropertyAnimator animation) { + animation.position(mTranslateNextBubbleXBy, getExpandedY()); + mTranslateNextBubbleXBy += mBubbleSizePx + mBubblePaddingPx; + } + }) + .startAll(after); - runAfterTranslationsEnd(after); + mCollapseToPoint = collapseTo; return getExpandedY(); } @@ -121,13 +128,14 @@ public class ExpandedAnimationController public void collapseBackToStack(Runnable after) { // Stack to the left if we're going to the left, or right if not. final float sideMultiplier = mLayout.isFirstChildXLeftOfCenter(mCollapseToPoint.x) ? -1 : 1; - for (int i = 0; i < mLayout.getChildCount(); i++) { - mLayout.animatePositionForChildAtIndex( - i, - mCollapseToPoint.x + (sideMultiplier * i * mStackOffsetPx), mCollapseToPoint.y); - } - runAfterTranslationsEnd(after); + animationsForChildrenFromIndex( + 0, /* startIndex */ + (index, animation) -> + animation.position( + mCollapseToPoint.x + (sideMultiplier * index * mStackOffsetPx), + mCollapseToPoint.y)) + .startAll(after /* endAction */); } /** Prepares the given bubble to be dragged out. */ @@ -164,20 +172,10 @@ public class ExpandedAnimationController public void snapBubbleBack(View bubbleView, float velX, float velY) { final int index = mLayout.indexOfChild(bubbleView); - // Snap the bubble back, respecting its current velocity. - mLayout.animateValueForChildAtIndex( - DynamicAnimation.TRANSLATION_X, index, getXForChildAtIndex(index), velX); - mLayout.animateValueForChildAtIndex( - DynamicAnimation.TRANSLATION_Y, index, getExpandedY(), velY); - mLayout.setEndListenerForProperties( - mLayout.new OneTimeMultiplePropertyEndListener() { - @Override - void onAllAnimationsForPropertiesEnd() { - // Reset Z translation once the bubble is done snapping back. - bubbleView.setTranslationZ(0f); - } - }, - DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y); + animationForChildAtIndex(index) + .position(getXForChildAtIndex(index), getExpandedY()) + .withPositionStartVelocities(velX, velY) + .start(() -> bubbleView.setTranslationZ(0f) /* after */); animateStackByBubbleWidthsStartingFrom( /* numBubbleWidths */ 0, /* startIndex */ index + 1); @@ -202,12 +200,8 @@ public class ExpandedAnimationController */ public void updateYPosition(Runnable after) { if (mLayout == null) return; - - for (int i = 0; i < mLayout.getChildCount(); i++) { - boolean isLast = i == mLayout.getChildCount() - 1; - mLayout.animateValueForChildAtIndex(DynamicAnimation.TRANSLATION_Y, i, - getExpandedY(), isLast ? after : null); - } + animationsForChildrenFromIndex( + 0, (i, anim) -> anim.translationY(getExpandedY())).startAll(after); } /** @@ -216,12 +210,11 @@ public class ExpandedAnimationController * positions. */ private void animateStackByBubbleWidthsStartingFrom(int numBubbleWidths, int startIndex) { - for (int i = startIndex; i < mLayout.getChildCount(); i++) { - mLayout.animateValueForChildAtIndex( - DynamicAnimation.TRANSLATION_X, - i, - getXForChildAtIndex(i + numBubbleWidths)); - } + animationsForChildrenFromIndex( + startIndex, + (index, animation) -> + animation.translationX(getXForChildAtIndex(index + numBubbleWidths))) + .startAll(); } /** The Y value of the row of expanded bubbles. */ @@ -248,21 +241,6 @@ public class ExpandedAnimationController } } - /** Runs the given Runnable after all translation-related animations have ended. */ - private void runAfterTranslationsEnd(Runnable after) { - DynamicAnimation.OnAnimationEndListener allEndedListener = - (animation, canceled, value, velocity) -> { - if (!mLayout.arePropertiesAnimating( - DynamicAnimation.TRANSLATION_X, - DynamicAnimation.TRANSLATION_Y)) { - after.run(); - } - }; - - mLayout.setEndListenerForProperty(allEndedListener, DynamicAnimation.TRANSLATION_X); - mLayout.setEndListenerForProperty(allEndedListener, DynamicAnimation.TRANSLATION_Y); - } - @Override Set<DynamicAnimation.ViewProperty> getAnimatedProperties() { return Sets.newHashSet( @@ -295,8 +273,12 @@ public class ExpandedAnimationController // Pop in from the top. // TODO: Reverse this when bubbles are at the bottom. child.setTranslationX(getXForChildAtIndex(index)); - child.setTranslationY(getExpandedY() - mBubbleSizePx * ANIMATE_TRANSLATION_FACTOR); - mLayout.animateValueForChild(DynamicAnimation.TRANSLATION_Y, child, getExpandedY()); + + animationForChild(child) + .translationY( + getExpandedY() - mBubbleSizePx * ANIMATE_TRANSLATION_FACTOR, /* from */ + getExpandedY() /* to */) + .start(); animateBubblesAfterIndexToCorrectX(index); } @@ -304,36 +286,26 @@ public class ExpandedAnimationController void onChildRemoved(View child, int index, Runnable finishRemoval) { // Bubble pops out to the top. // TODO: Reverse this when bubbles are at the bottom. - mLayout.animateValueForChild( - DynamicAnimation.ALPHA, child, 0f, finishRemoval); + + final PhysicsAnimationLayout.PhysicsPropertyAnimator animator = animationForChild(child); + animator.alpha(0f, finishRemoval /* endAction */); // If we're removing the dragged-out bubble, that means it got dismissed. if (child.equals(mBubbleDraggingOut)) { - // Throw it to the bottom of the screen, towards the center horizontally. - mLayout.animateValueForChild( - DynamicAnimation.TRANSLATION_X, - child, - mLayout.getWidth() / 2f - mBubbleSizePx / 2f, - mBubbleDraggingOutVelX); - mLayout.animateValueForChild( - DynamicAnimation.TRANSLATION_Y, - child, - mLayout.getHeight() + mBubbleSizePx, - mBubbleDraggingOutVelY); - - // Scale it down a bit so it looks like it's disappearing. - mLayout.animateValueForChild(DynamicAnimation.SCALE_X, child, ANIMATE_SCALE_PERCENT); - mLayout.animateValueForChild(DynamicAnimation.SCALE_Y, child, ANIMATE_SCALE_PERCENT); + animator.position( + mLayout.getWidth() / 2f - mBubbleSizePx / 2f, + mLayout.getHeight() + mBubbleSizePx) + .withPositionStartVelocities(mBubbleDraggingOutVelX, mBubbleDraggingOutVelY) + .scaleX(ANIMATE_SCALE_PERCENT) + .scaleY(ANIMATE_SCALE_PERCENT); mBubbleDraggingOut = null; } else { - // If we're removing some random bubble just throw it off the top. - mLayout.animateValueForChild( - DynamicAnimation.TRANSLATION_Y, - child, - getExpandedY() - mBubbleSizePx * ANIMATE_TRANSLATION_FACTOR); + animator.translationY(getExpandedY() - mBubbleSizePx * ANIMATE_TRANSLATION_FACTOR); } + animator.start(); + // Animate all the other bubbles to their new positions sans this bubble. animateBubblesAfterIndexToCorrectX(index); } @@ -346,12 +318,9 @@ public class ExpandedAnimationController child.setVisibility(View.VISIBLE); } - // Fade in. - mLayout.animateValueForChild( - DynamicAnimation.ALPHA, - child, - /* value */ visibility == View.GONE ? 0f : 1f, - () -> super.setChildVisibility(child, index, visibility)); + animationForChild(child) + .alpha(visibility == View.GONE ? 0f : 1f) + .start(() -> super.setChildVisibility(child, index, visibility) /* after */); } /** @@ -365,8 +334,9 @@ public class ExpandedAnimationController // Don't animate the dragging out bubble, or it'll jump around while being dragged. It // will be snapped to the correct X value after the drag (if it's not dismissed). if (!bubble.equals(mBubbleDraggingOut)) { - mLayout.animateValueForChild( - DynamicAnimation.TRANSLATION_X, bubble, getXForChildAtIndex(i)); + animationForChild(bubble) + .translationX(getXForChildAtIndex(i)) + .start(); } } } diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayout.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayout.java index dfdcfc9f3b74..2fa87d83f75d 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayout.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayout.java @@ -27,8 +27,11 @@ import androidx.dynamicanimation.animation.SpringForce; import com.android.systemui.R; +import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; +import java.util.List; +import java.util.Map; import java.util.Set; /** @@ -46,6 +49,35 @@ public class PhysicsAnimationLayout extends FrameLayout { */ abstract static class PhysicsAnimationController { + /** Configures a given {@link PhysicsPropertyAnimator} for a view at the given index. */ + interface ChildAnimationConfigurator { + + /** + * Called to configure the animator for the view at the given index. + * + * This method should make use of methods such as + * {@link PhysicsPropertyAnimator#translationX} and + * {@link PhysicsPropertyAnimator#withStartDelay} to configure the animation. + * + * Implementations should not call {@link PhysicsPropertyAnimator#start}, this will + * happen elsewhere after configuration is complete. + */ + void configureAnimationForChildAtIndex(int index, PhysicsPropertyAnimator animation); + } + + /** + * Returned by {@link #animationsForChildrenFromIndex} to allow starting multiple animations + * on multiple child views at the same time. + */ + interface MultiAnimationStarter { + + /** + * Start all animations and call the given end actions once all animations have + * completed. + */ + void startAll(Runnable... endActions); + } + /** * Constant to return from {@link #getNextAnimationInChain} if the animation should not be * chained at all. @@ -98,7 +130,7 @@ public class PhysicsAnimationLayout extends FrameLayout { * by getChildAt() and getChildCount(). * * The controller can perform animations on the child (either manually, or by using - * {@link #animateValueForChild}), and then call finishRemoval when complete. + * {@link #animationForChild(View)}), and then call finishRemoval when complete. * * finishRemoval must be called by implementations of this method, or transient views will * never be removed. @@ -125,14 +157,74 @@ public class PhysicsAnimationLayout extends FrameLayout { protected void setChildVisibility(View child, int index, int visibility) { child.setVisibility(visibility); } + + /** + * Returns a {@link PhysicsPropertyAnimator} instance for the given child view. + */ + protected PhysicsPropertyAnimator animationForChild(View child) { + PhysicsPropertyAnimator animator = + (PhysicsPropertyAnimator) child.getTag(R.id.physics_animator_tag); + + if (animator == null) { + animator = mLayout.new PhysicsPropertyAnimator(child); + child.setTag(R.id.physics_animator_tag, animator); + } + + return animator; + } + + /** Returns a {@link PhysicsPropertyAnimator} instance for child at the given index. */ + protected PhysicsPropertyAnimator animationForChildAtIndex(int index) { + return animationForChild(mLayout.getChildAt(index)); + } + + /** + * Returns a {@link MultiAnimationStarter} whose startAll method will start the physics + * animations for all children from startIndex onward. The provided configurator will be + * called with each child's {@link PhysicsPropertyAnimator}, where it can set up each + * animation appropriately. + */ + protected MultiAnimationStarter animationsForChildrenFromIndex( + int startIndex, ChildAnimationConfigurator configurator) { + final Set<DynamicAnimation.ViewProperty> allAnimatedProperties = new HashSet<>(); + final List<PhysicsPropertyAnimator> allChildAnims = new ArrayList<>(); + + // Retrieve the animator for each child, ask the configurator to configure it, then save + // it and the properties it chose to animate. + for (int i = startIndex; i < mLayout.getChildCount(); i++) { + final PhysicsPropertyAnimator anim = animationForChildAtIndex(i); + configurator.configureAnimationForChildAtIndex(i, anim); + allAnimatedProperties.addAll(anim.getAnimatedProperties()); + allChildAnims.add(anim); + } + + // Return a MultiAnimationStarter that will start all of the child animations, and also + // add a multiple property end listener to the layout that will call the end action + // provided to startAll() once all animations on the animated properties complete. + return (endActions) -> { + if (endActions != null) { + mLayout.setEndActionForMultipleProperties( + () -> { + for (Runnable action : endActions) { + action.run(); + } + }, + allAnimatedProperties.toArray( + new DynamicAnimation.ViewProperty[0])); + } + + for (PhysicsPropertyAnimator childAnim : allChildAnims) { + childAnim.start(); + } + }; + } } /** - * End listeners that are called when every child's animation of the given property has - * finished. + * End actions that are called when every child's animation of the given property has finished. */ - protected final HashMap<DynamicAnimation.ViewProperty, DynamicAnimation.OnAnimationEndListener> - mEndListenerForProperty = new HashMap<>(); + protected final HashMap<DynamicAnimation.ViewProperty, Runnable> mEndActionForProperty = + new HashMap<>(); /** Set of currently rendered transient views. */ private final Set<View> mTransientViews = new HashSet<>(); @@ -165,7 +257,7 @@ public class PhysicsAnimationLayout extends FrameLayout { */ public void setController(PhysicsAnimationController controller) { cancelAllAnimations(); - mEndListenerForProperty.clear(); + mEndActionForProperty.clear(); this.mController = controller; mController.setLayout(this); @@ -177,26 +269,27 @@ public class PhysicsAnimationLayout extends FrameLayout { } /** - * Sets an end listener that will be called when all child animations for a given property have + * Sets an end action that will be run when all child animations for a given property have * stopped running. */ - public void setEndListenerForProperty( - DynamicAnimation.OnAnimationEndListener listener, - DynamicAnimation.ViewProperty property) { - mEndListenerForProperty.put(property, listener); + public void setEndActionForProperty(Runnable action, DynamicAnimation.ViewProperty property) { + mEndActionForProperty.put(property, action); } /** - * Sets an end listener that will be called whenever any of the given properties' animations - * end. For example, setting a listener for TRANSLATION_X and TRANSLATION_Y will result in that - * listener being called twice - once when all TRANSLATION_X animations end, and again when all - * TRANSLATION_Y animations end. + * Sets an end action that will be run when all child animations for all of the given properties + * have stopped running. */ - public void setEndListenerForProperties( - DynamicAnimation.OnAnimationEndListener endListener, - DynamicAnimation.ViewProperty... properties) { + public void setEndActionForMultipleProperties( + Runnable action, DynamicAnimation.ViewProperty... properties) { + final Runnable checkIfAllFinished = () -> { + if (!arePropertiesAnimating(properties)) { + action.run(); + } + }; + for (DynamicAnimation.ViewProperty property : properties) { - setEndListenerForProperty(endListener, property); + setEndActionForProperty(checkIfAllFinished, property); } } @@ -204,8 +297,8 @@ public class PhysicsAnimationLayout extends FrameLayout { * Removes the end listener that would have been called when all child animations for a given * property stopped running. */ - public void removeEndListenerForProperty(DynamicAnimation.ViewProperty property) { - mEndListenerForProperty.remove(property); + public void removeEndActionForProperty(DynamicAnimation.ViewProperty property) { + mEndActionForProperty.remove(property); } @Override @@ -231,6 +324,11 @@ public class PhysicsAnimationLayout extends FrameLayout { } @Override + public void removeViewAt(int index) { + removeView(getChildAt(index)); + } + + @Override public void addTransientView(View view, int index) { super.addTransientView(view, index); mTransientViews.add(view); @@ -304,7 +402,10 @@ public class PhysicsAnimationLayout extends FrameLayout { for (int i = 0; i < getChildCount(); i++) { for (DynamicAnimation.ViewProperty property : mController.getAnimatedProperties()) { - getAnimationAtIndex(property, i).cancel(); + final DynamicAnimation anim = getAnimationAtIndex(property, i); + if (anim != null) { + anim.cancel(); + } } } } @@ -316,107 +417,6 @@ public class PhysicsAnimationLayout extends FrameLayout { } } - /** - * Animates the property of the given child view, then runs the callback provided when the - * animation ends. - */ - protected void animateValueForChild( - DynamicAnimation.ViewProperty property, - View view, - float value, - float startVel, - Runnable after) { - if (view != null) { - final SpringAnimation animation = - (SpringAnimation) view.getTag(getTagIdForProperty(property)); - if (after != null) { - animation.addEndListener(new OneTimeEndListener() { - @Override - public void onAnimationEnd(DynamicAnimation animation, boolean canceled, - float value, float velocity) { - super.onAnimationEnd(animation, canceled, value, velocity); - after.run(); - } - }); - } - - // Set the start velocity if it's something other than the not-set value. - if (startVel != Float.MAX_VALUE) { - animation.setStartVelocity(startVel); - } - - animation.animateToFinalPosition(value); - } - } - - protected void animateValueForChild( - DynamicAnimation.ViewProperty property, - View view, - float value, - Runnable after) { - animateValueForChild(property, view, value, Float.MAX_VALUE, after); - } - - protected void animateValueForChild( - DynamicAnimation.ViewProperty property, - View view, - float value) { - animateValueForChild(property, view, value, Float.MAX_VALUE, /* after */ null); - } - - protected void animateValueForChild( - DynamicAnimation.ViewProperty property, - View view, - float value, - float startVel) { - animateValueForChild(property, view, value, startVel, /* after */ null); - } - - /** - * Animates the property of the child at the given index to the given value, then runs the - * callback provided when the animation ends. - */ - protected void animateValueForChildAtIndex( - DynamicAnimation.ViewProperty property, - int index, - float value, - float startVel, - Runnable after) { - animateValueForChild(property, getChildAt(index), value, startVel, after); - } - - /** Shortcut to animate a value with a callback, but no start velocity. */ - protected void animateValueForChildAtIndex( - DynamicAnimation.ViewProperty property, - int index, - float value, - Runnable after) { - animateValueForChildAtIndex(property, index, value, Float.MAX_VALUE, after); - } - - /** Shortcut to animate a value with a start velocity, but no callback. */ - protected void animateValueForChildAtIndex( - DynamicAnimation.ViewProperty property, - int index, - float value, - float startVel) { - animateValueForChildAtIndex(property, index, value, startVel, /* callback */ null); - } - - /** Shortcut to animate a value without changing the velocity or providing a callback. */ - protected void animateValueForChildAtIndex( - DynamicAnimation.ViewProperty property, - int index, - float value) { - animateValueForChildAtIndex(property, index, value, Float.MAX_VALUE, /* callback */ null); - } - - /** Shortcut to animate a child view's TRANSLATION_X and TRANSLATION_Y values. */ - protected void animatePositionForChildAtIndex(int index, float x, float y) { - animateValueForChildAtIndex(DynamicAnimation.TRANSLATION_X, index, x); - animateValueForChildAtIndex(DynamicAnimation.TRANSLATION_Y, index, y); - } - /** Whether the first child would be left of center if translated to the given x value. */ protected boolean isFirstChildXLeftOfCenter(float x) { if (getChildCount() > 0) { @@ -562,40 +562,256 @@ public class PhysicsAnimationLayout extends FrameLayout { public void onAnimationEnd( DynamicAnimation anim, boolean canceled, float value, float velocity) { if (!arePropertiesAnimating(mProperty)) { - if (mEndListenerForProperty.containsKey(mProperty)) { - mEndListenerForProperty.get(mProperty).onAnimationEnd(anim, canceled, value, - velocity); + if (mEndActionForProperty.containsKey(mProperty)) { + mEndActionForProperty.get(mProperty).run(); } } } } /** - * One time end listener that waits for every animation on every given property to finish. At - * that point, it calls {@link #onAllAnimationsForPropertiesEnd} and then removes itself as an - * end listener from each property. + * Animator class returned by {@link PhysicsAnimationController#animationForChild}, to allow + * controllers to animate child views using physics animations. + * + * See docs/physics-animation-layout.md for documentation and examples. */ - public abstract class OneTimeMultiplePropertyEndListener - implements DynamicAnimation.OnAnimationEndListener { - final DynamicAnimation.ViewProperty[] mViewProperties; + protected class PhysicsPropertyAnimator { + /** The view whose properties this animator animates. */ + private View mView; + + /** Start velocity to use for all property animations. */ + private float mDefaultStartVelocity = 0f; + + /** Start delay to use when start is called. */ + private long mStartDelay = 0; + + /** End actions to call when animations for the given property complete. */ + private Map<DynamicAnimation.ViewProperty, Runnable[]> mEndActionsForProperty = + new HashMap<>(); + + /** + * Start velocities to use for TRANSLATION_X and TRANSLATION_Y, since these are often + * provided by VelocityTrackers and differ from each other. + */ + private Map<DynamicAnimation.ViewProperty, Float> mPositionStartVelocities = + new HashMap<>(); + + /** + * End actions to call when both TRANSLATION_X and TRANSLATION_Y animations have completed, + * if {@link #position} was used to animate TRANSLATION_X and TRANSLATION_Y simultaneously. + */ + private Runnable[] mPositionEndActions; - OneTimeMultiplePropertyEndListener(DynamicAnimation.ViewProperty... properties) { - mViewProperties = properties; + /** + * All of the properties that have been set and will animate when {@link #start} is called. + */ + private Map<DynamicAnimation.ViewProperty, Float> mAnimatedProperties = new HashMap<>(); + + protected PhysicsPropertyAnimator(View view) { + this.mView = view; } - @Override - public void onAnimationEnd(DynamicAnimation animation, boolean canceled, float value, - float velocity) { - if (!arePropertiesAnimating(mViewProperties)) { - onAllAnimationsForPropertiesEnd(); + /** Animate a property to the given value, then call the optional end actions. */ + public PhysicsPropertyAnimator property( + DynamicAnimation.ViewProperty property, float value, Runnable... endActions) { + mAnimatedProperties.put(property, value); + mEndActionsForProperty.put(property, endActions); + return this; + } + + /** Animate the view's alpha value to the provided value. */ + public PhysicsPropertyAnimator alpha(float alpha, Runnable... endActions) { + return property(DynamicAnimation.ALPHA, alpha, endActions); + } + + /** Set the view's alpha value to 'from', then animate it to the given value. */ + public PhysicsPropertyAnimator alpha(float from, float to, Runnable... endActions) { + mView.setAlpha(from); + return alpha(to, endActions); + } + + /** Animate the view's translationX value to the provided value. */ + public PhysicsPropertyAnimator translationX(float translationX, Runnable... endActions) { + return property(DynamicAnimation.TRANSLATION_X, translationX, endActions); + } + + /** Set the view's translationX value to 'from', then animate it to the given value. */ + public PhysicsPropertyAnimator translationX( + float from, float to, Runnable... endActions) { + mView.setTranslationX(from); + return translationX(to, endActions); + } + + /** Animate the view's translationY value to the provided value. */ + public PhysicsPropertyAnimator translationY(float translationY, Runnable... endActions) { + return property(DynamicAnimation.TRANSLATION_Y, translationY, endActions); + } + + /** Set the view's translationY value to 'from', then animate it to the given value. */ + public PhysicsPropertyAnimator translationY( + float from, float to, Runnable... endActions) { + mView.setTranslationY(from); + return translationY(to, endActions); + } + + /** + * Animate the view's translationX and translationY values, and call the end actions only + * once both TRANSLATION_X and TRANSLATION_Y animations have completed. + */ + public PhysicsPropertyAnimator position( + float translationX, float translationY, Runnable... endActions) { + mPositionEndActions = endActions; + translationX(translationX); + return translationY(translationY); + } + + /** Animate the view's scaleX value to the provided value. */ + public PhysicsPropertyAnimator scaleX(float scaleX, Runnable... endActions) { + return property(DynamicAnimation.SCALE_X, scaleX, endActions); + } + + /** Set the view's scaleX value to 'from', then animate it to the given value. */ + public PhysicsPropertyAnimator scaleX(float from, float to, Runnable... endActions) { + mView.setScaleX(from); + return scaleX(to, endActions); + } + + /** Animate the view's scaleY value to the provided value. */ + public PhysicsPropertyAnimator scaleY(float scaleY, Runnable... endActions) { + return property(DynamicAnimation.SCALE_Y, scaleY, endActions); + } + + /** Set the view's scaleY value to 'from', then animate it to the given value. */ + public PhysicsPropertyAnimator scaleY(float from, float to, Runnable... endActions) { + mView.setScaleY(from); + return scaleY(to, endActions); + } + + /** Set the start velocity to use for all property animations. */ + public PhysicsPropertyAnimator withStartVelocity(float startVel) { + mDefaultStartVelocity = startVel; + return this; + } + + /** + * Set the start velocities to use for TRANSLATION_X and TRANSLATION_Y animations. This + * overrides any value set via {@link #withStartVelocity(float)} for those properties. + */ + public PhysicsPropertyAnimator withPositionStartVelocities(float velX, float velY) { + mPositionStartVelocities.put(DynamicAnimation.TRANSLATION_X, velX); + mPositionStartVelocities.put(DynamicAnimation.TRANSLATION_Y, velY); + return this; + } + + /** Set a delay, in milliseconds, before kicking off the animations. */ + public PhysicsPropertyAnimator withStartDelay(long startDelay) { + mStartDelay = startDelay; + return this; + } - for (DynamicAnimation.ViewProperty property : mViewProperties) { - removeEndListenerForProperty(property); + /** + * Start the animations, and call the optional end actions once all animations for every + * animated property on every child (including chained animations) have ended. + */ + public void start(Runnable... after) { + final Set<DynamicAnimation.ViewProperty> properties = getAnimatedProperties(); + + // If there are end actions, set an end listener on the layout for all the properties + // we're about to animate. + if (after != null) { + final DynamicAnimation.ViewProperty[] propertiesArray = + properties.toArray(new DynamicAnimation.ViewProperty[0]); + for (Runnable callback : after) { + setEndActionForMultipleProperties(callback, propertiesArray); } } + + // If we used position-specific end actions, we'll need to listen for both TRANSLATION_X + // and TRANSLATION_Y animations ending, and call them once both have finished. + if (mPositionEndActions != null) { + final SpringAnimation translationXAnim = + getAnimationFromView(DynamicAnimation.TRANSLATION_X, mView); + final SpringAnimation translationYAnim = + getAnimationFromView(DynamicAnimation.TRANSLATION_Y, mView); + final Runnable waitForBothXAndY = () -> { + if (!translationXAnim.isRunning() && !translationYAnim.isRunning()) { + if (mPositionEndActions != null) { + for (Runnable callback : mPositionEndActions) { + callback.run(); + } + } + + mPositionEndActions = null; + } + }; + + mEndActionsForProperty.put(DynamicAnimation.TRANSLATION_X, + new Runnable[]{waitForBothXAndY}); + mEndActionsForProperty.put(DynamicAnimation.TRANSLATION_Y, + new Runnable[]{waitForBothXAndY}); + } + + // Actually start the animations. + for (DynamicAnimation.ViewProperty property : properties) { + animateValueForChild( + property, + mView, + mAnimatedProperties.get(property), + mPositionStartVelocities.getOrDefault(property, mDefaultStartVelocity), + mStartDelay, + mEndActionsForProperty.get(property)); + } + + // Clear out the animator. + mAnimatedProperties.clear(); + mPositionStartVelocities.clear(); + mDefaultStartVelocity = 0; + mStartDelay = 0; + mEndActionsForProperty.clear(); } - /** Called when every animation for every property has finished. */ - abstract void onAllAnimationsForPropertiesEnd(); + /** Returns the set of properties that will animate once {@link #start} is called. */ + protected Set<DynamicAnimation.ViewProperty> getAnimatedProperties() { + return mAnimatedProperties.keySet(); + } + + /** + * Animates the property of the given child view, then runs the callback provided when the + * animation ends. + */ + protected void animateValueForChild( + DynamicAnimation.ViewProperty property, + View view, + float value, + float startVel, + long startDelay, + Runnable[] afterCallbacks) { + if (view != null) { + final SpringAnimation animation = + (SpringAnimation) view.getTag(getTagIdForProperty(property)); + if (afterCallbacks != null) { + animation.addEndListener(new OneTimeEndListener() { + @Override + public void onAnimationEnd(DynamicAnimation animation, boolean canceled, + float value, float velocity) { + super.onAnimationEnd(animation, canceled, value, velocity); + for (Runnable runnable : afterCallbacks) { + runnable.run(); + } + } + }); + } + + if (startVel > 0) { + animation.setStartVelocity(startVel); + } + + if (startDelay > 0) { + postDelayed(() -> animation.animateToFinalPosition(value), startDelay); + } else { + animation.animateToFinalPosition(value); + } + } + } } } 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 3c4bc7259a62..c39503129454 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java @@ -206,12 +206,12 @@ public class StackAnimationController extends .setDampingRatio(SPRING_DAMPING_RATIO), /* destination */ null); - mLayout.setEndListenerForProperties( - (animation, canceled, value, velocity) -> { + mLayout.setEndActionForMultipleProperties( + () -> { mRestingStackPosition = new PointF(); mRestingStackPosition.set(mStackPosition); - mLayout.removeEndListenerForProperty(DynamicAnimation.TRANSLATION_X); - mLayout.removeEndListenerForProperty(DynamicAnimation.TRANSLATION_Y); + mLayout.removeEndActionForProperty(DynamicAnimation.TRANSLATION_X); + mLayout.removeEndActionForProperty(DynamicAnimation.TRANSLATION_Y); }, DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y); } @@ -292,8 +292,8 @@ public class StackAnimationController extends cancelStackPositionAnimation(DynamicAnimation.TRANSLATION_X); cancelStackPositionAnimation(DynamicAnimation.TRANSLATION_Y); - mLayout.removeEndListenerForProperty(DynamicAnimation.TRANSLATION_X); - mLayout.removeEndListenerForProperty(DynamicAnimation.TRANSLATION_Y); + mLayout.removeEndActionForProperty(DynamicAnimation.TRANSLATION_X); + mLayout.removeEndActionForProperty(DynamicAnimation.TRANSLATION_Y); } /** @@ -441,19 +441,18 @@ public class StackAnimationController extends @Override void onChildRemoved(View child, int index, Runnable finishRemoval) { - // Animate the child out, actually removing it once its alpha is zero. - mLayout.animateValueForChild(DynamicAnimation.ALPHA, child, 0f, finishRemoval); - mLayout.animateValueForChild(DynamicAnimation.SCALE_X, child, ANIMATE_IN_STARTING_SCALE); - mLayout.animateValueForChild(DynamicAnimation.SCALE_Y, child, ANIMATE_IN_STARTING_SCALE); - // Animate the removing view in the opposite direction of the stack. final float xOffset = getOffsetForChainedPropertyAnimation(DynamicAnimation.TRANSLATION_X); - mLayout.animateValueForChild(DynamicAnimation.TRANSLATION_X, child, - mStackPosition.x - (-xOffset * ANIMATE_TRANSLATION_FACTOR)); + animationForChild(child) + .alpha(0f, finishRemoval /* after */) + .scaleX(ANIMATE_IN_STARTING_SCALE) + .scaleY(ANIMATE_IN_STARTING_SCALE) + .translationX(mStackPosition.x - (-xOffset * ANIMATE_TRANSLATION_FACTOR)) + .start(); - // Pull the top of the stack to the correct position, the chained animations will instruct - // any children that are out of place to animate to the correct position. - mLayout.animateValueForChildAtIndex(DynamicAnimation.TRANSLATION_X, 0, mStackPosition.x); + if (mLayout.getChildCount() > 0) { + animationForChildAtIndex(0).translationX(mStackPosition.x).start(); + } } /** Moves the stack, without any animation, to the starting position. */ @@ -486,10 +485,12 @@ public class StackAnimationController extends if (mLayout.getChildCount() > 0) { property.setValue(mLayout.getChildAt(0), value); - mLayout.animateValueForChildAtIndex( - property, - /* index */ 1, - value + getOffsetForChainedPropertyAnimation(property)); + + if (mLayout.getChildCount() > 1) { + animationForChildAtIndex(1) + .property(property, value + getOffsetForChainedPropertyAnimation(property)) + .start(); + } } } @@ -520,23 +521,15 @@ public class StackAnimationController extends private void animateInBubble(View child) { child.setTranslationY(mStackPosition.y); - // Pop in the new bubble. - child.setScaleX(ANIMATE_IN_STARTING_SCALE); - child.setScaleY(ANIMATE_IN_STARTING_SCALE); - mLayout.animateValueForChildAtIndex(DynamicAnimation.SCALE_X, 0, 1f); - mLayout.animateValueForChildAtIndex(DynamicAnimation.SCALE_Y, 0, 1f); - - // Fade in the new bubble. - child.setAlpha(0); - mLayout.animateValueForChildAtIndex(DynamicAnimation.ALPHA, 0, 1f); - - // Start the new bubble 4x the normal offset distance in the opposite direction. We'll - // animate in from this position. Since the animations are chained, when the new bubble - // flies in from the side, it will push the other ones out of the way. float xOffset = getOffsetForChainedPropertyAnimation(DynamicAnimation.TRANSLATION_X); - child.setTranslationX(mStackPosition.x - ANIMATE_TRANSLATION_FACTOR * xOffset); - mLayout.animateValueForChildAtIndex( - DynamicAnimation.TRANSLATION_X, 0, mStackPosition.x); + animationForChild(child) + .scaleX(ANIMATE_IN_STARTING_SCALE /* from */, 1f /* to */) + .scaleY(ANIMATE_IN_STARTING_SCALE /* from */, 1f /* to */) + .alpha(0f /* from */, 1f /* to */) + .translationX( + mStackPosition.x - ANIMATE_TRANSLATION_FACTOR * xOffset /* from */, + mStackPosition.x /* to */) + .start(); } /** diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java index 6c4be0617043..c243899c6bc9 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java @@ -211,7 +211,7 @@ public class DozeMachine { mDozeService.requestWakeUp(); } - private boolean isExecutingTransition() { + public boolean isExecutingTransition() { return !mQueuedRequests.isEmpty(); } diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java index bc3f48dac769..7189a48fed1f 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java @@ -164,16 +164,9 @@ public class DozeTriggers implements DozeMachine.Part { if (screenX != -1 && screenY != -1) { mDozeHost.onSlpiTap(screenX, screenY); } - // Logs screen wake up reason of either single or double tap. - mMetricsLogger.write(new LogMaker(MetricsEvent.DOZING) - .setType(MetricsEvent.TYPE_UPDATE).setSubtype(pulseReason)); - mMachine.wakeUp(); + gentleWakeUp(pulseReason); } else if (isPickup) { - // Logs screen wake up reason of lift. - mMetricsLogger.write(new LogMaker(MetricsEvent.DOZING) - .setType(MetricsEvent.TYPE_UPDATE) - .setSubtype(DozeLog.REASON_SENSOR_PICKUP)); - mMachine.wakeUp(); + gentleWakeUp(pulseReason); } else { mDozeHost.extendPulse(); } @@ -190,7 +183,29 @@ public class DozeTriggers implements DozeMachine.Part { } } + private void gentleWakeUp(int reason) { + // Log screen wake up reason (lift/pickup, tap, double-tap) + mMetricsLogger.write(new LogMaker(MetricsEvent.DOZING) + .setType(MetricsEvent.TYPE_UPDATE) + .setSubtype(reason)); + if (mDozeParameters.getDisplayNeedsBlanking()) { + // Let's prepare the display to wake-up by drawing black. + // This will cover the hardware wake-up sequence, where the display + // becomes black for a few frames. + mDozeHost.setAodDimmingScrim(255f); + } + mMachine.wakeUp(); + } + private void onProximityFar(boolean far) { + // Proximity checks are asynchronous and the user might have interacted with the phone + // when a new event is arriving. This means that a state transition might have happened + // and the proximity check is now obsolete. + if (mMachine.isExecutingTransition()) { + Log.w(TAG, "onProximityFar called during transition. Ignoring sensor response."); + return; + } + final boolean near = !far; final DozeMachine.State state = mMachine.getState(); final boolean paused = (state == DozeMachine.State.DOZE_AOD_PAUSED); diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java index a313336e3d71..21406e57ad7b 100644 --- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java +++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java @@ -110,9 +110,10 @@ class ImageGLWallpaper { mTextureBuffer.position(0); } - void setup() { + void setup(Bitmap bitmap) { setupAttributes(); setupUniforms(); + setupTexture(bitmap); } private void setupAttributes() { @@ -159,7 +160,7 @@ class ImageGLWallpaper { glDrawArrays(GL_TRIANGLES, 0, VERTICES.length / 2); } - void setupTexture(Bitmap bitmap) { + private void setupTexture(Bitmap bitmap) { final int[] tids = new int[1]; if (bitmap == null) { @@ -174,7 +175,7 @@ class ImageGLWallpaper { return; } - // Bind a named texture to a texturing target. + // Bind a named texture to a target. glBindTexture(GL_TEXTURE_2D, tids[0]); // Load the bitmap data and copy it over into the texture object that is currently bound. GLUtils.texImage2D(GL_TEXTURE_2D, 0, bitmap, 0); @@ -195,15 +196,8 @@ class ImageGLWallpaper { glUniform1i(mUniTexture, 0); } - void adjustTextureCoordinates(Bitmap bitmap, int surfaceWidth, int surfaceHeight, - float xOffset, float yOffset) { - if (bitmap == null) { - Log.d(TAG, "adjustTextureCoordinates: invalid bitmap"); - return; - } - - int bitmapWidth = bitmap.getWidth(); - int bitmapHeight = bitmap.getHeight(); + void adjustTextureCoordinates(int bitmapWidth, int bitmapHeight, + int surfaceWidth, int surfaceHeight, float xOffset, float yOffset) { float ratioW = 1f; float ratioH = 1f; float rX = 0f; diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java index 9df6ba5b1193..464cbe33c5f0 100644 --- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java +++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java @@ -58,6 +58,10 @@ public class ImageWallpaperRenderer implements GLSurfaceView.Renderer, private int mWidth = 0; private int mHeight = 0; + private Bitmap mBitmap; + private int mBitmapWidth = 0; + private int mBitmapHeight = 0; + public ImageWallpaperRenderer(Context context, ImageGLView glView) { mWallpaperManager = context.getSystemService(WallpaperManager.class); if (mWallpaperManager == null) { @@ -71,8 +75,12 @@ public class ImageWallpaperRenderer implements GLSurfaceView.Renderer, mGLView = glView; if (mWallpaperManager != null) { + mBitmap = mWallpaperManager.getBitmap(); + mBitmapWidth = mBitmap.getWidth(); + mBitmapHeight = mBitmap.getHeight(); // Compute per85 as transition threshold, this is an async work. - mImageProcessHelper.startComputingPercentile85(mWallpaperManager.getBitmap()); + mImageProcessHelper.startComputingPercentile85(mBitmap); + mWallpaperManager.forgetLoadedWallpaper(); } } @@ -81,8 +89,8 @@ public class ImageWallpaperRenderer implements GLSurfaceView.Renderer, glClearColor(0f, 0f, 0f, 1.0f); mProgram.useGLProgram( R.raw.image_wallpaper_vertex_shader, R.raw.image_wallpaper_fragment_shader); - mWallpaper.setup(); - mWallpaper.setupTexture(mWallpaperManager.getBitmap()); + mWallpaper.setup(mBitmap); + mBitmap = null; } @Override @@ -94,8 +102,8 @@ public class ImageWallpaperRenderer implements GLSurfaceView.Renderer, } mWidth = width; mHeight = height; - mWallpaper.adjustTextureCoordinates(mWallpaperManager.getBitmap(), - width, height, mXOffset, mYOffset); + mWallpaper.adjustTextureCoordinates( + mBitmapWidth, mBitmapHeight, width, height, mXOffset, mYOffset); } @Override @@ -132,13 +140,7 @@ public class ImageWallpaperRenderer implements GLSurfaceView.Renderer, @Override public void onOffsetsChanged(float xOffset, float yOffset, Rect frame) { - if (frame == null || mWallpaperManager == null - || (xOffset == mXOffset && yOffset == mYOffset)) { - return; - } - - Bitmap bitmap = mWallpaperManager.getBitmap(); - if (bitmap == null) { + if (frame == null || (xOffset == mXOffset && yOffset == mYOffset)) { return; } @@ -151,7 +153,8 @@ public class ImageWallpaperRenderer implements GLSurfaceView.Renderer, Log.d(TAG, "onOffsetsChanged: width=" + width + ", height=" + height + ", xOffset=" + mXOffset + ", yOffset=" + mYOffset); } - mWallpaper.adjustTextureCoordinates(bitmap, width, height, mXOffset, mYOffset); + mWallpaper.adjustTextureCoordinates( + mBitmapWidth, mBitmapHeight, width, height, mXOffset, mYOffset); requestRender(); } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index 0be9e25bfc27..676e59428075 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -2031,7 +2031,6 @@ public class KeyguardViewMediator extends SystemUI { private void handleNotifyScreenTurnedOff() { synchronized (this) { if (DEBUG) Log.d(TAG, "handleNotifyScreenTurnedOff"); - mStatusBarKeyguardViewManager.onScreenTurnedOff(); mDrawnCallback = null; } } diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java index 9f0f53e0d508..3a0534d24f59 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java +++ b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java @@ -38,8 +38,10 @@ import android.text.TextPaint; import android.text.TextUtils; import android.text.style.StyleSpan; import android.util.Log; +import android.view.View; import android.view.Window; import android.view.WindowManager; +import android.widget.TextView; import com.android.systemui.R; @@ -133,9 +135,12 @@ public class MediaProjectionPermissionActivity extends Activity String dialogTitle = getString(R.string.media_projection_dialog_title, appName); + View dialogTitleView = View.inflate(this, R.layout.media_projection_dialog_title, null); + TextView titleText = (TextView) dialogTitleView.findViewById(R.id.dialog_title); + titleText.setText(dialogTitle); + mDialog = new AlertDialog.Builder(this) - .setTitle(dialogTitle) - .setIcon(R.drawable.ic_media_projection_permission) + .setCustomTitle(dialogTitleView) .setMessage(message) .setPositiveButton(R.string.media_projection_action_text, this) .setNegativeButton(android.R.string.cancel, this) diff --git a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyDialog.kt b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyDialog.kt deleted file mode 100644 index cf170187cdaa..000000000000 --- a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyDialog.kt +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -package com.android.systemui.privacy - -import android.app.AlertDialog -import android.app.Dialog -import android.content.Context -import android.content.DialogInterface -import android.content.Intent -import android.content.pm.PackageManager -import android.content.res.ColorStateList -import android.os.UserHandle -import android.provider.Settings -import android.util.IconDrawableFactory -import android.util.StatsLog -import android.view.Gravity -import android.view.LayoutInflater -import android.view.View -import android.widget.ImageView -import android.widget.LinearLayout -import android.widget.TextView -import com.android.systemui.Dependency -import com.android.systemui.R -import com.android.systemui.plugins.ActivityStarter -import java.util.concurrent.TimeUnit - -class OngoingPrivacyDialog constructor( - private val context: Context, - private val dialogBuilder: PrivacyDialogBuilder -) { - - private val iconSize = context.resources.getDimensionPixelSize( - R.dimen.ongoing_appops_dialog_icon_size) - private val iconColor = context.resources.getColor( - com.android.internal.R.color.text_color_primary, context.theme) - private val iconMargin = context.resources.getDimensionPixelSize( - R.dimen.ongoing_appops_dialog_icon_margin) - private val iconFactory = IconDrawableFactory.newInstance(context, true) - private var dismissDialog: (() -> Unit)? = null - private val appsAndTypes = dialogBuilder.appsAndTypes - .sortedWith(compareBy({ -it.second.size }, // Sort by number of AppOps - { it.second.min() }, - { it.first })) - - fun createDialog(): Dialog { - val builder = AlertDialog.Builder(context).apply { - setPositiveButton(R.string.ongoing_privacy_dialog_ok, - object : DialogInterface.OnClickListener { - override fun onClick(dialog: DialogInterface?, which: Int) { - StatsLog.write(StatsLog.PRIVACY_INDICATORS_INTERACTED, - StatsLog.PRIVACY_INDICATORS_INTERACTED__TYPE__DIALOG_DISMISS) - } - }) - setNeutralButton(R.string.ongoing_privacy_dialog_open_settings, - object : DialogInterface.OnClickListener { - val intent = Intent(Settings.ACTION_PRIVACY_SETTINGS).putExtra( - Intent.EXTRA_DURATION_MILLIS, TimeUnit.MINUTES.toMillis(1)) - - @Suppress("DEPRECATION") - override fun onClick(dialog: DialogInterface?, which: Int) { - StatsLog.write(StatsLog.PRIVACY_INDICATORS_INTERACTED, StatsLog - .PRIVACY_INDICATORS_INTERACTED__TYPE__DIALOG_PRIVACY_SETTINGS) - Dependency.get(ActivityStarter::class.java) - .postStartActivityDismissingKeyguard(intent, 0) - } - }) - } - builder.setView(getContentView()) - val dialog = builder.create() - dismissDialog = dialog::dismiss - return dialog - } - - fun getContentView(): View { - val layoutInflater = LayoutInflater.from(context) - val contentView = layoutInflater.inflate(R.layout.ongoing_privacy_dialog_content, null) - - val title = contentView.findViewById(R.id.title) as TextView - val appsList = contentView.findViewById(R.id.items_container) as LinearLayout - - title.setText(dialogBuilder.getDialogTitle()) - - val numItems = appsAndTypes.size - for (i in 0..(numItems - 1)) { - val item = appsAndTypes[i] - addAppItem(appsList, item.first, item.second, dialogBuilder.types.size > 1) - } - return contentView - } - - @Suppress("DEPRECATION") - private fun addAppItem( - itemList: LinearLayout, - app: PrivacyApplication, - types: List<PrivacyType>, - showIcons: Boolean = true - ) { - val layoutInflater = LayoutInflater.from(context) - val item = layoutInflater.inflate(R.layout.ongoing_privacy_dialog_item, itemList, false) - val appIcon = item.findViewById(R.id.app_icon) as ImageView - val appName = item.findViewById(R.id.app_name) as TextView - val icons = item.findViewById(R.id.icons) as LinearLayout - - val lp = LinearLayout.LayoutParams(iconSize, iconSize).apply { - gravity = Gravity.CENTER_VERTICAL - marginStart = iconMargin - } - - app.icon.let { - appIcon.setImageDrawable(iconFactory.getShadowedIcon(it)) - } - - appName.text = app.applicationName - if (showIcons) { - dialogBuilder.generateIconsForApp(types).forEachIndexed { index, it -> - it.setBounds(0, 0, iconSize, iconSize) - val image = ImageView(context).apply { - imageTintList = ColorStateList.valueOf(iconColor) - setImageDrawable(it) - } - image.contentDescription = types[index].getName(context) - icons.addView(image, lp) - } - icons.visibility = View.VISIBLE - } else { - icons.visibility = View.GONE - } - try { - // Check if package exists - context.packageManager.getPackageInfo(app.packageName, 0) - item.setOnClickListener(object : View.OnClickListener { - val intent = Intent(Intent.ACTION_MANAGE_APP_PERMISSIONS) - .putExtra(Intent.EXTRA_PACKAGE_NAME, app.packageName) - .putExtra(Intent.EXTRA_USER, UserHandle.getUserHandleForUid(app.uid)) - override fun onClick(v: View?) { - StatsLog.write(StatsLog.PRIVACY_INDICATORS_INTERACTED, - StatsLog.PRIVACY_INDICATORS_INTERACTED__TYPE__DIALOG_LINE_ITEM, - app.packageName) - Dependency.get(ActivityStarter::class.java) - .postStartActivityDismissingKeyguard(intent, 0) - dismissDialog?.invoke() - } - }) - } catch (e: PackageManager.NameNotFoundException) {} - - itemList.addView(item) - } -} diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSCarrier.java b/packages/SystemUI/src/com/android/systemui/qs/QSCarrier.java index 3ff30c527f39..f19445c1f33b 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSCarrier.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSCarrier.java @@ -89,16 +89,22 @@ public class QSCarrier extends LinearLayout { .append(", "); } // TODO: show mobile data off/no internet text for 5 seconds before carrier text - if (TextUtils.equals(state.typeContentDescription, - mContext.getString(R.string.data_connection_no_internet)) - || TextUtils.equals(state.typeContentDescription, - mContext.getString(R.string.cell_data_off_content_description))) { + if (hasValidTypeContentDescription(state.typeContentDescription)) { contentDescription.append(state.typeContentDescription); } mMobileSignal.setContentDescription(contentDescription); } } + private boolean hasValidTypeContentDescription(String typeContentDescription) { + return TextUtils.equals(typeContentDescription, + mContext.getString(R.string.data_connection_no_internet)) + || TextUtils.equals(typeContentDescription, + mContext.getString(R.string.cell_data_off_content_description)) + || TextUtils.equals(typeContentDescription, + mContext.getString(R.string.not_default_data_content_description)); + } + public void setCarrierText(CharSequence text) { mCarrierText.setText(text); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java index 0ae8f6c9de5b..10eacbaefd9a 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java @@ -87,7 +87,6 @@ public class QSFooterImpl extends FrameLayout implements QSFooter, private boolean mListening; - private View mDivider; protected MultiUserSwitch mMultiUserSwitch; private ImageView mMultiUserAvatar; @@ -133,7 +132,6 @@ public class QSFooterImpl extends FrameLayout implements QSFooter, @Override protected void onFinishInflate() { super.onFinishInflate(); - mDivider = findViewById(R.id.qs_footer_divider); mEdit = findViewById(android.R.id.edit); mEdit.setOnClickListener(view -> mActivityStarter.postQSRunnableDismissingKeyguard(() -> @@ -218,7 +216,6 @@ public class QSFooterImpl extends FrameLayout implements QSFooter, @Nullable private TouchAnimator createFooterAnimator() { return new TouchAnimator.Builder() - .addFloat(mDivider, "alpha", 0, 1) .addFloat(mActionsContainer, "alpha", 0, 1) .addFloat(mEditContainer, "alpha", 0, 1) .addFloat(mDragHandle, "alpha", 1, 0, 0) diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java index 4862b9eddc85..d78982183db9 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java @@ -23,7 +23,6 @@ import android.animation.AnimatorListenerAdapter; import android.annotation.ColorInt; import android.app.ActivityManager; import android.app.AlarmManager; -import android.app.Dialog; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -62,7 +61,6 @@ import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.DarkIconDispatcher; import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver; import com.android.systemui.privacy.OngoingPrivacyChip; -import com.android.systemui.privacy.OngoingPrivacyDialog; import com.android.systemui.privacy.PrivacyDialogBuilder; import com.android.systemui.privacy.PrivacyItem; import com.android.systemui.privacy.PrivacyItemController; @@ -71,7 +69,6 @@ import com.android.systemui.statusbar.phone.PhoneStatusBarView; import com.android.systemui.statusbar.phone.StatusBarIconController; import com.android.systemui.statusbar.phone.StatusBarIconController.TintedIconManager; import com.android.systemui.statusbar.phone.StatusIconContainer; -import com.android.systemui.statusbar.phone.SystemUIDialog; import com.android.systemui.statusbar.policy.Clock; import com.android.systemui.statusbar.policy.DateView; import com.android.systemui.statusbar.policy.NextAlarmController; @@ -398,14 +395,13 @@ public class QuickStatusBarHeader extends RelativeLayout implements private void updateStatusIconAlphaAnimator() { mStatusIconsAlphaAnimator = new TouchAnimator.Builder() - .addFloat(mQuickQsStatusIcons, "alpha", 1, 0) + .addFloat(mQuickQsStatusIcons, "alpha", 1, 0, 0) .build(); } private void updateHeaderTextContainerAlphaAnimator() { mHeaderTextContainerAlphaAnimator = new TouchAnimator.Builder() - .addFloat(mHeaderTextContainerView, "alpha", 0, 1) - .setStartDelay(.5f) + .addFloat(mHeaderTextContainerView, "alpha", 0, 0, 1) .build(); } @@ -561,11 +557,8 @@ public class QuickStatusBarHeader extends RelativeLayout implements StatsLog.write(StatsLog.PRIVACY_INDICATORS_INTERACTED, StatsLog.PRIVACY_INDICATORS_INTERACTED__TYPE__CHIP_CLICKED); mUiHandler.post(() -> { - Dialog mDialog = new OngoingPrivacyDialog(mContext, builder).createDialog(); - SystemUIDialog.setShowForAllUsers(mDialog, false); - SystemUIDialog.registerDismissListener(mDialog); - SystemUIDialog.setWindowOnTop(mDialog); - mActivityStarter.postQSRunnableDismissingKeyguard(() -> mDialog.show()); + mActivityStarter.postStartActivityDismissingKeyguard( + new Intent(Intent.ACTION_REVIEW_ONGOING_PERMISSION_USAGE), 0); mHost.collapsePanels(); }); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java index d26cee982b64..2956ad0600a7 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java @@ -41,7 +41,6 @@ import com.android.systemui.qs.tiles.LocationTile; import com.android.systemui.qs.tiles.NfcTile; import com.android.systemui.qs.tiles.NightDisplayTile; import com.android.systemui.qs.tiles.RotationLockTile; -import com.android.systemui.qs.tiles.SensorPrivacyTile; import com.android.systemui.qs.tiles.UserTile; import com.android.systemui.qs.tiles.WifiTile; import com.android.systemui.qs.tiles.WorkModeTile; @@ -73,7 +72,6 @@ public class QSFactoryImpl implements QSFactory { private final Provider<DataSaverTile> mDataSaverTileProvider; private final Provider<NightDisplayTile> mNightDisplayTileProvider; private final Provider<NfcTile> mNfcTileProvider; - private final Provider<SensorPrivacyTile> mSensorPrivacyTileProvider; private final Provider<GarbageMonitor.MemoryTile> mMemoryTileProvider; private QSTileHost mHost; @@ -96,7 +94,6 @@ public class QSFactoryImpl implements QSFactory { Provider<DataSaverTile> dataSaverTileProvider, Provider<NightDisplayTile> nightDisplayTileProvider, Provider<NfcTile> nfcTileProvider, - Provider<SensorPrivacyTile> sensorPrivacyTileProvider, Provider<GarbageMonitor.MemoryTile> memoryTileProvider) { mWifiTileProvider = wifiTileProvider; mBluetoothTileProvider = bluetoothTileProvider; @@ -115,7 +112,6 @@ public class QSFactoryImpl implements QSFactory { mDataSaverTileProvider = dataSaverTileProvider; mNightDisplayTileProvider = nightDisplayTileProvider; mNfcTileProvider = nfcTileProvider; - mSensorPrivacyTileProvider = sensorPrivacyTileProvider; mMemoryTileProvider = memoryTileProvider; } @@ -168,8 +164,6 @@ public class QSFactoryImpl implements QSFactory { return mNightDisplayTileProvider.get(); case "nfc": return mNfcTileProvider.get(); - case "sensorprivacy": - return mSensorPrivacyTileProvider.get(); } // Intent tiles. diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyTile.java deleted file mode 100644 index 7ee37d567a55..000000000000 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyTile.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui.qs.tiles; - -import android.content.Intent; -import android.hardware.SensorPrivacyManager; -import android.service.quicksettings.Tile; -import android.widget.Switch; - -import com.android.internal.logging.MetricsLogger; -import com.android.internal.logging.nano.MetricsProto.MetricsEvent; -import com.android.systemui.R; -import com.android.systemui.plugins.ActivityStarter; -import com.android.systemui.plugins.qs.QSTile.BooleanState; -import com.android.systemui.qs.QSHost; -import com.android.systemui.qs.tileimpl.QSTileImpl; -import com.android.systemui.statusbar.policy.KeyguardMonitor; - -import javax.inject.Inject; - -/** Quick settings tile: SensorPrivacy mode **/ -public class SensorPrivacyTile extends QSTileImpl<BooleanState> implements - SensorPrivacyManager.OnSensorPrivacyChangedListener { - private static final String TAG = "SensorPrivacy"; - private final Icon mIcon = - ResourceIcon.get(R.drawable.ic_signal_sensors); - private final KeyguardMonitor mKeyguard; - private final SensorPrivacyManager mSensorPrivacyManager; - private final ActivityStarter mActivityStarter; - - @Inject - public SensorPrivacyTile(QSHost host, SensorPrivacyManager sensorPrivacyManager, - KeyguardMonitor keyguardMonitor, ActivityStarter activityStarter) { - super(host); - - mSensorPrivacyManager = sensorPrivacyManager; - mKeyguard = keyguardMonitor; - mActivityStarter = activityStarter; - } - - @Override - public BooleanState newTileState() { - return new BooleanState(); - } - - @Override - public void handleClick() { - final boolean wasEnabled = mState.value; - // Don't allow disabling from the lockscreen. - if (wasEnabled && mKeyguard.isSecure() && mKeyguard.isShowing()) { - mActivityStarter.postQSRunnableDismissingKeyguard(() -> { - MetricsLogger.action(mContext, getMetricsCategory(), !wasEnabled); - setEnabled(!wasEnabled); - }); - return; - } - - MetricsLogger.action(mContext, getMetricsCategory(), !wasEnabled); - setEnabled(!wasEnabled); - } - - private void setEnabled(boolean enabled) { - mSensorPrivacyManager.setSensorPrivacy(enabled); - } - - @Override - public CharSequence getTileLabel() { - return mContext.getString(R.string.sensor_privacy_mode); - } - - @Override - public Intent getLongClickIntent() { - return new Intent(); - } - - @Override - protected void handleUpdateState(BooleanState state, Object arg) { - final boolean enabled = arg instanceof Boolean ? (Boolean) arg - : mSensorPrivacyManager.isSensorPrivacyEnabled(); - state.value = enabled; - state.label = mContext.getString(R.string.sensor_privacy_mode); - state.icon = mIcon; - state.state = enabled ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE; - state.contentDescription = state.label; - state.expandedAccessibilityClassName = Switch.class.getName(); - } - - @Override - public int getMetricsCategory() { - return MetricsEvent.QS_SENSOR_PRIVACY; - } - - @Override - protected String composeChangeAnnouncement() { - if (mState.value) { - return mContext - .getString(R.string.accessibility_quick_settings_sensor_privacy_changed_on); - } else { - return mContext - .getString(R.string.accessibility_quick_settings_sensor_privacy_changed_off); - } - } - - @Override - protected void handleSetListening(boolean listening) { - if (listening) { - mSensorPrivacyManager.addSensorPrivacyListener(this); - } else { - mSensorPrivacyManager.removeSensorPrivacyListener(this); - } - } - - @Override - public void onSensorPrivacyChanged(boolean enabled) { - refreshState(enabled); - } -} diff --git a/packages/SystemUI/src/com/android/systemui/recents/TriangleShape.java b/packages/SystemUI/src/com/android/systemui/recents/TriangleShape.java index ef4e19559f1f..de8e6ea4a0cb 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/TriangleShape.java +++ b/packages/SystemUI/src/com/android/systemui/recents/TriangleShape.java @@ -50,6 +50,24 @@ public class TriangleShape extends PathShape { return new TriangleShape(triangularPath, width, height); } + /** Create an arrow TriangleShape that points to the left or the right */ + public static TriangleShape createHorizontal( + float width, float height, boolean isPointingLeft) { + Path triangularPath = new Path(); + if (isPointingLeft) { + triangularPath.moveTo(0, height / 2); + triangularPath.lineTo(width, height); + triangularPath.lineTo(width, 0); + triangularPath.close(); + } else { + triangularPath.moveTo(0, height); + triangularPath.lineTo(width, height / 2); + triangularPath.lineTo(0, 0); + triangularPath.close(); + } + return new TriangleShape(triangularPath, width, height); + } + @Override public void getOutline(@NonNull Outline outline) { outline.setConvexPath(mTriangularPath); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt index ccb8d9bf46c1..3433fa8ffff0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt @@ -17,6 +17,7 @@ package com.android.systemui.statusbar.notification import android.animation.ObjectAnimator +import android.content.Context import android.util.FloatProperty import com.android.systemui.Interpolators import com.android.systemui.plugins.statusbar.StatusBarStateController @@ -25,12 +26,14 @@ import com.android.systemui.statusbar.SysuiStatusBarStateController import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout import com.android.systemui.statusbar.notification.stack.StackStateAnimator +import com.android.systemui.statusbar.phone.DozeParameters import javax.inject.Inject import javax.inject.Singleton @Singleton class NotificationWakeUpCoordinator @Inject constructor( + private val mContext: Context, private val mAmbientPulseManager: AmbientPulseManager, private val mStatusBarStateController: StatusBarStateController) : AmbientPulseManager.OnAmbientChangedListener, StatusBarStateController.StateListener { @@ -59,10 +62,12 @@ class NotificationWakeUpCoordinator @Inject constructor( private var mLinearVisibilityAmount = 0.0f private var mWakingUp = false private val mEntrySetToClearWhenFinished = mutableSetOf<NotificationEntry>() + private val mDozeParameters: DozeParameters; init { mAmbientPulseManager.addListener(this) mStatusBarStateController.addCallback(this) + mDozeParameters = DozeParameters.getInstance(mContext) } fun setStackScroller(stackScroller: NotificationStackScrollLayout) { @@ -194,7 +199,7 @@ class NotificationWakeUpCoordinator @Inject constructor( } override fun onAmbientStateChanged(entry: NotificationEntry, isPulsing: Boolean) { - var animate = true + var animate = mDozeParameters.getAlwaysOn() && !mDozeParameters.getDisplayNeedsBlanking() if (!isPulsing) { if (mLinearDozeAmount != 0.0f) { if (entry.isRowDismissed) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java index d7baeee9aec9..9630727c8f3d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java @@ -2432,7 +2432,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView protected void onLayout(boolean changed, int left, int top, int right, int bottom) { int intrinsicBefore = getIntrinsicHeight(); super.onLayout(changed, left, top, right, bottom); - if (intrinsicBefore != getIntrinsicHeight()) { + if (intrinsicBefore != getIntrinsicHeight() && intrinsicBefore != 0) { notifyHeightChanged(true /* needsAnimation */); } if (mMenuRow.getMenuView() != null) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java index b4dd1144e761..09f513dc1579 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java @@ -679,16 +679,25 @@ public class NotificationContentInflater { if (runningInflations.isEmpty()) { if ((reInflateFlags & FLAG_CONTENT_VIEW_CONTRACTED) != 0) { if (result.inflatedContentView != null) { + // New view case privateLayout.setContractedChild(result.inflatedContentView); + cachedContentViews.put(FLAG_CONTENT_VIEW_CONTRACTED, result.newContentView); + } else if (cachedContentViews.get(FLAG_CONTENT_VIEW_CONTRACTED) != null) { + // Reinflation case. Only update if it's still cached (i.e. view has not been + // freed while inflating). + cachedContentViews.put(FLAG_CONTENT_VIEW_CONTRACTED, result.newContentView); } - cachedContentViews.put(FLAG_CONTENT_VIEW_CONTRACTED, result.newContentView); } if ((reInflateFlags & FLAG_CONTENT_VIEW_EXPANDED) != 0) { if (result.inflatedExpandedView != null) { privateLayout.setExpandedChild(result.inflatedExpandedView); + cachedContentViews.put(FLAG_CONTENT_VIEW_EXPANDED, result.newExpandedView); } else if (result.newExpandedView == null) { privateLayout.setExpandedChild(null); + cachedContentViews.put(FLAG_CONTENT_VIEW_EXPANDED, null); + } else if (cachedContentViews.get(FLAG_CONTENT_VIEW_EXPANDED) != null) { + cachedContentViews.put(FLAG_CONTENT_VIEW_EXPANDED, result.newExpandedView); } if (result.newExpandedView != null) { privateLayout.setExpandedInflatedSmartReplies( @@ -696,15 +705,18 @@ public class NotificationContentInflater { } else { privateLayout.setExpandedInflatedSmartReplies(null); } - cachedContentViews.put(FLAG_CONTENT_VIEW_EXPANDED, result.newExpandedView); row.setExpandable(result.newExpandedView != null); } if ((reInflateFlags & FLAG_CONTENT_VIEW_HEADS_UP) != 0) { if (result.inflatedHeadsUpView != null) { privateLayout.setHeadsUpChild(result.inflatedHeadsUpView); + cachedContentViews.put(FLAG_CONTENT_VIEW_HEADS_UP, result.newHeadsUpView); } else if (result.newHeadsUpView == null) { privateLayout.setHeadsUpChild(null); + cachedContentViews.put(FLAG_CONTENT_VIEW_HEADS_UP, null); + } else if (cachedContentViews.get(FLAG_CONTENT_VIEW_HEADS_UP) != null) { + cachedContentViews.put(FLAG_CONTENT_VIEW_HEADS_UP, result.newHeadsUpView); } if (result.newHeadsUpView != null) { privateLayout.setHeadsUpInflatedSmartReplies( @@ -712,14 +724,15 @@ public class NotificationContentInflater { } else { privateLayout.setHeadsUpInflatedSmartReplies(null); } - cachedContentViews.put(FLAG_CONTENT_VIEW_HEADS_UP, result.newHeadsUpView); } if ((reInflateFlags & FLAG_CONTENT_VIEW_PUBLIC) != 0) { if (result.inflatedPublicView != null) { publicLayout.setContractedChild(result.inflatedPublicView); + cachedContentViews.put(FLAG_CONTENT_VIEW_PUBLIC, result.newPublicView); + } else if (cachedContentViews.get(FLAG_CONTENT_VIEW_PUBLIC) != null) { + cachedContentViews.put(FLAG_CONTENT_VIEW_PUBLIC, result.newPublicView); } - cachedContentViews.put(FLAG_CONTENT_VIEW_PUBLIC, result.newPublicView); } if ((reInflateFlags & FLAG_CONTENT_VIEW_AMBIENT) != 0) { @@ -730,8 +743,10 @@ public class NotificationContentInflater { ? publicLayout : privateLayout; newParent.setAmbientChild(result.inflatedAmbientView); otherParent.setAmbientChild(null); + cachedContentViews.put(FLAG_CONTENT_VIEW_AMBIENT, result.newAmbientView); + } else if (cachedContentViews.get(FLAG_CONTENT_VIEW_AMBIENT) != null) { + cachedContentViews.put(FLAG_CONTENT_VIEW_AMBIENT, result.newAmbientView); } - cachedContentViews.put(FLAG_CONTENT_VIEW_AMBIENT, result.newAmbientView); } entry.headsUpStatusBarText = result.headsUpStatusBarText; entry.headsUpStatusBarTextPublic = result.headsUpStatusBarTextPublic; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java index 410eeae4e946..ca452093eb20 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java @@ -18,6 +18,7 @@ package com.android.systemui.statusbar.phone; import android.content.Context; import android.hardware.biometrics.BiometricSourceType; +import android.metrics.LogMaker; import android.os.Handler; import android.os.PowerManager; import android.os.SystemClock; @@ -26,6 +27,8 @@ import android.provider.Settings; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.logging.MetricsLogger; +import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.util.LatencyTracker; import com.android.keyguard.KeyguardConstants; import com.android.keyguard.KeyguardUpdateMonitor; @@ -140,6 +143,8 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback { } }; + private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class); + public BiometricUnlockController(Context context, DozeScrimController dozeScrimController, KeyguardViewMediator keyguardViewMediator, @@ -253,6 +258,8 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback { Trace.endSection(); return; } + mMetricsLogger.write(new LogMaker(MetricsEvent.BIOMETRIC_AUTH) + .setType(MetricsEvent.TYPE_SUCCESS).setSubtype(toSubtype(biometricSourceType))); startWakeAndUnlock(calculateMode(biometricSourceType)); } @@ -303,7 +310,6 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback { case MODE_SHOW_BOUNCER: Trace.beginSection("MODE_UNLOCK or MODE_SHOW_BOUNCER"); if (!wasDeviceInteractive) { - mStatusBarKeyguardViewManager.notifyDeviceWakeUpRequested(); mPendingShowBouncer = true; } else { showBouncer(); @@ -421,12 +427,16 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback { @Override public void onBiometricAuthFailed(BiometricSourceType biometricSourceType) { + mMetricsLogger.write(new LogMaker(MetricsEvent.BIOMETRIC_AUTH) + .setType(MetricsEvent.TYPE_FAILURE).setSubtype(toSubtype(biometricSourceType))); cleanup(); } @Override public void onBiometricError(int msgId, String errString, BiometricSourceType biometricSourceType) { + mMetricsLogger.write(new LogMaker(MetricsEvent.BIOMETRIC_AUTH) + .setType(MetricsEvent.TYPE_ERROR).setSubtype(toSubtype(biometricSourceType))); cleanup(); } @@ -502,4 +512,20 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback { public boolean isBiometricUnlock() { return isWakeAndUnlock() || mMode == MODE_UNLOCK; } + + /** + * Translates biometric source type for logging purpose. + */ + private int toSubtype(BiometricSourceType biometricSourceType) { + switch (biometricSourceType) { + case FINGERPRINT: + return 0; + case FACE: + return 1; + case IRIS: + return 2; + default: + return 3; + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java index 19373ac8e28b..fe3a455302d4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java @@ -137,7 +137,7 @@ public class KeyguardBouncer { if (resetSecuritySelection) { // showPrimarySecurityScreen() updates the current security method. This is needed in // case we are already showing and the current security method changed. - mKeyguardView.showPrimarySecurityScreen(); + showPrimarySecurityScreen(); } if (mRoot.getVisibility() == View.VISIBLE || mShowingSoon) { return; @@ -344,11 +344,20 @@ public class KeyguardBouncer { boolean wasInitialized = mRoot != null; ensureView(); if (wasInitialized) { - mKeyguardView.showPrimarySecurityScreen(); + showPrimarySecurityScreen(); } mBouncerPromptReason = mCallback.getBouncerPromptReason(); } + private void showPrimarySecurityScreen() { + mKeyguardView.showPrimarySecurityScreen(); + KeyguardSecurityView keyguardSecurityView = mKeyguardView.getCurrentSecurityView(); + if (keyguardSecurityView != null) { + mLockIconContainer = ((ViewGroup) keyguardSecurityView) + .findViewById(R.id.lock_icon_container); + } + } + /** * Current notification panel expansion * @param fraction 0 when notification panel is collapsed and 1 when expanded. @@ -406,7 +415,6 @@ public class KeyguardBouncer { removeView(); mHandler.removeCallbacks(mRemoveViewRunnable); mRoot = (ViewGroup) LayoutInflater.from(mContext).inflate(R.layout.keyguard_bouncer, null); - mLockIconContainer = mRoot.findViewById(R.id.lock_icon_container); mKeyguardView = mRoot.findViewById(R.id.keyguard_host_view); mKeyguardView.setLockPatternUtils(mLockPatternUtils); mKeyguardView.setViewMediatorCallback(mCallback); @@ -414,6 +422,8 @@ public class KeyguardBouncer { mStatusBarHeight = mRoot.getResources().getDimensionPixelOffset( com.android.systemui.R.dimen.status_bar_height); mRoot.setVisibility(View.INVISIBLE); + mRoot.addOnLayoutChangeListener((v, left, top, right, bottom, oldLeft, oldTop, oldRight, + oldBottom) -> mExpansionCallback.onLayout()); mRoot.setAccessibilityPaneTitle(mKeyguardView.getAccessibilityTitleForCurrentMode()); final WindowInsets rootInsets = mRoot.getRootWindowInsets(); @@ -426,7 +436,6 @@ public class KeyguardBouncer { if (mRoot != null && mRoot.getParent() == mContainer) { mContainer.removeView(mRoot); mRoot = null; - mLockIconContainer = null; } } @@ -495,5 +504,6 @@ public class KeyguardBouncer { void onFullyShown(); void onStartingToHide(); void onFullyHidden(); + void onLayout(); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java index c8ce39230da8..4c50d07aa6ea 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java @@ -468,6 +468,11 @@ public class KeyguardStatusBarView extends RelativeLayout } @Override + public void onDensityOrFontScaleChanged() { + loadDimens(); + } + + @Override public void onOverlayChanged() { mCarrierLabel.setTextAppearance( Utils.getThemeAttr(mContext, com.android.internal.R.attr.textAppearanceSmall)); @@ -514,6 +519,8 @@ public class KeyguardStatusBarView extends RelativeLayout return; } mDozing = dozing; + setClipChildren(!dozing); + setClipToPadding(!dozing); updateVisibilities(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java index 18612c359dae..ef82b3402b15 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java @@ -182,7 +182,6 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav private NavigationBackAction mBackAction; private QuickSwitchAction mQuickSwitchAction; private NavigationAssistantAction mAssistantAction; - private NavigationNotificationPanelAction mNotificationPanelAction; private NavigationBarEdgePanel mLeftEdgePanel; private NavigationBarEdgePanel mRightEdgePanel; @@ -475,10 +474,6 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav mAssistantAction = new NavigationAssistantAction(this, mOverviewProxyService, assistManager); } - if (mNotificationPanelAction == null) { - mNotificationPanelAction = new NavigationNotificationPanelAction(this, - mOverviewProxyService, panel); - } if (mGestureHelper instanceof QuickStepController) { ((QuickStepController) mGestureHelper).setComponents(this); updateNavigationGestures(); @@ -517,8 +512,6 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav return mQuickSwitchAction; case NavigationPrototypeController.ACTION_ASSISTANT: return mAssistantAction; - case NavigationPrototypeController.ACTION_EXPAND_NOTIFICATION: - return mNotificationPanelAction; case NavigationPrototypeController.ACTION_NOTHING: return null; default: diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationNotificationPanelAction.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationNotificationPanelAction.java deleted file mode 100644 index 6c7870dccd27..000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationNotificationPanelAction.java +++ /dev/null @@ -1,50 +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 com.android.systemui.statusbar.phone; - -import android.annotation.NonNull; -import android.view.MotionEvent; - -import com.android.systemui.recents.OverviewProxyService; - -/** - * Triggers notification panel to be expanded when executed - */ -public class NavigationNotificationPanelAction extends NavigationGestureAction { - private final NotificationPanelView mPanelView; - - public NavigationNotificationPanelAction(@NonNull NavigationBarView navigationBarView, - @NonNull OverviewProxyService service, @NonNull NotificationPanelView panelView) { - super(navigationBarView, service); - mPanelView = panelView; - } - - @Override - public boolean isEnabled() { - return true; - } - - @Override - public boolean disableProxyEvents() { - return true; - } - - @Override - public void onGestureStart(MotionEvent event) { - mPanelView.expand(true); - } -} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationPrototypeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationPrototypeController.java index 31579c26bbd0..979de07fce73 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationPrototypeController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationPrototypeController.java @@ -47,7 +47,7 @@ public class NavigationPrototypeController extends ContentObserver { @Retention(RetentionPolicy.SOURCE) @IntDef({ACTION_DEFAULT, ACTION_QUICKSTEP, ACTION_QUICKSCRUB, ACTION_BACK, - ACTION_QUICKSWITCH, ACTION_NOTHING, ACTION_ASSISTANT, ACTION_EXPAND_NOTIFICATION}) + ACTION_QUICKSWITCH, ACTION_NOTHING, ACTION_ASSISTANT}) @interface GestureAction {} static final int ACTION_DEFAULT = 0; static final int ACTION_QUICKSTEP = 1; @@ -56,7 +56,6 @@ public class NavigationPrototypeController extends ContentObserver { static final int ACTION_QUICKSWITCH = 4; static final int ACTION_NOTHING = 5; static final int ACTION_ASSISTANT = 6; - static final int ACTION_EXPAND_NOTIFICATION = 7; private OnPrototypeChangedListener mListener; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java index 4a86484393a9..b7a78738828e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java @@ -60,6 +60,7 @@ import com.android.systemui.statusbar.policy.LocationController; import com.android.systemui.statusbar.policy.NextAlarmController; import com.android.systemui.statusbar.policy.RotationLockController; import com.android.systemui.statusbar.policy.RotationLockController.RotationLockControllerCallback; +import com.android.systemui.statusbar.policy.SensorPrivacyController; import com.android.systemui.statusbar.policy.UserInfoController; import com.android.systemui.statusbar.policy.ZenModeController; @@ -100,6 +101,7 @@ public class PhoneStatusBarPolicy private final String mSlotLocation; private final String mSlotMicrophone; private final String mSlotCamera; + private final String mSlotSensorsOff; private final Context mContext; private final Handler mHandler = new Handler(); @@ -118,6 +120,7 @@ public class PhoneStatusBarPolicy private final LocationController mLocationController; private final PrivacyItemController mPrivacyItemController; private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class); + private final SensorPrivacyController mSensorPrivacyController; // Assume it's all good unless we hear otherwise. We don't always seem // to get broadcasts that it *is* there. @@ -149,6 +152,7 @@ public class PhoneStatusBarPolicy mKeyguardMonitor = Dependency.get(KeyguardMonitor.class); mLocationController = Dependency.get(LocationController.class); mPrivacyItemController = Dependency.get(PrivacyItemController.class); + mSensorPrivacyController = Dependency.get(SensorPrivacyController.class); mSlotCast = context.getString(com.android.internal.R.string.status_bar_cast); mSlotHotspot = context.getString(com.android.internal.R.string.status_bar_hotspot); @@ -165,6 +169,7 @@ public class PhoneStatusBarPolicy mSlotLocation = context.getString(com.android.internal.R.string.status_bar_location); mSlotMicrophone = context.getString(com.android.internal.R.string.status_bar_microphone); mSlotCamera = context.getString(com.android.internal.R.string.status_bar_camera); + mSlotSensorsOff = context.getString(com.android.internal.R.string.status_bar_sensors_off); // listen for broadcasts IntentFilter filter = new IntentFilter(); @@ -232,6 +237,11 @@ public class PhoneStatusBarPolicy mContext.getString(R.string.accessibility_location_active)); mIconController.setIconVisibility(mSlotLocation, false); + // sensors off + mIconController.setIcon(mSlotSensorsOff, R.drawable.stat_sys_sensors_off, null); + mIconController.setIconVisibility(mSlotSensorsOff, + mSensorPrivacyController.isSensorPrivacyEnabled()); + mRotationLockController.addCallback(this); mBluetooth.addCallback(this); mProvisionedController.addCallback(this); @@ -242,6 +252,7 @@ public class PhoneStatusBarPolicy mDataSaver.addCallback(this); mKeyguardMonitor.addCallback(this); mPrivacyItemController.addCallback(this); + mSensorPrivacyController.addCallback(mSensorPrivacyListener); SysUiServiceProvider.getComponent(mContext, CommandQueue.class).addCallback(this); } @@ -514,6 +525,16 @@ public class PhoneStatusBarPolicy } }; + private final SensorPrivacyController.OnSensorPrivacyChangedListener mSensorPrivacyListener = + new SensorPrivacyController.OnSensorPrivacyChangedListener() { + @Override + public void onSensorPrivacyChanged(boolean enabled) { + mHandler.post(() -> { + mIconController.setIconVisibility(mSlotSensorsOff, enabled); + }); + } + }; + @Override public void appTransitionStarting(int displayId, long startTime, long duration, boolean forced) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index c4b41d458893..319a504c17a5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -1109,7 +1109,6 @@ public class StatusBar extends SystemUI implements DemoMode, where.getLocationInWindow(mTmpInt2); mWakeUpTouchLocation = new PointF(mTmpInt2[0] + where.getWidth() / 2, mTmpInt2[1] + where.getHeight() / 2); - mStatusBarKeyguardViewManager.notifyDeviceWakeUpRequested(); mFalsingManager.onScreenOnFromTouch(); } } @@ -3005,7 +3004,7 @@ public class StatusBar extends SystemUI implements DemoMode, private void updatePanelExpansionForKeyguard() { if (mState == StatusBarState.KEYGUARD && mBiometricUnlockController.getMode() - != BiometricUnlockController.MODE_WAKE_AND_UNLOCK) { + != BiometricUnlockController.MODE_WAKE_AND_UNLOCK && !mBouncerShowing) { instantExpandNotificationsPanel(); } else if (mState == StatusBarState.FULLSCREEN_USER_SWITCHER) { instantCollapseNotificationPanel(); @@ -3563,6 +3562,9 @@ public class StatusBar extends SystemUI implements DemoMode, } } + /** + * Propagation of the bouncer state, indicating that it's fully visible. + */ public void setBouncerShowing(boolean bouncerShowing) { mBouncerShowing = bouncerShowing; if (mStatusBarView != null) mStatusBarView.setBouncerShowing(bouncerShowing); @@ -3620,10 +3622,13 @@ public class StatusBar extends SystemUI implements DemoMode, mWakeUpCoordinator.setWakingUp(true); mAmbientPulseManager.releaseAllImmediately(); mVisualStabilityManager.setScreenOn(true); - updateNotificationPanelTouchState(); updateVisibleToUser(); updateIsKeyguard(); mDozeServiceHost.stopDozing(); + // This is intentionally below the stopDozing call above, since it avoids that we're + // unnecessarily animating the wakeUp transition. Animations should only be enabled + // once we fully woke up. + updateNotificationPanelTouchState(); mPulseExpansionHandler.onStartedWakingUp(); } @@ -3736,7 +3741,6 @@ public class StatusBar extends SystemUI implements DemoMode, PowerManager pm = mContext.getSystemService(PowerManager.class); pm.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_CAMERA_LAUNCH, "com.android.systemui:CAMERA_GESTURE"); - mStatusBarKeyguardViewManager.notifyDeviceWakeUpRequested(); } vibrateForCameraGesture(); if (!mStatusBarKeyguardViewManager.isShowing()) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java index e8a5c7a5c14a..441285138afd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -85,6 +85,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb @Override public void onFullyShown() { updateStates(); + mStatusBar.wakeUpIfDozing(SystemClock.uptimeMillis(), mContainer, "BOUNCER_VISIBLE"); } @Override @@ -96,6 +97,11 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb public void onFullyHidden() { updateStates(); } + + @Override + public void onLayout() { + mNotificationPanelView.updateLockIcon(); + } }; protected LockPatternUtils mLockPatternUtils; @@ -346,14 +352,6 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb } } - public void onScreenTurnedOff() { - // TODO: remove - } - - public void notifyDeviceWakeUpRequested() { - // TODO: remove - } - public void setNeedsInput(boolean needsInput) { mStatusBarWindowController.setKeyguardNeedsInput(needsInput); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java index c8f389e4ccbe..5bd394fb7187 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java @@ -256,7 +256,8 @@ public class MobileSignalController extends SignalController< level++; } boolean dataDisabled = mCurrentState.userSetup - && mCurrentState.iconGroup == TelephonyIcons.DATA_DISABLED; + && (mCurrentState.iconGroup == TelephonyIcons.DATA_DISABLED + || mCurrentState.iconGroup == TelephonyIcons.NOT_DEFAULT_DATA); boolean noInternet = mCurrentState.inetCondition == 0; boolean cutOut = dataDisabled || noInternet; return SignalDrawable.getState(level, getNumLevels(), cutOut); @@ -285,7 +286,8 @@ public class MobileSignalController extends SignalController< if (mCurrentState.inetCondition == 0) { dataContentDescription = mContext.getString(R.string.data_connection_no_internet); } - final boolean dataDisabled = mCurrentState.iconGroup == TelephonyIcons.DATA_DISABLED + final boolean dataDisabled = (mCurrentState.iconGroup == TelephonyIcons.DATA_DISABLED + || mCurrentState.iconGroup == TelephonyIcons.NOT_DEFAULT_DATA) && mCurrentState.userSetup; // Show icon in QS when we are connected or data is disabled. @@ -456,7 +458,12 @@ public class MobileSignalController extends SignalController< if (isCarrierNetworkChangeActive()) { mCurrentState.iconGroup = TelephonyIcons.CARRIER_NETWORK_CHANGE; } else if (isDataDisabled() && !mConfig.alwaysShowDataRatIcon) { - mCurrentState.iconGroup = TelephonyIcons.DATA_DISABLED; + if (mSubscriptionInfo.getSubscriptionId() + != mDefaults.getDefaultDataSubId()) { + mCurrentState.iconGroup = TelephonyIcons.NOT_DEFAULT_DATA; + } else { + mCurrentState.iconGroup = TelephonyIcons.DATA_DISABLED; + } } if (isEmergencyOnly() != mCurrentState.isEmergency) { mCurrentState.isEmergency = isEmergencyOnly(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java index f4d623770c57..ef39912b6578 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java @@ -987,6 +987,7 @@ public class NetworkControllerImpl extends BroadcastReceiver datatype.equals("lte") ? TelephonyIcons.LTE : datatype.equals("lte+") ? TelephonyIcons.LTE_PLUS : datatype.equals("dis") ? TelephonyIcons.DATA_DISABLED : + datatype.equals("not") ? TelephonyIcons.NOT_DEFAULT_DATA : TelephonyIcons.UNKNOWN; } if (args.containsKey("roam")) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyController.java new file mode 100644 index 000000000000..6d5ce60ef621 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyController.java @@ -0,0 +1,36 @@ +/* + * 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 com.android.systemui.statusbar.policy; + +/** + * Interface for classes to control sensor privacy state and notification. + */ +public interface SensorPrivacyController extends + CallbackController<SensorPrivacyController.OnSensorPrivacyChangedListener> { + + /** + * Returns whether sensor privacy is enabled. + */ + boolean isSensorPrivacyEnabled(); + + /** + * Interface for classes to receive callbacks when sensor privacy state changes. + */ + interface OnSensorPrivacyChangedListener { + void onSensorPrivacyChanged(boolean enabled); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyControllerImpl.java new file mode 100644 index 000000000000..5db66932d3c1 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyControllerImpl.java @@ -0,0 +1,94 @@ +/* + * 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 com.android.systemui.statusbar.policy; + +import android.content.Context; +import android.hardware.SensorPrivacyManager; + +import java.util.ArrayList; +import java.util.List; + +import javax.inject.Inject; +import javax.inject.Singleton; + +/** + * Controls sensor privacy state and notification. + */ +@Singleton +public class SensorPrivacyControllerImpl implements SensorPrivacyController, + SensorPrivacyManager.OnSensorPrivacyChangedListener { + private SensorPrivacyManager mSensorPrivacyManager; + private final List<OnSensorPrivacyChangedListener> mListeners; + private Object mLock = new Object(); + private boolean mSensorPrivacyEnabled; + + /** + * Public constructor. + */ + @Inject + public SensorPrivacyControllerImpl(Context context) { + mSensorPrivacyManager = (SensorPrivacyManager) context.getSystemService( + Context.SENSOR_PRIVACY_SERVICE); + mSensorPrivacyEnabled = mSensorPrivacyManager.isSensorPrivacyEnabled(); + mSensorPrivacyManager.addSensorPrivacyListener(this); + mListeners = new ArrayList<>(1); + } + + /** + * Returns whether sensor privacy is enabled. + */ + public boolean isSensorPrivacyEnabled() { + synchronized (mLock) { + return mSensorPrivacyEnabled; + } + } + + /** + * Adds the provided listener for callbacks when sensor privacy state changes. + */ + public void addCallback(OnSensorPrivacyChangedListener listener) { + synchronized (mLock) { + mListeners.add(listener); + notifyListenerLocked(listener); + } + } + + /** + * Removes the provided listener from callbacks when sensor privacy state changes. + */ + public void removeCallback(OnSensorPrivacyChangedListener listener) { + synchronized (mLock) { + mListeners.remove(listener); + } + } + + /** + * Callback invoked by the SensorPrivacyService when sensor privacy state changes. + */ + public void onSensorPrivacyChanged(boolean enabled) { + synchronized (mLock) { + mSensorPrivacyEnabled = enabled; + for (OnSensorPrivacyChangedListener listener : mListeners) { + notifyListenerLocked(listener); + } + } + } + + private void notifyListenerLocked(OnSensorPrivacyChangedListener listener) { + listener.onSensorPrivacyChanged(mSensorPrivacyEnabled); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java index 7347f66de8ce..e151ca3e23f3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java @@ -245,6 +245,22 @@ class TelephonyIcons { 0, false); + static final MobileIconGroup NOT_DEFAULT_DATA = new MobileIconGroup( + "NotDefaultData", + null, + null, + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH, + 0, 0, + 0, + 0, + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0], + R.string.not_default_data_content_description, + 0, + false); + + // When adding a new MobileIconGround, check if the dataContentDescription has to be filtered + // in QSCarrier#hasValidTypeContentDescription + /** Mapping icon name(lower case) to the icon object. */ static final Map<String, MobileIconGroup> ICON_NAME_TO_ICON; static { @@ -265,6 +281,7 @@ class TelephonyIcons { ICON_NAME_TO_ICON.put("5g", NR_5G); ICON_NAME_TO_ICON.put("5g_plus", NR_5G_PLUS); ICON_NAME_TO_ICON.put("datadisable", DATA_DISABLED); + ICON_NAME_TO_ICON.put("notdefaultdata", NOT_DEFAULT_DATA); } } diff --git a/packages/SystemUI/src/com/android/systemui/volume/Events.java b/packages/SystemUI/src/com/android/systemui/volume/Events.java index 6e740b8536b3..2a84c5d4d44d 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/Events.java +++ b/packages/SystemUI/src/com/android/systemui/volume/Events.java @@ -56,6 +56,7 @@ public class Events { public static final int EVENT_SHOW_USB_OVERHEAT_ALARM = 19; // (reason|int) (keyguard|bool) public static final int EVENT_DISMISS_USB_OVERHEAT_ALARM = 20; // (reason|int) (keyguard|bool) public static final int EVENT_ODI_CAPTIONS_CLICK = 21; + public static final int EVENT_ODI_CAPTIONS_TOOLTIP_CLICK = 22; private static final String[] EVENT_TAGS = { "show_dialog", @@ -79,7 +80,8 @@ public class Events { "ringer_toggle", "show_usb_overheat_alarm", "dismiss_usb_overheat_alarm", - "odi_captions_click" + "odi_captions_click", + "odi_captions_tooltip_click" }; public static final int DISMISS_REASON_UNKNOWN = 0; diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java index 9192a25dcd3b..2fa8889a02f9 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java @@ -282,9 +282,9 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa Settings.Secure.ODI_CAPTIONS_ENABLED, isEnabled ? 1 : 0); } - public void getCaptionsComponentState() { + public void getCaptionsComponentState(boolean fromTooltip) { if (mDestroyed) return; - mWorker.sendEmptyMessage(W.GET_CAPTIONS_COMPONENT_STATE); + mWorker.obtainMessage(W.GET_CAPTIONS_COMPONENT_STATE, fromTooltip).sendToTarget(); } public void notifyVisible(boolean visible) { @@ -382,13 +382,13 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa } } - private void onGetCaptionsComponentStateW() { + private void onGetCaptionsComponentStateW(boolean fromTooltip) { try { String componentNameString = mContext.getString( com.android.internal.R.string.config_defaultSystemCaptionsService); if (TextUtils.isEmpty(componentNameString)) { // component doesn't exist - mCallbacks.onCaptionComponentStateChanged(false); + mCallbacks.onCaptionComponentStateChanged(false, fromTooltip); return; } @@ -399,18 +399,18 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa ComponentName componentName = ComponentName.unflattenFromString(componentNameString); if (componentName == null) { - mCallbacks.onCaptionComponentStateChanged(false); + mCallbacks.onCaptionComponentStateChanged(false, fromTooltip); return; } PackageManager packageManager = mContext.getPackageManager(); mCallbacks.onCaptionComponentStateChanged( packageManager.getComponentEnabledSetting(componentName) - == PackageManager.COMPONENT_ENABLED_STATE_ENABLED); + == PackageManager.COMPONENT_ENABLED_STATE_ENABLED, fromTooltip); } catch (Exception ex) { Log.e(TAG, "isCaptionsServiceEnabled failed to check for captions component", ex); - mCallbacks.onCaptionComponentStateChanged(false); + mCallbacks.onCaptionComponentStateChanged(false, fromTooltip); } } @@ -790,7 +790,8 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa case NOTIFY_VISIBLE: onNotifyVisibleW(msg.arg1 != 0); break; case USER_ACTIVITY: onUserActivityW(); break; case SHOW_SAFETY_WARNING: onShowSafetyWarningW(msg.arg1); break; - case GET_CAPTIONS_COMPONENT_STATE: onGetCaptionsComponentStateW(); break; + case GET_CAPTIONS_COMPONENT_STATE: + onGetCaptionsComponentStateW((Boolean) msg.obj); break; case ACCESSIBILITY_MODE_CHANGED: onAccessibilityModeChanged((Boolean) msg.obj); } } @@ -933,11 +934,13 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa } @Override - public void onCaptionComponentStateChanged(Boolean isComponentEnabled) { + public void onCaptionComponentStateChanged( + Boolean isComponentEnabled, Boolean fromTooltip) { boolean componentEnabled = isComponentEnabled == null ? false : isComponentEnabled; for (final Map.Entry<Callbacks, Handler> entry : mCallbackMap.entrySet()) { entry.getValue().post( - () -> entry.getKey().onCaptionComponentStateChanged(componentEnabled)); + () -> entry.getKey().onCaptionComponentStateChanged( + componentEnabled, fromTooltip)); } } } diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java index 398b30963da7..cdda216c5220 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java @@ -28,6 +28,7 @@ import static android.media.AudioManager.STREAM_VOICE_CALL; import static android.view.View.ACCESSIBILITY_LIVE_REGION_POLITE; import static android.view.View.GONE; import static android.view.View.VISIBLE; +import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; import static com.android.systemui.volume.Events.DISMISS_REASON_ODI_CAPTIONS_CLICKED; import static com.android.systemui.volume.Events.DISMISS_REASON_SETTINGS_CLICKED; @@ -64,11 +65,13 @@ import android.util.Log; import android.util.Slog; import android.util.SparseBooleanArray; import android.view.ContextThemeWrapper; +import android.view.Gravity; import android.view.MotionEvent; import android.view.View; import android.view.View.AccessibilityDelegate; import android.view.ViewGroup; import android.view.ViewPropertyAnimator; +import android.view.ViewStub; import android.view.Window; import android.view.WindowManager; import android.view.accessibility.AccessibilityEvent; @@ -113,7 +116,10 @@ public class VolumeDialogImpl implements VolumeDialog { static final int DIALOG_TIMEOUT_MILLIS = 3000; static final int DIALOG_SAFETYWARNING_TIMEOUT_MILLIS = 5000; + static final int DIALOG_ODI_CAPTIONS_TOOLTIP_TIMEOUT_MILLIS = 5000; static final int DIALOG_HOVERING_TIMEOUT_MILLIS = 16000; + static final int DIALOG_SHOW_ANIMATION_DURATION = 300; + static final int DIALOG_HIDE_ANIMATION_DURATION = 250; private final Context mContext; private final H mHandler = new H(); @@ -152,15 +158,21 @@ public class VolumeDialogImpl implements VolumeDialog { private boolean mHovering = false; private boolean mShowActiveStreamOnly; private boolean mConfigChanged = false; + private boolean mHasSeenODICaptionsTooltip; + private ViewStub mODICaptionsTooltipViewStub; + private View mODICaptionsTooltipView = null; public VolumeDialogImpl(Context context) { - mContext = new ContextThemeWrapper(context, com.android.systemui.R.style.qs_theme); + mContext = + new ContextThemeWrapper(context, com.android.systemui.R.style.volume_dialog_theme); mController = Dependency.get(VolumeDialogController.class); mKeyguard = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE); mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE); mAccessibilityMgr = Dependency.get(AccessibilityManagerWrapper.class); mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class); mShowActiveStreamOnly = showActiveStreamOnly(); + mHasSeenODICaptionsTooltip = + Prefs.getBoolean(context, Prefs.Key.HAS_SEEN_ODI_CAPTIONS_TOOLTIP, false); } public void init(int windowType, Callback callback) { @@ -201,8 +213,9 @@ public class VolumeDialogImpl implements VolumeDialog { lp.format = PixelFormat.TRANSLUCENT; lp.setTitle(VolumeDialogImpl.class.getSimpleName()); lp.windowAnimations = -1; + lp.gravity = Gravity.RIGHT | Gravity.CENTER_VERTICAL; mWindow.setAttributes(lp); - mWindow.setLayout(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); + mWindow.setLayout(WRAP_CONTENT, WRAP_CONTENT); mDialog.setContentView(R.layout.volume_dialog); mDialogView = mDialog.findViewById(R.id.volume_dialog); @@ -213,12 +226,13 @@ public class VolumeDialogImpl implements VolumeDialog { mDialogView.animate() .alpha(1) .translationX(0) - .setDuration(300) + .setDuration(DIALOG_SHOW_ANIMATION_DURATION) .setInterpolator(new SystemUIInterpolators.LogDecelerateInterpolator()) .withEndAction(() -> { if (!Prefs.getBoolean(mContext, Prefs.Key.TOUCHED_RINGER_TOGGLE, false)) { if (mRingerIcon != null) { - mRingerIcon.postOnAnimationDelayed(mSinglePress, 1500); + mRingerIcon.postOnAnimationDelayed( + getSinglePressFor(mRingerIcon), 1500); } } }) @@ -233,20 +247,23 @@ public class VolumeDialogImpl implements VolumeDialog { return true; }); - lp = mWindow.getAttributes(); - lp.gravity = ((FrameLayout.LayoutParams) mDialogView.getLayoutParams()).gravity; - mWindow.setAttributes(lp); - mDialogRowsView = mDialog.findViewById(R.id.volume_dialog_rows); mRinger = mDialog.findViewById(R.id.ringer); if (mRinger != null) { mRingerIcon = mRinger.findViewById(R.id.ringer_icon); mZenIcon = mRinger.findViewById(R.id.dnd_icon); } + mODICaptionsView = mDialog.findViewById(R.id.odi_captions); if (mODICaptionsView != null) { mODICaptionsIcon = mODICaptionsView.findViewById(R.id.odi_captions_icon); } + mODICaptionsTooltipViewStub = mDialog.findViewById(R.id.odi_captions_tooltip_stub); + if (mHasSeenODICaptionsTooltip && mODICaptionsTooltipViewStub != null) { + mDialogView.removeView(mODICaptionsTooltipViewStub); + mODICaptionsTooltipViewStub = null; + } + mSettingsView = mDialog.findViewById(R.id.settings_container); mSettingsIcon = mDialog.findViewById(R.id.settings); @@ -495,10 +512,70 @@ public class VolumeDialogImpl implements VolumeDialog { }); } - mController.getCaptionsComponentState(); + mController.getCaptionsComponentState(false); + } + + private void checkODICaptionsTooltip(boolean fromDismiss) { + if (!mHasSeenODICaptionsTooltip && !fromDismiss && mODICaptionsTooltipViewStub != null) { + mController.getCaptionsComponentState(true); + } else { + if (mHasSeenODICaptionsTooltip && mODICaptionsTooltipView != null) { + hideCaptionsTooltip(); + } + } + } + + protected void showCaptionsTooltip() { + if (!mHasSeenODICaptionsTooltip && mODICaptionsTooltipViewStub != null) { + mODICaptionsTooltipView = mODICaptionsTooltipViewStub.inflate(); + mODICaptionsTooltipView.findViewById(R.id.dismiss).setOnClickListener(v -> { + hideCaptionsTooltip(); + Events.writeEvent(mContext, Events.EVENT_ODI_CAPTIONS_TOOLTIP_CLICK); + }); + mODICaptionsTooltipViewStub = null; + rescheduleTimeoutH(); + } + + if (mODICaptionsTooltipView != null) { + mODICaptionsTooltipView.setAlpha(0.f); + mODICaptionsTooltipView.animate() + .alpha(1.f) + .setStartDelay(DIALOG_SHOW_ANIMATION_DURATION) + .withEndAction(() -> { + if (D.BUG) Log.d(TAG, "tool:checkODICaptionsTooltip() putBoolean true"); + Prefs.putBoolean(mContext, + Prefs.Key.HAS_SEEN_ODI_CAPTIONS_TOOLTIP, true); + mHasSeenODICaptionsTooltip = true; + if (mODICaptionsIcon != null) { + mODICaptionsIcon + .postOnAnimation(getSinglePressFor(mODICaptionsIcon)); + } + }) + .start(); + } } - private void updateODICaptionsH(boolean isServiceComponentEnabled) { + private void hideCaptionsTooltip() { + if (mODICaptionsTooltipView != null) { + mODICaptionsTooltipView.animate().cancel(); + mODICaptionsTooltipView.setAlpha(1.f); + mODICaptionsTooltipView.animate() + .alpha(0.f) + .setStartDelay(0) + .setDuration(DIALOG_HIDE_ANIMATION_DURATION) + .start(); + } + } + + protected void tryToRemoveCaptionsTooltip() { + if (mHasSeenODICaptionsTooltip && mODICaptionsTooltipView != null) { + ViewGroup container = mDialog.findViewById(R.id.volume_dialog_container); + container.removeView(mODICaptionsTooltipView); + mODICaptionsTooltipView = null; + } + } + + private void updateODICaptionsH(boolean isServiceComponentEnabled, boolean fromTooltip) { if (mODICaptionsView != null) { mODICaptionsView.setVisibility(isServiceComponentEnabled ? VISIBLE : GONE); } @@ -506,6 +583,7 @@ public class VolumeDialogImpl implements VolumeDialog { if (!isServiceComponentEnabled) return; updateCaptionsIcon(); + if (fromTooltip) showCaptionsTooltip(); } private void updateCaptionsIcon() { @@ -602,7 +680,8 @@ public class VolumeDialogImpl implements VolumeDialog { mDialog.show(); Events.writeEvent(mContext, Events.EVENT_SHOW_DIALOG, reason, mKeyguard.isKeyguardLocked()); mController.notifyVisible(true); - mController.getCaptionsComponentState(); + mController.getCaptionsComponentState(false); + checkODICaptionsTooltip(false); } protected void rescheduleTimeoutH() { @@ -625,11 +704,21 @@ public class VolumeDialogImpl implements VolumeDialog { AccessibilityManager.FLAG_CONTENT_TEXT | AccessibilityManager.FLAG_CONTENT_CONTROLS); } + if (!mHasSeenODICaptionsTooltip && mODICaptionsTooltipView != null) { + return mAccessibilityMgr.getRecommendedTimeoutMillis( + DIALOG_ODI_CAPTIONS_TOOLTIP_TIMEOUT_MILLIS, + AccessibilityManager.FLAG_CONTENT_TEXT + | AccessibilityManager.FLAG_CONTENT_CONTROLS); + } return mAccessibilityMgr.getRecommendedTimeoutMillis(DIALOG_TIMEOUT_MILLIS, AccessibilityManager.FLAG_CONTENT_CONTROLS); } protected void dismissH(int reason) { + if (D.BUG) { + Log.d(TAG, "mDialog.dismiss() reason: " + Events.DISMISS_REASONS[reason] + + " from: " + Debug.getCaller()); + } mHandler.removeMessages(H.DISMISS); mHandler.removeMessages(H.SHOW); mDialogView.animate().cancel(); @@ -642,14 +731,15 @@ public class VolumeDialogImpl implements VolumeDialog { mDialogView.setAlpha(1); ViewPropertyAnimator animator = mDialogView.animate() .alpha(0) - .setDuration(250) + .setDuration(DIALOG_HIDE_ANIMATION_DURATION) .setInterpolator(new SystemUIInterpolators.LogAccelerateInterpolator()) .withEndAction(() -> mHandler.postDelayed(() -> { - if (D.BUG) Log.d(TAG, "mDialog.dismiss()"); mDialog.dismiss(); + tryToRemoveCaptionsTooltip(); }, 50)); if (!isLandscape()) animator.translationX(mDialogView.getWidth() / 2); animator.start(); + checkODICaptionsTooltip(true); mController.notifyVisible(false); synchronized (mSafetyWarningLock) { if (mSafetyWarning != null) { @@ -822,6 +912,7 @@ public class VolumeDialogImpl implements VolumeDialog { } protected void onStateChangedH(State state) { + if (D.BUG) Log.d(TAG, "onStateChangedH() state: " + state.toString()); if (mState != null && state != null && mState.ringerModeInternal != state.ringerModeInternal && state.ringerModeInternal == AudioManager.RINGER_MODE_VIBRATE) { @@ -847,7 +938,7 @@ public class VolumeDialogImpl implements VolumeDialog { mActiveStream = state.activeStream; VolumeRow activeRow = getActiveRow(); updateRowsH(activeRow); - rescheduleTimeoutH(); + if (mShowing) rescheduleTimeoutH(); } for (VolumeRow row : mRows) { updateVolumeRowH(row); @@ -1114,24 +1205,22 @@ public class VolumeDialogImpl implements VolumeDialog { } } - private Runnable mSinglePress = new Runnable() { - @Override - public void run() { - if (mRingerIcon != null) { - mRingerIcon.setPressed(true); - mRingerIcon.postOnAnimationDelayed(mSingleUnpress, 200); + private Runnable getSinglePressFor(ImageButton button) { + return () -> { + if (button != null) { + button.setPressed(true); + button.postOnAnimationDelayed(getSingleUnpressFor(button), 200); } - } - }; + }; + } - private Runnable mSingleUnpress = new Runnable() { - @Override - public void run() { - if (mRingerIcon != null) { - mRingerIcon.setPressed(false); + private Runnable getSingleUnpressFor(ImageButton button) { + return () -> { + if (button != null) { + button.setPressed(false); } - } - }; + }; + } private final VolumeDialogController.Callbacks mControllerCallbackH = new VolumeDialogController.Callbacks() { @@ -1198,8 +1287,9 @@ public class VolumeDialogImpl implements VolumeDialog { } @Override - public void onCaptionComponentStateChanged(Boolean isComponentEnabled) { - updateODICaptionsH(isComponentEnabled); + public void onCaptionComponentStateChanged( + Boolean isComponentEnabled, Boolean fromTooltip) { + updateODICaptionsH(isComponentEnabled, fromTooltip); } }; @@ -1232,7 +1322,7 @@ public class VolumeDialogImpl implements VolumeDialog { private final class CustomDialog extends Dialog implements DialogInterface { public CustomDialog(Context context) { - super(context, com.android.systemui.R.style.qs_theme); + super(context, com.android.systemui.R.style.volume_dialog_theme); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeToolTipView.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeToolTipView.java new file mode 100644 index 000000000000..1de55856f942 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeToolTipView.java @@ -0,0 +1,76 @@ +/* + * 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 com.android.systemui.volume; + +import android.content.Context; +import android.graphics.CornerPathEffect; +import android.graphics.Paint; +import android.graphics.drawable.ShapeDrawable; +import android.util.AttributeSet; +import android.util.TypedValue; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; + +import androidx.core.content.ContextCompat; + +import com.android.systemui.R; +import com.android.systemui.recents.TriangleShape; + +/** + * Tool tip view that draws an arrow that points to the volume dialog. + */ +public class VolumeToolTipView extends LinearLayout { + public VolumeToolTipView(Context context) { + super(context); + } + + public VolumeToolTipView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public VolumeToolTipView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + public VolumeToolTipView(Context context, AttributeSet attrs, int defStyleAttr, + int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + drawArrow(); + } + + private void drawArrow() { + View arrowView = findViewById(R.id.arrow); + ViewGroup.LayoutParams arrowLp = arrowView.getLayoutParams(); + ShapeDrawable arrowDrawable = new ShapeDrawable(TriangleShape.createHorizontal( + arrowLp.width, arrowLp.height, false)); + Paint arrowPaint = arrowDrawable.getPaint(); + TypedValue typedValue = new TypedValue(); + getContext().getTheme().resolveAttribute(android.R.attr.colorAccent, typedValue, true); + arrowPaint.setColor(ContextCompat.getColor(getContext(), typedValue.resourceId)); + // The corner path effect won't be reflected in the shadow, but shouldn't be noticeable. + arrowPaint.setPathEffect(new CornerPathEffect( + getResources().getDimension(R.dimen.volume_tool_tip_arrow_corner_radius))); + arrowView.setBackground(arrowDrawable); + + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java index b8add89243ce..cd8480505c04 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java @@ -43,7 +43,6 @@ public class ExpandedAnimationControllerTest extends PhysicsAnimationLayoutTestC @Spy private ExpandedAnimationController mExpandedController = new ExpandedAnimationController(new Point(500, 1000) /* displaySize */); - private int mStackOffset; private float mBubblePadding; private float mBubbleSize; diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayoutTest.java index a50919b22a6a..38a90f7a52d2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayoutTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayoutTest.java @@ -20,12 +20,11 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.ArgumentMatchers.anyFloat; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; import android.os.SystemClock; import android.testing.AndroidTestingRunner; @@ -68,7 +67,8 @@ public class PhysicsAnimationLayoutTest extends PhysicsAnimationLayoutTestCase { // offset, and don't actually remove views immediately (since most implementations will wait // to animate child views out before actually removing them). mTestableController.setAnimatedProperties(Sets.newHashSet( - DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y)); + DynamicAnimation.TRANSLATION_X, + DynamicAnimation.TRANSLATION_Y)); mTestableController.setChainedProperties(Sets.newHashSet(DynamicAnimation.TRANSLATION_X)); mTestableController.setOffsetForProperty( DynamicAnimation.TRANSLATION_X, TEST_TRANSLATION_X_OFFSET); @@ -126,11 +126,11 @@ public class PhysicsAnimationLayoutTest extends PhysicsAnimationLayoutTestCase { // Animate the first child's translation X. final CountDownLatch animLatch = new CountDownLatch(1); - mLayout.animateValueForChildAtIndex( - DynamicAnimation.TRANSLATION_X, - 0, - 100, - animLatch::countDown); + + mTestableController + .animationForChildAtIndex(0) + .translationX(100) + .start(animLatch::countDown); animLatch.await(1, TimeUnit.SECONDS); // Ensure that the first view has been translated, but not the second one. @@ -140,60 +140,50 @@ public class PhysicsAnimationLayoutTest extends PhysicsAnimationLayoutTestCase { @Test public void testUpdateValueXChained() throws InterruptedException { - mLayout.setController(mTestableController); - addOneMoreThanRenderLimitBubbles(); testChainedTranslationAnimations(); } @Test - public void testSetEndListeners() throws InterruptedException { + public void testSetEndActions() throws InterruptedException { mLayout.setController(mTestableController); addOneMoreThanRenderLimitBubbles(); mTestableController.setChainedProperties(Sets.newHashSet()); final CountDownLatch xLatch = new CountDownLatch(1); - OneTimeEndListener xEndListener = Mockito.spy(new OneTimeEndListener() { + Runnable xEndAction = Mockito.spy(new Runnable() { + @Override - public void onAnimationEnd(DynamicAnimation animation, boolean canceled, float value, - float velocity) { - super.onAnimationEnd(animation, canceled, value, velocity); + public void run() { xLatch.countDown(); } }); final CountDownLatch yLatch = new CountDownLatch(1); - final OneTimeEndListener yEndListener = Mockito.spy(new OneTimeEndListener() { + Runnable yEndAction = Mockito.spy(new Runnable() { + @Override - public void onAnimationEnd(DynamicAnimation animation, boolean canceled, float value, - float velocity) { - super.onAnimationEnd(animation, canceled, value, velocity); + public void run() { yLatch.countDown(); } }); // Set end listeners for both x and y. - mLayout.setEndListenerForProperty(xEndListener, DynamicAnimation.TRANSLATION_X); - mLayout.setEndListenerForProperty(yEndListener, DynamicAnimation.TRANSLATION_Y); + mLayout.setEndActionForProperty(xEndAction, DynamicAnimation.TRANSLATION_X); + mLayout.setEndActionForProperty(yEndAction, DynamicAnimation.TRANSLATION_Y); // Animate x, and wait for it to finish. - mLayout.animateValueForChildAtIndex( - DynamicAnimation.TRANSLATION_X, - 0, - 100); + mTestableController.animationForChildAtIndex(0) + .translationX(100) + .start(); + xLatch.await(); yLatch.await(1, TimeUnit.SECONDS); // Make sure the x end listener was called only one time, and the y listener was never // called since we didn't animate y. Wait 1 second after the original animation end trigger // to make sure it doesn't get called again. - Mockito.verify(xEndListener, Mockito.after(1000).times(1)) - .onAnimationEnd( - any(), - eq(false), - eq(100f), - anyFloat()); - Mockito.verify(yEndListener, Mockito.after(1000).never()) - .onAnimationEnd(any(), anyBoolean(), anyFloat(), anyFloat()); + Mockito.verify(xEndAction, Mockito.after(1000).times(1)).run(); + Mockito.verify(yEndAction, Mockito.after(1000).never()).run(); } @Test @@ -203,39 +193,31 @@ public class PhysicsAnimationLayoutTest extends PhysicsAnimationLayoutTestCase { mTestableController.setChainedProperties(Sets.newHashSet()); final CountDownLatch xLatch = new CountDownLatch(1); - OneTimeEndListener xEndListener = Mockito.spy(new OneTimeEndListener() { + Runnable xEndListener = Mockito.spy(new Runnable() { + @Override - public void onAnimationEnd(DynamicAnimation animation, boolean canceled, float value, - float velocity) { - super.onAnimationEnd(animation, canceled, value, velocity); + public void run() { xLatch.countDown(); } }); // Set the end listener. - mLayout.setEndListenerForProperty(xEndListener, DynamicAnimation.TRANSLATION_X); + mLayout.setEndActionForProperty(xEndListener, DynamicAnimation.TRANSLATION_X); // Animate x, and wait for it to finish. - mLayout.animateValueForChildAtIndex( - DynamicAnimation.TRANSLATION_X, - 0, - 100); + mTestableController.animationForChildAtIndex(0) + .translationX(100) + .start(); xLatch.await(); InOrder endListenerCalls = inOrder(xEndListener); - endListenerCalls.verify(xEndListener, Mockito.times(1)) - .onAnimationEnd( - any(), - eq(false), - eq(100f), - anyFloat()); + endListenerCalls.verify(xEndListener, Mockito.times(1)).run(); // Animate X again, remove the end listener. - mLayout.animateValueForChildAtIndex( - DynamicAnimation.TRANSLATION_X, - 0, - 1000); - mLayout.removeEndListenerForProperty(DynamicAnimation.TRANSLATION_X); + mTestableController.animationForChildAtIndex(0) + .translationX(1000) + .start(); + mLayout.removeEndActionForProperty(DynamicAnimation.TRANSLATION_X); xLatch.await(1, TimeUnit.SECONDS); // Make sure the end listener was not called. @@ -261,10 +243,9 @@ public class PhysicsAnimationLayoutTest extends PhysicsAnimationLayoutTestCase { secondController.setRemoveImmediately(true); mLayout.setController(secondController); - mLayout.animateValueForChildAtIndex( - DynamicAnimation.SCALE_X, - 0, - 1.5f); + mTestableController.animationForChildAtIndex(0) + .scaleX(1.5f) + .start(); waitForPropertyAnimations(DynamicAnimation.SCALE_X); @@ -285,10 +266,9 @@ public class PhysicsAnimationLayoutTest extends PhysicsAnimationLayoutTestCase { .getOffsetForChainedPropertyAnimation(eq(DynamicAnimation.SCALE_X)); mLayout.setController(mTestableController); - mLayout.animateValueForChildAtIndex( - DynamicAnimation.TRANSLATION_X, - 0, - 100f); + mTestableController.animationForChildAtIndex(0) + .translationX(100f) + .start(); waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X); @@ -308,10 +288,9 @@ public class PhysicsAnimationLayoutTest extends PhysicsAnimationLayoutTestCase { assertFalse(mLayout.arePropertiesAnimating( DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y)); - mLayout.animateValueForChildAtIndex( - DynamicAnimation.TRANSLATION_X, - 0, - 100); + mTestableController.animationForChildAtIndex(0) + .translationX(100f) + .start(); // Wait for the animations to get underway. SystemClock.sleep(50); @@ -330,14 +309,9 @@ public class PhysicsAnimationLayoutTest extends PhysicsAnimationLayoutTestCase { mLayout.setController(mTestableController); addOneMoreThanRenderLimitBubbles(); - mLayout.animateValueForChildAtIndex( - DynamicAnimation.TRANSLATION_X, - 0, - 1000); - mLayout.animateValueForChildAtIndex( - DynamicAnimation.TRANSLATION_Y, - 0, - 1000); + mTestableController.animationForChildAtIndex(0) + .position(1000, 1000) + .start(); mLayout.cancelAllAnimations(); @@ -367,13 +341,15 @@ public class PhysicsAnimationLayoutTest extends PhysicsAnimationLayoutTestCase { /** Standard test of chained translation animations. */ private void testChainedTranslationAnimations() throws InterruptedException { + mLayout.setController(mTestableController); + addOneMoreThanRenderLimitBubbles(); + assertEquals(0, mLayout.getChildAt(0).getTranslationX(), .1f); assertEquals(0, mLayout.getChildAt(1).getTranslationX(), .1f); - mLayout.animateValueForChildAtIndex( - DynamicAnimation.TRANSLATION_X, - 0, - 100); + mTestableController.animationForChildAtIndex(0) + .translationX(100f) + .start(); waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X); @@ -392,10 +368,9 @@ public class PhysicsAnimationLayoutTest extends PhysicsAnimationLayoutTestCase { assertEquals(0, mLayout.getChildAt(1).getTranslationY(), .1f); // Animate the first child's Y translation. - mLayout.animateValueForChildAtIndex( - DynamicAnimation.TRANSLATION_Y, - 0, - 100); + mTestableController.animationForChildAtIndex(0) + .translationY(100f) + .start(); waitForPropertyAnimations(DynamicAnimation.TRANSLATION_Y); @@ -405,6 +380,75 @@ public class PhysicsAnimationLayoutTest extends PhysicsAnimationLayoutTestCase { assertEquals(0, mLayout.getChildAt(1).getTranslationY(), .1f); } + @Test + public void testPhysicsAnimator() throws InterruptedException { + mLayout.setController(mTestableController); + addOneMoreThanRenderLimitBubbles(); + + Runnable afterAll = Mockito.mock(Runnable.class); + Runnable after = Mockito.spy(new Runnable() { + int mCallCount = 0; + + @Override + public void run() { + // Make sure that if only one of the animations has finished, we didn't already call + // afterAll. + if (mCallCount == 1) { + Mockito.verifyNoMoreInteractions(afterAll); + } + } + }); + + // Animate from x = 7 to x = 100, and from y = 100 to 7 = 200, calling 'after' after each + // property's animation completes, then call afterAll when they're all complete. + mTestableController.animationForChildAtIndex(0) + .translationX(7, 100, after) + .translationY(100, 200, after) + .start(afterAll); + + // We should have immediately set the 'from' values. + assertEquals(7, mViews.get(0).getTranslationX(), .01f); + assertEquals(100, mViews.get(0).getTranslationY(), .01f); + + waitForPropertyAnimations( + DynamicAnimation.TRANSLATION_X, + DynamicAnimation.TRANSLATION_Y); + + // We should have called the after callback twice, and afterAll once. We verify in the + // mocked callback that afterAll isn't called before both finish. + Mockito.verify(after, times(2)).run(); + Mockito.verify(afterAll).run(); + + // Make sure we actually animated the views. + assertEquals(100, mViews.get(0).getTranslationX(), .01f); + assertEquals(200, mViews.get(0).getTranslationY(), .01f); + } + + @Test + public void testAnimationsForChildrenFromIndex() throws InterruptedException { + // Don't chain since we're going to invoke each animation independently. + mTestableController.setChainedProperties(new HashSet<>()); + + mLayout.setController(mTestableController); + + addOneMoreThanRenderLimitBubbles(); + + Runnable allEnd = Mockito.mock(Runnable.class); + + mTestableController.animationsForChildrenFromIndex( + 1, (index, animation) -> animation.translationX((index - 1) * 50)) + .startAll(allEnd); + + waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X); + + assertEquals(0, mViews.get(0).getTranslationX(), .1f); + assertEquals(0, mViews.get(1).getTranslationX(), .1f); + assertEquals(50, mViews.get(2).getTranslationX(), .1f); + assertEquals(100, mViews.get(3).getTranslationX(), .1f); + + Mockito.verify(allEnd, times(1)).run(); + } + /** * Animation controller with configuration methods whose return values can be set by individual * tests. diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayoutTestCase.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayoutTestCase.java index d94b6694c7fa..9fce092ef7ce 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayoutTestCase.java +++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayoutTestCase.java @@ -28,6 +28,7 @@ import android.view.WindowInsets; import android.widget.FrameLayout; import androidx.dynamicanimation.animation.DynamicAnimation; +import androidx.dynamicanimation.animation.SpringForce; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; @@ -38,6 +39,7 @@ import org.mockito.MockitoAnnotations; import java.util.ArrayList; import java.util.List; +import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -113,25 +115,17 @@ public class PhysicsAnimationLayoutTestCase extends SysuiTestCase { throws InterruptedException { final CountDownLatch animLatch = new CountDownLatch(properties.length); for (DynamicAnimation.ViewProperty property : properties) { - mLayout.setTestEndListenerForProperty(new OneTimeEndListener() { - @Override - public void onAnimationEnd(DynamicAnimation animation, boolean canceled, - float value, - float velocity) { - super.onAnimationEnd(animation, canceled, value, velocity); - animLatch.countDown(); - } - }, property); + mLayout.setTestEndActionForProperty(animLatch::countDown, property); } - animLatch.await(1, TimeUnit.SECONDS); + + animLatch.await(2, TimeUnit.SECONDS); } - /** Uses a latch to wait for the message queue to finish. */ + /** Uses a latch to wait for the main thread message queue to finish. */ void waitForLayoutMessageQueue() throws InterruptedException { - // Wait for layout, then the view should be actually removed. CountDownLatch layoutLatch = new CountDownLatch(1); mMainThreadHandler.post(layoutLatch::countDown); - layoutLatch.await(1, TimeUnit.SECONDS); + layoutLatch.await(2, TimeUnit.SECONDS); } /** @@ -145,8 +139,9 @@ public class PhysicsAnimationLayoutTestCase extends SysuiTestCase { @Override public void setController(PhysicsAnimationController controller) { - mMainThreadHandler.post(() -> super.setController(controller)); - waitForMessageQueueAndIgnoreIfInterrupted(); + runOnMainThreadAndBlock( + () -> super.setController( + new MainThreadAnimationControllerWrapper(controller))); } @Override @@ -160,59 +155,139 @@ public class PhysicsAnimationLayoutTestCase extends SysuiTestCase { } @Override - protected void animateValueForChildAtIndex(DynamicAnimation.ViewProperty property, - int index, float value, float startVel, Runnable after) { - mMainThreadHandler.post(() -> - super.animateValueForChildAtIndex(property, index, value, startVel, after)); - } - - @Override public WindowInsets getRootWindowInsets() { return mWindowInsets; } @Override - public void removeView(View view) { - mMainThreadHandler.post(() -> - super.removeView(view)); - waitForMessageQueueAndIgnoreIfInterrupted(); + public void addView(View child, int index) { + child.setTag(R.id.physics_animator_tag, new TestablePhysicsPropertyAnimator(child)); + super.addView(child, index); } @Override public void addView(View child, int index, ViewGroup.LayoutParams params) { - mMainThreadHandler.post(() -> - super.addView(child, index, params)); - waitForMessageQueueAndIgnoreIfInterrupted(); + child.setTag(R.id.physics_animator_tag, new TestablePhysicsPropertyAnimator(child)); + super.addView(child, index, params); } /** - * Wait for the queue but just catch and print the exception if interrupted, since we can't - * just add the exception to the overridden methods' signatures. + * Sets an end action that will be called after the 'real' end action that was already set. */ - private void waitForMessageQueueAndIgnoreIfInterrupted() { - try { - waitForLayoutMessageQueue(); - } catch (InterruptedException e) { - e.printStackTrace(); + private void setTestEndActionForProperty( + Runnable action, DynamicAnimation.ViewProperty property) { + final Runnable realEndAction = mEndActionForProperty.get(property); + + setEndActionForProperty(() -> { + if (realEndAction != null) { + realEndAction.run(); + } + + action.run(); + }, property); + } + + /** PhysicsPropertyAnimator that posts its animations to the main thread. */ + protected class TestablePhysicsPropertyAnimator extends PhysicsPropertyAnimator { + public TestablePhysicsPropertyAnimator(View view) { + super(view); + } + + @Override + protected void animateValueForChild(DynamicAnimation.ViewProperty property, View view, + float value, float startVel, long startDelay, Runnable[] afterCallbacks) { + mMainThreadHandler.post(() -> super.animateValueForChild( + property, view, value, startVel, startDelay, afterCallbacks)); } } /** - * Sets an end listener that will be called after the 'real' end listener that was already - * set. + * Wrapper around an animation controller that dispatches methods that could start + * animations to the main thread. */ - private void setTestEndListenerForProperty(DynamicAnimation.OnAnimationEndListener listener, - DynamicAnimation.ViewProperty property) { - final DynamicAnimation.OnAnimationEndListener realEndListener = - mEndListenerForProperty.get(property); - - setEndListenerForProperty((animation, canceled, value, velocity) -> { - if (realEndListener != null) { - realEndListener.onAnimationEnd(animation, canceled, value, velocity); + protected class MainThreadAnimationControllerWrapper extends PhysicsAnimationController { + + private final PhysicsAnimationController mWrappedController; + + protected MainThreadAnimationControllerWrapper(PhysicsAnimationController controller) { + mWrappedController = controller; + } + + @Override + protected void setLayout(PhysicsAnimationLayout layout) { + mWrappedController.setLayout(layout); + } + + @Override + protected PhysicsAnimationLayout getLayout() { + return mWrappedController.getLayout(); + } + + @Override + Set<DynamicAnimation.ViewProperty> getAnimatedProperties() { + return mWrappedController.getAnimatedProperties(); + } + + @Override + int getNextAnimationInChain(DynamicAnimation.ViewProperty property, int index) { + return mWrappedController.getNextAnimationInChain(property, index); + } + + @Override + float getOffsetForChainedPropertyAnimation(DynamicAnimation.ViewProperty property) { + return mWrappedController.getOffsetForChainedPropertyAnimation(property); + } + + @Override + SpringForce getSpringForce(DynamicAnimation.ViewProperty property, View view) { + return mWrappedController.getSpringForce(property, view); + } + + @Override + void onChildAdded(View child, int index) { + runOnMainThreadAndBlock(() -> mWrappedController.onChildAdded(child, index)); + } + + @Override + void onChildRemoved(View child, int index, Runnable finishRemoval) { + runOnMainThreadAndBlock( + () -> mWrappedController.onChildRemoved(child, index, finishRemoval)); + } + + @Override + protected void setChildVisibility(View child, int index, int visibility) { + mWrappedController.setChildVisibility(child, index, visibility); + } + + @Override + protected PhysicsPropertyAnimator animationForChild(View child) { + PhysicsPropertyAnimator animator = + (PhysicsPropertyAnimator) child.getTag(R.id.physics_animator_tag); + + if (!(animator instanceof TestablePhysicsPropertyAnimator)) { + animator = new TestablePhysicsPropertyAnimator(child); + child.setTag(R.id.physics_animator_tag, animator); } - listener.onAnimationEnd(animation, canceled, value, velocity); - }, property); + return animator; + } + } + } + + /** + * Posts the given Runnable on the main thread, and blocks the calling thread until it's run. + */ + private void runOnMainThreadAndBlock(Runnable action) { + final CountDownLatch latch = new CountDownLatch(1); + mMainThreadHandler.post(() -> { + action.run(); + latch.countDown(); + }); + + try { + latch.await(5, TimeUnit.SECONDS); + } catch (InterruptedException e) { + e.printStackTrace(); } } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/StackAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/StackAnimationControllerTest.java index 2ee73f30ea5a..096f205e7a56 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/StackAnimationControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/StackAnimationControllerTest.java @@ -209,6 +209,9 @@ public class StackAnimationControllerTest extends PhysicsAnimationLayoutTestCase final PointF prevStackPos = mStackController.getStackPosition(); mLayout.removeAllViews(); + + waitForLayoutMessageQueue(); + mLayout.addView(new FrameLayout(getContext())); waitForLayoutMessageQueue(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java index 8941182b1384..1ac6bef1c7a5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java @@ -18,6 +18,7 @@ package com.android.systemui.doze; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; @@ -136,13 +137,14 @@ public class DozeTriggersTest extends SysuiTestCase { @Test public void testOnSensor_whenDockedWithNearAndDoubleTapScreen_shouldWakeUp() { doReturn(true).when(mDockManagerFake).isDocked(); + doReturn(true).when(mParameters).getDisplayNeedsBlanking(); mSensors.getMockProximitySensor().sendProximityResult(false /* far */); mTriggers.onSensor(DozeLog.REASON_SENSOR_DOUBLE_TAP, false /* sensorPerformedProxCheck */, 50 /* screenX */, 50 /* screenY */, null /* rawValues */); + verify(mHost).setAodDimmingScrim(eq(255)); verify(mMachine).wakeUp(); } - } diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/SensorPrivacyTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/SensorPrivacyTileTest.java deleted file mode 100644 index 6386c4cd6331..000000000000 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/SensorPrivacyTileTest.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui.qs.tiles; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.hardware.SensorPrivacyManager; -import android.testing.AndroidTestingRunner; -import android.testing.TestableLooper; - -import androidx.test.filters.SmallTest; - -import com.android.systemui.Dependency; -import com.android.systemui.SysuiTestCase; -import com.android.systemui.plugins.ActivityStarter; -import com.android.systemui.qs.QSTileHost; -import com.android.systemui.statusbar.policy.KeyguardMonitor; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -@RunWith(AndroidTestingRunner.class) -@TestableLooper.RunWithLooper -@SmallTest -public class SensorPrivacyTileTest extends SysuiTestCase { - - @Mock - private KeyguardMonitor mKeyguard; - @Mock - private QSTileHost mHost; - @Mock - SensorPrivacyManager mSensorPrivacyManager; - - private TestableLooper mTestableLooper; - - private SensorPrivacyTile mSensorPrivacyTile; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - - mTestableLooper = TestableLooper.get(this); - mDependency.injectTestDependency(Dependency.BG_LOOPER, mTestableLooper.getLooper()); - mKeyguard = mDependency.injectMockDependency(KeyguardMonitor.class); - - mSensorPrivacyManager = mDependency.injectMockDependency(SensorPrivacyManager.class); - - when(mHost.getContext()).thenReturn(mContext); - - mSensorPrivacyTile = new SensorPrivacyTile(mHost, mSensorPrivacyManager, mKeyguard, - mock(ActivityStarter.class)); - } - - @Test - public void testSensorPrivacyListenerAdded_handleListeningTrue() { - // To prevent access to privacy related features from apps with WRITE_SECURE_SETTINGS the - // sensor privacy state is not stored in Settings; to receive notification apps must add - // themselves as a listener with the SensorPrivacyManager. This test verifies when - // setListening is called with a value of true the tile adds itself as a listener. - mSensorPrivacyTile.handleSetListening(true); - mTestableLooper.processAllMessages(); - verify(mSensorPrivacyManager).addSensorPrivacyListener(mSensorPrivacyTile); - } - - @Test - public void testSensorPrivacyListenerRemoved_handleListeningFalse() { - // Similar to the test above verifies that the tile removes itself as a listener when - // setListening is called with a value of false. - mSensorPrivacyTile.handleSetListening(false); - mTestableLooper.processAllMessages(); - verify(mSensorPrivacyManager).removeSensorPrivacyListener((mSensorPrivacyTile)); - } - - @Test - public void testSensorPrivacyEnabled_handleClick() { - // Verifies when the SensorPrivacy tile is clicked it invokes the SensorPrivacyManager to - // set sensor privacy. - mSensorPrivacyTile.getState().value = false; - mSensorPrivacyTile.handleClick(); - mTestableLooper.processAllMessages(); - verify(mSensorPrivacyManager).setSensorPrivacy(true); - - mSensorPrivacyTile.getState().value = true; - mSensorPrivacyTile.handleClick(); - mTestableLooper.processAllMessages(); - verify(mSensorPrivacyManager).setSensorPrivacy(false); - } - - @Test - public void testSensorPrivacyNotDisabled_keyguard() { - // Verifies when the device is locked that sensor privacy cannot be disabled - when(mKeyguard.isSecure()).thenReturn(true); - when(mKeyguard.isShowing()).thenReturn(true); - mSensorPrivacyTile.getState().value = true; - mSensorPrivacyTile.handleClick(); - mTestableLooper.processAllMessages(); - verify(mSensorPrivacyManager, never()).setSensorPrivacy(false); - } -} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java index de155055b76b..1bcf8803b5cf 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java @@ -312,8 +312,7 @@ public class NotificationTestHelper { return new BubbleMetadata.Builder() .setIntent(bubbleIntent) .setDeleteIntent(deleteIntent) - .setTitle("bubble title") - .setIcon(Icon.createWithResource(mContext, 1)) + .setIcon(Icon.createWithResource(mContext, R.drawable.android)) .setDesiredHeight(314) .build(); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java index db8357a5a9db..6889c57d74df 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java @@ -71,7 +71,7 @@ public class NotificationPanelViewTest extends SysuiTestCase { mDependency.injectMockDependency(ConfigurationController.class); mDependency.injectMockDependency(ZenModeController.class); NotificationWakeUpCoordinator coordinator = - new NotificationWakeUpCoordinator( + new NotificationWakeUpCoordinator(mContext, new AmbientPulseManager(mContext), new StatusBarStateControllerImpl()); PulseExpansionHandler expansionHandler = new PulseExpansionHandler(mContext, coordinator); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java index cb5612d165d9..5f7f42285f30 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java @@ -29,6 +29,7 @@ import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; @@ -719,12 +720,25 @@ public class StatusBarTest extends SysuiTestCase { public void testOnStartedWakingUp_isNotDozing() { mStatusBar.setBarStateForTest(StatusBarState.KEYGUARD); when(mStatusBarStateController.isKeyguardRequested()).thenReturn(true); - mStatusBar.mDozeServiceHost.startDozing(); verify(mStatusBarStateController).setIsDozing(eq(true)); + clearInvocations(mNotificationPanelView); mStatusBar.mWakefulnessObserver.onStartedWakingUp(); verify(mStatusBarStateController).setIsDozing(eq(false)); + verify(mNotificationPanelView).expand(eq(false)); + } + + @Test + public void testOnStartedWakingUp_doesNotDismissBouncer_whenPulsing() { + mStatusBar.setBarStateForTest(StatusBarState.KEYGUARD); + when(mStatusBarStateController.isKeyguardRequested()).thenReturn(true); + mStatusBar.mDozeServiceHost.startDozing(); + clearInvocations(mNotificationPanelView); + + mStatusBar.setBouncerShowing(true); + mStatusBar.mWakefulnessObserver.onStartedWakingUp(); + verify(mNotificationPanelView, never()).expand(anyBoolean()); } static class TestableStatusBar extends StatusBar { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java index c1f88855ac24..5cafc028d379 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java @@ -45,11 +45,13 @@ import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.testing.TestableLooper; +import android.testing.TestableResources; import android.util.Log; import com.android.internal.telephony.cdma.EriInfo; import com.android.settingslib.graph.SignalDrawable; import com.android.settingslib.net.DataUsageController; +import com.android.systemui.R; import com.android.systemui.SysuiTestCase; import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener; import com.android.systemui.statusbar.policy.NetworkController.IconState; @@ -76,6 +78,8 @@ public class NetworkControllerBaseTest extends SysuiTestCase { protected static final int DEFAULT_QS_SIGNAL_STRENGTH = DEFAULT_LEVEL; protected static final int DEFAULT_ICON = TelephonyIcons.ICON_3G; protected static final int DEFAULT_QS_ICON = TelephonyIcons.ICON_3G; + protected static final String NO_DATA_STRING = "Data disabled"; + protected static final String NOT_DEFAULT_DATA_STRING = "Not default data"; protected NetworkControllerImpl mNetworkController; protected MobileSignalController mMobileSignalController; @@ -113,6 +117,10 @@ public class NetworkControllerBaseTest extends SysuiTestCase { @Before public void setUp() throws Exception { Settings.Global.putInt(mContext.getContentResolver(), Global.AIRPLANE_MODE_ON, 0); + TestableResources res = mContext.getOrCreateTestableResources(); + res.addOverride(R.string.cell_data_off_content_description, NO_DATA_STRING); + res.addOverride(R.string.not_default_data_content_description, NOT_DEFAULT_DATA_STRING); + mMockWm = mock(WifiManager.class); mMockTm = mock(TelephonyManager.class); mMockSm = mock(SubscriptionManager.class); @@ -392,12 +400,21 @@ public class NetworkControllerBaseTest extends SysuiTestCase { protected void verifyLastMobileDataIndicators(boolean visible, int icon, int typeIcon, boolean qsVisible, int qsIcon, int qsTypeIcon, boolean dataIn, boolean dataOut, boolean cutOut) { + verifyLastMobileDataIndicators( + visible, icon, typeIcon, qsVisible, qsIcon, qsTypeIcon, dataIn, dataOut, cutOut, + null); + } + + protected void verifyLastMobileDataIndicators(boolean visible, int icon, int typeIcon, + boolean qsVisible, int qsIcon, int qsTypeIcon, boolean dataIn, boolean dataOut, + boolean cutOut, String typeContentDescription) { ArgumentCaptor<IconState> iconArg = ArgumentCaptor.forClass(IconState.class); ArgumentCaptor<Integer> typeIconArg = ArgumentCaptor.forClass(Integer.class); ArgumentCaptor<IconState> qsIconArg = ArgumentCaptor.forClass(IconState.class); ArgumentCaptor<Integer> qsTypeIconArg = ArgumentCaptor.forClass(Integer.class); ArgumentCaptor<Boolean> dataInArg = ArgumentCaptor.forClass(Boolean.class); ArgumentCaptor<Boolean> dataOutArg = ArgumentCaptor.forClass(Boolean.class); + ArgumentCaptor<String> typeContentDescriptionArg = ArgumentCaptor.forClass(String.class); Mockito.verify(mCallbackHandler, Mockito.atLeastOnce()).setMobileDataIndicators( iconArg.capture(), @@ -406,7 +423,8 @@ public class NetworkControllerBaseTest extends SysuiTestCase { qsTypeIconArg.capture(), dataInArg.capture(), dataOutArg.capture(), - anyString(), anyString(), anyBoolean(), anyInt(), anyBoolean()); + typeContentDescriptionArg.capture(), + anyString(), anyBoolean(), anyInt(), anyBoolean()); IconState iconState = iconArg.getValue(); @@ -424,6 +442,10 @@ public class NetworkControllerBaseTest extends SysuiTestCase { (boolean) dataInArg.getValue()); assertEquals("Data direction out in quick settings", dataOut, (boolean) dataOutArg.getValue()); + if (typeContentDescription != null) { // Only check if it was provided + assertEquals("Type content description", typeContentDescription, + typeContentDescriptionArg.getValue()); + } } protected void assertNetworkNameEquals(String expected) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java index 96fad21ed7a3..68323c912fdb 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java @@ -117,7 +117,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { } @Test - public void testNoInternetIcon() { + public void testNoInternetIcon_withDefaultSub() { setupNetworkController(); when(mMockTm.getDataEnabled(mSubId)).thenReturn(false); setupDefaultSignal(); @@ -127,11 +127,11 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { // Verify that a SignalDrawable with a cut out is used to display data disabled. verifyLastMobileDataIndicators(true, DEFAULT_SIGNAL_STRENGTH, 0, true, DEFAULT_QS_SIGNAL_STRENGTH, 0, false, - false, true); + false, true, NO_DATA_STRING); } @Test - public void testDataDisabledIcon() { + public void testDataDisabledIcon_withDefaultSub() { setupNetworkController(); when(mMockTm.getDataEnabled(mSubId)).thenReturn(false); setupDefaultSignal(); @@ -141,7 +141,37 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { // Verify that a SignalDrawable with a cut out is used to display data disabled. verifyLastMobileDataIndicators(true, DEFAULT_SIGNAL_STRENGTH, 0, true, DEFAULT_QS_SIGNAL_STRENGTH, 0, false, - false, true); + false, true, NO_DATA_STRING); + } + + @Test + public void testNoInternetIcon_withoutDefaultSub() { + setupNetworkController(); + when(mMockTm.getDataEnabled(mSubId)).thenReturn(false); + setupDefaultSignal(); + setDefaultSubId(mSubId + 1); + updateDataConnectionState(TelephonyManager.DATA_CONNECTED, 0); + setConnectivityViaBroadcast(NetworkCapabilities.TRANSPORT_CELLULAR, false, false); + + // Verify that a SignalDrawable with a cut out is used to display data disabled. + verifyLastMobileDataIndicators(true, DEFAULT_SIGNAL_STRENGTH, 0, + true, DEFAULT_QS_SIGNAL_STRENGTH, 0, false, + false, true, NOT_DEFAULT_DATA_STRING); + } + + @Test + public void testDataDisabledIcon_withoutDefaultSub() { + setupNetworkController(); + when(mMockTm.getDataEnabled(mSubId)).thenReturn(false); + setupDefaultSignal(); + setDefaultSubId(mSubId + 1); + updateDataConnectionState(TelephonyManager.DATA_DISCONNECTED, 0); + setConnectivityViaBroadcast(NetworkCapabilities.TRANSPORT_CELLULAR, false, false); + + // Verify that a SignalDrawable with a cut out is used to display data disabled. + verifyLastMobileDataIndicators(true, DEFAULT_SIGNAL_STRENGTH, 0, + true, DEFAULT_QS_SIGNAL_STRENGTH, 0, false, + false, true, NOT_DEFAULT_DATA_STRING); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java index 617c17e48452..f3cdbf7409c1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java @@ -118,6 +118,17 @@ public class VolumeDialogImplTest extends SysuiTestCase { } @Test + public void testComputeTimeout_tooltip() { + Mockito.reset(mAccessibilityMgr); + mDialog.showCaptionsTooltip(); + verify(mAccessibilityMgr).getRecommendedTimeoutMillis( + VolumeDialogImpl.DIALOG_ODI_CAPTIONS_TOOLTIP_TIMEOUT_MILLIS, + AccessibilityManager.FLAG_CONTENT_CONTROLS + | AccessibilityManager.FLAG_CONTENT_TEXT); + } + + + @Test public void testComputeTimeout_withHovering() { Mockito.reset(mAccessibilityMgr); View dialog = mDialog.getDialogView(); @@ -146,6 +157,16 @@ public class VolumeDialogImplTest extends SysuiTestCase { | AccessibilityManager.FLAG_CONTENT_CONTROLS); } + @Test + public void testComputeTimeout_standard() { + Mockito.reset(mAccessibilityMgr); + mDialog.tryToRemoveCaptionsTooltip(); + mDialog.rescheduleTimeoutH(); + verify(mAccessibilityMgr).getRecommendedTimeoutMillis( + VolumeDialogImpl.DIALOG_TIMEOUT_MILLIS, + AccessibilityManager.FLAG_CONTENT_CONTROLS); + } + /* @Test public void testContentDescriptions() { diff --git a/proto/src/metrics_constants/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto index 78f22e0cc9e7..32c595af4497 100644 --- a/proto/src/metrics_constants/metrics_constants.proto +++ b/proto/src/metrics_constants/metrics_constants.proto @@ -74,6 +74,9 @@ message MetricsEvent { // The view switched to summary mode (most relevant for notifications) TYPE_COLLAPSE = 14; + // The action results an error. + TYPE_ERROR = 15; + // The notification was adjusted by the assistant. Enum value is // out of sequence due to b/122737498. TYPE_NOTIFICATION_ASSISTANT_ADJUSTMENT = 1573; @@ -7132,6 +7135,18 @@ message MetricsEvent { // OS: Q FIELD_SCREEN_SLEEP_REASON = 1695; + // UPDATE: The screen changed policy + // SUBTYPE: The applied policy. One of the DISPLAY_POLICY_* constants in + // DisplayManagerInternal. + // OS: Q + DISPLAY_POLICY = 1696; + + // Biometric authentication. + // TYPE: SUCCESS, FAILURE or ERROR + // SUBTYPE: 0 is fingerprint, 1 is face, 2 is iris and 3 is unknown. + // OS: Q + BIOMETRIC_AUTH = 1697; + // ---- End Q Constants, all Q constants go above this line ---- // Add new aosp constants above this line. // END OF AOSP CONSTANTS diff --git a/services/appprediction/java/com/android/server/appprediction/AppPredictionManagerService.java b/services/appprediction/java/com/android/server/appprediction/AppPredictionManagerService.java index 833eaa06d759..6bb537041668 100644 --- a/services/appprediction/java/com/android/server/appprediction/AppPredictionManagerService.java +++ b/services/appprediction/java/com/android/server/appprediction/AppPredictionManagerService.java @@ -94,10 +94,10 @@ public class AppPredictionManagerService extends } @Override - public void notifyLocationShown(@NonNull AppPredictionSessionId sessionId, + public void notifyLaunchLocationShown(@NonNull AppPredictionSessionId sessionId, @NonNull String launchLocation, @NonNull ParceledListSlice targetIds) { runForUserLocked((service) -> - service.notifyLocationShownLocked(sessionId, launchLocation, targetIds)); + service.notifyLaunchLocationShownLocked(sessionId, launchLocation, targetIds)); } @Override diff --git a/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java b/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java index 24d592c38afb..430abf5c479d 100644 --- a/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java +++ b/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java @@ -111,11 +111,11 @@ public class AppPredictionPerUserService extends * Records when a launch location is shown. */ @GuardedBy("mLock") - public void notifyLocationShownLocked(@NonNull AppPredictionSessionId sessionId, + public void notifyLaunchLocationShownLocked(@NonNull AppPredictionSessionId sessionId, @NonNull String launchLocation, @NonNull ParceledListSlice targetIds) { final RemoteAppPredictionService service = getRemoteServiceLocked(); if (service != null) { - service.notifyLocationShown(sessionId, launchLocation, targetIds); + service.notifyLaunchLocationShown(sessionId, launchLocation, targetIds); } } diff --git a/services/appprediction/java/com/android/server/appprediction/RemoteAppPredictionService.java b/services/appprediction/java/com/android/server/appprediction/RemoteAppPredictionService.java index 922b3271e20c..21088e442212 100644 --- a/services/appprediction/java/com/android/server/appprediction/RemoteAppPredictionService.java +++ b/services/appprediction/java/com/android/server/appprediction/RemoteAppPredictionService.java @@ -85,9 +85,10 @@ public class RemoteAppPredictionService extends /** * Records when a launch location is shown. */ - public void notifyLocationShown(@NonNull AppPredictionSessionId sessionId, + public void notifyLaunchLocationShown(@NonNull AppPredictionSessionId sessionId, @NonNull String launchLocation, @NonNull ParceledListSlice targetIds) { - scheduleAsyncRequest((s) -> s.notifyLocationShown(sessionId, launchLocation, targetIds)); + scheduleAsyncRequest((s) + -> s.notifyLaunchLocationShown(sessionId, launchLocation, targetIds)); } /** diff --git a/services/art-profile b/services/art-profile index 6368c632d5a0..f0b9234ff4a6 100644 --- a/services/art-profile +++ b/services/art-profile @@ -1136,7 +1136,7 @@ Lcom/android/server/DropBoxManagerService$4; Lcom/android/server/DropBoxManagerService$EntryFile; Lcom/android/server/DropBoxManagerService$FileList; Lcom/android/server/DropBoxManagerService; -Lcom/android/server/DynamicAndroidService; +Lcom/android/server/DynamicSystemService; Lcom/android/server/EntropyMixer$1; Lcom/android/server/EntropyMixer$2; Lcom/android/server/EntropyMixer; @@ -4769,9 +4769,9 @@ PLcom/android/server/DropBoxManagerService$2;->getNextEntry(Ljava/lang/String;JL PLcom/android/server/DropBoxManagerService$EntryFile;->getFile(Ljava/io/File;)Ljava/io/File; PLcom/android/server/DropBoxManagerService;->checkPermission(ILjava/lang/String;)Z PLcom/android/server/DropBoxManagerService;->getNextEntry(Ljava/lang/String;JLjava/lang/String;)Landroid/os/DropBoxManager$Entry; -PLcom/android/server/DynamicAndroidService;->connect(Landroid/os/IBinder$DeathRecipient;)Landroid/gsi/IGsiService; -PLcom/android/server/DynamicAndroidService;->getGsiService()Landroid/gsi/IGsiService; -PLcom/android/server/DynamicAndroidService;->isInUse()Z +PLcom/android/server/DynamicSystemService;->connect(Landroid/os/IBinder$DeathRecipient;)Landroid/gsi/IGsiService; +PLcom/android/server/DynamicSystemService;->getGsiService()Landroid/gsi/IGsiService; +PLcom/android/server/DynamicSystemService;->isInUse()Z PLcom/android/server/EntropyMixer$1;->handleMessage(Landroid/os/Message;)V PLcom/android/server/EntropyMixer$2;->onReceive(Landroid/content/Context;Landroid/content/Intent;)V PLcom/android/server/EventLogTags;->writeBatterySaverMode(IIIIILjava/lang/String;I)V @@ -15043,7 +15043,7 @@ SPLcom/android/server/DropBoxManagerService;->isTagEnabled(Ljava/lang/String;)Z SPLcom/android/server/DropBoxManagerService;->onBootPhase(I)V SPLcom/android/server/DropBoxManagerService;->onStart()V SPLcom/android/server/DropBoxManagerService;->trimToFit()J -SPLcom/android/server/DynamicAndroidService;-><init>(Landroid/content/Context;)V +SPLcom/android/server/DynamicSystemService;-><init>(Landroid/content/Context;)V SPLcom/android/server/EntropyMixer;-><init>(Landroid/content/Context;)V SPLcom/android/server/EntropyMixer;-><init>(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V SPLcom/android/server/EntropyMixer;->addDeviceSpecificEntropy()V diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java index c1c125da1f69..3d41d71d6e9a 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java @@ -80,6 +80,7 @@ import com.android.server.FgThread; import com.android.server.LocalServices; import com.android.server.autofill.ui.AutoFillUI; import com.android.server.infra.AbstractMasterSystemService; +import com.android.server.infra.FrameworkResourcesServiceNameResolver; import com.android.server.infra.SecureSettingsServiceNameResolver; import java.io.FileDescriptor; @@ -132,6 +133,12 @@ public final class AutofillManagerService @GuardedBy("sLock") private static int sVisibleDatasetsMaxCount = 0; + /** + * Object used to set the name of the augmented autofill service. + */ + @NonNull + final FrameworkResourcesServiceNameResolver mAugmentedAutofillResolver; + private final AutoFillUI mUi; private final LocalLog mRequestsHistory = new LocalLog(20); @@ -200,6 +207,11 @@ public final class AutofillManagerService getServiceForUserLocked(userId); } } + + mAugmentedAutofillResolver = new FrameworkResourcesServiceNameResolver(getContext(), + com.android.internal.R.string.config_defaultAugmentedAutofillService); + mAugmentedAutofillResolver.setOnTemporaryServiceNameChangedCallback( + (u, s) -> getServiceForUserLocked(u).updateRemoteAugmentedAutofillService()); } @Override // from AbstractMasterSystemService @@ -549,37 +561,19 @@ public final class AutofillManagerService + MAX_TEMP_AUGMENTED_SERVICE_DURATION_MS + " (called with " + durationMs + ")"); } - synchronized (mLock) { - final AutofillManagerServiceImpl service = getServiceForUserLocked(userId); - if (service != null) { - service.mAugmentedAutofillResolver.setTemporaryService(userId, serviceName, - durationMs); - } - } + mAugmentedAutofillResolver.setTemporaryService(userId, serviceName, durationMs); } // Called by Shell command void resetTemporaryAugmentedAutofillService(@UserIdInt int userId) { enforceCallingPermissionForManagement(); - synchronized (mLock) { - final AutofillManagerServiceImpl service = getServiceForUserLocked(userId); - if (service != null) { - service.mAugmentedAutofillResolver.resetTemporaryService(userId); - } - } + mAugmentedAutofillResolver.resetTemporaryService(userId); } // Called by Shell command boolean isDefaultAugmentedServiceEnabled(@UserIdInt int userId) { enforceCallingPermissionForManagement(); - - synchronized (mLock) { - final AutofillManagerServiceImpl service = getServiceForUserLocked(userId); - if (service != null) { - return service.mAugmentedAutofillResolver.isDefaultServiceEnabled(userId); - } - } - return false; + return mAugmentedAutofillResolver.isDefaultServiceEnabled(userId); } // Called by Shell command @@ -590,7 +584,7 @@ public final class AutofillManagerService synchronized (mLock) { final AutofillManagerServiceImpl service = getServiceForUserLocked(userId); if (service != null) { - final boolean changed = service.mAugmentedAutofillResolver + final boolean changed = mAugmentedAutofillResolver .setDefaultServiceEnabled(userId, enabled); if (changed) { service.updateRemoteAugmentedAutofillService(); @@ -942,12 +936,14 @@ public final class AutofillManagerService final class AutoFillManagerServiceStub extends IAutoFillManager.Stub { @Override - public void addClient(IAutoFillManagerClient client, int userId, - @NonNull IResultReceiver receiver) { + public void addClient(IAutoFillManagerClient client, ComponentName componentName, + int userId, IResultReceiver receiver) { int flags = 0; synchronized (mLock) { - if (getServiceForUserLocked(userId).addClientLocked(client)) { - flags |= AutofillManager.FLAG_ADD_CLIENT_ENABLED; + final int enabledFlags = getServiceForUserLocked(userId).addClientLocked(client, + componentName); + if (enabledFlags != 0) { + flags |= enabledFlags; } if (sDebug) { flags |= AutofillManager.FLAG_ADD_CLIENT_DEBUG; @@ -1346,6 +1342,7 @@ public final class AutofillManagerService pw.print(" sVerbose: "); pw.println(realVerbose); // Dump per-user services dumpLocked("", pw); + mAugmentedAutofillResolver.dumpShort(pw); pw.println(); pw.print("Max partitions per session: "); pw.println(sPartitionMaxCount); pw.print("Max visible datasets: "); pw.println(sVisibleDatasetsMaxCount); if (sFullScreenMode != null) { diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java index 720d319b12f8..89c404307202 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java @@ -18,6 +18,8 @@ package com.android.server.autofill; import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST; import static android.view.autofill.AutofillManager.ACTION_START_SESSION; +import static android.view.autofill.AutofillManager.FLAG_ADD_CLIENT_ENABLED; +import static android.view.autofill.AutofillManager.FLAG_ADD_CLIENT_ENABLED_FOR_AUGMENTED_AUTOFILL_ONLY; import static android.view.autofill.AutofillManager.FLAG_SESSION_FOR_AUGMENTED_AUTOFILL_ONLY; import static android.view.autofill.AutofillManager.NO_SESSION; @@ -54,7 +56,6 @@ import android.service.autofill.FieldClassification; import android.service.autofill.FieldClassification.Match; import android.service.autofill.FillEventHistory; import android.service.autofill.FillEventHistory.Event; -import android.service.autofill.FillRequest; import android.service.autofill.FillResponse; import android.service.autofill.IAutoFillService; import android.service.autofill.UserData; @@ -82,7 +83,6 @@ import com.android.server.autofill.AutofillManagerService.AutofillCompatState; import com.android.server.autofill.RemoteAugmentedAutofillService.RemoteAugmentedAutofillServiceCallbacks; import com.android.server.autofill.ui.AutoFillUI; import com.android.server.infra.AbstractPerUserSystemService; -import com.android.server.infra.FrameworkResourcesServiceNameResolver; import java.io.PrintWriter; import java.util.ArrayList; @@ -158,13 +158,6 @@ final class AutofillManagerServiceImpl /** When was {@link PruneTask} last executed? */ private long mLastPrune = 0; - // TODO(b/128911469): move to AutofillManagerService - /** - * Object used to set the name of the augmented autofill service. - */ - @NonNull - final FrameworkResourcesServiceNameResolver mAugmentedAutofillResolver; - /** * Reference to the {@link RemoteAugmentedAutofillService}, is set on demand. */ @@ -194,11 +187,6 @@ final class AutofillManagerServiceImpl mFieldClassificationStrategy = new FieldClassificationStrategy(getContext(), userId); mAutofillCompatState = autofillCompatState; - mAugmentedAutofillResolver = new FrameworkResourcesServiceNameResolver(master.getContext(), - com.android.internal.R.string.config_defaultAugmentedAutofillService); - mAugmentedAutofillResolver.setOnTemporaryServiceNameChangedCallback( - (u, s) -> updateRemoteAugmentedAutofillService()); - updateLocked(disabled); } @@ -242,13 +230,28 @@ final class AutofillManagerServiceImpl return mAutofillCompatState.getUrlBarResourceIds(packageName, mUserId); } + /** + * Adds the client and return the proper flags + * + * @return {@code 0} if disabled, {@code FLAG_ADD_CLIENT_ENABLED} if enabled (it might be + * OR'ed with {@code FLAG_AUGMENTED_AUTOFILL_REQUEST}). + */ @GuardedBy("mLock") - boolean addClientLocked(IAutoFillManagerClient client) { + int addClientLocked(IAutoFillManagerClient client, ComponentName componentName) { if (mClients == null) { mClients = new RemoteCallbackList<>(); } mClients.register(client); - return isEnabledLocked(); + + if (isEnabledLocked()) return FLAG_ADD_CLIENT_ENABLED; + + // Check if it's enabled for augmented autofill + if (isSetupCompletedLocked() && isWhitelistedForAugmentedAutofillLocked(componentName)) { + return FLAG_ADD_CLIENT_ENABLED_FOR_AUGMENTED_AUTOFILL_ONLY; + } + + // No flags / disabled + return 0; } @GuardedBy("mLock") @@ -286,7 +289,7 @@ final class AutofillManagerServiceImpl * * @return {@code long} whose right-most 32 bits represent the session id (which is always * non-negative), and the left-most contains extra flags (currently either {@code 0} or - * {@link FillRequest#FLAG_SESSION_FOR_AUGMENTED_AUTOFILL_ONLY}). + * {@link AutofillManager#FLAG_SESSION_FOR_AUGMENTED_AUTOFILL_ONLY}). */ @GuardedBy("mLock") long startSessionLocked(@NonNull IBinder activityToken, int taskId, int uid, @@ -294,26 +297,27 @@ final class AutofillManagerServiceImpl @NonNull Rect virtualBounds, @Nullable AutofillValue value, boolean hasCallback, @NonNull ComponentName componentName, boolean compatMode, boolean bindInstantServiceAllowed, int flags) { - if (!isEnabledLocked()) { + // FLAG_AUGMENTED_AUTOFILL_REQUEST is set in the flags when standard autofill is disabled + // but the package is whitelisted for augmented autofill + boolean forAugmentedAutofillOnly = (flags + & FLAG_ADD_CLIENT_ENABLED_FOR_AUGMENTED_AUTOFILL_ONLY) != 0; + if (!isEnabledLocked() && !forAugmentedAutofillOnly) { return 0; } - final String shortComponentName = componentName.toShortString(); - boolean forAugmentedAutofillOnly = false; - - if (isAutofillDisabledLocked(componentName)) { - // Service disabled autofill; that means no session, unless the activity is whitelisted - // for augmented autofill + if (!forAugmentedAutofillOnly && isAutofillDisabledLocked(componentName)) { + // Standard autofill is enabled, but service disabled autofill for this activity; that + // means no session, unless the activity is whitelisted for augmented autofill if (isWhitelistedForAugmentedAutofillLocked(componentName)) { if (sDebug) { - Slog.d(TAG, "startSession(" + shortComponentName + "): disabled by service but " + Slog.d(TAG, "startSession(" + componentName + "): disabled by service but " + "whitelisted for augmented autofill"); } forAugmentedAutofillOnly = true; } else { if (sDebug) { - Slog.d(TAG, "startSession(" + shortComponentName + "): ignored because " + Slog.d(TAG, "startSession(" + componentName + "): ignored because " + "disabled by service and not whitelisted for augmented autofill"); } final IAutoFillManagerClient client = IAutoFillManagerClient.Stub @@ -323,7 +327,7 @@ final class AutofillManagerServiceImpl /* autofillableIds= */ null); } catch (RemoteException e) { Slog.w(TAG, - "Could not notify " + shortComponentName + " that it's disabled: " + e); + "Could not notify " + componentName + " that it's disabled: " + e); } return NO_SESSION; @@ -345,9 +349,11 @@ final class AutofillManagerServiceImpl return NO_SESSION; } + // Service can be null when it's only for augmented autofill + String servicePackageName = mInfo == null ? null : mInfo.getServiceInfo().packageName; final String historyItem = - "id=" + newSession.id + " uid=" + uid + " a=" + shortComponentName - + " s=" + mInfo.getServiceInfo().packageName + "id=" + newSession.id + " uid=" + uid + " a=" + componentName.toShortString() + + " s=" + servicePackageName + " u=" + mUserId + " i=" + autofillId + " b=" + virtualBounds + " hc=" + hasCallback + " f=" + flags + " aa=" + forAugmentedAutofillOnly; mMaster.logRequestLocked(historyItem); @@ -485,9 +491,12 @@ final class AutofillManagerServiceImpl assertCallerLocked(componentName, compatMode); + // It's null when the session is just for augmented autofill + final ComponentName serviceComponentName = mInfo == null ? null + : mInfo.getServiceInfo().getComponentName(); final Session newSession = new Session(this, mUi, getContext(), mHandler, mUserId, mLock, sessionId, taskId, uid, activityToken, appCallbackToken, hasCallback, - mUiLatencyHistory, mWtfHistory, mInfo.getServiceInfo().getComponentName(), + mUiLatencyHistory, mWtfHistory, serviceComponentName, componentName, compatMode, bindInstantServiceAllowed, forAugmentedAutofillOnly, flags); mSessions.put(newSession.id, newSession); @@ -929,8 +938,7 @@ final class AutofillManagerServiceImpl .getString(R.string.config_defaultAutofillService)); pw.print(prefix); pw.println("mAugmentedAutofillNamer: "); - pw.print(prefix2); mAugmentedAutofillResolver.dumpShort(pw); pw.println(); - pw.print(prefix2); mAugmentedAutofillResolver.dumpShort(pw, mUserId); pw.println(); + pw.print(prefix2); mMaster.mAugmentedAutofillResolver.dumpShort(pw, mUserId); pw.println(); if (mRemoteAugmentedAutofillService != null) { pw.print(prefix); pw.println("RemoteAugmentedAutofillService: "); @@ -1087,7 +1095,7 @@ final class AutofillManagerServiceImpl @GuardedBy("mLock") @Nullable RemoteAugmentedAutofillService getRemoteAugmentedAutofillServiceLocked() { if (mRemoteAugmentedAutofillService == null) { - final String serviceName = mAugmentedAutofillResolver.getServiceName(mUserId); + final String serviceName = mMaster.mAugmentedAutofillResolver.getServiceName(mUserId); if (serviceName == null) { if (mMaster.verbose) { Slog.v(TAG, "getRemoteAugmentedAutofillServiceLocked(): not set"); @@ -1095,8 +1103,8 @@ final class AutofillManagerServiceImpl return null; } final Pair<ServiceInfo, ComponentName> pair = RemoteAugmentedAutofillService - .getComponentName( - serviceName, mUserId, mAugmentedAutofillResolver.isTemporary(mUserId)); + .getComponentName(serviceName, mUserId, + mMaster.mAugmentedAutofillResolver.isTemporary(mUserId)); if (pair == null) return null; mRemoteAugmentedAutofillServiceInfo = pair.first; @@ -1126,7 +1134,8 @@ final class AutofillManagerServiceImpl } /** - * Called when the {@link #mAugmentedAutofillResolver} changed (among other places). + * Called when the {@link AutofillManagerService#mAugmentedAutofillResolver} + * changed (among other places). */ void updateRemoteAugmentedAutofillService() { synchronized (mLock) { diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java index f08bab3f60cb..ac8f61b50192 100644 --- a/services/autofill/java/com/android/server/autofill/Session.java +++ b/services/autofill/java/com/android/server/autofill/Session.java @@ -185,6 +185,12 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState @GuardedBy("mLock") private DeathRecipient mClientVulture; + /** + * Reference to the remote service. + * + * <p>Only {@code null} when the session is for augmented autofill only. + */ + @Nullable private final RemoteFillService mRemoteFillService; @GuardedBy("mLock") @@ -293,6 +299,11 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState private final IAssistDataReceiver mAssistReceiver = new IAssistDataReceiver.Stub() { @Override public void onHandleAssistData(Bundle resultData) throws RemoteException { + if (mRemoteFillService == null) { + wtf(null, "onHandleAssistData() called without a remote service. " + + "mForAugmentedAutofillOnly: %s", mForAugmentedAutofillOnly); + return; + } final AssistStructure structure = resultData.getParcelable(ASSIST_KEY_STRUCTURE); if (structure == null) { Slog.e(TAG, "No assist structure - app might have crashed providing it"); @@ -527,6 +538,11 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState */ @GuardedBy("mLock") private void cancelCurrentRequestLocked() { + if (mRemoteFillService == null) { + wtf(null, "cancelCurrentRequestLocked() called without a remote service. " + + "mForAugmentedAutofillOnly: %s", mForAugmentedAutofillOnly); + return; + } final int canceledRequest = mRemoteFillService.cancelCurrentRequest(); // Remove the FillContext as there will never be a response for the service @@ -608,7 +624,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState @NonNull Context context, @NonNull Handler handler, int userId, @NonNull Object lock, int sessionId, int taskId, int uid, @NonNull IBinder activityToken, @NonNull IBinder client, boolean hasCallback, @NonNull LocalLog uiLatencyHistory, - @NonNull LocalLog wtfHistory, @NonNull ComponentName serviceComponentName, + @NonNull LocalLog wtfHistory, @Nullable ComponentName serviceComponentName, @NonNull ComponentName componentName, boolean compatMode, boolean bindInstantServiceAllowed, boolean forAugmentedAutofillOnly, int flags) { if (sessionId < 0) { @@ -623,8 +639,9 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState mLock = lock; mUi = ui; mHandler = handler; - mRemoteFillService = new RemoteFillService(context, serviceComponentName, userId, this, - bindInstantServiceAllowed); + mRemoteFillService = serviceComponentName == null ? null + : new RemoteFillService(context, serviceComponentName, userId, this, + bindInstantServiceAllowed); mActivityToken = activityToken; mHasCallback = hasCallback; mUiLatencyHistory = uiLatencyHistory; @@ -2035,6 +2052,11 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState + id + " destroyed"); return; } + if (mRemoteFillService == null) { + wtf(null, "callSaveLocked() called without a remote service. " + + "mForAugmentedAutofillOnly: %s", mForAugmentedAutofillOnly); + return; + } if (sVerbose) Slog.v(TAG, "callSaveLocked(): mViewStates=" + mViewStates); @@ -3045,7 +3067,9 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState pw.print(prefix); pw.print("mAugmentedAutofillableIds: "); pw.println(mAugmentedAutofillableIds); } - mRemoteFillService.dump(prefix, pw); + if (mRemoteFillService != null) { + mRemoteFillService.dump(prefix, pw); + } } private static void dumpRequestLog(@NonNull PrintWriter pw, @NonNull LogMaker log) { diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java index ffda5819927b..7106664d0699 100644 --- a/services/backup/java/com/android/server/backup/BackupManagerService.java +++ b/services/backup/java/com/android/server/backup/BackupManagerService.java @@ -362,8 +362,8 @@ public class BackupManagerService { * @param dataManagementIntent An {@link Intent} that can be passed to {@link * Context#startActivity} in order to launch the transport's data-management UI. It may be * {@code null} if the transport does not offer any user-facing data management UI. - * @param dataManagementLabel A {@link String} to be used as the label for the transport's data - * management affordance. This MUST be {@code null} when dataManagementIntent is {@code + * @param dataManagementLabel A {@link CharSequence} to be used as the label for the transport's + * data management affordance. This MUST be {@code null} when dataManagementIntent is {@code * null} and MUST NOT be {@code null} when dataManagementIntent is not {@code null}. * @throws SecurityException If the UID of the calling process differs from the package UID of * {@code transportComponent} or if the caller does NOT have BACKUP permission. @@ -375,7 +375,7 @@ public class BackupManagerService { @Nullable Intent configurationIntent, String currentDestinationString, @Nullable Intent dataManagementIntent, - String dataManagementLabel) { + CharSequence dataManagementLabel) { UserBackupManagerService userBackupManagerService = getServiceForUserIfCallerHasPermission(userId, "updateTransportAttributes()"); @@ -521,7 +521,7 @@ public class BackupManagerService { * transport. */ @Nullable - public String getDataManagementLabel(@UserIdInt int userId, String transportName) { + public CharSequence getDataManagementLabel(@UserIdInt int userId, String transportName) { UserBackupManagerService userBackupManagerService = getServiceForUserIfCallerHasPermission(userId, "getDataManagementLabel()"); diff --git a/services/backup/java/com/android/server/backup/Trampoline.java b/services/backup/java/com/android/server/backup/Trampoline.java index 00cb6d3a0a26..8f0c5d812e1c 100644 --- a/services/backup/java/com/android/server/backup/Trampoline.java +++ b/services/backup/java/com/android/server/backup/Trampoline.java @@ -630,8 +630,7 @@ public class Trampoline extends IBackupManager.Stub { @Nullable Intent configurationIntent, String currentDestinationString, @Nullable Intent dataManagementIntent, - String dataManagementLabel) { - + CharSequence dataManagementLabel) { if (isUserReadyForBackup(userId)) { mService.updateTransportAttributes( userId, @@ -710,19 +709,13 @@ public class Trampoline extends IBackupManager.Stub { } @Override - public String getDataManagementLabelForUser(int userId, String transport) + public CharSequence getDataManagementLabelForUser(int userId, String transport) throws RemoteException { return isUserReadyForBackup(userId) ? mService.getDataManagementLabel(userId, transport) : null; } @Override - public String getDataManagementLabel(String transport) - throws RemoteException { - return getDataManagementLabelForUser(binderGetCallingUserId(), transport); - } - - @Override public IRestoreSession beginRestoreSessionForUser( int userId, String packageName, String transportID) throws RemoteException { return isUserReadyForBackup(userId) ? mService.beginRestoreSession(userId, packageName, diff --git a/services/backup/java/com/android/server/backup/TransportManager.java b/services/backup/java/com/android/server/backup/TransportManager.java index a7bada07ffa8..30ce4cf2fd3f 100644 --- a/services/backup/java/com/android/server/backup/TransportManager.java +++ b/services/backup/java/com/android/server/backup/TransportManager.java @@ -284,7 +284,7 @@ public class TransportManager { * @throws TransportNotRegisteredException if the transport is not registered. */ @Nullable - public String getTransportDataManagementLabel(String transportName) + public CharSequence getTransportDataManagementLabel(String transportName) throws TransportNotRegisteredException { synchronized (mTransportLock) { return getRegisteredTransportDescriptionOrThrowLocked(transportName) @@ -327,7 +327,7 @@ public class TransportManager { @Nullable Intent configurationIntent, String currentDestinationString, @Nullable Intent dataManagementIntent, - @Nullable String dataManagementLabel) { + @Nullable CharSequence dataManagementLabel) { synchronized (mTransportLock) { TransportDescription description = mRegisteredTransportsDescriptionMap.get(transportComponent); @@ -678,7 +678,7 @@ public class TransportManager { transport.configurationIntent(), transport.currentDestinationString(), transport.dataManagementIntent(), - transport.dataManagementLabel()); + transport.dataManagementIntentLabel()); synchronized (mTransportLock) { mRegisteredTransportsDescriptionMap.put(transportComponent, description); } @@ -707,7 +707,7 @@ public class TransportManager { @Nullable private Intent configurationIntent; private String currentDestinationString; @Nullable private Intent dataManagementIntent; - @Nullable private String dataManagementLabel; + @Nullable private CharSequence dataManagementLabel; private TransportDescription( String name, @@ -715,7 +715,7 @@ public class TransportManager { @Nullable Intent configurationIntent, String currentDestinationString, @Nullable Intent dataManagementIntent, - @Nullable String dataManagementLabel) { + @Nullable CharSequence dataManagementLabel) { this.name = name; this.transportDirName = transportDirName; this.configurationIntent = configurationIntent; diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java index 32e2cacbb37b..447bd8c237dd 100644 --- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java +++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java @@ -2929,8 +2929,8 @@ public class UserBackupManagerService { * {@link Context#startActivity} in order to launch the transport's data-management UI. It * may be {@code null} if the transport does not offer any user-facing data * management UI. - * @param dataManagementLabel A {@link String} to be used as the label for the transport's data - * management affordance. This MUST be {@code null} when dataManagementIntent is + * @param dataManagementLabel A {@link CharSequence} to be used as the label for the transport's + * data management affordance. This MUST be {@code null} when dataManagementIntent is * {@code null} and MUST NOT be {@code null} when dataManagementIntent is not {@code null}. * @throws SecurityException If the UID of the calling process differs from the package UID of * {@code transportComponent} or if the caller does NOT have BACKUP permission. @@ -2941,7 +2941,7 @@ public class UserBackupManagerService { @Nullable Intent configurationIntent, String currentDestinationString, @Nullable Intent dataManagementIntent, - @Nullable String dataManagementLabel) { + @Nullable CharSequence dataManagementLabel) { updateTransportAttributes( Binder.getCallingUid(), transportComponent, @@ -2960,7 +2960,7 @@ public class UserBackupManagerService { @Nullable Intent configurationIntent, String currentDestinationString, @Nullable Intent dataManagementIntent, - @Nullable String dataManagementLabel) { + @Nullable CharSequence dataManagementLabel) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.BACKUP, "updateTransportAttributes"); @@ -3159,12 +3159,12 @@ public class UserBackupManagerService { * Supply the menu label for affordances that fire the manage-data intent for the given * transport. */ - public String getDataManagementLabel(String transportName) { + public CharSequence getDataManagementLabel(String transportName) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "getDataManagementLabel"); try { - String label = mTransportManager.getTransportDataManagementLabel(transportName); + CharSequence label = mTransportManager.getTransportDataManagementLabel(transportName); if (MORE_DEBUG) { Slog.d(TAG, "getDataManagementLabel() returning " + label); } diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java index a85b69b528dd..39f7f0f0d1a8 100644 --- a/services/core/java/com/android/server/BatteryService.java +++ b/services/core/java/com/android/server/BatteryService.java @@ -127,6 +127,7 @@ public final class BatteryService extends SystemService { // discharge stats before the device dies. private int mCriticalBatteryLevel; + // TODO: Current args don't work since "--unplugged" flag was purposefully removed. private static final String[] DUMPSYS_ARGS = new String[] { "--checkin", "--unplugged" }; private static final String DUMPSYS_DATA_PATH = "/data/system/"; @@ -734,6 +735,7 @@ public final class BatteryService extends SystemService { mLastBatteryLevelChangedSentMs = SystemClock.elapsedRealtime(); } + // TODO: Current code doesn't work since "--unplugged" flag in BSS was purposefully removed. private void logBatteryStatsLocked() { IBinder batteryInfoService = ServiceManager.getService(BatteryStats.SERVICE_NAME); if (batteryInfoService == null) return; diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index b2ee68653dde..21c1e1247167 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -2174,7 +2174,7 @@ public class ConnectivityService extends IConnectivityManager.Stub if (VDBG) log("identical MTU - not setting"); return; } - if (LinkProperties.isValidMtu(mtu, newLp.hasGlobalIPv6Address()) == false) { + if (!LinkProperties.isValidMtu(mtu, newLp.hasGlobalIpv6Address())) { if (mtu != 0) loge("Unexpected mtu value: " + mtu + ", " + iface); return; } @@ -2561,19 +2561,16 @@ public class ConnectivityService extends IConnectivityManager.Stub final boolean partialConnectivity = (msg.arg1 == NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY) - // If user accepts partial connectivity network, NetworkMonitor - // will skip https probing. It will make partial connectivity - // network becomes valid. But user still need to know this - // network is limited. So, it's needed to refer to - // acceptPartialConnectivity to add - // NET_CAPABILITY_PARTIAL_CONNECTIVITY into NetworkCapabilities - // of this network. So that user can see "Limited connection" - // in the settings. || (nai.networkMisc.acceptPartialConnectivity && nai.partialConnectivity); // Once a network is determined to have partial connectivity, it cannot - // go back to full connectivity without a disconnect. - final boolean partialConnectivityChange = + // go back to full connectivity without a disconnect. This is because + // NetworkMonitor can only communicate either PARTIAL_CONNECTIVITY or VALID, + // but not both. + // TODO: Provide multi-testResult to improve the communication between + // ConnectivityService and NetworkMonitor, so that ConnectivityService could + // know the real status of network. + final boolean partialConnectivityChanged = (partialConnectivity && !nai.partialConnectivity); final boolean valid = (msg.arg1 == NETWORK_TEST_RESULT_VALID); @@ -2584,17 +2581,6 @@ public class ConnectivityService extends IConnectivityManager.Stub nai.captivePortalLoginNotified = true; showNetworkNotification(nai, NotificationType.LOGGED_IN); } - // If this network has just connected and partial connectivity has just been - // detected, tell NetworkMonitor if the user accepted partial connectivity on a - // previous connect. - if ((msg.arg1 == NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY) - && nai.networkMisc.acceptPartialConnectivity) { - try { - nai.networkMonitor().notifyAcceptPartialConnectivity(); - } catch (RemoteException e) { - e.rethrowFromSystemServer(); - } - } final String redirectUrl = (msg.obj instanceof String) ? (String) msg.obj : ""; @@ -2624,7 +2610,7 @@ public class ConnectivityService extends IConnectivityManager.Stub mNotifier.clearNotification(nai.network.netId, NotificationType.LOST_INTERNET); } - } else if (partialConnectivityChange) { + } else if (partialConnectivityChanged) { nai.partialConnectivity = partialConnectivity; updateCapabilities(nai.getCurrentScore(), nai, nai.networkCapabilities); } @@ -3378,8 +3364,11 @@ public class ConnectivityService extends IConnectivityManager.Stub // Tear down the network. teardownUnneededNetwork(nai); } else { + // Inform NetworkMonitor that partial connectivity is acceptable. This will likely + // result in a partial connectivity result which will be processed by + // maybeHandleNetworkMonitorMessage. try { - nai.networkMonitor().notifyAcceptPartialConnectivity(); + nai.networkMonitor().setAcceptPartialConnectivity(); } catch (RemoteException e) { e.rethrowFromSystemServer(); } @@ -3486,8 +3475,12 @@ public class ConnectivityService extends IConnectivityManager.Stub return mMultinetworkPolicyTracker.getAvoidBadWifi(); } - @Override - public boolean getAvoidBadWifi() { + /** + * Return whether the device should maintain continuous, working connectivity by switching away + * from WiFi networks having no connectivity. + * @see MultinetworkPolicyTracker#getAvoidBadWifi() + */ + public boolean shouldAvoidBadWifi() { if (!checkNetworkStackPermission()) { throw new SecurityException("avoidBadWifi requires NETWORK_STACK permission"); } @@ -3587,6 +3580,9 @@ public class ConnectivityService extends IConnectivityManager.Stub // because we're already prompting the user to sign in. if (nai == null || nai.everValidated || nai.everCaptivePortalDetected || !nai.networkMisc.explicitlySelected || nai.networkMisc.acceptUnvalidated + // TODO: Once the value of acceptPartialConnectivity is moved to IpMemoryStore, + // we should reevaluate how to handle acceptPartialConnectivity when network just + // connected. || nai.networkMisc.acceptPartialConnectivity) { return; } @@ -3594,9 +3590,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // NetworkMonitor detects the network is partial connectivity. Need to change the design to // popup the notification immediately when the network is partial connectivity. if (nai.partialConnectivity) { - // Treat PARTIAL_CONNECTIVITY as NO_INTERNET temporary until Settings has been updated. - // TODO: Need to change back to PARTIAL_CONNECTIVITY when Settings part is merged. - showNetworkNotification(nai, NotificationType.NO_INTERNET); + showNetworkNotification(nai, NotificationType.PARTIAL_CONNECTIVITY); } else { showNetworkNotification(nai, NotificationType.NO_INTERNET); } @@ -6395,6 +6389,9 @@ public class ConnectivityService extends IConnectivityManager.Stub // NetworkMonitor seeing the correct LinkProperties when starting. // TODO: pass LinkProperties to the NetworkMonitor in the notifyNetworkConnected call. try { + if (networkAgent.networkMisc.acceptPartialConnectivity) { + networkAgent.networkMonitor().setAcceptPartialConnectivity(); + } networkAgent.networkMonitor().notifyNetworkConnected(); } catch (RemoteException e) { e.rethrowFromSystemServer(); diff --git a/services/core/java/com/android/server/DynamicAndroidService.java b/services/core/java/com/android/server/DynamicSystemService.java index b02bfb111727..f5bd11cea779 100644 --- a/services/core/java/com/android/server/DynamicAndroidService.java +++ b/services/core/java/com/android/server/DynamicSystemService.java @@ -22,25 +22,25 @@ import android.gsi.GsiProgress; import android.gsi.IGsiService; import android.os.IBinder; import android.os.IBinder.DeathRecipient; -import android.os.IDynamicAndroidService; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemProperties; +import android.os.image.IDynamicSystemService; import android.util.Slog; /** - * DynamicAndroidService implements IDynamicAndroidService. It provides permission check before + * DynamicSystemService implements IDynamicSystemService. It provides permission check before * passing requests to gsid */ -public class DynamicAndroidService extends IDynamicAndroidService.Stub implements DeathRecipient { - private static final String TAG = "DynamicAndroidService"; +public class DynamicSystemService extends IDynamicSystemService.Stub implements DeathRecipient { + private static final String TAG = "DynamicSystemService"; private static final String NO_SERVICE_ERROR = "no gsiservice"; private static final int GSID_ROUGH_TIMEOUT_MS = 8192; private Context mContext; private volatile IGsiService mGsiService; - DynamicAndroidService(Context context) { + DynamicSystemService(Context context) { mContext = context; } @@ -93,9 +93,9 @@ public class DynamicAndroidService extends IDynamicAndroidService.Stub implement private void checkPermission() { if (mContext.checkCallingOrSelfPermission( - android.Manifest.permission.MANAGE_DYNAMIC_ANDROID) + android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM) != PackageManager.PERMISSION_GRANTED) { - throw new SecurityException("Requires MANAGE_DYNAMIC_ANDROID permission"); + throw new SecurityException("Requires MANAGE_DYNAMIC_SYSTEM permission"); } } diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java index 31010c9c9249..b89223b5cbda 100644 --- a/services/core/java/com/android/server/LocationManagerService.java +++ b/services/core/java/com/android/server/LocationManagerService.java @@ -64,6 +64,7 @@ import android.location.INetInitiatedListener; import android.location.Location; import android.location.LocationManager; import android.location.LocationRequest; +import android.location.LocationTime; import android.os.Binder; import android.os.Bundle; import android.os.Handler; @@ -2695,6 +2696,19 @@ public class LocationManagerService extends ILocationManager.Stub { } @Override + public LocationTime getGnssTimeMillis() { + synchronized (mLock) { + Location location = mLastLocation.get(LocationManager.GPS_PROVIDER); + if (location == null) { + return null; + } + long currentNanos = SystemClock.elapsedRealtimeNanos(); + long deltaMs = (currentNanos - location.getElapsedRealtimeNanos()) / 1000000L; + return new LocationTime(location.getTime() + deltaMs, currentNanos); + } + } + + @Override public boolean injectLocation(Location location) { mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE, "Location Hardware permission not granted to inject location"); diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java index d3298b9238fc..61a718231dd4 100644 --- a/services/core/java/com/android/server/NetworkManagementService.java +++ b/services/core/java/com/android/server/NetworkManagementService.java @@ -39,7 +39,6 @@ import static android.net.NetworkStats.TAG_NONE; import static android.net.NetworkStats.UID_ALL; import static android.net.TrafficStats.UID_TETHERING; -import static com.android.server.NetworkManagementService.NetdResponseCode.TtyListResult; import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED; import android.annotation.NonNull; @@ -70,7 +69,6 @@ import android.os.Handler; import android.os.IBinder; import android.os.INetworkActivityListener; import android.os.INetworkManagementService; -import android.os.PowerManager; import android.os.Process; import android.os.RemoteCallbackList; import android.os.RemoteException; @@ -112,13 +110,11 @@ import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.concurrent.CountDownLatch; /** * @hide */ -public class NetworkManagementService extends INetworkManagementService.Stub - implements Watchdog.Monitor { +public class NetworkManagementService extends INetworkManagementService.Stub { /** * Helper class that encapsulates NetworkManagementService dependencies and makes them @@ -138,8 +134,6 @@ public class NetworkManagementService extends INetworkManagementService.Stub private static final String TAG = "NetworkManagement"; private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG); - private static final String NETD_TAG = "NetdConnector"; - static final String NETD_SERVICE_NAME = "netd"; private static final int MAX_UID_RANGES_PER_COMMAND = 10; @@ -149,44 +143,6 @@ public class NetworkManagementService extends INetworkManagementService.Stub */ public static final String LIMIT_GLOBAL_ALERT = "globalAlert"; - static class NetdResponseCode { - /* Keep in sync with system/netd/server/ResponseCode.h */ - public static final int InterfaceListResult = 110; - public static final int TetherInterfaceListResult = 111; - public static final int TetherDnsFwdTgtListResult = 112; - public static final int TtyListResult = 113; - public static final int TetheringStatsListResult = 114; - - public static final int TetherStatusResult = 210; - public static final int IpFwdStatusResult = 211; - public static final int InterfaceGetCfgResult = 213; - public static final int SoftapStatusResult = 214; - public static final int InterfaceRxCounterResult = 216; - public static final int InterfaceTxCounterResult = 217; - public static final int QuotaCounterResult = 220; - public static final int TetheringStatsResult = 221; - public static final int DnsProxyQueryResult = 222; - public static final int ClatdStatusResult = 223; - - public static final int InterfaceChange = 600; - public static final int BandwidthControl = 601; - public static final int InterfaceClassActivity = 613; - public static final int InterfaceAddressChange = 614; - public static final int InterfaceDnsServerInfo = 615; - public static final int RouteChange = 616; - public static final int StrictCleartext = 617; - } - - /** - * String indicating a softap command. - */ - static final String SOFT_AP_COMMAND = "softap"; - - /** - * String passed back to netd connector indicating softap command success. - */ - static final String SOFT_AP_COMMAND_SUCCESS = "Ok"; - static final int DAEMON_MSG_MOBILE_CONN_REAL_TIME_INFO = 1; static final boolean MODIFY_OPERATION_ADD = true; @@ -197,12 +153,6 @@ public class NetworkManagementService extends INetworkManagementService.Stub */ private final Context mContext; - /** - * connector object for communicating with netd - */ - private final NativeDaemonConnector mConnector; - - private final Handler mFgHandler; private final Handler mDaemonHandler; private final SystemServices mServices; @@ -213,9 +163,6 @@ public class NetworkManagementService extends INetworkManagementService.Stub private IBatteryStats mBatteryStats; - private final Thread mThread; - private CountDownLatch mConnectedSignal = new CountDownLatch(1); - private final RemoteCallbackList<INetworkManagementEventObserver> mObservers = new RemoteCallbackList<>(); @@ -307,32 +254,14 @@ public class NetworkManagementService extends INetworkManagementService.Stub * @param context Binder context for this service */ private NetworkManagementService( - Context context, String socket, SystemServices services) { + Context context, SystemServices services) { mContext = context; mServices = services; - // make sure this is on the same looper as our NativeDaemonConnector for sync purposes - mFgHandler = new Handler(FgThread.get().getLooper()); - - // Don't need this wake lock, since we now have a time stamp for when - // the network actually went inactive. (It might be nice to still do this, - // but I don't want to do it through the power manager because that pollutes the - // battery stats history with pointless noise.) - //PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE); - PowerManager.WakeLock wl = null; //pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, NETD_TAG); - - mConnector = new NativeDaemonConnector( - new NetdCallbackReceiver(), socket, 10, NETD_TAG, 160, wl, - FgThread.get().getLooper()); - mThread = new Thread(mConnector, NETD_TAG); - mDaemonHandler = new Handler(FgThread.get().getLooper()); mNetdUnsolicitedEventListener = new NetdUnsolicitedEventListener(); - // Add ourself to the Watchdog monitors. - Watchdog.getInstance().addMonitor(this); - mServices.registerLocalService(new LocalService()); synchronized (mTetheringStatsProviders) { @@ -342,25 +271,17 @@ public class NetworkManagementService extends INetworkManagementService.Stub @VisibleForTesting NetworkManagementService() { - mConnector = null; mContext = null; mDaemonHandler = null; - mFgHandler = null; - mThread = null; mServices = null; mNetdUnsolicitedEventListener = null; } - static NetworkManagementService create(Context context, String socket, SystemServices services) + static NetworkManagementService create(Context context, SystemServices services) throws InterruptedException { final NetworkManagementService service = - new NetworkManagementService(context, socket, services); - final CountDownLatch connectedSignal = service.mConnectedSignal; + new NetworkManagementService(context, services); if (DBG) Slog.d(TAG, "Creating NetworkManagementService"); - service.mThread.start(); - if (DBG) Slog.d(TAG, "Awaiting socket connection"); - connectedSignal.await(); - if (DBG) Slog.d(TAG, "Connected"); if (DBG) Slog.d(TAG, "Connecting native netd service"); service.connectNativeNetdService(); if (DBG) Slog.d(TAG, "Connected"); @@ -368,7 +289,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub } public static NetworkManagementService create(Context context) throws InterruptedException { - return create(context, NETD_SERVICE_NAME, new SystemServices()); + return create(context, new SystemServices()); } public void systemReady() { @@ -812,212 +733,6 @@ public class NetworkManagementService extends INetworkManagementService.Stub } // - // Netd Callback handling - // - - private class NetdCallbackReceiver implements INativeDaemonConnectorCallbacks { - @Override - public void onDaemonConnected() { - Slog.i(TAG, "onDaemonConnected()"); - // event is dispatched from internal NDC thread, so we prepare the - // daemon back on main thread. - if (mConnectedSignal != null) { - // The system is booting and we're connecting to netd for the first time. - mConnectedSignal.countDown(); - mConnectedSignal = null; - } else { - // We're reconnecting to netd after the socket connection - // was interrupted (e.g., if it crashed). - mFgHandler.post(new Runnable() { - @Override - public void run() { - connectNativeNetdService(); - prepareNativeDaemon(); - } - }); - } - } - - @Override - public boolean onCheckHoldWakeLock(int code) { - return code == NetdResponseCode.InterfaceClassActivity; - } - - @Override - public boolean onEvent(int code, String raw, String[] cooked) { - String errorMessage = String.format("Invalid event from daemon (%s)", raw); - switch (code) { - case NetdResponseCode.InterfaceChange: - /* - * a network interface change occured - * Format: "NNN Iface added <name>" - * "NNN Iface removed <name>" - * "NNN Iface changed <name> <up/down>" - * "NNN Iface linkstatus <name> <up/down>" - */ - if (cooked.length < 4 || !cooked[1].equals("Iface")) { - throw new IllegalStateException(errorMessage); - } - if (cooked[2].equals("added")) { - notifyInterfaceAdded(cooked[3]); - return true; - } else if (cooked[2].equals("removed")) { - notifyInterfaceRemoved(cooked[3]); - return true; - } else if (cooked[2].equals("changed") && cooked.length == 5) { - notifyInterfaceStatusChanged(cooked[3], cooked[4].equals("up")); - return true; - } else if (cooked[2].equals("linkstate") && cooked.length == 5) { - notifyInterfaceLinkStateChanged(cooked[3], cooked[4].equals("up")); - return true; - } - throw new IllegalStateException(errorMessage); - // break; - case NetdResponseCode.BandwidthControl: - /* - * Bandwidth control needs some attention - * Format: "NNN limit alert <alertName> <ifaceName>" - */ - if (cooked.length < 5 || !cooked[1].equals("limit")) { - throw new IllegalStateException(errorMessage); - } - if (cooked[2].equals("alert")) { - notifyLimitReached(cooked[3], cooked[4]); - return true; - } - throw new IllegalStateException(errorMessage); - // break; - case NetdResponseCode.InterfaceClassActivity: - /* - * An network interface class state changed (active/idle) - * Format: "NNN IfaceClass <active/idle> <label>" - */ - if (cooked.length < 4 || !cooked[1].equals("IfaceClass")) { - throw new IllegalStateException(errorMessage); - } - long timestampNanos = 0; - int processUid = -1; - if (cooked.length >= 5) { - try { - timestampNanos = Long.parseLong(cooked[4]); - if (cooked.length == 6) { - processUid = Integer.parseInt(cooked[5]); - } - } catch(NumberFormatException ne) {} - } else { - timestampNanos = SystemClock.elapsedRealtimeNanos(); - } - boolean isActive = cooked[2].equals("active"); - notifyInterfaceClassActivity(Integer.parseInt(cooked[3]), - isActive, timestampNanos, processUid, false); - return true; - // break; - case NetdResponseCode.InterfaceAddressChange: - /* - * A network address change occurred - * Format: "NNN Address updated <addr> <iface> <flags> <scope>" - * "NNN Address removed <addr> <iface> <flags> <scope>" - */ - if (cooked.length < 7 || !cooked[1].equals("Address")) { - throw new IllegalStateException(errorMessage); - } - - String iface = cooked[4]; - LinkAddress address; - try { - int flags = Integer.parseInt(cooked[5]); - int scope = Integer.parseInt(cooked[6]); - address = new LinkAddress(cooked[3], flags, scope); - } catch(NumberFormatException e) { // Non-numeric lifetime or scope. - throw new IllegalStateException(errorMessage, e); - } catch(IllegalArgumentException e) { // Malformed/invalid IP address. - throw new IllegalStateException(errorMessage, e); - } - - if (cooked[2].equals("updated")) { - notifyAddressUpdated(iface, address); - } else { - notifyAddressRemoved(iface, address); - } - return true; - // break; - case NetdResponseCode.InterfaceDnsServerInfo: - /* - * Information about available DNS servers has been received. - * Format: "NNN DnsInfo servers <interface> <lifetime> <servers>" - */ - long lifetime; // Actually a 32-bit unsigned integer. - - if (cooked.length == 6 && - cooked[1].equals("DnsInfo") && - cooked[2].equals("servers")) { - try { - lifetime = Long.parseLong(cooked[4]); - } catch (NumberFormatException e) { - throw new IllegalStateException(errorMessage); - } - String[] servers = cooked[5].split(","); - notifyInterfaceDnsServerInfo(cooked[3], lifetime, servers); - } - return true; - // break; - case NetdResponseCode.RouteChange: - /* - * A route has been updated or removed. - * Format: "NNN Route <updated|removed> <dst> [via <gateway] [dev <iface>]" - */ - if (!cooked[1].equals("Route") || cooked.length < 6) { - throw new IllegalStateException(errorMessage); - } - - String via = null; - String dev = null; - boolean valid = true; - for (int i = 4; (i + 1) < cooked.length && valid; i += 2) { - if (cooked[i].equals("dev")) { - if (dev == null) { - dev = cooked[i+1]; - } else { - valid = false; // Duplicate interface. - } - } else if (cooked[i].equals("via")) { - if (via == null) { - via = cooked[i+1]; - } else { - valid = false; // Duplicate gateway. - } - } else { - valid = false; // Unknown syntax. - } - } - if (valid) { - try { - // InetAddress.parseNumericAddress(null) inexplicably returns ::1. - InetAddress gateway = null; - if (via != null) gateway = InetAddress.parseNumericAddress(via); - RouteInfo route = new RouteInfo(new IpPrefix(cooked[3]), gateway, dev); - notifyRouteChange(cooked[2].equals("updated"), route); - return true; - } catch (IllegalArgumentException e) {} - } - throw new IllegalStateException(errorMessage); - // break; - case NetdResponseCode.StrictCleartext: - final int uid = Integer.parseInt(cooked[1]); - final byte[] firstPacket = HexDump.hexStringToByteArray(cooked[2]); - try { - ActivityManager.getService().notifyCleartextNetwork(uid, firstPacket); - } catch (RemoteException ignored) { - } - break; - default: break; - } - return false; - } - } - - - // // INetworkManagementService members // @Override @@ -1439,42 +1154,6 @@ public class NetworkManagementService extends INetworkManagementService.Stub } @Override - public String[] listTtys() { - mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); - try { - return NativeDaemonEvent.filterMessageList( - mConnector.executeForList("list_ttys"), TtyListResult); - } catch (NativeDaemonConnectorException e) { - throw e.rethrowAsParcelableException(); - } - } - - @Override - public void attachPppd( - String tty, String localAddr, String remoteAddr, String dns1Addr, String dns2Addr) { - mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); - try { - mConnector.execute("pppd", "attach", tty, - NetworkUtils.numericToInetAddress(localAddr).getHostAddress(), - NetworkUtils.numericToInetAddress(remoteAddr).getHostAddress(), - NetworkUtils.numericToInetAddress(dns1Addr).getHostAddress(), - NetworkUtils.numericToInetAddress(dns2Addr).getHostAddress()); - } catch (NativeDaemonConnectorException e) { - throw e.rethrowAsParcelableException(); - } - } - - @Override - public void detachPppd(String tty) { - mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); - try { - mConnector.execute("pppd", "detach", tty); - } catch (NativeDaemonConnectorException e) { - throw e.rethrowAsParcelableException(); - } - } - - @Override public void addIdleTimer(String iface, int timeout, final int type) { mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); @@ -2295,22 +1974,10 @@ public class NetworkManagementService extends INetworkManagementService.Stub } } - /** {@inheritDoc} */ - @Override - public void monitor() { - if (mConnector != null) { - mConnector.monitor(); - } - } - @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; - pw.println("NetworkManagementService NativeDaemonConnector Log:"); - mConnector.dump(fd, pw, args); - pw.println(); - pw.print("mMobileActivityFromRadio="); pw.print(mMobileActivityFromRadio); pw.print(" mLastPowerStateFromRadio="); pw.println(mLastPowerStateFromRadio); pw.print("mNetworkActive="); pw.println(mNetworkActive); diff --git a/services/core/java/com/android/server/SensorPrivacyService.java b/services/core/java/com/android/server/SensorPrivacyService.java index 1cbcbe5a8bdb..edeb049c0802 100644 --- a/services/core/java/com/android/server/SensorPrivacyService.java +++ b/services/core/java/com/android/server/SensorPrivacyService.java @@ -18,20 +18,15 @@ package com.android.server; import static android.content.pm.PackageManager.PERMISSION_GRANTED; -import android.app.ActivityManager; import android.content.Context; import android.hardware.ISensorPrivacyListener; import android.hardware.ISensorPrivacyManager; -import android.location.LocationManager; -import android.net.ConnectivityManager; import android.os.Environment; import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.RemoteCallbackList; import android.os.RemoteException; -import android.os.UserHandle; -import android.provider.Settings; import android.util.ArrayMap; import android.util.AtomicFile; import android.util.Log; @@ -277,8 +272,6 @@ public final class SensorPrivacyService extends SystemService { } } mListeners.finishBroadcast(); - // Handle the state of all sensors managed by this service. - SensorState.handleSensorPrivacyToggled(mContext, enabled); } } @@ -306,121 +299,4 @@ public final class SensorPrivacyService extends SystemService { } } } - - /** - * Maintains the state of the sensors when sensor privacy is enabled to return them to their - * original state when sensor privacy is disabled. - */ - private static final class SensorState { - - private static Object sLock = new Object(); - @GuardedBy("sLock") - private static SensorState sPreviousState; - - private boolean mAirplaneEnabled; - private boolean mLocationEnabled; - - SensorState(boolean airplaneEnabled, boolean locationEnabled) { - mAirplaneEnabled = airplaneEnabled; - mLocationEnabled = locationEnabled; - } - - public static void handleSensorPrivacyToggled(Context context, boolean enabled) { - synchronized (sLock) { - SensorState state; - if (enabled) { - // if sensor privacy is being enabled then obtain the current state of the - // sensors to be persisted and restored when sensor privacy is disabled. - state = getCurrentSensorState(context); - } else { - // else obtain the previous sensor state to be restored, first from the saved - // state if available, otherwise attempt to read it from Settings. - if (sPreviousState != null) { - state = sPreviousState; - } else { - state = getPersistedSensorState(context); - } - // if the previous state is not available then return without attempting to - // modify the sensor state. - if (state == null) { - return; - } - } - // The SensorState represents the state of the sensor before sensor privacy was - // enabled; if airplane mode was not enabled then the state of airplane mode should - // be the same as the state of sensor privacy. - if (!state.mAirplaneEnabled) { - setAirplaneMode(context, enabled); - } - // Similar to airplane mode the state of location should be the opposite of sensor - // privacy mode, if it was enabled when sensor privacy was enabled then it should be - // disabled. If location is disabled when sensor privacy is enabled then it will be - // left disabled when sensor privacy is disabled. - if (state.mLocationEnabled) { - setLocationEnabled(context, !enabled); - } - - // if sensor privacy is being enabled then persist the current state. - if (enabled) { - sPreviousState = state; - persistState(context, sPreviousState); - } - } - } - - public static SensorState getCurrentSensorState(Context context) { - LocationManager locationManager = (LocationManager) context.getSystemService( - Context.LOCATION_SERVICE); - boolean airplaneEnabled = Settings.Global.getInt(context.getContentResolver(), - Settings.Global.AIRPLANE_MODE_ON, 0) != 0; - boolean locationEnabled = locationManager.isLocationEnabled(); - return new SensorState(airplaneEnabled, locationEnabled); - } - - public static void persistState(Context context, SensorState state) { - StringBuilder stateValue = new StringBuilder(); - stateValue.append(state.mAirplaneEnabled - ? Settings.Secure.MAINTAIN_AIRPLANE_MODE_AFTER_SP_DISABLED - : Settings.Secure.DISABLE_AIRPLANE_MODE_AFTER_SP_DISABLED); - stateValue.append(","); - stateValue.append( - state.mLocationEnabled ? Settings.Secure.REENABLE_LOCATION_AFTER_SP_DISABLED - : Settings.Secure.MAINTAIN_LOCATION_AFTER_SP_DISABLED); - Settings.Secure.putString(context.getContentResolver(), - Settings.Secure.SENSOR_PRIVACY_SENSOR_STATE, stateValue.toString()); - } - - public static SensorState getPersistedSensorState(Context context) { - String persistedState = Settings.Secure.getString(context.getContentResolver(), - Settings.Secure.SENSOR_PRIVACY_SENSOR_STATE); - if (persistedState == null) { - Log.e(TAG, "The persisted sensor state could not be obtained from Settings"); - return null; - } - String[] sensorStates = persistedState.split(","); - if (sensorStates.length < 2) { - Log.e(TAG, "The persisted sensor state does not contain the expected values: " - + persistedState); - return null; - } - boolean airplaneEnabled = sensorStates[0].equals( - Settings.Secure.MAINTAIN_AIRPLANE_MODE_AFTER_SP_DISABLED); - boolean locationEnabled = sensorStates[1].equals( - Settings.Secure.REENABLE_LOCATION_AFTER_SP_DISABLED); - return new SensorState(airplaneEnabled, locationEnabled); - } - - private static void setAirplaneMode(Context context, boolean enable) { - ConnectivityManager connectivityManager = - (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); - connectivityManager.setAirplaneMode(enable); - } - - private static void setLocationEnabled(Context context, boolean enable) { - LocationManager locationManager = (LocationManager) context.getSystemService( - Context.LOCATION_SERVICE); - locationManager.setLocationEnabledForUser(enable, - UserHandle.of(ActivityManager.getCurrentUser())); - } - } } diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java index 077920c04be6..052148242ba0 100644 --- a/services/core/java/com/android/server/StorageManagerService.java +++ b/services/core/java/com/android/server/StorageManagerService.java @@ -611,6 +611,7 @@ class StorageManagerService extends IStorageManager.Stub private static final int H_RESET = 10; private static final int H_RUN_IDLE_MAINT = 11; private static final int H_ABORT_IDLE_MAINT = 12; + private static final int H_BOOT_COMPLETED = 13; class StorageManagerServiceHandler extends Handler { public StorageManagerServiceHandler(Looper looper) { @@ -624,6 +625,10 @@ class StorageManagerService extends IStorageManager.Stub handleSystemReady(); break; } + case H_BOOT_COMPLETED: { + handleBootCompleted(); + break; + } case H_DAEMON_CONNECTED: { handleDaemonConnected(); break; @@ -712,7 +717,7 @@ class StorageManagerService extends IStorageManager.Stub break; } case H_RESET: { - resetIfReadyAndConnected(); + resetIfBootedAndConnected(); break; } case H_RUN_IDLE_MAINT: { @@ -785,9 +790,6 @@ class StorageManagerService extends IStorageManager.Stub } private void handleSystemReady() { - initIfReadyAndConnected(); - resetIfReadyAndConnected(); - // Start scheduling nominally-daily fstrim operations MountServiceIdler.scheduleIdlePass(mContext); @@ -933,10 +935,10 @@ class StorageManagerService extends IStorageManager.Stub mVolumes.put(internal.id, internal); } - private void initIfReadyAndConnected() { - Slog.d(TAG, "Thinking about init, mSystemReady=" + mSystemReady + private void initIfBootedAndConnected() { + Slog.d(TAG, "Thinking about init, mBootCompleted=" + mBootCompleted + ", mDaemonConnected=" + mDaemonConnected); - if (mSystemReady && mDaemonConnected + if (mBootCompleted && mDaemonConnected && !StorageManager.isFileEncryptedNativeOnly()) { // When booting a device without native support, make sure that our // user directories are locked or unlocked based on the current @@ -959,10 +961,10 @@ class StorageManagerService extends IStorageManager.Stub } } - private void resetIfReadyAndConnected() { - Slog.d(TAG, "Thinking about reset, mSystemReady=" + mSystemReady + private void resetIfBootedAndConnected() { + Slog.d(TAG, "Thinking about reset, mBootCompleted=" + mBootCompleted + ", mDaemonConnected=" + mDaemonConnected); - if (mSystemReady && mDaemonConnected) { + if (mBootCompleted && mDaemonConnected) { final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers(); killMediaProvider(users); @@ -1121,8 +1123,8 @@ class StorageManagerService extends IStorageManager.Stub } private void handleDaemonConnected() { - initIfReadyAndConnected(); - resetIfReadyAndConnected(); + initIfBootedAndConnected(); + resetIfBootedAndConnected(); // On an encrypted device we can't see system properties yet, so pull // the system locale out of the mount service. @@ -1856,6 +1858,12 @@ class StorageManagerService extends IStorageManager.Stub private void bootCompleted() { mBootCompleted = true; + mHandler.obtainMessage(H_BOOT_COMPLETED).sendToTarget(); + } + + private void handleBootCompleted() { + initIfBootedAndConnected(); + resetIfBootedAndConnected(); } private String getDefaultPrimaryStorageUuid() { @@ -3854,6 +3862,14 @@ class StorageManagerService extends IStorageManager.Stub case "jp.naver.line.android": // b/124767356 case "com.mxtech.videoplayer.ad": // b/124531483 case "com.whatsapp": // b/124766614 + case "com.maxmpz.audioplayer": // b/127886230 + case "com.estrongs.android.pop": // b/127926473 + case "com.roidapp.photogrid": // b/128269119 + case "com.cleanmaster.mguard": // b/128384413 + case "com.skype.raider": // b/128487044 + case "org.telegram.messenger": // b/128652960 + case "com.jrtstudio.AnotherMusicPlayer": // b/129084562 + case "ak.alizandro.smartaudiobookplayer": // b/129084042 return Zygote.MOUNT_EXTERNAL_LEGACY; } } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 97cc756e3924..a1f2ac630c04 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -5121,6 +5121,7 @@ public class ActivityManagerService extends IActivityManager.Stub String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) { synchronized (ActivityManagerService.this) { + mOomAdjuster.mAppCompact.compactAllSystem(); requestPssAllProcsLocked(SystemClock.uptimeMillis(), true, false); } } @@ -8614,6 +8615,10 @@ public class ActivityManagerService extends IActivityManager.Stub synchronized (this) { final long now = SystemClock.uptimeMillis(); final long timeSinceLastIdle = now - mLastIdleTime; + + // Compact all non-zygote processes to freshen up the page cache. + mOomAdjuster.mAppCompact.compactAllSystem(); + final long lowRamSinceLastIdle = getLowRamTimeSinceIdle(now); mLastIdleTime = now; mLowRamTimeSinceLastIdle = 0; diff --git a/services/core/java/com/android/server/am/AppCompactor.java b/services/core/java/com/android/server/am/AppCompactor.java index 9216343e05d8..f58fb95b1ec9 100644 --- a/services/core/java/com/android/server/am/AppCompactor.java +++ b/services/core/java/com/android/server/am/AppCompactor.java @@ -51,6 +51,8 @@ public final class AppCompactor { @VisibleForTesting static final String KEY_COMPACT_THROTTLE_2 = "compact_throttle_2"; @VisibleForTesting static final String KEY_COMPACT_THROTTLE_3 = "compact_throttle_3"; @VisibleForTesting static final String KEY_COMPACT_THROTTLE_4 = "compact_throttle_4"; + @VisibleForTesting static final String KEY_COMPACT_THROTTLE_5 = "compact_throttle_5"; + @VisibleForTesting static final String KEY_COMPACT_THROTTLE_6 = "compact_throttle_6"; @VisibleForTesting static final String KEY_COMPACT_STATSD_SAMPLE_RATE = "compact_statsd_sample_rate"; @@ -73,6 +75,8 @@ public final class AppCompactor { @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_2 = 10_000; @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_3 = 500; @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_4 = 10_000; + @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_5 = 10 * 60 * 1000; + @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_6 = 10 * 60 * 1000; // The sampling rate to push app compaction events into statsd for upload. @VisibleForTesting static final float DEFAULT_STATSD_SAMPLE_RATE = 0.1f; @@ -85,7 +89,10 @@ public final class AppCompactor { // Handler constants. static final int COMPACT_PROCESS_SOME = 1; static final int COMPACT_PROCESS_FULL = 2; + static final int COMPACT_PROCESS_PERSISTENT = 3; + static final int COMPACT_PROCESS_BFGS = 4; static final int COMPACT_PROCESS_MSG = 1; + static final int COMPACT_SYSTEM_MSG = 2; /** * This thread must be moved to the system background cpuset. @@ -142,6 +149,10 @@ public final class AppCompactor { @GuardedBy("mPhenotypeFlagLock") @VisibleForTesting volatile long mCompactThrottleFullFull = DEFAULT_COMPACT_THROTTLE_4; @GuardedBy("mPhenotypeFlagLock") + @VisibleForTesting volatile long mCompactThrottleBFGS = DEFAULT_COMPACT_THROTTLE_5; + @GuardedBy("mPhenotypeFlagLock") + @VisibleForTesting volatile long mCompactThrottlePersistent = DEFAULT_COMPACT_THROTTLE_6; + @GuardedBy("mPhenotypeFlagLock") private volatile boolean mUseCompaction = DEFAULT_USE_COMPACTION; private final Random mRandom = new Random(); @@ -224,6 +235,46 @@ public final class AppCompactor { } + @GuardedBy("mAm") + void compactAppPersistent(ProcessRecord app) { + app.reqCompactAction = COMPACT_PROCESS_PERSISTENT; + mPendingCompactionProcesses.add(app); + mCompactionHandler.sendMessage( + mCompactionHandler.obtainMessage( + COMPACT_PROCESS_MSG, app.curAdj, app.setProcState)); + } + + @GuardedBy("mAm") + boolean shouldCompactPersistent(ProcessRecord app, long now) { + return (app.lastCompactTime == 0 + || (now - app.lastCompactTime) > mCompactThrottlePersistent); + } + + @GuardedBy("mAm") + void compactAppBfgs(ProcessRecord app) { + app.reqCompactAction = COMPACT_PROCESS_BFGS; + mPendingCompactionProcesses.add(app); + mCompactionHandler.sendMessage( + mCompactionHandler.obtainMessage( + COMPACT_PROCESS_MSG, app.curAdj, app.setProcState)); + } + + @GuardedBy("mAm") + boolean shouldCompactBFGS(ProcessRecord app, long now) { + return (app.lastCompactTime == 0 + || (now - app.lastCompactTime) > mCompactThrottleBFGS); + } + + @GuardedBy("mAm") + void compactAllSystem() { + if (mUseCompaction) { + mCompactionHandler.sendMessage(mCompactionHandler.obtainMessage( + COMPACT_SYSTEM_MSG)); + } + } + + private native void compactSystem(); + /** * Reads the flag value from DeviceConfig to determine whether app compaction * should be enabled, and starts/stops the compaction thread as needed. @@ -265,10 +316,18 @@ public final class AppCompactor { String throttleFullFullFlag = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_COMPACT_THROTTLE_4); + String throttleBFGSFlag = + DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, + KEY_COMPACT_THROTTLE_5); + String throttlePersistentFlag = + DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, + KEY_COMPACT_THROTTLE_6); if (TextUtils.isEmpty(throttleSomeSomeFlag) || TextUtils.isEmpty(throttleSomeFullFlag) || TextUtils.isEmpty(throttleFullSomeFlag) - || TextUtils.isEmpty(throttleFullFullFlag)) { + || TextUtils.isEmpty(throttleFullFullFlag) + || TextUtils.isEmpty(throttleBFGSFlag) + || TextUtils.isEmpty(throttlePersistentFlag)) { // Set defaults for all if any are not set. useThrottleDefaults = true; } else { @@ -277,6 +336,8 @@ public final class AppCompactor { mCompactThrottleSomeFull = Integer.parseInt(throttleSomeFullFlag); mCompactThrottleFullSome = Integer.parseInt(throttleFullSomeFlag); mCompactThrottleFullFull = Integer.parseInt(throttleFullFullFlag); + mCompactThrottleBFGS = Integer.parseInt(throttleBFGSFlag); + mCompactThrottlePersistent = Integer.parseInt(throttlePersistentFlag); } catch (NumberFormatException e) { useThrottleDefaults = true; } @@ -287,6 +348,8 @@ public final class AppCompactor { mCompactThrottleSomeFull = DEFAULT_COMPACT_THROTTLE_2; mCompactThrottleFullSome = DEFAULT_COMPACT_THROTTLE_3; mCompactThrottleFullFull = DEFAULT_COMPACT_THROTTLE_4; + mCompactThrottleBFGS = DEFAULT_COMPACT_THROTTLE_5; + mCompactThrottlePersistent = DEFAULT_COMPACT_THROTTLE_6; } } @@ -332,14 +395,19 @@ public final class AppCompactor { synchronized (mAm) { proc = mPendingCompactionProcesses.remove(0); + pendingAction = proc.reqCompactAction; + // don't compact if the process has returned to perceptible - if (proc.setAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) { + // and this is only a cached/home/prev compaction + if ((pendingAction == COMPACT_PROCESS_SOME + || pendingAction == COMPACT_PROCESS_FULL) + && (proc.setAdj <= ProcessList.PERCEPTIBLE_APP_ADJ)) { return; } pid = proc.pid; name = proc.processName; - pendingAction = proc.reqCompactAction; + lastCompactAction = proc.lastCompactAction; lastCompactTime = proc.lastCompactTime; } @@ -356,31 +424,49 @@ public final class AppCompactor { // Note that we explicitly don't take mPhenotypeFlagLock here as the flags // should very seldom change, and taking the risk of using the wrong action is // preferable to taking the lock for every single compaction action. - if (pendingAction == COMPACT_PROCESS_SOME) { - if ((lastCompactAction == COMPACT_PROCESS_SOME - && (start - lastCompactTime < mCompactThrottleSomeSome)) - || (lastCompactAction == COMPACT_PROCESS_FULL - && (start - lastCompactTime - < mCompactThrottleSomeFull))) { - return; - } - } else { - if ((lastCompactAction == COMPACT_PROCESS_SOME - && (start - lastCompactTime < mCompactThrottleFullSome)) - || (lastCompactAction == COMPACT_PROCESS_FULL - && (start - lastCompactTime - < mCompactThrottleFullFull))) { - return; + if (lastCompactTime != 0) { + if (pendingAction == COMPACT_PROCESS_SOME) { + if ((lastCompactAction == COMPACT_PROCESS_SOME + && (start - lastCompactTime < mCompactThrottleSomeSome)) + || (lastCompactAction == COMPACT_PROCESS_FULL + && (start - lastCompactTime + < mCompactThrottleSomeFull))) { + return; + } + } else if (pendingAction == COMPACT_PROCESS_FULL) { + if ((lastCompactAction == COMPACT_PROCESS_SOME + && (start - lastCompactTime < mCompactThrottleFullSome)) + || (lastCompactAction == COMPACT_PROCESS_FULL + && (start - lastCompactTime + < mCompactThrottleFullFull))) { + return; + } + } else if (pendingAction == COMPACT_PROCESS_PERSISTENT) { + if (start - lastCompactTime < mCompactThrottlePersistent) { + return; + } + } else if (pendingAction == COMPACT_PROCESS_BFGS) { + if (start - lastCompactTime < mCompactThrottleBFGS) { + return; + } } } - - if (pendingAction == COMPACT_PROCESS_SOME) { - action = mCompactActionSome; - } else { - action = mCompactActionFull; + switch (pendingAction) { + case COMPACT_PROCESS_SOME: + action = mCompactActionSome; + break; + // For the time being, treat these as equivalent. + case COMPACT_PROCESS_FULL: + case COMPACT_PROCESS_PERSISTENT: + case COMPACT_PROCESS_BFGS: + action = mCompactActionFull; + break; + default: + action = COMPACT_ACTION_NONE; + break; } - if (action.equals(COMPACT_ACTION_NONE)) { + if (COMPACT_ACTION_NONE.equals(action)) { return; } @@ -422,6 +508,13 @@ public final class AppCompactor { // nothing to do, presumably the process died Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } + break; + } + case COMPACT_SYSTEM_MSG: { + Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "compactSystem"); + compactSystem(); + Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); + break; } } } diff --git a/services/core/java/com/android/server/am/BaseErrorDialog.java b/services/core/java/com/android/server/am/BaseErrorDialog.java index dc9a4bf1ad94..aabb5877764e 100644 --- a/services/core/java/com/android/server/am/BaseErrorDialog.java +++ b/services/core/java/com/android/server/am/BaseErrorDialog.java @@ -16,6 +16,8 @@ package com.android.server.am; +import com.android.internal.R; + import android.app.AlertDialog; import android.content.Context; import android.os.Handler; @@ -24,8 +26,6 @@ import android.view.KeyEvent; import android.view.WindowManager; import android.widget.Button; -import com.android.internal.R; - public class BaseErrorDialog extends AlertDialog { private static final int ENABLE_BUTTONS = 0; private static final int DISABLE_BUTTONS = 1; @@ -36,7 +36,7 @@ public class BaseErrorDialog extends AlertDialog { super(context, com.android.internal.R.style.Theme_DeviceDefault_Dialog_AppError); context.assertRuntimeOverlayThemable(); - getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY); + getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM, WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); WindowManager.LayoutParams attrs = getWindow().getAttributes(); diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java index 4d5cb8cb4473..f86ba278138c 100644 --- a/services/core/java/com/android/server/am/BatteryStatsService.java +++ b/services/core/java/com/android/server/am/BatteryStatsService.java @@ -754,7 +754,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub } public void noteStartAudio(int uid) { - enforceCallingPermission(); + enforceSelfOrCallingPermission(uid); synchronized (mStats) { mStats.noteAudioOnLocked(uid); StatsLog.write_non_chained(StatsLog.AUDIO_STATE_CHANGED, uid, null, @@ -763,7 +763,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub } public void noteStopAudio(int uid) { - enforceCallingPermission(); + enforceSelfOrCallingPermission(uid); synchronized (mStats) { mStats.noteAudioOffLocked(uid); StatsLog.write_non_chained(StatsLog.AUDIO_STATE_CHANGED, uid, null, @@ -772,7 +772,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub } public void noteStartVideo(int uid) { - enforceCallingPermission(); + enforceSelfOrCallingPermission(uid); synchronized (mStats) { mStats.noteVideoOnLocked(uid); StatsLog.write_non_chained(StatsLog.MEDIA_CODEC_STATE_CHANGED, uid, null, @@ -781,7 +781,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub } public void noteStopVideo(int uid) { - enforceCallingPermission(); + enforceSelfOrCallingPermission(uid); synchronized (mStats) { mStats.noteVideoOffLocked(uid); StatsLog.write_non_chained(StatsLog.MEDIA_CODEC_STATE_CHANGED, uid, @@ -1182,6 +1182,13 @@ public final class BatteryStatsService extends IBatteryStats.Stub Binder.getCallingPid(), Binder.getCallingUid(), null); } + private void enforceSelfOrCallingPermission(int uid) { + if (Binder.getCallingUid() == uid) { + return; + } + enforceCallingPermission(); + } + final class WakeupReasonThread extends Thread { private static final int MAX_REASON_SIZE = 512; private CharsetDecoder mDecoder; diff --git a/services/core/java/com/android/server/am/HealthStatsBatteryStatsWriter.java b/services/core/java/com/android/server/am/HealthStatsBatteryStatsWriter.java index c2f1890699a8..1c916e94fc0b 100644 --- a/services/core/java/com/android/server/am/HealthStatsBatteryStatsWriter.java +++ b/services/core/java/com/android/server/am/HealthStatsBatteryStatsWriter.java @@ -17,7 +17,7 @@ package com.android.server.am; import android.os.BatteryStats; -import static android.os.BatteryStats.STATS_SINCE_UNPLUGGED; +import static android.os.BatteryStats.STATS_SINCE_CHARGED; import android.os.PowerManager; import android.os.SystemClock; import android.os.health.HealthKeys; @@ -63,20 +63,20 @@ public class HealthStatsBatteryStatsWriter { // MEASUREMENT_REALTIME_BATTERY_MS uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_REALTIME_BATTERY_MS, - bs.computeBatteryRealtime(mNowRealtimeMs*1000, STATS_SINCE_UNPLUGGED)/1000); + bs.computeBatteryRealtime(mNowRealtimeMs*1000, STATS_SINCE_CHARGED)/1000); // MEASUREMENT_UPTIME_BATTERY_MS uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_UPTIME_BATTERY_MS, - bs.computeBatteryUptime(mNowUptimeMs*1000, STATS_SINCE_UNPLUGGED)/1000); + bs.computeBatteryUptime(mNowUptimeMs*1000, STATS_SINCE_CHARGED)/1000); // MEASUREMENT_REALTIME_SCREEN_OFF_BATTERY_MS uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_REALTIME_SCREEN_OFF_BATTERY_MS, bs.computeBatteryScreenOffRealtime( - mNowRealtimeMs*1000, STATS_SINCE_UNPLUGGED)/1000); + mNowRealtimeMs*1000, STATS_SINCE_CHARGED)/1000); // MEASUREMENT_UPTIME_SCREEN_OFF_BATTERY_MS uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_UPTIME_SCREEN_OFF_BATTERY_MS, - bs.computeBatteryScreenOffUptime(mNowUptimeMs*1000, STATS_SINCE_UNPLUGGED)/1000); + bs.computeBatteryScreenOffUptime(mNowUptimeMs*1000, STATS_SINCE_CHARGED)/1000); // // Now on to the real per-uid stats... @@ -161,75 +161,75 @@ public class HealthStatsBatteryStatsWriter { if (controller != null) { // MEASUREMENT_WIFI_IDLE_MS uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_IDLE_MS, - controller.getIdleTimeCounter().getCountLocked(STATS_SINCE_UNPLUGGED)); + controller.getIdleTimeCounter().getCountLocked(STATS_SINCE_CHARGED)); // MEASUREMENT_WIFI_RX_MS uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_RX_MS, - controller.getRxTimeCounter().getCountLocked(STATS_SINCE_UNPLUGGED)); + controller.getRxTimeCounter().getCountLocked(STATS_SINCE_CHARGED)); // MEASUREMENT_WIFI_TX_MS sum = 0; for (final BatteryStats.LongCounter counter: controller.getTxTimeCounters()) { - sum += counter.getCountLocked(STATS_SINCE_UNPLUGGED); + sum += counter.getCountLocked(STATS_SINCE_CHARGED); } uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_TX_MS, sum); // MEASUREMENT_WIFI_POWER_MAMS uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_POWER_MAMS, - controller.getPowerCounter().getCountLocked(STATS_SINCE_UNPLUGGED)); + controller.getPowerCounter().getCountLocked(STATS_SINCE_CHARGED)); } controller = uid.getBluetoothControllerActivity(); if (controller != null) { // MEASUREMENT_BLUETOOTH_IDLE_MS uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_BLUETOOTH_IDLE_MS, - controller.getIdleTimeCounter().getCountLocked(STATS_SINCE_UNPLUGGED)); + controller.getIdleTimeCounter().getCountLocked(STATS_SINCE_CHARGED)); // MEASUREMENT_BLUETOOTH_RX_MS uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_BLUETOOTH_RX_MS, - controller.getRxTimeCounter().getCountLocked(STATS_SINCE_UNPLUGGED)); + controller.getRxTimeCounter().getCountLocked(STATS_SINCE_CHARGED)); // MEASUREMENT_BLUETOOTH_TX_MS sum = 0; for (final BatteryStats.LongCounter counter: controller.getTxTimeCounters()) { - sum += counter.getCountLocked(STATS_SINCE_UNPLUGGED); + sum += counter.getCountLocked(STATS_SINCE_CHARGED); } uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_BLUETOOTH_TX_MS, sum); // MEASUREMENT_BLUETOOTH_POWER_MAMS uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_BLUETOOTH_POWER_MAMS, - controller.getPowerCounter().getCountLocked(STATS_SINCE_UNPLUGGED)); + controller.getPowerCounter().getCountLocked(STATS_SINCE_CHARGED)); } controller = uid.getModemControllerActivity(); if (controller != null) { // MEASUREMENT_MOBILE_IDLE_MS uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_MOBILE_IDLE_MS, - controller.getIdleTimeCounter().getCountLocked(STATS_SINCE_UNPLUGGED)); + controller.getIdleTimeCounter().getCountLocked(STATS_SINCE_CHARGED)); // MEASUREMENT_MOBILE_RX_MS uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_MOBILE_RX_MS, - controller.getRxTimeCounter().getCountLocked(STATS_SINCE_UNPLUGGED)); + controller.getRxTimeCounter().getCountLocked(STATS_SINCE_CHARGED)); // MEASUREMENT_MOBILE_TX_MS sum = 0; for (final BatteryStats.LongCounter counter: controller.getTxTimeCounters()) { - sum += counter.getCountLocked(STATS_SINCE_UNPLUGGED); + sum += counter.getCountLocked(STATS_SINCE_CHARGED); } uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_MOBILE_TX_MS, sum); // MEASUREMENT_MOBILE_POWER_MAMS uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_MOBILE_POWER_MAMS, - controller.getPowerCounter().getCountLocked(STATS_SINCE_UNPLUGGED)); + controller.getPowerCounter().getCountLocked(STATS_SINCE_CHARGED)); } // MEASUREMENT_WIFI_RUNNING_MS uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_RUNNING_MS, - uid.getWifiRunningTime(mNowRealtimeMs*1000, STATS_SINCE_UNPLUGGED)/1000); + uid.getWifiRunningTime(mNowRealtimeMs*1000, STATS_SINCE_CHARGED)/1000); // MEASUREMENT_WIFI_FULL_LOCK_MS uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_FULL_LOCK_MS, - uid.getFullWifiLockTime(mNowRealtimeMs*1000, STATS_SINCE_UNPLUGGED)/1000); + uid.getFullWifiLockTime(mNowRealtimeMs*1000, STATS_SINCE_CHARGED)/1000); // TIMER_WIFI_SCAN uidWriter.addTimer(UidHealthStats.TIMER_WIFI_SCAN, - uid.getWifiScanCount(STATS_SINCE_UNPLUGGED), - uid.getWifiScanTime(mNowRealtimeMs*1000, STATS_SINCE_UNPLUGGED)/1000); + uid.getWifiScanCount(STATS_SINCE_CHARGED), + uid.getWifiScanTime(mNowRealtimeMs*1000, STATS_SINCE_CHARGED)/1000); // MEASUREMENT_WIFI_MULTICAST_MS uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_MULTICAST_MS, - uid.getWifiMulticastTime(mNowRealtimeMs*1000, STATS_SINCE_UNPLUGGED)/1000); + uid.getWifiMulticastTime(mNowRealtimeMs*1000, STATS_SINCE_CHARGED)/1000); // TIMER_AUDIO addTimer(uidWriter, UidHealthStats.TIMER_AUDIO, uid.getAudioTurnedOnTimer()); @@ -280,90 +280,90 @@ public class HealthStatsBatteryStatsWriter { // MEASUREMENT_OTHER_USER_ACTIVITY_COUNT uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_OTHER_USER_ACTIVITY_COUNT, uid.getUserActivityCount(PowerManager.USER_ACTIVITY_EVENT_OTHER, - STATS_SINCE_UNPLUGGED)); + STATS_SINCE_CHARGED)); // MEASUREMENT_BUTTON_USER_ACTIVITY_COUNT uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_BUTTON_USER_ACTIVITY_COUNT, uid.getUserActivityCount(PowerManager.USER_ACTIVITY_EVENT_BUTTON, - STATS_SINCE_UNPLUGGED)); + STATS_SINCE_CHARGED)); // MEASUREMENT_TOUCH_USER_ACTIVITY_COUNT uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_TOUCH_USER_ACTIVITY_COUNT, uid.getUserActivityCount(PowerManager.USER_ACTIVITY_EVENT_TOUCH, - STATS_SINCE_UNPLUGGED)); + STATS_SINCE_CHARGED)); // MEASUREMENT_MOBILE_RX_BYTES uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_MOBILE_RX_BYTES, uid.getNetworkActivityBytes(BatteryStats.NETWORK_MOBILE_RX_DATA, - STATS_SINCE_UNPLUGGED)); + STATS_SINCE_CHARGED)); // MEASUREMENT_MOBILE_TX_BYTES uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_MOBILE_TX_BYTES, uid.getNetworkActivityBytes(BatteryStats.NETWORK_MOBILE_TX_DATA, - STATS_SINCE_UNPLUGGED)); + STATS_SINCE_CHARGED)); // MEASUREMENT_WIFI_RX_BYTES uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_RX_BYTES, uid.getNetworkActivityBytes(BatteryStats.NETWORK_WIFI_RX_DATA, - STATS_SINCE_UNPLUGGED)); + STATS_SINCE_CHARGED)); // MEASUREMENT_WIFI_TX_BYTES uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_TX_BYTES, uid.getNetworkActivityBytes(BatteryStats.NETWORK_WIFI_TX_DATA, - STATS_SINCE_UNPLUGGED)); + STATS_SINCE_CHARGED)); // MEASUREMENT_BLUETOOTH_RX_BYTES uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_BLUETOOTH_RX_BYTES, uid.getNetworkActivityBytes(BatteryStats.NETWORK_BT_RX_DATA, - STATS_SINCE_UNPLUGGED)); + STATS_SINCE_CHARGED)); // MEASUREMENT_BLUETOOTH_TX_BYTES uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_BLUETOOTH_TX_BYTES, uid.getNetworkActivityBytes(BatteryStats.NETWORK_BT_TX_DATA, - STATS_SINCE_UNPLUGGED)); + STATS_SINCE_CHARGED)); // MEASUREMENT_MOBILE_RX_PACKETS uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_MOBILE_RX_PACKETS, uid.getNetworkActivityPackets(BatteryStats.NETWORK_MOBILE_RX_DATA, - STATS_SINCE_UNPLUGGED)); + STATS_SINCE_CHARGED)); // MEASUREMENT_MOBILE_TX_PACKETS uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_MOBILE_TX_PACKETS, uid.getNetworkActivityPackets(BatteryStats.NETWORK_MOBILE_TX_DATA, - STATS_SINCE_UNPLUGGED)); + STATS_SINCE_CHARGED)); // MEASUREMENT_WIFI_RX_PACKETS uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_RX_PACKETS, uid.getNetworkActivityPackets(BatteryStats.NETWORK_WIFI_RX_DATA, - STATS_SINCE_UNPLUGGED)); + STATS_SINCE_CHARGED)); // MEASUREMENT_WIFI_TX_PACKETS uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_TX_PACKETS, uid.getNetworkActivityPackets(BatteryStats.NETWORK_WIFI_TX_DATA, - STATS_SINCE_UNPLUGGED)); + STATS_SINCE_CHARGED)); // MEASUREMENT_BLUETOOTH_RX_PACKETS uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_BLUETOOTH_RX_PACKETS, uid.getNetworkActivityPackets(BatteryStats.NETWORK_BT_RX_DATA, - STATS_SINCE_UNPLUGGED)); + STATS_SINCE_CHARGED)); // MEASUREMENT_BLUETOOTH_TX_PACKETS uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_BLUETOOTH_TX_PACKETS, uid.getNetworkActivityPackets(BatteryStats.NETWORK_BT_TX_DATA, - STATS_SINCE_UNPLUGGED)); + STATS_SINCE_CHARGED)); // TIMER_MOBILE_RADIO_ACTIVE uidWriter.addTimer(UidHealthStats.TIMER_MOBILE_RADIO_ACTIVE, - uid.getMobileRadioActiveCount(STATS_SINCE_UNPLUGGED), - uid.getMobileRadioActiveTime(STATS_SINCE_UNPLUGGED)); + uid.getMobileRadioActiveCount(STATS_SINCE_CHARGED), + uid.getMobileRadioActiveTime(STATS_SINCE_CHARGED)); // MEASUREMENT_USER_CPU_TIME_MS uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_USER_CPU_TIME_MS, - uid.getUserCpuTimeUs(STATS_SINCE_UNPLUGGED)/1000); + uid.getUserCpuTimeUs(STATS_SINCE_CHARGED)/1000); // MEASUREMENT_SYSTEM_CPU_TIME_MS uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_SYSTEM_CPU_TIME_MS, - uid.getSystemCpuTimeUs(STATS_SINCE_UNPLUGGED)/1000); + uid.getSystemCpuTimeUs(STATS_SINCE_CHARGED)/1000); // MEASUREMENT_CPU_POWER_MAMS uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_CPU_POWER_MAMS, 0); @@ -393,27 +393,27 @@ public class HealthStatsBatteryStatsWriter { public void writeProc(HealthStatsWriter procWriter, BatteryStats.Uid.Proc proc) { // MEASUREMENT_USER_TIME_MS procWriter.addMeasurement(ProcessHealthStats.MEASUREMENT_USER_TIME_MS, - proc.getUserTime(STATS_SINCE_UNPLUGGED)); + proc.getUserTime(STATS_SINCE_CHARGED)); // MEASUREMENT_SYSTEM_TIME_MS procWriter.addMeasurement(ProcessHealthStats.MEASUREMENT_SYSTEM_TIME_MS, - proc.getSystemTime(STATS_SINCE_UNPLUGGED)); + proc.getSystemTime(STATS_SINCE_CHARGED)); // MEASUREMENT_STARTS_COUNT procWriter.addMeasurement(ProcessHealthStats.MEASUREMENT_STARTS_COUNT, - proc.getStarts(STATS_SINCE_UNPLUGGED)); + proc.getStarts(STATS_SINCE_CHARGED)); // MEASUREMENT_CRASHES_COUNT procWriter.addMeasurement(ProcessHealthStats.MEASUREMENT_CRASHES_COUNT, - proc.getNumCrashes(STATS_SINCE_UNPLUGGED)); + proc.getNumCrashes(STATS_SINCE_CHARGED)); // MEASUREMENT_ANR_COUNT procWriter.addMeasurement(ProcessHealthStats.MEASUREMENT_ANR_COUNT, - proc.getNumAnrs(STATS_SINCE_UNPLUGGED)); + proc.getNumAnrs(STATS_SINCE_CHARGED)); // MEASUREMENT_FOREGROUND_MS procWriter.addMeasurement(ProcessHealthStats.MEASUREMENT_FOREGROUND_MS, - proc.getForegroundTime(STATS_SINCE_UNPLUGGED)); + proc.getForegroundTime(STATS_SINCE_CHARGED)); } /** @@ -434,7 +434,7 @@ public class HealthStatsBatteryStatsWriter { final BatteryStats.Counter counter = entry.getValue(); if (counter != null) { pkgWriter.addMeasurements(PackageHealthStats.MEASUREMENTS_WAKEUP_ALARMS_COUNT, - entry.getKey(), counter.getCountLocked(STATS_SINCE_UNPLUGGED)); + entry.getKey(), counter.getCountLocked(STATS_SINCE_CHARGED)); } } } @@ -445,11 +445,11 @@ public class HealthStatsBatteryStatsWriter { public void writeServ(HealthStatsWriter servWriter, BatteryStats.Uid.Pkg.Serv serv) { // MEASUREMENT_START_SERVICE_COUNT servWriter.addMeasurement(ServiceHealthStats.MEASUREMENT_START_SERVICE_COUNT, - serv.getStarts(STATS_SINCE_UNPLUGGED)); + serv.getStarts(STATS_SINCE_CHARGED)); // MEASUREMENT_LAUNCH_COUNT servWriter.addMeasurement(ServiceHealthStats.MEASUREMENT_LAUNCH_COUNT, - serv.getLaunches(STATS_SINCE_UNPLUGGED)); + serv.getLaunches(STATS_SINCE_CHARGED)); } /** @@ -457,8 +457,8 @@ public class HealthStatsBatteryStatsWriter { */ private void addTimer(HealthStatsWriter writer, int key, BatteryStats.Timer timer) { if (timer != null) { - writer.addTimer(key, timer.getCountLocked(STATS_SINCE_UNPLUGGED), - timer.getTotalTimeLocked(mNowRealtimeMs*1000, STATS_SINCE_UNPLUGGED) / 1000); + writer.addTimer(key, timer.getCountLocked(STATS_SINCE_CHARGED), + timer.getTotalTimeLocked(mNowRealtimeMs*1000, STATS_SINCE_CHARGED) / 1000); } } @@ -468,8 +468,8 @@ public class HealthStatsBatteryStatsWriter { private void addTimers(HealthStatsWriter writer, int key, String name, BatteryStats.Timer timer) { if (timer != null) { - writer.addTimers(key, name, new TimerStat(timer.getCountLocked(STATS_SINCE_UNPLUGGED), - timer.getTotalTimeLocked(mNowRealtimeMs*1000, STATS_SINCE_UNPLUGGED) / 1000)); + writer.addTimers(key, name, new TimerStat(timer.getCountLocked(STATS_SINCE_CHARGED), + timer.getTotalTimeLocked(mNowRealtimeMs*1000, STATS_SINCE_CHARGED) / 1000)); } } } diff --git a/services/core/java/com/android/server/am/MemoryStatUtil.java b/services/core/java/com/android/server/am/MemoryStatUtil.java index 0d035805274c..9cda89a17766 100644 --- a/services/core/java/com/android/server/am/MemoryStatUtil.java +++ b/services/core/java/com/android/server/am/MemoryStatUtil.java @@ -166,17 +166,11 @@ public final class MemoryStatUtil { } final MemoryStat memoryStat = new MemoryStat(); - Matcher m; - m = PGFAULT.matcher(memoryStatContents); - memoryStat.pgfault = m.find() ? Long.parseLong(m.group(1)) : 0; - m = PGMAJFAULT.matcher(memoryStatContents); - memoryStat.pgmajfault = m.find() ? Long.parseLong(m.group(1)) : 0; - m = RSS_IN_BYTES.matcher(memoryStatContents); - memoryStat.rssInBytes = m.find() ? Long.parseLong(m.group(1)) : 0; - m = CACHE_IN_BYTES.matcher(memoryStatContents); - memoryStat.cacheInBytes = m.find() ? Long.parseLong(m.group(1)) : 0; - m = SWAP_IN_BYTES.matcher(memoryStatContents); - memoryStat.swapInBytes = m.find() ? Long.parseLong(m.group(1)) : 0; + memoryStat.pgfault = tryParseLong(PGFAULT, memoryStatContents); + memoryStat.pgmajfault = tryParseLong(PGMAJFAULT, memoryStatContents); + memoryStat.rssInBytes = tryParseLong(RSS_IN_BYTES, memoryStatContents); + memoryStat.cacheInBytes = tryParseLong(CACHE_IN_BYTES, memoryStatContents); + memoryStat.swapInBytes = tryParseLong(SWAP_IN_BYTES, memoryStatContents); return memoryStat; } @@ -217,9 +211,8 @@ public final class MemoryStatUtil { if (procStatusContents == null || procStatusContents.isEmpty()) { return 0; } - Matcher m = RSS_HIGH_WATERMARK_IN_BYTES.matcher(procStatusContents); // Convert value read from /proc/pid/status from kilobytes to bytes. - return m.find() ? Long.parseLong(m.group(1)) * BYTES_IN_KILOBYTE : 0; + return tryParseLong(RSS_HIGH_WATERMARK_IN_BYTES, procStatusContents) * BYTES_IN_KILOBYTE; } @@ -249,8 +242,7 @@ public final class MemoryStatUtil { if (contents == null || contents.isEmpty()) { return 0; } - Matcher m = ION_HEAP_SIZE_IN_BYTES.matcher(contents); - return m.find() ? Long.parseLong(m.group(1)) : 0; + return tryParseLong(ION_HEAP_SIZE_IN_BYTES, contents); } /** @@ -260,6 +252,20 @@ public final class MemoryStatUtil { return DEVICE_HAS_PER_APP_MEMCG; } + /** + * Parses a long from the input using the pattern. Returns 0 if the captured value is not + * parsable. The pattern must have a single capturing group. + */ + private static long tryParseLong(Pattern pattern, String input) { + final Matcher m = pattern.matcher(input); + try { + return m.find() ? Long.parseLong(m.group(1)) : 0; + } catch (NumberFormatException e) { + Slog.e(TAG, "Failed to parse value", e); + return 0; + } + } + public static final class MemoryStat { /** Number of page faults */ public long pgfault; diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java index aa03de1115b2..c1b9a20d143d 100644 --- a/services/core/java/com/android/server/am/OomAdjuster.java +++ b/services/core/java/com/android/server/am/OomAdjuster.java @@ -1686,9 +1686,10 @@ public final class OomAdjuster { int changes = 0; - if (app.curAdj != app.setAdj) { - // don't compact during bootup - if (mAppCompact.useCompaction() && mService.mBooted) { + // don't compact during bootup + if (mAppCompact.useCompaction() && mService.mBooted) { + // Cached and prev/home compaction + if (app.curAdj != app.setAdj) { // Perform a minor compaction when a perceptible app becomes the prev/home app // Perform a major compaction when any app enters cached // reminder: here, setAdj is previous state, curAdj is upcoming state @@ -1702,7 +1703,23 @@ public final class OomAdjuster { && app.curAdj <= ProcessList.CACHED_APP_MAX_ADJ) { mAppCompact.compactAppFull(app); } + } else if (mService.mWakefulness != PowerManagerInternal.WAKEFULNESS_AWAKE + && app.setAdj < ProcessList.FOREGROUND_APP_ADJ + // Because these can fire independent of oom_adj/procstate changes, we need + // to throttle the actual dispatch of these requests in addition to the + // processing of the requests. As a result, there is throttling both here + // and in AppCompactor. + && mAppCompact.shouldCompactPersistent(app, now)) { + mAppCompact.compactAppPersistent(app); + } else if (mService.mWakefulness != PowerManagerInternal.WAKEFULNESS_AWAKE + && app.getCurProcState() + == ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE + && mAppCompact.shouldCompactBFGS(app, now)) { + mAppCompact.compactAppBfgs(app); } + } + + if (app.curAdj != app.setAdj) { ProcessList.setOomAdj(app.pid, app.uid, app.curAdj); if (DEBUG_SWITCH || DEBUG_OOM_ADJ || mService.mCurOomAdjUid == app.info.uid) { String msg = "Set " + app.pid + " " + app.processName + " adj " diff --git a/services/core/java/com/android/server/attention/AttentionManagerService.java b/services/core/java/com/android/server/attention/AttentionManagerService.java index 42a7a5c18a48..b447c538e1a6 100644 --- a/services/core/java/com/android/server/attention/AttentionManagerService.java +++ b/services/core/java/com/android/server/attention/AttentionManagerService.java @@ -17,9 +17,12 @@ package com.android.server.attention; import static android.provider.DeviceConfig.NAMESPACE_ATTENTION_MANAGER_SERVICE; +import static android.provider.Settings.System.ADAPTIVE_SLEEP; import android.Manifest; +import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.TestApi; import android.annotation.UserIdInt; import android.app.ActivityManager; import android.attention.AttentionManagerInternal; @@ -43,6 +46,7 @@ import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; import android.provider.DeviceConfig; +import android.provider.Settings; import android.service.attention.AttentionService; import android.service.attention.AttentionService.AttentionFailureCodes; import android.service.attention.IAttentionCallback; @@ -70,6 +74,15 @@ import java.io.PrintWriter; public class AttentionManagerService extends SystemService { private static final String LOG_TAG = "AttentionManagerService"; + /** + * DeviceConfig flag name, allows a CTS to inject a fake implementation. + * + * @hide + */ + @TestApi + public static final String COMPONENT_NAME = "component_name"; + + /** Default value in absence of {@link DeviceConfig} override. */ private static final boolean DEFAULT_SERVICE_ENABLED = true; @@ -81,10 +94,6 @@ public class AttentionManagerService extends SystemService { /** DeviceConfig flag name, if {@code true}, enables AttentionManagerService features. */ private static final String SERVICE_ENABLED = "service_enabled"; - - /** DeviceConfig flag name, allows a CTS to inject a fake implementation. */ - private static final String COMPONENT_NAME = "component_name"; - private final Context mContext; private final PowerManager mPowerManager; private final Object mLock; @@ -246,6 +255,16 @@ public class AttentionManagerService extends SystemService { } } + /** Disables service dependants. */ + private void disableSelf() { + final long identity = Binder.clearCallingIdentity(); + try { + Settings.System.putInt(mContext.getContentResolver(), ADAPTIVE_SLEEP, 0); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + @GuardedBy("mLock") private void freeIfInactiveLocked() { // If we are called here, it means someone used the API again - reset the timer then. @@ -377,6 +396,11 @@ public class AttentionManagerService extends SystemService { public void cancelAttentionCheck(int requestCode) { AttentionManagerService.this.cancelAttentionCheck(requestCode); } + + @Override + public void disableSelf() { + AttentionManagerService.this.disableSelf(); + } } private static final class AttentionCheckCache { @@ -560,8 +584,8 @@ public class AttentionManagerService extends SystemService { } } - private void cancel(UserState userState, @AttentionFailureCodes int failureCode) { - if (userState != null && userState.mService != null) { + private void cancel(@NonNull UserState userState, @AttentionFailureCodes int failureCode) { + if (userState.mService != null) { try { userState.mService.cancelAttentionCheck( userState.mCurrentAttentionCheckRequestCode); @@ -578,6 +602,9 @@ public class AttentionManagerService extends SystemService { @GuardedBy("mLock") private void cancelAndUnbindLocked(UserState userState) { synchronized (mLock) { + if (userState == null) { + return; + } cancel(userState, AttentionService.ATTENTION_FAILURE_UNKNOWN); mContext.unbindService(userState.mConnection); diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index a14a638395db..93f7831e8886 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -78,6 +78,8 @@ import android.media.IPlaybackConfigDispatcher; import android.media.IRecordingConfigDispatcher; import android.media.IRingtonePlayer; import android.media.IVolumeController; +import android.media.MediaExtractor; +import android.media.MediaFormat; import android.media.MediaPlayer; import android.media.MediaPlayer.OnCompletionListener; import android.media.MediaPlayer.OnErrorListener; @@ -94,6 +96,7 @@ import android.media.audiopolicy.AudioVolumeGroups; import android.media.audiopolicy.IAudioPolicyCallback; import android.media.projection.IMediaProjection; import android.media.projection.IMediaProjectionManager; +import android.net.Uri; import android.os.Binder; import android.os.Build; import android.os.Bundle; @@ -4146,6 +4149,26 @@ public class AudioService extends IAudioService.Stub } } + /** + * See AudioManager.hasHapticChannels(Uri). + */ + public boolean hasHapticChannels(Uri uri) { + MediaExtractor extractor = new MediaExtractor(); + try { + extractor.setDataSource(mContext, uri, null); + for (int i = 0; i < extractor.getTrackCount(); i++) { + MediaFormat format = extractor.getTrackFormat(i); + if (format.containsKey(MediaFormat.KEY_HAPTIC_CHANNEL_COUNT) + && format.getInteger(MediaFormat.KEY_HAPTIC_CHANNEL_COUNT) > 0) { + return true; + } + } + } catch (IOException e) { + Log.e(TAG, "hasHapticChannels failure:" + e); + } + return false; + } + /////////////////////////////////////////////////////////////////////////// // Inner classes /////////////////////////////////////////////////////////////////////////// @@ -6290,8 +6313,8 @@ public class AudioService extends IAudioService.Stub // Audio policy management //========================================================================================== public String registerAudioPolicy(AudioPolicyConfig policyConfig, IAudioPolicyCallback pcb, - boolean hasFocusListener, boolean isFocusPolicy, boolean isVolumeController, - IMediaProjection projection) { + boolean hasFocusListener, boolean isFocusPolicy, boolean isTestFocusPolicy, + boolean isVolumeController, IMediaProjection projection) { AudioSystem.setDynamicPolicyCallback(mDynPolicyCallback); if (!isPolicyRegisterAllowed(policyConfig, projection)) { @@ -6312,7 +6335,7 @@ public class AudioService extends IAudioService.Stub return null; } AudioPolicyProxy app = new AudioPolicyProxy(policyConfig, pcb, hasFocusListener, - isFocusPolicy, isVolumeController); + isFocusPolicy, isTestFocusPolicy, isVolumeController); pcb.asBinder().linkToDeath(app, 0/*flags*/); regId = app.getRegistrationId(); mAudioPolicies.put(pcb.asBinder(), app); @@ -6730,9 +6753,11 @@ public class AudioService extends IAudioService.Stub */ int mFocusDuckBehavior = AudioPolicy.FOCUS_POLICY_DUCKING_DEFAULT; boolean mIsFocusPolicy = false; + boolean mIsTestFocusPolicy = false; AudioPolicyProxy(AudioPolicyConfig config, IAudioPolicyCallback token, - boolean hasFocusListener, boolean isFocusPolicy, boolean isVolumeController) { + boolean hasFocusListener, boolean isFocusPolicy, boolean isTestFocusPolicy, + boolean isVolumeController) { super(config); setRegistration(new String(config.hashCode() + ":ap:" + mAudioPolicyCounter++)); mPolicyCallback = token; @@ -6743,7 +6768,8 @@ public class AudioService extends IAudioService.Stub // can only ever be true if there is a focus listener if (isFocusPolicy) { mIsFocusPolicy = true; - mMediaFocusControl.setFocusPolicy(mPolicyCallback); + mIsTestFocusPolicy = isTestFocusPolicy; + mMediaFocusControl.setFocusPolicy(mPolicyCallback, mIsTestFocusPolicy); } } if (mIsVolumeController) { @@ -6771,7 +6797,7 @@ public class AudioService extends IAudioService.Stub void release() { if (mIsFocusPolicy) { - mMediaFocusControl.unsetFocusPolicy(mPolicyCallback); + mMediaFocusControl.unsetFocusPolicy(mPolicyCallback, mIsTestFocusPolicy); } if (mFocusDuckBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY) { mMediaFocusControl.setDuckingInExtPolicyAvailable(false); diff --git a/services/core/java/com/android/server/audio/MediaFocusControl.java b/services/core/java/com/android/server/audio/MediaFocusControl.java index d028e88fa160..1e58b454a15b 100644 --- a/services/core/java/com/android/server/audio/MediaFocusControl.java +++ b/services/core/java/com/android/server/audio/MediaFocusControl.java @@ -17,6 +17,7 @@ package com.android.server.audio; import android.annotation.NonNull; +import android.annotation.Nullable; import android.app.AppOpsManager; import android.content.Context; import android.media.AudioAttributes; @@ -458,7 +459,15 @@ public class MediaFocusControl implements PlayerFocusEnforcer { } } - private IAudioPolicyCallback mFocusPolicy = null; + /** The current audio focus policy */ + @GuardedBy("mAudioFocusLock") + @Nullable private IAudioPolicyCallback mFocusPolicy = null; + /** + * The audio focus policy that was registered before a test focus policy was registered + * during a test + */ + @GuardedBy("mAudioFocusLock") + @Nullable private IAudioPolicyCallback mPreviousFocusPolicy = null; // Since we don't have a stack of focus owners when using an external focus policy, we keep // track of all the focus requesters in this map, with their clientId as the key. This is @@ -466,22 +475,30 @@ public class MediaFocusControl implements PlayerFocusEnforcer { private HashMap<String, FocusRequester> mFocusOwnersForFocusPolicy = new HashMap<String, FocusRequester>(); - void setFocusPolicy(IAudioPolicyCallback policy) { + void setFocusPolicy(IAudioPolicyCallback policy, boolean isTestFocusPolicy) { if (policy == null) { return; } synchronized (mAudioFocusLock) { + if (isTestFocusPolicy) { + mPreviousFocusPolicy = mFocusPolicy; + } mFocusPolicy = policy; } } - void unsetFocusPolicy(IAudioPolicyCallback policy) { + void unsetFocusPolicy(IAudioPolicyCallback policy, boolean isTestFocusPolicy) { if (policy == null) { return; } synchronized (mAudioFocusLock) { if (mFocusPolicy == policy) { - mFocusPolicy = null; + if (isTestFocusPolicy) { + // restore the focus policy that was there before the focus policy test started + mFocusPolicy = mPreviousFocusPolicy; + } else { + mFocusPolicy = null; + } } } } diff --git a/services/core/java/com/android/server/connectivity/DefaultNetworkMetrics.java b/services/core/java/com/android/server/connectivity/DefaultNetworkMetrics.java index e43d1526f760..96a202fa2b10 100644 --- a/services/core/java/com/android/server/connectivity/DefaultNetworkMetrics.java +++ b/services/core/java/com/android/server/connectivity/DefaultNetworkMetrics.java @@ -163,8 +163,8 @@ public class DefaultNetworkMetrics { LinkProperties lp = nai.linkProperties; ev.netId = nai.network().netId; ev.transports |= BitUtils.packBits(nai.networkCapabilities.getTransportTypes()); - ev.ipv4 |= lp.hasIPv4Address() && lp.hasIPv4DefaultRoute(); - ev.ipv6 |= lp.hasGlobalIPv6Address() && lp.hasIPv6DefaultRoute(); + ev.ipv4 |= lp.hasIpv4Address() && lp.hasIpv4DefaultRoute(); + ev.ipv6 |= lp.hasGlobalIpv6Address() && lp.hasIpv6DefaultRoute(); } private static void printEvent(long localTimeMs, PrintWriter pw, DefaultNetworkEvent ev) { diff --git a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java index 35d6860080d1..0e3d82c0a660 100644 --- a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java +++ b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java @@ -42,7 +42,6 @@ import android.net.NetworkUtils; import android.net.SocketKeepalive.InvalidPacketException; import android.net.SocketKeepalive.InvalidSocketException; import android.net.TcpKeepalivePacketData; -import android.net.TcpKeepalivePacketData.TcpSocketInfo; import android.net.util.IpUtils; import android.os.Binder; import android.os.Handler; @@ -492,19 +491,14 @@ public class KeepaliveTracker { return; } - TcpKeepalivePacketData packet = null; + final TcpKeepalivePacketData packet; try { - TcpSocketInfo tsi = TcpKeepaliveController.switchToRepairMode(fd); - packet = TcpKeepalivePacketData.tcpKeepalivePacket(tsi); + packet = TcpKeepaliveController.getTcpKeepalivePacket(fd); } catch (InvalidPacketException | InvalidSocketException e) { - try { - TcpKeepaliveController.switchOutOfRepairMode(fd); - } catch (ErrnoException e1) { - Log.e(TAG, "Couldn't move fd out of repair mode after failure to start keepalive"); - } notifyErrorCallback(cb, e.error); return; } + KeepaliveInfo ki = new KeepaliveInfo(cb, nai, packet, intervalSeconds, KeepaliveInfo.TYPE_TCP, fd); Log.d(TAG, "Created keepalive: " + ki.toString()); diff --git a/services/core/java/com/android/server/connectivity/Nat464Xlat.java b/services/core/java/com/android/server/connectivity/Nat464Xlat.java index 2646d7669d79..262ba7a475bb 100644 --- a/services/core/java/com/android/server/connectivity/Nat464Xlat.java +++ b/services/core/java/com/android/server/connectivity/Nat464Xlat.java @@ -107,8 +107,8 @@ public class Nat464Xlat extends BaseNetworkObserver { // Only run clat on networks that have a global IPv6 address and don't have a native IPv4 // address. LinkProperties lp = nai.linkProperties; - final boolean isIpv6OnlyNetwork = (lp != null) && lp.hasGlobalIPv6Address() - && !lp.hasIPv4Address(); + final boolean isIpv6OnlyNetwork = (lp != null) && lp.hasGlobalIpv6Address() + && !lp.hasIpv4Address(); // If the network tells us it doesn't use clat, respect that. final boolean skip464xlat = (nai.netMisc() != null) && nai.netMisc().skip464xlat; diff --git a/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java b/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java index c471f0caa3cc..948c690956d3 100644 --- a/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java +++ b/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java @@ -34,10 +34,12 @@ import android.util.Pair; import com.android.internal.util.IndentingPrintWriter; +import libcore.io.IoUtils; + import java.io.Closeable; import java.io.FileDescriptor; -import java.io.InterruptedIOException; import java.io.IOException; +import java.io.InterruptedIOException; import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; @@ -48,17 +50,13 @@ import java.net.SocketException; import java.net.UnknownHostException; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.Arrays; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Random; - -import libcore.io.IoUtils; - +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; /** * NetworkDiagnostics @@ -186,7 +184,7 @@ public class NetworkDiagnostics { // TODO: we could use mLinkProperties.isReachable(TEST_DNS6) here, because we won't set any // DNS servers for which isReachable() is false, but since this is diagnostic code, be extra // careful. - if (mLinkProperties.hasGlobalIPv6Address() || mLinkProperties.hasIPv6DefaultRoute()) { + if (mLinkProperties.hasGlobalIpv6Address() || mLinkProperties.hasIpv6DefaultRoute()) { mLinkProperties.addDnsServer(TEST_DNS6); } diff --git a/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java b/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java index 3e21b5b15ea1..f4d9006a7068 100644 --- a/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java +++ b/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java @@ -28,8 +28,10 @@ import static android.system.OsConstants.TIOCOUTQ; import android.annotation.NonNull; import android.net.NetworkUtils; +import android.net.SocketKeepalive.InvalidPacketException; import android.net.SocketKeepalive.InvalidSocketException; -import android.net.TcpKeepalivePacketData.TcpSocketInfo; +import android.net.TcpKeepalivePacketData; +import android.net.TcpKeepalivePacketDataParcelable; import android.net.TcpRepairWindow; import android.os.Handler; import android.os.MessageQueue; @@ -44,7 +46,6 @@ import com.android.internal.annotations.GuardedBy; import com.android.server.connectivity.KeepaliveTracker.KeepaliveInfo; import java.io.FileDescriptor; -import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.net.SocketException; @@ -103,26 +104,30 @@ public class TcpKeepaliveController { mFdHandlerQueue = connectivityServiceHandler.getLooper().getQueue(); } + /** Build tcp keepalive packet. */ + public static TcpKeepalivePacketData getTcpKeepalivePacket(@NonNull FileDescriptor fd) + throws InvalidPacketException, InvalidSocketException { + try { + final TcpKeepalivePacketDataParcelable tcpDetails = switchToRepairMode(fd); + return TcpKeepalivePacketData.tcpKeepalivePacket(tcpDetails); + } catch (InvalidPacketException | InvalidSocketException e) { + switchOutOfRepairMode(fd); + throw e; + } + } /** - * Switch the tcp socket to repair mode and query tcp socket information. + * Switch the tcp socket to repair mode and query detail tcp information. * - * @param fd the fd of socket on which to use keepalive offload - * @return a {@link TcpKeepalivePacketData#TcpSocketInfo} object for current + * @param fd the fd of socket on which to use keepalive offload. + * @return a {@link TcpKeepalivePacketData#TcpKeepalivePacketDataParcelable} object for current * tcp/ip information. */ - // TODO : make this private. It's far too confusing that this gets called from outside - // at a time that nobody can understand. - public static TcpSocketInfo switchToRepairMode(FileDescriptor fd) + private static TcpKeepalivePacketDataParcelable switchToRepairMode(FileDescriptor fd) throws InvalidSocketException { if (DBG) Log.i(TAG, "switchToRepairMode to start tcp keepalive : " + fd); + final TcpKeepalivePacketDataParcelable tcpDetails = new TcpKeepalivePacketDataParcelable(); final SocketAddress srcSockAddr; final SocketAddress dstSockAddr; - final InetAddress srcAddress; - final InetAddress dstAddress; - final int srcPort; - final int dstPort; - int seq; - final int ack; final TcpRepairWindow trw; // Query source address and port. @@ -133,8 +138,8 @@ public class TcpKeepaliveController { throw new InvalidSocketException(ERROR_INVALID_SOCKET, e); } if (srcSockAddr instanceof InetSocketAddress) { - srcAddress = getAddress((InetSocketAddress) srcSockAddr); - srcPort = getPort((InetSocketAddress) srcSockAddr); + tcpDetails.srcAddress = getAddress((InetSocketAddress) srcSockAddr); + tcpDetails.srcPort = getPort((InetSocketAddress) srcSockAddr); } else { Log.e(TAG, "Invalid or mismatched SocketAddress"); throw new InvalidSocketException(ERROR_INVALID_SOCKET); @@ -147,8 +152,8 @@ public class TcpKeepaliveController { throw new InvalidSocketException(ERROR_INVALID_SOCKET, e); } if (dstSockAddr instanceof InetSocketAddress) { - dstAddress = getAddress((InetSocketAddress) dstSockAddr); - dstPort = getPort((InetSocketAddress) dstSockAddr); + tcpDetails.dstAddress = getAddress((InetSocketAddress) dstSockAddr); + tcpDetails.dstPort = getPort((InetSocketAddress) dstSockAddr); } else { Log.e(TAG, "Invalid or mismatched peer SocketAddress"); throw new InvalidSocketException(ERROR_INVALID_SOCKET); @@ -157,28 +162,37 @@ public class TcpKeepaliveController { // Query sequence and ack number dropAllIncomingPackets(fd, true); try { - // Enter tcp repair mode. + // Switch to tcp repair mode. Os.setsockoptInt(fd, IPPROTO_TCP, TCP_REPAIR, TCP_REPAIR_ON); + // Check if socket is idle. if (!isSocketIdle(fd)) { + Log.e(TAG, "Socket is not idle"); throw new InvalidSocketException(ERROR_SOCKET_NOT_IDLE); } // Query write sequence number from SEND_QUEUE. Os.setsockoptInt(fd, IPPROTO_TCP, TCP_REPAIR_QUEUE, TCP_SEND_QUEUE); - seq = Os.getsockoptInt(fd, IPPROTO_TCP, TCP_QUEUE_SEQ); + tcpDetails.seq = Os.getsockoptInt(fd, IPPROTO_TCP, TCP_QUEUE_SEQ); // Query read sequence number from RECV_QUEUE. Os.setsockoptInt(fd, IPPROTO_TCP, TCP_REPAIR_QUEUE, TCP_RECV_QUEUE); - ack = Os.getsockoptInt(fd, IPPROTO_TCP, TCP_QUEUE_SEQ); + tcpDetails.ack = Os.getsockoptInt(fd, IPPROTO_TCP, TCP_QUEUE_SEQ); // Switch to NO_QUEUE to prevent illegal socket read/write in repair mode. Os.setsockoptInt(fd, IPPROTO_TCP, TCP_REPAIR_QUEUE, TCP_NO_QUEUE); // Finally, check if socket is still idle. TODO : this check needs to move to // after starting polling to prevent a race. - if (!isSocketIdle(fd)) { + if (!isReceiveQueueEmpty(fd)) { + Log.e(TAG, "Fatal: receive queue of this socket is not empty"); throw new InvalidSocketException(ERROR_INVALID_SOCKET); } + if (!isSendQueueEmpty(fd)) { + Log.e(TAG, "Socket is not idle"); + throw new InvalidSocketException(ERROR_SOCKET_NOT_IDLE); + } // Query tcp window size. trw = NetworkUtils.getTcpRepairWindow(fd); + tcpDetails.rcvWnd = trw.rcvWnd; + tcpDetails.rcvWndScale = trw.rcvWndScale; } catch (ErrnoException e) { Log.e(TAG, "Exception reading TCP state from socket", e); if (e.errno == ENOPROTOOPT) { @@ -194,10 +208,9 @@ public class TcpKeepaliveController { // Keepalive sequence number is last sequence number - 1. If it couldn't be retrieved, // then it must be set to -1, so decrement in all cases. - seq = seq - 1; + tcpDetails.seq = tcpDetails.seq - 1; - return new TcpSocketInfo(srcAddress, srcPort, dstAddress, dstPort, seq, ack, trw.rcvWnd, - trw.rcvWndScale); + return tcpDetails; } /** @@ -205,10 +218,13 @@ public class TcpKeepaliveController { * * @param fd the fd of socket to switch back to normal. */ - // TODO : make this private. - public static void switchOutOfRepairMode(@NonNull final FileDescriptor fd) - throws ErrnoException { - Os.setsockoptInt(fd, IPPROTO_TCP, TCP_REPAIR, TCP_REPAIR_OFF); + private static void switchOutOfRepairMode(@NonNull final FileDescriptor fd) { + try { + Os.setsockoptInt(fd, IPPROTO_TCP, TCP_REPAIR, TCP_REPAIR_OFF); + } catch (ErrnoException e) { + Log.e(TAG, "Cannot switch socket out of repair mode", e); + // Well, there is not much to do here to recover + } } /** @@ -262,17 +278,12 @@ public class TcpKeepaliveController { mListeners.remove(slot); } mFdHandlerQueue.removeOnFileDescriptorEventListener(fd); - try { - if (DBG) Log.d(TAG, "Moving socket out of repair mode for stop : " + fd); - switchOutOfRepairMode(fd); - } catch (ErrnoException e) { - Log.e(TAG, "Cannot switch socket out of repair mode", e); - // Well, there is not much to do here to recover - } + if (DBG) Log.d(TAG, "Moving socket out of repair mode for stop : " + fd); + switchOutOfRepairMode(fd); } - private static InetAddress getAddress(InetSocketAddress inetAddr) { - return inetAddr.getAddress(); + private static byte [] getAddress(InetSocketAddress inetAddr) { + return inetAddr.getAddress().getAddress(); } private static int getPort(InetSocketAddress inetAddr) { diff --git a/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java b/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java index 100014898127..38eb0bcfd3cc 100644 --- a/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java +++ b/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java @@ -17,7 +17,6 @@ package com.android.server.connectivity.tethering; import android.net.ConnectivityManager; -import android.net.ip.IpServer; import android.net.IpPrefix; import android.net.LinkAddress; import android.net.LinkProperties; @@ -25,6 +24,7 @@ import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkState; import android.net.RouteInfo; +import android.net.ip.IpServer; import android.net.util.NetworkConstants; import android.net.util.SharedLog; import android.util.Log; @@ -191,7 +191,7 @@ public class IPv6TetheringCoordinator { if (currentActive != null && currentActive.ipServer == ipServer) { final LinkProperties lp = getIPv6OnlyLinkProperties( mUpstreamNetworkState.linkProperties); - if (lp.hasIPv6DefaultRoute() && lp.hasGlobalIPv6Address()) { + if (lp.hasIpv6DefaultRoute() && lp.hasGlobalIpv6Address()) { return lp; } } diff --git a/services/core/java/com/android/server/connectivity/tethering/TetheringInterfaceUtils.java b/services/core/java/com/android/server/connectivity/tethering/TetheringInterfaceUtils.java index 6c7ff91761ac..0ef3805ff7c0 100644 --- a/services/core/java/com/android/server/connectivity/tethering/TetheringInterfaceUtils.java +++ b/services/core/java/com/android/server/connectivity/tethering/TetheringInterfaceUtils.java @@ -67,14 +67,14 @@ public final class TetheringInterfaceUtils { // because "[t]he 3GPP network allocates each default bearer a unique // /64 prefix", per RFC 6459, Section 5.2. final boolean canTether = - (ns != null) && (ns.network != null) && - (ns.linkProperties != null) && (ns.networkCapabilities != null) && + (ns != null) && (ns.network != null) + && (ns.linkProperties != null) && (ns.networkCapabilities != null) // At least one upstream DNS server: - ns.linkProperties.hasIPv6DnsServer() && + && ns.linkProperties.hasIpv6DnsServer() // Minimal amount of IPv6 provisioning: - ns.linkProperties.hasGlobalIPv6Address() && + && ns.linkProperties.hasGlobalIpv6Address() // Temporary approximation of "dedicated prefix": - ns.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR); + && ns.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR); return canTether ? getInterfaceForDestination(ns.linkProperties, Inet6Address.ANY) diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java index b79ead05c074..e2ea42e51d04 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController.java +++ b/services/core/java/com/android/server/display/DisplayPowerController.java @@ -34,6 +34,7 @@ import android.hardware.display.BrightnessChangeEvent; import android.hardware.display.BrightnessConfiguration; import android.hardware.display.DisplayManagerInternal.DisplayPowerCallbacks; import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest; +import android.metrics.LogMaker; import android.net.Uri; import android.os.Handler; import android.os.Looper; @@ -51,6 +52,8 @@ import android.util.TimeUtils; import android.view.Display; import com.android.internal.app.IBatteryStats; +import com.android.internal.logging.MetricsLogger; +import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.server.LocalServices; import com.android.server.am.BatteryStatsService; import com.android.server.display.whitebalance.DisplayWhiteBalanceController; @@ -731,6 +734,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call private void updatePowerState() { // Update the power state request. final boolean mustNotify; + final int previousPolicy; boolean mustInitialize = false; synchronized (mLock) { @@ -745,12 +749,18 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call mPendingWaitForNegativeProximityLocked = false; mPendingRequestChangedLocked = false; mustInitialize = true; + // Assume we're on and bright until told otherwise, since that's the state we turn + // on in. + previousPolicy = DisplayPowerRequest.POLICY_BRIGHT; } else if (mPendingRequestChangedLocked) { + previousPolicy = mPowerRequest.policy; mPowerRequest.copyFrom(mPendingRequestLocked); mWaitingForNegativeProximity |= mPendingWaitForNegativeProximityLocked; mPendingWaitForNegativeProximityLocked = false; mPendingRequestChangedLocked = false; mDisplayReadyLocked = false; + } else { + previousPolicy = mPowerRequest.policy; } mustNotify = !mDisplayReadyLocked; @@ -1103,6 +1113,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call // Record if dozing for future comparison. mDozing = state != Display.STATE_ON; + + if (previousPolicy != mPowerRequest.policy) { + logDisplayPolicyChanged(mPowerRequest.policy); + } } @Override @@ -1523,6 +1537,13 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call mHandler.post(mOnStateChangedRunnable); } + private void logDisplayPolicyChanged(int newPolicy) { + LogMaker log = new LogMaker(MetricsEvent.DISPLAY_POLICY); + log.setType(MetricsEvent.TYPE_UPDATE); + log.setSubtype(newPolicy); + MetricsLogger.action(log); + } + private void handleSettingsChange(boolean userSwitch) { mPendingScreenBrightnessSetting = getScreenBrightnessSetting(); if (userSwitch) { diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java index 293813add594..3e134b266a88 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsService.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java @@ -21,6 +21,9 @@ import static android.Manifest.permission.READ_CONTACTS; import static android.content.Context.KEYGUARD_SERVICE; import static android.content.pm.PackageManager.PERMISSION_GRANTED; +import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE; +import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD; +import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PATTERN; import static com.android.internal.widget.LockPatternUtils.EscrowTokenStateChangeCallback; import static com.android.internal.widget.LockPatternUtils.SYNTHETIC_PASSWORD_ENABLED_KEY; import static com.android.internal.widget.LockPatternUtils.SYNTHETIC_PASSWORD_HANDLE_KEY; @@ -106,6 +109,7 @@ import com.android.internal.util.Preconditions; import com.android.internal.widget.ICheckCredentialProgressCallback; import com.android.internal.widget.ILockSettings; import com.android.internal.widget.LockPatternUtils; +import com.android.internal.widget.LockPatternUtils.CredentialType; import com.android.internal.widget.LockSettingsInternal; import com.android.internal.widget.VerifyCredentialResponse; import com.android.server.LocalServices; @@ -319,8 +323,8 @@ public class LockSettingsService extends ILockSettings.Stub { } Arrays.fill(newPasswordChars, '\u0000'); final int quality = DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC; - setLockCredentialInternal(newPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, - managedUserPassword, quality, managedUserId); + setLockCredentialInternal(newPassword, CREDENTIAL_TYPE_PASSWORD, managedUserPassword, + quality, managedUserId, false); // We store a private credential for the managed user that's unlocked by the primary // account holder's credential. As such, the user will never be prompted to enter this // password directly, so we always store a password. @@ -1082,13 +1086,12 @@ public class LockSettingsService extends ILockSettings.Stub { } @Override - public boolean havePassword(int userId) throws RemoteException { + public boolean havePassword(int userId) { checkPasswordHavePermission(userId); synchronized (mSpManager) { if (isSyntheticPasswordBasedCredentialLocked(userId)) { - long handle = getSyntheticPasswordHandleLocked(userId); - return mSpManager.getCredentialType(handle, userId) == - LockPatternUtils.CREDENTIAL_TYPE_PASSWORD; + final long handle = getSyntheticPasswordHandleLocked(userId); + return mSpManager.getCredentialType(handle, userId) == CREDENTIAL_TYPE_PASSWORD; } } // Do we need a permissions check here? @@ -1096,13 +1099,12 @@ public class LockSettingsService extends ILockSettings.Stub { } @Override - public boolean havePattern(int userId) throws RemoteException { + public boolean havePattern(int userId) { checkPasswordHavePermission(userId); synchronized (mSpManager) { if (isSyntheticPasswordBasedCredentialLocked(userId)) { - long handle = getSyntheticPasswordHandleLocked(userId); - return mSpManager.getCredentialType(handle, userId) == - LockPatternUtils.CREDENTIAL_TYPE_PATTERN; + final long handle = getSyntheticPasswordHandleLocked(userId); + return mSpManager.getCredentialType(handle, userId) == CREDENTIAL_TYPE_PATTERN; } } // Do we need a permissions check here? @@ -1112,9 +1114,8 @@ public class LockSettingsService extends ILockSettings.Stub { private boolean isUserSecure(int userId) { synchronized (mSpManager) { if (isSyntheticPasswordBasedCredentialLocked(userId)) { - long handle = getSyntheticPasswordHandleLocked(userId); - return mSpManager.getCredentialType(handle, userId) != - LockPatternUtils.CREDENTIAL_TYPE_NONE; + final long handle = getSyntheticPasswordHandleLocked(userId); + return mSpManager.getCredentialType(handle, userId) != CREDENTIAL_TYPE_NONE; } } return mStorage.hasCredential(userId); @@ -1167,7 +1168,7 @@ public class LockSettingsService extends ILockSettings.Stub { throws RemoteException { try { doVerifyCredential(getDecryptedPasswordForTiedProfile(profileHandle), - LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, + CREDENTIAL_TYPE_PASSWORD, false, 0 /* no challenge */, profileHandle, null /* progressCallback */); } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException | NoSuchAlgorithmException | NoSuchPaddingException @@ -1299,14 +1300,16 @@ public class LockSettingsService extends ILockSettings.Stub { // We use cached work profile password computed before clearing the parent's // credential, otherwise they get lost if (profilePasswordMap != null && profilePasswordMap.containsKey(managedUserId)) { - setLockCredentialInternal(null, LockPatternUtils.CREDENTIAL_TYPE_NONE, + setLockCredentialInternal(null, CREDENTIAL_TYPE_NONE, profilePasswordMap.get(managedUserId), - DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, managedUserId); + DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, managedUserId, + false); } else { Slog.wtf(TAG, "clear tied profile challenges, but no password supplied."); // Supplying null here would lead to untrusted credential change - setLockCredentialInternal(null, LockPatternUtils.CREDENTIAL_TYPE_NONE, null, - DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, managedUserId); + setLockCredentialInternal(null, CREDENTIAL_TYPE_NONE, null, + DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, managedUserId, + true); } mStorage.removeChildProfileLock(managedUserId); removeKeystoreProfileKey(managedUserId); @@ -1329,8 +1332,8 @@ public class LockSettingsService extends ILockSettings.Stub { // should call setLockCredentialInternal. @Override public void setLockCredential(byte[] credential, int type, - byte[] savedCredential, int requestedQuality, int userId) - throws RemoteException { + byte[] savedCredential, int requestedQuality, int userId, + boolean allowUntrustedChange) throws RemoteException { if (!mLockPatternUtils.hasSecureLockScreen()) { throw new UnsupportedOperationException( @@ -1338,15 +1341,17 @@ public class LockSettingsService extends ILockSettings.Stub { } checkWritePermission(userId); synchronized (mSeparateChallengeLock) { - setLockCredentialInternal(credential, type, savedCredential, requestedQuality, userId); + setLockCredentialInternal(credential, type, savedCredential, requestedQuality, userId, + allowUntrustedChange); setSeparateProfileChallengeEnabledLocked(userId, true, null); notifyPasswordChanged(userId); } notifySeparateProfileChallengeChanged(userId); } - private void setLockCredentialInternal(byte[] credential, int credentialType, - byte[] savedCredential, int requestedQuality, int userId) throws RemoteException { + private void setLockCredentialInternal(byte[] credential, @CredentialType int credentialType, + byte[] savedCredential, int requestedQuality, int userId, + boolean allowUntrustedChange) throws RemoteException { // Normalize savedCredential and credential such that empty string is always represented // as null. if (savedCredential == null || savedCredential.length == 0) { @@ -1358,12 +1363,12 @@ public class LockSettingsService extends ILockSettings.Stub { synchronized (mSpManager) { if (isSyntheticPasswordBasedCredentialLocked(userId)) { spBasedSetLockCredentialInternalLocked(credential, credentialType, savedCredential, - requestedQuality, userId); + requestedQuality, userId, allowUntrustedChange); return; } } - if (credentialType == LockPatternUtils.CREDENTIAL_TYPE_NONE) { + if (credentialType == CREDENTIAL_TYPE_NONE) { if (credential != null) { Slog.wtf(TAG, "CredentialType is none, but credential is non-null."); } @@ -1373,7 +1378,7 @@ public class LockSettingsService extends ILockSettings.Stub { setKeystorePassword(null, userId); fixateNewestUserKeyAuth(userId); synchronizeUnifiedWorkChallengeForProfiles(userId, null); - notifyActivePasswordMetricsAvailable(null, userId); + notifyActivePasswordMetricsAvailable(CREDENTIAL_TYPE_NONE, null, userId); mRecoverableKeyStoreManager.lockScreenSecretChanged(credentialType, credential, userId); return; } @@ -1409,7 +1414,7 @@ public class LockSettingsService extends ILockSettings.Stub { initializeSyntheticPasswordLocked(currentHandle.hash, savedCredential, currentHandle.type, requestedQuality, userId); spBasedSetLockCredentialInternalLocked(credential, credentialType, savedCredential, - requestedQuality, userId); + requestedQuality, userId, allowUntrustedChange); return; } } @@ -1431,8 +1436,7 @@ public class LockSettingsService extends ILockSettings.Stub { userId); } else { throw new RemoteException("Failed to enroll " + - (credentialType == LockPatternUtils.CREDENTIAL_TYPE_PASSWORD ? "password" - : "pattern")); + (credentialType == CREDENTIAL_TYPE_PASSWORD ? "password" : "pattern")); } } @@ -1688,7 +1692,7 @@ public class LockSettingsService extends ILockSettings.Stub { return VerifyCredentialResponse.ERROR; } - boolean shouldReEnrollBaseZero = storedHash.type == LockPatternUtils.CREDENTIAL_TYPE_PATTERN + boolean shouldReEnrollBaseZero = storedHash.type == CREDENTIAL_TYPE_PATTERN && storedHash.isBaseZeroPattern; byte[] credentialToVerify; @@ -1705,7 +1709,7 @@ public class LockSettingsService extends ILockSettings.Stub { mStrongAuth.reportSuccessfulStrongAuthUnlock(userId); if (shouldReEnrollBaseZero) { setLockCredentialInternal(credential, storedHash.type, credentialToVerify, - DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, userId); + DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, userId, false); } } @@ -1736,7 +1740,7 @@ public class LockSettingsService extends ILockSettings.Stub { try { // Unlock work profile, and work profile with unified lock must use password only return doVerifyCredential(getDecryptedPasswordForTiedProfile(userId), - LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, + CREDENTIAL_TYPE_PASSWORD, true, challenge, userId, null /* progressCallback */); @@ -1773,14 +1777,14 @@ public class LockSettingsService extends ILockSettings.Stub { if (storedHash.version == CredentialHash.VERSION_LEGACY) { final byte[] hash; - if (storedHash.type == LockPatternUtils.CREDENTIAL_TYPE_PATTERN) { + if (storedHash.type == CREDENTIAL_TYPE_PATTERN) { hash = LockPatternUtils.patternToHash( LockPatternUtils.byteArrayToPattern(credential)); } else { hash = mLockPatternUtils.legacyPasswordToHash(credential, userId).getBytes(); } if (Arrays.equals(hash, storedHash.hash)) { - if (storedHash.type == LockPatternUtils.CREDENTIAL_TYPE_PATTERN) { + if (storedHash.type == CREDENTIAL_TYPE_PATTERN) { unlockKeystore(LockPatternUtils.patternByteArrayToBaseZero(credential), userId); } else { unlockKeystore(credential, userId); @@ -1793,12 +1797,12 @@ public class LockSettingsService extends ILockSettings.Stub { // migrate credential to GateKeeper setLockCredentialInternal(credential, storedHash.type, null, - storedHash.type == LockPatternUtils.CREDENTIAL_TYPE_PATTERN + storedHash.type == CREDENTIAL_TYPE_PATTERN ? DevicePolicyManager.PASSWORD_QUALITY_SOMETHING : DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC - /* TODO(roosa): keep the same password quality */, userId); + /* TODO(roosa): keep the same password quality */, userId, false); if (!hasChallenge) { - notifyActivePasswordMetricsAvailable(credential, userId); + notifyActivePasswordMetricsAvailable(storedHash.type, credential, userId); // Use credentials to create recoverable keystore snapshot. mRecoverableKeyStoreManager.lockScreenSecretAvailable( storedHash.type, credential, userId); @@ -1823,7 +1827,7 @@ public class LockSettingsService extends ILockSettings.Stub { if (progressCallback != null) { progressCallback.onCredentialVerified(); } - notifyActivePasswordMetricsAvailable(credential, userId); + notifyActivePasswordMetricsAvailable(storedHash.type, credential, userId); unlockKeystore(credential, userId); Slog.i(TAG, "Unlocking user " + userId + " with token length " @@ -1835,13 +1839,13 @@ public class LockSettingsService extends ILockSettings.Stub { (TrustManager) mContext.getSystemService(Context.TRUST_SERVICE); trustManager.setDeviceLockedForUser(userId, false); } - int reEnrollQuality = storedHash.type == LockPatternUtils.CREDENTIAL_TYPE_PATTERN + int reEnrollQuality = storedHash.type == CREDENTIAL_TYPE_PATTERN ? DevicePolicyManager.PASSWORD_QUALITY_SOMETHING : DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC /* TODO(roosa): keep the same password quality */; if (shouldReEnroll) { setLockCredentialInternal(credential, storedHash.type, credential, - reEnrollQuality, userId); + reEnrollQuality, userId, false); } else { // Now that we've cleared of all required GK migration, let's do the final // migration to synthetic password. @@ -1871,18 +1875,14 @@ public class LockSettingsService extends ILockSettings.Stub { * Call this method to notify DPMS regarding the latest password metric. This should be called * when the user is authenticating or when a new password is being set. */ - private void notifyActivePasswordMetricsAvailable(byte[] password, @UserIdInt int userId) { - final PasswordMetrics metrics; - if (password == null) { - metrics = new PasswordMetrics(); - } else { - metrics = PasswordMetrics.computeForPassword(password); - metrics.quality = mLockPatternUtils.getKeyguardStoredPasswordQuality(userId); - } + private void notifyActivePasswordMetricsAvailable( + @CredentialType int credentialType, byte[] password, @UserIdInt int userId) { + final PasswordMetrics metrics = + PasswordMetrics.computeForCredential(credentialType, password); // Asynchronous to avoid dead lock mHandler.post(() -> { - DevicePolicyManager dpm = (DevicePolicyManager) + final DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); dpm.setActivePasswordState(metrics, userId); }); @@ -1935,7 +1935,7 @@ public class LockSettingsService extends ILockSettings.Stub { try { if (mLockPatternUtils.isLockPatternEnabled(userId)) { - if (checkCredential(password.getBytes(), LockPatternUtils.CREDENTIAL_TYPE_PATTERN, + if (checkCredential(password.getBytes(), CREDENTIAL_TYPE_PATTERN, userId, null /* progressCallback */) .getResponseCode() == GateKeeperResponse.RESPONSE_OK) { return true; @@ -1946,7 +1946,7 @@ public class LockSettingsService extends ILockSettings.Stub { try { if (mLockPatternUtils.isLockPasswordEnabled(userId)) { - if (checkCredential(password.getBytes(), LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, + if (checkCredential(password.getBytes(), CREDENTIAL_TYPE_PASSWORD, userId, null /* progressCallback */) .getResponseCode() == GateKeeperResponse.RESPONSE_OK) { return true; @@ -2392,11 +2392,11 @@ public class LockSettingsService extends ILockSettings.Stub { setLong(SYNTHETIC_PASSWORD_ENABLED_KEY, 1, UserHandle.USER_SYSTEM); } - private VerifyCredentialResponse spBasedDoVerifyCredential(byte[] userCredential, int - credentialType, boolean hasChallenge, long challenge, int userId, + private VerifyCredentialResponse spBasedDoVerifyCredential(byte[] userCredential, + @CredentialType int credentialType, boolean hasChallenge, long challenge, int userId, ICheckCredentialProgressCallback progressCallback) throws RemoteException { if (DEBUG) Slog.d(TAG, "spBasedDoVerifyCredential: user=" + userId); - if (credentialType == LockPatternUtils.CREDENTIAL_TYPE_NONE) { + if (credentialType == CREDENTIAL_TYPE_NONE) { userCredential = null; } @@ -2444,7 +2444,7 @@ public class LockSettingsService extends ILockSettings.Stub { } if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) { - notifyActivePasswordMetricsAvailable(userCredential, userId); + notifyActivePasswordMetricsAvailable(credentialType, userCredential, userId); unlockKeystore(authResult.authToken.deriveKeyStorePassword(), userId); // Reset lockout if (mInjector.hasBiometrics()) { @@ -2491,8 +2491,9 @@ public class LockSettingsService extends ILockSettings.Stub { * added back when new password is set in future. */ @GuardedBy("mSpManager") - private long setLockCredentialWithAuthTokenLocked(byte[] credential, int credentialType, - AuthenticationToken auth, int requestedQuality, int userId) throws RemoteException { + private long setLockCredentialWithAuthTokenLocked(byte[] credential, + @CredentialType int credentialType, AuthenticationToken auth, int requestedQuality, + int userId) throws RemoteException { if (DEBUG) Slog.d(TAG, "setLockCredentialWithAuthTokenLocked: user=" + userId); long newHandle = mSpManager.createPasswordBasedSyntheticPassword(getGateKeeperService(), credential, credentialType, auth, requestedQuality, userId); @@ -2534,7 +2535,7 @@ public class LockSettingsService extends ILockSettings.Stub { setLong(SYNTHETIC_PASSWORD_HANDLE_KEY, newHandle, userId); synchronizeUnifiedWorkChallengeForProfiles(userId, profilePasswords); - notifyActivePasswordMetricsAvailable(credential, userId); + notifyActivePasswordMetricsAvailable(credentialType, credential, userId); if (profilePasswords != null) { for (Map.Entry<Integer, byte[]> entry : profilePasswords.entrySet()) { @@ -2547,7 +2548,8 @@ public class LockSettingsService extends ILockSettings.Stub { @GuardedBy("mSpManager") private void spBasedSetLockCredentialInternalLocked(byte[] credential, int credentialType, - byte[] savedCredential, int requestedQuality, int userId) throws RemoteException { + byte[] savedCredential, int requestedQuality, int userId, + boolean allowUntrustedChange) throws RemoteException { if (DEBUG) Slog.d(TAG, "spBasedSetLockCredentialInternalLocked: user=" + userId); if (isManagedProfileWithUnifiedLock(userId)) { // get credential from keystore when managed profile has unified lock @@ -2568,28 +2570,31 @@ public class LockSettingsService extends ILockSettings.Stub { VerifyCredentialResponse response = authResult.gkResponse; AuthenticationToken auth = authResult.authToken; - // If existing credential is provided, then it must match. + // If existing credential is provided, the existing credential must match. if (savedCredential != null && auth == null) { - throw new RemoteException("Failed to enroll " + - (credentialType == LockPatternUtils.CREDENTIAL_TYPE_PASSWORD ? "password" - : "pattern")); + throw new IllegalStateException("Failed to enroll " + + (credentialType == CREDENTIAL_TYPE_PASSWORD + ? "password" : "pattern")); } - boolean untrustedReset = false; if (auth != null) { onAuthTokenKnownForUser(userId, auth); - } else if (response != null - && response.getResponseCode() == VerifyCredentialResponse.RESPONSE_ERROR) { + } else if (response == null) { + throw new IllegalStateException("Password change failed."); + } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_ERROR) { // We are performing an untrusted credential change, by DevicePolicyManager or other // internal callers that don't provide the existing credential Slog.w(TAG, "Untrusted credential change invoked"); // Try to get a cached auth token, so we can keep SP unchanged. auth = mSpCache.get(userId); + if (!allowUntrustedChange) { + throw new IllegalStateException("Untrusted credential change was invoked but it was" + + " not allowed. This is likely a bug. Auth token is null: " + + Boolean.toString(auth == null)); + } untrustedReset = true; - } else /* response == null || responseCode == VerifyCredentialResponse.RESPONSE_RETRY */ { - Slog.w(TAG, "spBasedSetLockCredentialInternalLocked: " + - (response != null ? "rate limit exceeded" : "failed")); - return; + } else /* responseCode == VerifyCredentialResponse.RESPONSE_RETRY */ { + throw new IllegalStateException("Rate limit exceeded, so password was not changed."); } if (auth != null) { @@ -2660,7 +2665,7 @@ public class LockSettingsService extends ILockSettings.Stub { if (!isUserSecure(userId)) { if (shouldMigrateToSyntheticPasswordLocked(userId)) { auth = initializeSyntheticPasswordLocked(null, null, - LockPatternUtils.CREDENTIAL_TYPE_NONE, + CREDENTIAL_TYPE_NONE, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userId); } else /* isSyntheticPasswordBasedCredentialLocked(userId) */ { long pwdHandle = getSyntheticPasswordHandleLocked(userId); diff --git a/services/core/java/com/android/server/locksettings/LockSettingsStorage.java b/services/core/java/com/android/server/locksettings/LockSettingsStorage.java index 2ede384f3edf..f0e431ee0354 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsStorage.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsStorage.java @@ -37,6 +37,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; import com.android.internal.util.Preconditions; import com.android.internal.widget.LockPatternUtils; +import com.android.internal.widget.LockPatternUtils.CredentialType; import com.android.server.LocalServices; import com.android.server.PersistentDataBlockManagerInternal; @@ -96,11 +97,12 @@ class LockSettingsStorage { static final int VERSION_LEGACY = 0; static final int VERSION_GATEKEEPER = 1; - private CredentialHash(byte[] hash, int type, int version) { + private CredentialHash(byte[] hash, @CredentialType int type, int version) { this(hash, type, version, false /* isBaseZeroPattern */); } - private CredentialHash(byte[] hash, int type, int version, boolean isBaseZeroPattern) { + private CredentialHash( + byte[] hash, @CredentialType int type, int version, boolean isBaseZeroPattern) { if (type != LockPatternUtils.CREDENTIAL_TYPE_NONE) { if (hash == null) { throw new RuntimeException("Empty hash for CredentialHash"); @@ -134,7 +136,7 @@ class LockSettingsStorage { } byte[] hash; - int type; + @CredentialType int type; int version; boolean isBaseZeroPattern; diff --git a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java index 3872523492a7..1f1ba203e716 100644 --- a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java +++ b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java @@ -63,6 +63,7 @@ import java.util.Map; */ public final class MediaProjectionManagerService extends SystemService implements Watchdog.Monitor { + private static final boolean REQUIRE_FG_SERVICE_FOR_PROJECTION = false; private static final String TAG = "MediaProjectionManagerService"; private final Object mLock = new Object(); // Protects the list of media projections @@ -100,21 +101,23 @@ public final class MediaProjectionManagerService extends SystemService false /*allowIsolated*/); mMediaRouter.addCallback(MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY, mMediaRouterCallback, MediaRouter.CALLBACK_FLAG_PASSIVE_DISCOVERY); - mActivityManagerInternal.registerProcessObserver(new IProcessObserver.Stub() { - @Override - public void onForegroundActivitiesChanged(int pid, int uid, boolean fg) { - } + if (REQUIRE_FG_SERVICE_FOR_PROJECTION) { + mActivityManagerInternal.registerProcessObserver(new IProcessObserver.Stub() { + @Override + public void onForegroundActivitiesChanged(int pid, int uid, boolean fg) { + } - @Override - public void onForegroundServicesChanged(int pid, int uid, int serviceTypes) { - MediaProjectionManagerService.this.handleForegroundServicesChanged(pid, uid, - serviceTypes); - } + @Override + public void onForegroundServicesChanged(int pid, int uid, int serviceTypes) { + MediaProjectionManagerService.this.handleForegroundServicesChanged(pid, uid, + serviceTypes); + } - @Override - public void onProcessDied(int pid, int uid) { - } - }); + @Override + public void onProcessDied(int pid, int uid) { + } + }); + } } @Override @@ -462,7 +465,8 @@ public final class MediaProjectionManagerService extends SystemService return; } - if (targetSdkVersion >= Build.VERSION_CODES.Q + if (REQUIRE_FG_SERVICE_FOR_PROJECTION + && targetSdkVersion >= Build.VERSION_CODES.Q && !mActivityManagerInternal.hasRunningForegroundService( uid, ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION)) { throw new SecurityException("Media projections require a foreground service" diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java index 0c0c23a47999..0488d3a822ad 100644 --- a/services/core/java/com/android/server/notification/ManagedServices.java +++ b/services/core/java/com/android/server/notification/ManagedServices.java @@ -347,6 +347,9 @@ abstract public class ManagedServices { } } } + + writeExtraXmlTags(out); + out.endTag(null, getConfig().xmlTag); } @@ -355,6 +358,16 @@ abstract public class ManagedServices { */ protected void writeExtraAttributes(XmlSerializer out, int userId) throws IOException {} + /** + * Writes extra xml tags within the parent tag specified in {@link Config#xmlTag}. + */ + protected void writeExtraXmlTags(XmlSerializer out) throws IOException {} + + /** + * This is called to process tags other than {@link #TAG_MANAGED_SERVICES}. + */ + protected void readExtraTag(String tag, XmlPullParser parser) throws IOException {} + protected void migrateToXml() { loadAllowedComponentsFromSettings(); } @@ -391,6 +404,8 @@ abstract public class ManagedServices { } mUseXml = true; } + } else { + readExtraTag(tag, parser); } } } diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 4a215cf7febb..ca3c826d77dd 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -294,6 +294,12 @@ public class NotificationManagerService extends SystemService { static final boolean ENABLE_BLOCKED_TOASTS = true; + static final String[] DEFAULT_ALLOWED_ADJUSTMENTS = new String[] { + Adjustment.KEY_IMPORTANCE, + Adjustment.KEY_CONTEXTUAL_ACTIONS, + Adjustment.KEY_TEXT_REPLIES, + Adjustment.KEY_USER_SENTIMENT}; + // When #matchesCallFilter is called from the ringer, wait at most // 3s to resolve the contacts. This timeout is required since // ContactsProvider might take a long time to start up. @@ -2513,6 +2519,9 @@ public class NotificationManagerService extends SystemService { android.Manifest.permission.INTERACT_ACROSS_USERS, "canNotifyAsPackage for user " + userId); } + if (callingPkg.equals(targetPkg)) { + return true; + } try { ApplicationInfo info = mPackageManager.getApplicationInfo(targetPkg, @@ -2582,10 +2591,21 @@ public class NotificationManagerService extends SystemService { } @Override - public NotificationChannel getNotificationChannel(String pkg, String channelId) { - checkCallerIsSystemOrSameApp(pkg); - return mPreferencesHelper.getNotificationChannel( - pkg, Binder.getCallingUid(), channelId, false /* includeDeleted */); + public NotificationChannel getNotificationChannel(String callingPkg, int userId, + String targetPkg, String channelId) { + if (canNotifyAsPackage(callingPkg, targetPkg, userId) + || isCallingUidSystem()) { + int targetUid = -1; + try { + targetUid = mPackageManagerClient.getPackageUidAsUser(targetPkg, userId); + } catch (NameNotFoundException e) { + /* ignore */ + } + return mPreferencesHelper.getNotificationChannel( + targetPkg, targetUid, channelId, false /* includeDeleted */); + } + throw new SecurityException("Pkg " + callingPkg + + " cannot read channels for " + targetPkg + " in " + userId); } @Override @@ -2720,10 +2740,21 @@ public class NotificationManagerService extends SystemService { } @Override - public ParceledListSlice<NotificationChannel> getNotificationChannels(String pkg) { - checkCallerIsSystemOrSameApp(pkg); - return mPreferencesHelper.getNotificationChannels( - pkg, Binder.getCallingUid(), false /* includeDeleted */); + public ParceledListSlice<NotificationChannel> getNotificationChannels( + String callingPkg, String targetPkg, int userId) { + if (canNotifyAsPackage(callingPkg, targetPkg, userId) + || isCallingUidSystem()) { + int targetUid = -1; + try { + targetUid = mPackageManagerClient.getPackageUidAsUser(targetPkg, userId); + } catch (NameNotFoundException e) { + /* ignore */ + } + return mPreferencesHelper.getNotificationChannels( + targetPkg, targetUid, false /* includeDeleted */); + } + throw new SecurityException("Pkg " + callingPkg + + " cannot read channels for " + targetPkg + " in " + userId); } @Override @@ -2790,6 +2821,33 @@ public class NotificationManagerService extends SystemService { handleSavePolicyFile(); } + @Override + public List<String> getAllowedAssistantCapabilities(String pkg) { + checkCallerIsSystemOrSameApp(pkg); + + if (!isCallerSystemOrPhone() + && !mAssistants.isPackageAllowed(pkg, UserHandle.getCallingUserId())) { + throw new SecurityException("Not currently an assistant"); + } + + return mAssistants.getAllowedAssistantCapabilities(); + } + + @Override + public void allowAssistantCapability(String adjustmentType) { + checkCallerIsSystemOrShell(); + mAssistants.allowAdjustmentType(adjustmentType); + + handleSavePolicyFile(); + } + + @Override + public void disallowAssistantCapability(String adjustmentType) { + checkCallerIsSystemOrShell(); + mAssistants.disallowAdjustmentType(adjustmentType); + + handleSavePolicyFile(); + } /** * System-only API for getting a list of current (i.e. not cleared) notifications. @@ -7143,15 +7201,26 @@ public class NotificationManagerService extends SystemService { static final String TAG_ENABLED_NOTIFICATION_ASSISTANTS = "enabled_assistants"; private static final String ATT_USER_SET = "user_set"; + // TODO: STOPSHIP (b/127994217) switch to final value when onboarding flow is implemented + private static final String TAG_ALLOWED_ADJUSTMENT_TYPES = "allowed_adjustments_tmp"; + private static final String ATT_TYPES = "types"; private final Object mLock = new Object(); @GuardedBy("mLock") private ArrayMap<Integer, Boolean> mUserSetMap = new ArrayMap<>(); + private List<String> mAllowedAdjustments = new ArrayList<>(); public NotificationAssistants(Context context, Object lock, UserProfiles up, IPackageManager pm) { super(context, lock, up, pm); + + // TODO: STOPSHIP (b/127994217) remove when the onboarding flow is implemented + // Add all default allowed adjustment types. Will be overwritten by values in xml, + // if they exist + for (int i = 0; i < DEFAULT_ALLOWED_ADJUSTMENTS.length; i++) { + mAllowedAdjustments.add(DEFAULT_ALLOWED_ADJUSTMENTS[i]); + } } @Override @@ -7202,6 +7271,48 @@ public class NotificationManagerService extends SystemService { return android.Manifest.permission.REQUEST_NOTIFICATION_ASSISTANT_SERVICE; } + @Override + protected void writeExtraXmlTags(XmlSerializer out) throws IOException { + synchronized (mLock) { + out.startTag(null, TAG_ALLOWED_ADJUSTMENT_TYPES); + out.attribute(null, ATT_TYPES, TextUtils.join(",", mAllowedAdjustments)); + out.endTag(null, TAG_ALLOWED_ADJUSTMENT_TYPES); + } + } + + @Override + protected void readExtraTag(String tag, XmlPullParser parser) throws IOException { + if (TAG_ALLOWED_ADJUSTMENT_TYPES.equals(tag)) { + final String types = XmlUtils.readStringAttribute(parser, ATT_TYPES); + if (!TextUtils.isEmpty(types)) { + synchronized (mLock) { + mAllowedAdjustments.clear(); + mAllowedAdjustments.addAll(Arrays.asList(types.split(","))); + } + } + } + } + + protected void allowAdjustmentType(String type) { + synchronized (mLock) { + mAllowedAdjustments.add(type); + } + } + + protected void disallowAdjustmentType(String type) { + synchronized (mLock) { + mAllowedAdjustments.remove(type); + } + } + + protected List<String> getAllowedAssistantCapabilities() { + synchronized (mLock) { + List<String> types = new ArrayList<>(); + types.addAll(mAllowedAdjustments); + return types; + } + } + protected void onNotificationsSeenLocked(ArrayList<NotificationRecord> records) { // There should be only one, but it's a list, so while we enforce // singularity elsewhere, we keep it general here, to avoid surprises. diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index ec2ff28b4a88..c17b6c8d700e 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -4979,7 +4979,9 @@ public class PackageManagerService extends IPackageManager.Stub PackageManager.MATCH_STATIC_SHARED_LIBRARIES, userId, false /* throwIfPermNotDeclared*/) || mContext.checkCallingOrSelfPermission(REQUEST_DELETE_PACKAGES) - == PERMISSION_GRANTED; + == PERMISSION_GRANTED + || mContext.checkCallingOrSelfPermission( + Manifest.permission.ACCESS_SHARED_LIBRARIES) == PERMISSION_GRANTED; synchronized (mPackages) { List<SharedLibraryInfo> result = null; @@ -5029,6 +5031,76 @@ public class PackageManagerService extends IPackageManager.Stub } } + @Nullable + @Override + public ParceledListSlice<SharedLibraryInfo> getDeclaredSharedLibraries( + @NonNull String packageName, int flags, @NonNull int userId) { + mContext.enforceCallingOrSelfPermission(Manifest.permission.ACCESS_SHARED_LIBRARIES, + "getDeclaredSharedLibraries"); + int callingUid = Binder.getCallingUid(); + mPermissionManager.enforceCrossUserPermission(callingUid, userId, + true /* requireFullPermission */, false /* checkShell */, + "getDeclaredSharedLibraries"); + + Preconditions.checkNotNull(packageName, "packageName cannot be null"); + Preconditions.checkArgumentNonnegative(userId, "userId must be >= 0"); + if (!sUserManager.exists(userId)) { + return null; + } + + if (getInstantAppPackageName(callingUid) != null) { + return null; + } + + synchronized (mPackages) { + List<SharedLibraryInfo> result = null; + + int libraryCount = mSharedLibraries.size(); + for (int i = 0; i < libraryCount; i++) { + LongSparseArray<SharedLibraryInfo> versionedLibrary = mSharedLibraries.valueAt(i); + if (versionedLibrary == null) { + continue; + } + + int versionCount = versionedLibrary.size(); + for (int j = 0; j < versionCount; j++) { + SharedLibraryInfo libraryInfo = versionedLibrary.valueAt(j); + + VersionedPackage declaringPackage = libraryInfo.getDeclaringPackage(); + if (!Objects.equals(declaringPackage.getPackageName(), packageName)) { + continue; + } + + long identity = Binder.clearCallingIdentity(); + try { + PackageInfo packageInfo = getPackageInfoVersioned(declaringPackage, flags + | PackageManager.MATCH_STATIC_SHARED_LIBRARIES, userId); + if (packageInfo == null) { + continue; + } + } finally { + Binder.restoreCallingIdentity(identity); + } + + SharedLibraryInfo resultLibraryInfo = new SharedLibraryInfo( + libraryInfo.getPath(), libraryInfo.getPackageName(), + libraryInfo.getAllCodePaths(), libraryInfo.getName(), + libraryInfo.getLongVersion(), libraryInfo.getType(), + libraryInfo.getDeclaringPackage(), getPackagesUsingSharedLibraryLPr( + libraryInfo, flags, userId), libraryInfo.getDependencies() == null + ? null : new ArrayList<>(libraryInfo.getDependencies())); + + if (result == null) { + result = new ArrayList<>(); + } + result.add(resultLibraryInfo); + } + } + + return result != null ? new ParceledListSlice<>(result) : null; + } + } + @GuardedBy("mPackages") private List<VersionedPackage> getPackagesUsingSharedLibraryLPr( SharedLibraryInfo libInfo, int flags, int userId) { diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index e7c9a0819896..55af3571f63a 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -917,9 +917,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { mWindowManagerFuncs.onPowerKeyDown(interactive); - // Abort possibly stuck animations. - mHandler.post(mWindowManagerFuncs::triggerAnimationFailsafe); - // Latch power key state to detect screenshot chord. if (interactive && !mScreenshotChordPowerKeyTriggered && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { @@ -1026,6 +1023,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { cancelPendingPowerKeyAction(); if (!handled) { + if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) == 0) { + // Abort possibly stuck animations only when power key up without long press case. + mHandler.post(mWindowManagerFuncs::triggerAnimationFailsafe); + } + // Figure out how to handle the key now that it has been released. mPowerKeyPressCounter += 1; @@ -2520,7 +2522,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { } private static final int[] WINDOW_TYPES_WHERE_HOME_DOESNT_WORK = { - WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, WindowManager.LayoutParams.TYPE_SYSTEM_ERROR, }; @@ -3362,9 +3363,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { */ void launchHomeFromHotKey(int displayId, final boolean awakenFromDreams, final boolean respectKeyguard) { - // Abort possibly stuck animations. - mHandler.post(mWindowManagerFuncs::triggerAnimationFailsafe); - if (respectKeyguard) { if (isKeyguardShowingAndNotOccluded()) { // don't launch home if keyguard showing @@ -5128,7 +5126,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { // Start home. mActivityTaskManagerInternal.startHomeOnDisplay(mCurrentUserId, "startDockOrHome", - displayId, fromHomeKey); + displayId, true /* allowInstrumenting */, fromHomeKey); } /** @@ -5216,13 +5214,15 @@ public class PhoneWindowManager implements WindowManagerPolicy { private VibrationEffect getVibrationEffect(int effectId) { long[] pattern; switch (effectId) { - case HapticFeedbackConstants.CLOCK_TICK: case HapticFeedbackConstants.CONTEXT_CLICK: return VibrationEffect.get(VibrationEffect.EFFECT_TICK); case HapticFeedbackConstants.TEXT_HANDLE_MOVE: if (!mHapticTextHandleEnabled) { return null; } + // fallthrough + case HapticFeedbackConstants.CLOCK_TICK: + return VibrationEffect.get(VibrationEffect.EFFECT_TEXTURE_TICK); case HapticFeedbackConstants.KEYBOARD_RELEASE: case HapticFeedbackConstants.VIRTUAL_KEY_RELEASE: case HapticFeedbackConstants.ENTRY_BUMP: diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java index 2af234252e0f..b196754796e9 100644 --- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java +++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java @@ -829,9 +829,11 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants { return 9; case TYPE_SYSTEM_ALERT: // like the ANR / app crashed dialogs - return canAddInternalSystemWindow ? 11 : 10; + // Type is deprecated for non-system apps. For system apps, this type should be + // in a higher layer than TYPE_APPLICATION_OVERLAY. + return canAddInternalSystemWindow ? 13 : 10; case TYPE_APPLICATION_OVERLAY: - return canAddInternalSystemWindow ? 13 : 12; + return 12; case TYPE_DREAM: // used for Dreams (screensavers with TYPE_DREAM windows) return 14; diff --git a/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java b/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java index 8f2e997d319e..61daca7c93bc 100644 --- a/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java +++ b/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java @@ -17,6 +17,8 @@ package com.android.server.power.batterysaver; import static com.android.server.power.batterysaver.BatterySaverController.reasonToString; +import android.annotation.NonNull; +import android.annotation.StringRes; import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationManager; @@ -91,7 +93,9 @@ import java.io.PrintWriter; public class BatterySaverStateMachine { private static final String TAG = "BatterySaverStateMachine"; private static final String DYNAMIC_MODE_NOTIF_CHANNEL_ID = "dynamic_mode_notification"; + private static final String BATTERY_SAVER_NOTIF_CHANNEL_ID = "battery_saver_channel"; private static final int DYNAMIC_MODE_NOTIFICATION_ID = 1992; + private static final int STICKY_AUTO_DISABLED_NOTIFICATION_ID = 1993; private final Object mLock; private static final boolean DEBUG = BatterySaverPolicy.DEBUG; @@ -446,6 +450,10 @@ public class BatterySaverStateMachine { runOnBgThreadLazy(mThresholdChangeLogger, 2000); } + if (!mSettingBatterySaverStickyAutoDisableEnabled) { + hideStickyDisabledNotification(); + } + if (enabledChanged) { final String reason = batterySaverEnabled ? "Global.low_power changed to 1" : "Global.low_power changed to 0"; @@ -577,14 +585,17 @@ public class BatterySaverStateMachine { } enableBatterySaverLocked(/*enable*/ true, /*manual*/ true, BatterySaverController.REASON_MANUAL_ON); + hideStickyDisabledNotification(); mState = STATE_MANUAL_ON; } else if (isAutomaticModeActiveLocked() && isInAutomaticLowZoneLocked()) { enableBatterySaverLocked(/*enable*/ true, /*manual*/ false, BatterySaverController.REASON_PERCENTAGE_AUTOMATIC_ON); + hideStickyDisabledNotification(); mState = STATE_AUTOMATIC_ON; } else if (isDynamicModeActiveLocked() && isInDynamicLowZoneLocked()) { enableBatterySaverLocked(/*enable*/ true, /*manual*/ false, BatterySaverController.REASON_DYNAMIC_POWER_SAVINGS_AUTOMATIC_ON); + hideStickyDisabledNotification(); mState = STATE_AUTOMATIC_ON; } } @@ -678,6 +689,7 @@ public class BatterySaverStateMachine { mBatterySaverStickyBehaviourDisabled || !mSettingBatterySaverEnabledSticky; if (isStickyDisabled || shouldTurnOffSticky) { setStickyActive(false); + triggerStickyDisabledNotification(); mState = STATE_OFF; } else if (!mIsPowered) { // Re-enable BS. @@ -774,40 +786,66 @@ public class BatterySaverStateMachine { @VisibleForTesting void triggerDynamicModeNotification() { NotificationManager manager = mContext.getSystemService(NotificationManager.class); - ensureNotificationChannelExists(manager); + ensureNotificationChannelExists(manager, DYNAMIC_MODE_NOTIF_CHANNEL_ID, + R.string.dynamic_mode_notification_channel_name); + + manager.notify(DYNAMIC_MODE_NOTIFICATION_ID, + buildNotification(DYNAMIC_MODE_NOTIF_CHANNEL_ID, + R.string.dynamic_mode_notification_title, + R.string.dynamic_mode_notification_summary, + Intent.ACTION_POWER_USAGE_SUMMARY)); + } - manager.notify(DYNAMIC_MODE_NOTIFICATION_ID, buildNotification()); + private void triggerStickyDisabledNotification() { + NotificationManager manager = mContext.getSystemService(NotificationManager.class); + ensureNotificationChannelExists(manager, BATTERY_SAVER_NOTIF_CHANNEL_ID, + R.string.battery_saver_notification_channel_name); + + manager.notify(STICKY_AUTO_DISABLED_NOTIFICATION_ID, + buildNotification(BATTERY_SAVER_NOTIF_CHANNEL_ID, + R.string.battery_saver_sticky_disabled_notification_title, + R.string.battery_saver_sticky_disabled_notification_summary, + Settings.ACTION_BATTERY_SAVER_SETTINGS)); } - private void ensureNotificationChannelExists(NotificationManager manager) { + private void ensureNotificationChannelExists(NotificationManager manager, + @NonNull String channelId, @StringRes int nameId) { NotificationChannel channel = new NotificationChannel( - DYNAMIC_MODE_NOTIF_CHANNEL_ID, - mContext.getText( - R.string.dynamic_mode_notification_channel_name), - NotificationManager.IMPORTANCE_DEFAULT); + channelId, mContext.getText(nameId), NotificationManager.IMPORTANCE_DEFAULT); channel.setSound(null, null); manager.createNotificationChannel(channel); } - private Notification buildNotification() { + private Notification buildNotification(@NonNull String channelId, @StringRes int titleId, + @StringRes int summaryId, @NonNull String intentAction) { Resources res = mContext.getResources(); - Intent intent = new Intent(Intent.ACTION_POWER_USAGE_SUMMARY); + Intent intent = new Intent(intentAction); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); PendingIntent batterySaverIntent = PendingIntent.getActivity( mContext, 0 /* requestCode */, intent, PendingIntent.FLAG_UPDATE_CURRENT); + final String summary = res.getString(summaryId); - return new Notification.Builder(mContext, DYNAMIC_MODE_NOTIF_CHANNEL_ID) + return new Notification.Builder(mContext, channelId) .setSmallIcon(R.drawable.ic_battery) - .setContentTitle(res.getString(R.string.dynamic_mode_notification_title)) - .setContentText(res.getString(R.string.dynamic_mode_notification_summary)) + .setContentTitle(res.getString(titleId)) + .setContentText(summary) .setContentIntent(batterySaverIntent) + .setStyle(new Notification.BigTextStyle().bigText(summary)) .setOnlyAlertOnce(true) .build(); } private void hideDynamicModeNotification() { + hideNotification(DYNAMIC_MODE_NOTIFICATION_ID); + } + + private void hideStickyDisabledNotification() { + hideNotification(STICKY_AUTO_DISABLED_NOTIFICATION_ID); + } + + private void hideNotification(int notificationId) { NotificationManager manager = mContext.getSystemService(NotificationManager.class); - manager.cancel(DYNAMIC_MODE_NOTIFICATION_ID); + manager.cancel(notificationId); } private void setStickyActive(boolean active) { diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java index b262a006a545..fc7646f8ae4e 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java @@ -364,7 +364,7 @@ public abstract class ActivityTaskManagerInternal { * - Use the secondary home defined in the config. */ public abstract boolean startHomeOnDisplay(int userId, String reason, int displayId, - boolean fromHomeKey); + boolean allowInstrumenting, boolean fromHomeKey); /** Start home activities on all displays that support system decorations. */ public abstract boolean startHomeOnAllDisplays(int userId, String reason); /** @return true if the given process is the factory test process. */ diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index 118eb5bea602..b8e6b0c6fe9a 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -6492,9 +6492,11 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { @Override public boolean startHomeOnDisplay(int userId, String reason, int displayId, - boolean fromHomeKey) { - return mRootActivityContainer.startHomeOnDisplay(userId, reason, displayId, - fromHomeKey); + boolean allowInstrumenting, boolean fromHomeKey) { + synchronized (mGlobalLock) { + return mRootActivityContainer.startHomeOnDisplay(userId, reason, displayId, + allowInstrumenting, fromHomeKey); + } } @Override diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java index af05a271efef..e053ff338a25 100644 --- a/services/core/java/com/android/server/wm/AppTransition.java +++ b/services/core/java/com/android/server/wm/AppTransition.java @@ -484,6 +484,10 @@ public class AppTransition implements Dump { mListeners.add(listener); } + void unregisterListener(AppTransitionListener listener) { + mListeners.remove(listener); + } + public void notifyAppTransitionFinishedLocked(IBinder token) { for (int i = 0; i < mListeners.size(); i++) { mListeners.get(i).onAppTransitionFinishedLocked(token); diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java index 3f29181f0215..955f2e9ce050 100644 --- a/services/core/java/com/android/server/wm/AppWindowToken.java +++ b/services/core/java/com/android/server/wm/AppWindowToken.java @@ -666,7 +666,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree } } - if (isReallyAnimating()) { + if (isSelfAnimating()) { delayed = true; } else { @@ -2436,6 +2436,12 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; final boolean allowSplitScreenPrimaryAnimation = transit != TRANSIT_WALLPAPER_OPEN; + // Don't animate when the task runs recents animation. + final RecentsAnimationController controller = mWmService.getRecentsAnimationController(); + if (controller != null && controller.isAnimatingTask(getTask())) { + return false; + } + // We animate always if it's not split screen primary, and only some special cases in split // screen primary because it causes issues with stack clipping when we run an un-minimize // animation at the same time. diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index ba1dfbba06f8..6605f3c605ed 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -59,7 +59,6 @@ import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLES import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING; import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST; -import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS; import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER; @@ -335,6 +334,11 @@ public class DisplayPolicy { private int mForcingShowNavBarLayer; private boolean mForceShowSystemBars; + /** + * Force the display of system bars regardless of other settings. + */ + private boolean mForceShowSystemBarsFromExternal; + private boolean mShowingDream; private boolean mLastShowingDream; private boolean mDreamingLockscreen; @@ -410,6 +414,7 @@ public class DisplayPolicy { mCarDockEnablesAccelerometer = r.getBoolean(R.bool.config_carDockEnablesAccelerometer); mDeskDockEnablesAccelerometer = r.getBoolean(R.bool.config_deskDockEnablesAccelerometer); mTranslucentDecorEnabled = r.getBoolean(R.bool.config_enableTranslucentDecor); + mForceShowSystemBarsFromExternal = r.getBoolean(R.bool.config_forceShowSystemBars); updateConfigurationDependentBehaviors(); mAccessibilityManager = (AccessibilityManager) mContext.getSystemService( @@ -614,6 +619,13 @@ public class DisplayPolicy { return mDockMode; } + /** + * @see WindowManagerService.setForceShowSystemBars + */ + void setForceShowSystemBars(boolean forceShowSystemBars) { + mForceShowSystemBarsFromExternal = forceShowSystemBars; + } + public boolean hasNavigationBar() { return mHasNavigationBar; } @@ -1120,9 +1132,9 @@ public class DisplayPolicy { } /** - * @return true if the navigation bar is forced to stay visible + * @return true if the system bars are forced to stay visible */ - public boolean isNavBarForcedShownLw(WindowState windowState) { + public boolean areSystemBarsForcedShownLw(WindowState windowState) { return mForceShowSystemBars; } @@ -1142,8 +1154,8 @@ public class DisplayPolicy { * current visibility. Expressed as positive insets. * @param outOutsets The areas that are not real display, but we would like to treat as such. * @param outDisplayCutout The area that has been cut away from the display. - * @return Whether to always consume the navigation bar. - * See {@link #isNavBarForcedShownLw(WindowState)}. + * @return Whether to always consume the system bars. + * See {@link #areSystemBarsForcedShownLw(WindowState)}. */ public boolean getLayoutHintLw(LayoutParams attrs, Rect taskBounds, DisplayFrames displayFrames, boolean floatingStack, Rect outFrame, @@ -2067,8 +2079,7 @@ public class DisplayPolicy { of.set(displayFrames.mRestricted); df.set(displayFrames.mRestricted); pf.set(displayFrames.mRestricted); - } else if (type == TYPE_TOAST || type == TYPE_SYSTEM_ALERT - || type == TYPE_APPLICATION_OVERLAY) { + } else if (type == TYPE_TOAST || type == TYPE_SYSTEM_ALERT) { // These dialogs are stable to interim decor changes. cf.set(displayFrames.mStable); of.set(displayFrames.mStable); @@ -3050,7 +3061,8 @@ public class DisplayPolicy { // We need to force system bars when the docked stack is visible, when the freeform stack // is visible but also when we are resizing for the transitions when docked stack // visibility changes. - mForceShowSystemBars = dockedStackVisible || freeformStackVisible || resizing; + mForceShowSystemBars = dockedStackVisible || freeformStackVisible || resizing + || mForceShowSystemBarsFromExternal; final boolean forceOpaqueStatusBar = mForceShowSystemBars && !mForceStatusBarFromKeyguard; // apply translucent bar vis flags @@ -3422,6 +3434,8 @@ public class DisplayPolicy { pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen); pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar); pw.print(" mForceStatusBarFromKeyguard="); pw.println(mForceStatusBarFromKeyguard); + pw.print(" mForceShowSystemBarsFromExternal="); + pw.println(mForceShowSystemBarsFromExternal); pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.println(mAllowLockscreenWhenOn); mStatusBarController.dump(pw, prefix); mNavigationBarController.dump(pw, prefix); diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java index 72a1a2f0cac2..432d75e9a4e3 100644 --- a/services/core/java/com/android/server/wm/KeyguardController.java +++ b/services/core/java/com/android/server/wm/KeyguardController.java @@ -95,13 +95,15 @@ class KeyguardController { } /** - * @return {@code true} if 1) Keyguard is showing, not going away, and not being occluded on the - * given display, or 2) AOD is showing, {@code false} otherwise. + * @return {@code true} for default display when AOD is showing. Otherwise, same as + * {@link #isKeyguardOrAodShowing(int)} * TODO(b/125198167): Replace isKeyguardOrAodShowing() by this logic. */ boolean isKeyguardUnoccludedOrAodShowing(int displayId) { - return (mKeyguardShowing && !mKeyguardGoingAway && !isDisplayOccluded(displayId)) - || mAodShowing; + if (displayId == DEFAULT_DISPLAY && mAodShowing) { + return true; + } + return isKeyguardOrAodShowing(displayId); } /** diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java index cb9cbd6465fb..f1560d961209 100644 --- a/services/core/java/com/android/server/wm/RecentsAnimation.java +++ b/services/core/java/com/android/server/wm/RecentsAnimation.java @@ -31,6 +31,7 @@ import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS; import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_IN_PLACE; import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_ORIGINAL_POSITION; import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_TOP; +import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_RECENTS_ANIMATIONS; import android.app.ActivityOptions; import android.app.AppOpsManager; @@ -59,7 +60,7 @@ import java.util.List; class RecentsAnimation implements RecentsAnimationCallbacks, ActivityDisplay.OnStackOrderChangedListener { private static final String TAG = RecentsAnimation.class.getSimpleName(); - private static final boolean DEBUG = false; + private static final boolean DEBUG = DEBUG_RECENTS_ANIMATIONS; private final ActivityTaskManagerService mService; private final ActivityStackSupervisor mStackSupervisor; @@ -395,11 +396,23 @@ class RecentsAnimation implements RecentsAnimationCallbacks, // The stack is not visible, so ignore this change return; } - - // If the activity display stack order changes, cancel any running recents animation in - // place - mWindowManager.cancelRecentsAnimationSynchronously(REORDER_KEEP_IN_PLACE, - "stackOrderChanged"); + final RecentsAnimationController controller = + mWindowManager.getRecentsAnimationController(); + + // Cancel running recents animation and screenshot previous task when the next + // transition starts in below cases: + // 1) The next launching task is not in recents animation task. + // 2) The next task is home activity. (i.e. pressing home key to back home in recents). + if ((!controller.isAnimatingTask(stack.getTaskStack().getTopChild()) + || controller.isTargetApp(stack.getTopActivity().mAppWindowToken)) + && controller.shouldCancelWithDeferredScreenshot()) { + controller.cancelOnNextTransitionStart(); + } else { + // Just cancel directly to unleash from launcher when the next launching task is the + // current top task. + mWindowManager.cancelRecentsAnimationSynchronously(REORDER_KEEP_IN_PLACE, + "stackOrderChanged"); + } } /** @@ -407,7 +420,7 @@ class RecentsAnimation implements RecentsAnimationCallbacks, */ private void notifyAnimationCancelBeforeStart(IRecentsAnimationRunner recentsAnimationRunner) { try { - recentsAnimationRunner.onAnimationCanceled(); + recentsAnimationRunner.onAnimationCanceled(false /* deferredWithScreenshot */); } catch (RemoteException e) { Slog.e(TAG, "Failed to cancel recents animation before start", e); } diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java index 105ff0674ef0..381366995dd5 100644 --- a/services/core/java/com/android/server/wm/RecentsAnimationController.java +++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java @@ -29,6 +29,7 @@ import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_R import static com.android.server.wm.AnimationAdapterProto.REMOTE; import static com.android.server.wm.RemoteAnimationAdapterWrapperProto.TARGET; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_RECENTS_ANIMATIONS; +import static com.android.server.wm.WindowManagerInternal.AppTransitionListener; import android.annotation.IntDef; import android.app.ActivityManager.TaskSnapshot; @@ -92,6 +93,8 @@ public class RecentsAnimationController implements DeathRecipient { private final Runnable mFailsafeRunnable = () -> cancelAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION, "failSafeRunnable"); + final Object mLock = new Object(); + // The recents component app token that is shown behind the visibile tasks private AppWindowToken mTargetAppToken; private int mTargetActivityType; @@ -117,6 +120,27 @@ public class RecentsAnimationController implements DeathRecipient { private boolean mLinkedToDeathOfRunner; + private boolean mCancelWithDeferredScreenshot; + + private boolean mCancelOnNextTransitionStart; + + /** + * Animates the screenshot of task that used to be controlled by RecentsAnimation. + * @see {@link #cancelOnNextTransitionStart} + */ + SurfaceAnimator mRecentScreenshotAnimator; + + final AppTransitionListener mAppTransitionListener = new AppTransitionListener() { + @Override + public int onAppTransitionStartingLocked(int transit, long duration, + long statusBarAnimationStartTime, long statusBarAnimationDuration) { + onTransitionStart(); + mService.mRoot.getDisplayContent(mDisplayId).mAppTransition + .unregisterListener(this); + return 0; + } + }; + public interface RecentsAnimationCallbacks { void onAnimationFinished(@ReorderMode int reorderMode, boolean runSychronously); } @@ -184,7 +208,10 @@ public class RecentsAnimationController implements DeathRecipient { try { synchronized (mService.getWindowManagerLock()) { for (int i = mPendingAnimations.size() - 1; i >= 0; i--) { - mPendingAnimations.get(i).mTask.setCanAffectSystemUiFlags(behindSystemBars); + final Task task = mPendingAnimations.get(i).mTask; + if (task.getActivityType() != mTargetActivityType) { + task.setCanAffectSystemUiFlags(behindSystemBars); + } } mService.mWindowPlacerLocked.requestTraversal(); } @@ -245,6 +272,23 @@ public class RecentsAnimationController implements DeathRecipient { Binder.restoreCallingIdentity(token); } } + + @Override + public void setCancelWithDeferredScreenshot(boolean screenshot) { + synchronized (mLock) { + setCancelWithDeferredScreenshotLocked(screenshot); + } + } + + @Override + public void cleanupScreenshot() { + synchronized (mLock) { + if (mRecentScreenshotAnimator != null) { + mRecentScreenshotAnimator.cancelAnimation(); + mRecentScreenshotAnimator = null; + } + } + } }; /** @@ -273,6 +317,7 @@ public class RecentsAnimationController implements DeathRecipient { @VisibleForTesting void initialize(DisplayContent dc, int targetActivityType, SparseBooleanArray recentTaskIds) { mTargetActivityType = targetActivityType; + dc.mAppTransition.registerListenerLocked(mAppTransitionListener); // Make leashes for each of the visible/target tasks and add it to the recents animation to // be started @@ -416,15 +461,20 @@ public class RecentsAnimationController implements DeathRecipient { } void cancelAnimation(@ReorderMode int reorderMode, String reason) { - cancelAnimation(reorderMode, false /* runSynchronously */, reason); + cancelAnimation(reorderMode, false /* runSynchronously */, false /*screenshot */, reason); } void cancelAnimationSynchronously(@ReorderMode int reorderMode, String reason) { - cancelAnimation(reorderMode, true /* runSynchronously */, reason); + cancelAnimation(reorderMode, true /* runSynchronously */, false /* screenshot */, reason); + } + + void cancelAnimationWithScreenShot() { + cancelAnimation(REORDER_KEEP_IN_PLACE, true /* sync */, true /* screenshot */, + "stackOrderChanged"); } private void cancelAnimation(@ReorderMode int reorderMode, boolean runSynchronously, - String reason) { + boolean screenshot, String reason) { if (DEBUG_RECENTS_ANIMATIONS) Slog.d(TAG, "cancelAnimation(): reason=" + reason + " runSynchronously=" + runSynchronously); synchronized (mService.getWindowManagerLock()) { @@ -435,14 +485,67 @@ public class RecentsAnimationController implements DeathRecipient { mService.mH.removeCallbacks(mFailsafeRunnable); mCanceled = true; try { - mRunner.onAnimationCanceled(); + if (screenshot) { + // Screen shot previous task when next task starts transition. + final Task task = mPendingAnimations.get(0).mTask; + screenshotRecentTask(task, reorderMode, runSynchronously); + mRunner.onAnimationCanceled(true /* deferredWithScreenshot */); + return; + } + mRunner.onAnimationCanceled(false /* deferredWithScreenshot */); } catch (RemoteException e) { Slog.e(TAG, "Failed to cancel recents animation", e); } + // Clean up and return to the previous app + mCallbacks.onAnimationFinished(reorderMode, runSynchronously); } + } - // Clean up and return to the previous app - mCallbacks.onAnimationFinished(reorderMode, runSynchronously); + /** + * Cancel recents animation when the next app transition starts. + * <p> + * When we cancel the recents animation due to a stack order change, we can't just cancel it + * immediately as it would lead to a flicker in Launcher if we just remove the task from the + * leash. Instead we screenshot the previous task and replace the child of the leash with the + * screenshot, so that Launcher can still control the leash lifecycle & make the next app + * transition animate smoothly without flickering. + */ + void cancelOnNextTransitionStart() { + mCancelOnNextTransitionStart = true; + } + + void setCancelWithDeferredScreenshotLocked(boolean screenshot) { + mCancelWithDeferredScreenshot = screenshot; + } + + boolean shouldCancelWithDeferredScreenshot() { + return mCancelWithDeferredScreenshot; + } + + void onTransitionStart() { + if (mCanceled) { + return; + } + + if (mCancelOnNextTransitionStart) { + mCancelOnNextTransitionStart = false; + cancelAnimationWithScreenShot(); + } + } + + void screenshotRecentTask(Task task, @ReorderMode int reorderMode, boolean runSynchronously) { + final TaskScreenshotAnimatable animatable = TaskScreenshotAnimatable.create(task); + if (animatable != null) { + mRecentScreenshotAnimator = new SurfaceAnimator( + animatable, + () -> { + if (DEBUG_RECENTS_ANIMATIONS) { + Slog.d(TAG, "mRecentScreenshotAnimator finish"); + } + mCallbacks.onAnimationFinished(reorderMode, runSynchronously); + }, mService); + mRecentScreenshotAnimator.transferAnimation(task.mSurfaceAnimator); + } } void cleanupAnimation(@ReorderMode int reorderMode) { @@ -465,6 +568,12 @@ public class RecentsAnimationController implements DeathRecipient { mRunner = null; mCanceled = true; + // Make sure previous animator has cleaned-up. + if (mRecentScreenshotAnimator != null) { + mRecentScreenshotAnimator.cancelAnimation(); + mRecentScreenshotAnimator = null; + } + // Update the input windows after the animation is complete final InputMonitor inputMonitor = mService.mRoot.getDisplayContent(mDisplayId).getInputMonitor(); diff --git a/services/core/java/com/android/server/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java index 24cf7f127e18..46b5f3ab38f9 100644 --- a/services/core/java/com/android/server/wm/RootActivityContainer.java +++ b/services/core/java/com/android/server/wm/RootActivityContainer.java @@ -347,7 +347,8 @@ class RootActivityContainer extends ConfigurationContainer } boolean startHomeOnDisplay(int userId, String reason, int displayId) { - return startHomeOnDisplay(userId, reason, displayId, false /*fromHomeKey*/); + return startHomeOnDisplay(userId, reason, displayId, false /* allowInstrumenting */, + false /* fromHomeKey */); } /** @@ -361,7 +362,8 @@ class RootActivityContainer extends ConfigurationContainer * If there are multiple activities matched, use first one. * - Use the secondary home defined in the config. */ - boolean startHomeOnDisplay(int userId, String reason, int displayId, boolean fromHomeKey) { + boolean startHomeOnDisplay(int userId, String reason, int displayId, boolean allowInstrumenting, + boolean fromHomeKey) { // Fallback to top focused display if the displayId is invalid. if (displayId == INVALID_DISPLAY) { displayId = getTopDisplayFocusedStack().mDisplayId; @@ -383,7 +385,7 @@ class RootActivityContainer extends ConfigurationContainer return false; } - if (!canStartHomeOnDisplay(aInfo, displayId, false /* allowInstrumenting */)) { + if (!canStartHomeOnDisplay(aInfo, displayId, allowInstrumenting)) { return false; } diff --git a/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java b/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java new file mode 100644 index 000000000000..e0d85e876476 --- /dev/null +++ b/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java @@ -0,0 +1,124 @@ +/* + * 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 com.android.server.wm; + +import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_RECENTS_ANIMATIONS; + +import android.graphics.GraphicBuffer; +import android.graphics.Rect; +import android.util.Slog; +import android.view.Surface; +import android.view.SurfaceControl; +import android.view.SurfaceSession; + +/** + * Class used by {@link RecentsAnimationController} to create a surface control with taking + * screenshot of task when canceling recents animation. + * + * @see {@link RecentsAnimationController#cancelOnNextTransitionStart} + */ +class TaskScreenshotAnimatable implements SurfaceAnimator.Animatable { + private static final String TAG = "TaskScreenshotAnim"; + private Task mTask; + private SurfaceControl mSurfaceControl; + private int mWidth; + private int mHeight; + + public static TaskScreenshotAnimatable create(Task task) { + return new TaskScreenshotAnimatable(task, getBufferFromTask(task)); + } + + private static GraphicBuffer getBufferFromTask(Task task) { + if (task == null) { + return null; + } + final Rect tmpRect = task.getBounds(); + tmpRect.offset(0, 0); + return SurfaceControl.captureLayers( + task.getSurfaceControl().getHandle(), tmpRect, 1f); + } + + private TaskScreenshotAnimatable(Task task, GraphicBuffer buffer) { + mTask = task; + mWidth = (buffer != null) ? buffer.getWidth() : 1; + mHeight = (buffer != null) ? buffer.getHeight() : 1; + if (DEBUG_RECENTS_ANIMATIONS) { + Slog.d(TAG, "Creating TaskScreenshotAnimatable: task: " + task + + "width: " + mWidth + "height: " + mHeight); + } + mSurfaceControl = new SurfaceControl.Builder(new SurfaceSession()) + .setName("RecentTaskScreenshotSurface") + .setBufferSize(mWidth, mHeight) + .build(); + if (buffer != null) { + final Surface surface = new Surface(); + surface.copyFrom(mSurfaceControl); + surface.attachAndQueueBuffer(buffer); + surface.release(); + } + getPendingTransaction().show(mSurfaceControl); + } + + @Override + public SurfaceControl.Transaction getPendingTransaction() { + return mTask.mPendingTransaction; + } + + @Override + public void commitPendingTransaction() { + mTask.commitPendingTransaction(); + } + + @Override + public void onAnimationLeashCreated(SurfaceControl.Transaction t, SurfaceControl leash) { + t.setLayer(leash, 1); + } + + @Override + public void onAnimationLeashDestroyed(SurfaceControl.Transaction t) { + t.remove(mSurfaceControl); + } + + @Override + public SurfaceControl.Builder makeAnimationLeash() { + return mTask.makeAnimationLeash(); + } + + @Override + public SurfaceControl getAnimationLeashParent() { + return mTask.getAnimationLeashParent(); + } + + @Override + public SurfaceControl getSurfaceControl() { + return mSurfaceControl; + } + + @Override + public SurfaceControl getParentSurfaceControl() { + return mTask.mSurfaceAnimator.mLeash; + } + + @Override + public int getSurfaceWidth() { + return mWidth; + } + + @Override + public int getSurfaceHeight() { + return mHeight; + } +} diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java index 938c8b452e29..dafed9ed919a 100644 --- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java +++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java @@ -454,7 +454,7 @@ class TaskSnapshotSurface implements StartingSurface { public void resized(Rect frame, Rect overscanInsets, Rect contentInsets, Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw, MergedConfiguration mergedConfiguration, Rect backDropFrame, boolean forceLayout, - boolean alwaysConsumeNavBar, int displayId, + boolean alwaysConsumeSystemBars, int displayId, DisplayCutout.ParcelableWrapper displayCutout) { if (mergedConfiguration != null && mOuter != null && mOuter.mOrientationOnCreation diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 7751560203e7..4aa844ff4f49 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -1534,7 +1534,7 @@ public class WindowManagerService extends IWindowManager.Stub } if (displayPolicy.getLayoutHintLw(win.mAttrs, taskBounds, displayFrames, floatingStack, outFrame, outContentInsets, outStableInsets, outOutsets, outDisplayCutout)) { - res |= WindowManagerGlobal.ADD_FLAG_ALWAYS_CONSUME_NAV_BAR; + res |= WindowManagerGlobal.ADD_FLAG_ALWAYS_CONSUME_SYSTEM_BARS; } outInsetsState.set(displayContent.getInsetsStateController().getInsetsForDispatch(win)); @@ -2206,8 +2206,8 @@ public class WindowManagerService extends IWindowManager.Stub winAnimator.mReportSurfaceResized = false; result |= WindowManagerGlobal.RELAYOUT_RES_SURFACE_RESIZED; } - if (displayPolicy.isNavBarForcedShownLw(win)) { - result |= WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_NAV_BAR; + if (displayPolicy.areSystemBarsForcedShownLw(win)) { + result |= WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_SYSTEM_BARS; } if (!win.isGoneForLayoutLw()) { win.mResizedWhileGone = false; @@ -5638,6 +5638,19 @@ public class WindowManagerService extends IWindowManager.Stub } } + @Override + public void setForceShowSystemBars(boolean show) { + if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) + != PackageManager.PERMISSION_GRANTED) { + throw new SecurityException("Caller does not hold permission " + + android.Manifest.permission.STATUS_BAR); + } + synchronized (mGlobalLock) { + mRoot.forAllDisplayPolicies(PooledLambda.obtainConsumer( + DisplayPolicy::setForceShowSystemBars, PooledLambda.__(), show)); + } + } + public void setNavBarVirtualKeyHapticFeedbackEnabled(boolean enabled) { if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) != PackageManager.PERMISSION_GRANTED) { diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 600178fa3276..6a21327d8bb9 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -3117,7 +3117,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP mClient.resized(frame, overscanInsets, contentInsets, visibleInsets, stableInsets, outsets, reportDraw, mergedConfiguration, getBackdropFrame(frame), forceRelayout, - getDisplayContent().getDisplayPolicy().isNavBarForcedShownLw(this), displayId, + getDisplayContent().getDisplayPolicy().areSystemBarsForcedShownLw(this), displayId, new DisplayCutout.ParcelableWrapper(displayCutout)); mDragResizingChangeReported = true; } diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp index 00b815ae1bfa..a7423ea40bf0 100644 --- a/services/core/jni/Android.bp +++ b/services/core/jni/Android.bp @@ -50,6 +50,7 @@ cc_library_static { "com_android_server_VibratorService.cpp", "com_android_server_PersistentDataBlockService.cpp", "com_android_server_GraphicsStatsService.cpp", + "com_android_server_am_AppCompactor.cpp", "onload.cpp", ], diff --git a/services/core/jni/com_android_server_VibratorService.cpp b/services/core/jni/com_android_server_VibratorService.cpp index 63dca62104a1..d5fbd2b316e7 100644 --- a/services/core/jni/com_android_server_VibratorService.cpp +++ b/services/core/jni/com_android_server_VibratorService.cpp @@ -96,7 +96,7 @@ bool isValidEffect(jlong effect) { } R val = static_cast<R>(effect); auto iter = hardware::hidl_enum_range<R>(); - return val >= *iter.begin() && val < *std::prev(iter.end()); + return val >= *iter.begin() && val <= *std::prev(iter.end()); } static void vibratorInit(JNIEnv /* env */, jobject /* clazz */) @@ -170,6 +170,9 @@ static jlong vibratorPerformEffect(JNIEnv*, jobject, jlong effect, jint strength } else if (isValidEffect<V1_2::Effect>(effect)) { ret = halCall(&V1_2::IVibrator::perform_1_2, static_cast<V1_2::Effect>(effect), effectStrength, callback); + } else if (isValidEffect<V1_3::Effect>(effect)) { + ret = halCall(&V1_3::IVibrator::perform_1_3, static_cast<V1_3::Effect>(effect), + effectStrength, callback); } else { ALOGW("Unable to perform haptic effect, invalid effect ID (%" PRId32 ")", static_cast<int32_t>(effect)); diff --git a/services/core/jni/com_android_server_am_AppCompactor.cpp b/services/core/jni/com_android_server_am_AppCompactor.cpp new file mode 100644 index 000000000000..de6aa8b3266b --- /dev/null +++ b/services/core/jni/com_android_server_am_AppCompactor.cpp @@ -0,0 +1,88 @@ +/* + * 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. + */ + +#define LOG_TAG "AppCompactor" +//#define LOG_NDEBUG 0 + +#include <dirent.h> +#include <stddef.h> +#include <stdio.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> + +#include <android-base/stringprintf.h> +#include <android-base/file.h> + +#include <nativehelper/JNIHelp.h> +#include <android_runtime/AndroidRuntime.h> +#include <jni.h> + +using android::base::StringPrintf; +using android::base::WriteStringToFile; + +namespace android { + +// This performs per-process reclaim on all processes belonging to non-app UIDs. +// For the most part, these are non-zygote processes like Treble HALs, but it +// also includes zygote-derived processes that run in system UIDs, like bluetooth +// or potentially some mainline modules. The only process that should definitely +// not be compacted is system_server, since compacting system_server around the +// time of BOOT_COMPLETE could result in perceptible issues. +static void com_android_server_am_AppCompactor_compactSystem(JNIEnv *, jobject) { + std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir); + struct dirent* current; + while ((current = readdir(proc.get()))) { + if (current->d_type != DT_DIR) { + continue; + } + + // don't compact system_server, rely on persistent compaction during screen off + // in order to avoid mmap_sem-related stalls + if (atoi(current->d_name) == getpid()) { + continue; + } + + std::string status_name = StringPrintf("/proc/%s/status", current->d_name); + struct stat status_info; + + if (stat(status_name.c_str(), &status_info) != 0) { + // must be some other directory that isn't a pid + continue; + } + + // android.os.Process.FIRST_APPLICATION_UID + if (status_info.st_uid >= 10000) { + continue; + } + + std::string reclaim_path = StringPrintf("/proc/%s/reclaim", current->d_name); + WriteStringToFile(std::string("all"), reclaim_path); + } +} + +static const JNINativeMethod sMethods[] = { + /* name, signature, funcPtr */ + {"compactSystem", "()V", (void*)com_android_server_am_AppCompactor_compactSystem}, +}; + +int register_android_server_am_AppCompactor(JNIEnv* env) +{ + return jniRegisterNativeMethods(env, "com/android/server/am/AppCompactor", + sMethods, NELEM(sMethods)); +} + +} diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp index 57377c633c9a..3d84bd40fb5a 100644 --- a/services/core/jni/com_android_server_input_InputManagerService.cpp +++ b/services/core/jni/com_android_server_input_InputManagerService.cpp @@ -228,7 +228,7 @@ public: virtual void getReaderConfiguration(InputReaderConfiguration* outConfig); virtual sp<PointerControllerInterface> obtainPointerController(int32_t deviceId); - virtual void notifyInputDevicesChanged(const Vector<InputDeviceInfo>& inputDevices); + virtual void notifyInputDevicesChanged(const std::vector<InputDeviceInfo>& inputDevices); virtual sp<KeyCharacterMap> getKeyboardLayoutOverlay(const InputDeviceIdentifier& identifier); virtual std::string getDeviceAlias(const InputDeviceIdentifier& identifier); virtual TouchAffineTransformation getTouchAffineTransformation(JNIEnv *env, @@ -598,7 +598,7 @@ void NativeInputManager::ensureSpriteControllerLocked() REQUIRES(mLock) { } } -void NativeInputManager::notifyInputDevicesChanged(const Vector<InputDeviceInfo>& inputDevices) { +void NativeInputManager::notifyInputDevicesChanged(const std::vector<InputDeviceInfo>& inputDevices) { ATRACE_CALL(); JNIEnv* env = jniEnv(); @@ -608,7 +608,7 @@ void NativeInputManager::notifyInputDevicesChanged(const Vector<InputDeviceInfo> if (inputDevicesObjArray) { bool error = false; for (size_t i = 0; i < count; i++) { - jobject inputDeviceObj = android_view_InputDevice_create(env, inputDevices.itemAt(i)); + jobject inputDeviceObj = android_view_InputDevice_create(env, inputDevices[i]); if (!inputDeviceObj) { error = true; break; @@ -775,7 +775,7 @@ void NativeInputManager::getDispatcherConfiguration(InputDispatcherConfiguration void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowHandleObjArray, int32_t displayId) { - Vector<sp<InputWindowHandle> > windowHandles; + std::vector<sp<InputWindowHandle> > windowHandles; if (windowHandleObjArray) { jsize length = env->GetArrayLength(windowHandleObjArray); @@ -788,7 +788,7 @@ void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowHandleO sp<InputWindowHandle> windowHandle = android_view_InputWindowHandle_getHandle(env, windowHandleObj); if (windowHandle != nullptr) { - windowHandles.push(windowHandle); + windowHandles.push_back(windowHandle); } env->DeleteLocalRef(windowHandleObj); } @@ -800,7 +800,7 @@ void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowHandleO bool newPointerGesturesEnabled = true; size_t numWindows = windowHandles.size(); for (size_t i = 0; i < numWindows; i++) { - const sp<InputWindowHandle>& windowHandle = windowHandles.itemAt(i); + const sp<InputWindowHandle>& windowHandle = windowHandles[i]; const InputWindowInfo* windowInfo = windowHandle->getInfo(); if (windowInfo && windowInfo->hasFocus && (windowInfo->inputFeatures & InputWindowInfo::INPUT_FEATURE_DISABLE_TOUCH_PAD_GESTURES)) { diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp index a6e9fdde7735..65a7eec60f63 100644 --- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp +++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp @@ -117,8 +117,6 @@ using android::hardware::hidl_death_recipient; using android::hardware::gnss::V1_0::GnssConstellationType; using android::hardware::gnss::V1_0::GnssLocationFlags; using android::hardware::gnss::V1_0::IAGnssRilCallback; -using android::hardware::gnss::V1_0::IGnssBatching; -using android::hardware::gnss::V1_0::IGnssBatchingCallback; using android::hardware::gnss::V1_0::IGnssGeofenceCallback; using android::hardware::gnss::V1_0::IGnssGeofencing; using android::hardware::gnss::V1_0::IGnssNavigationMessage; @@ -160,6 +158,10 @@ using IAGnss_V1_0 = android::hardware::gnss::V1_0::IAGnss; using IAGnss_V2_0 = android::hardware::gnss::V2_0::IAGnss; using IAGnssCallback_V1_0 = android::hardware::gnss::V1_0::IAGnssCallback; using IAGnssCallback_V2_0 = android::hardware::gnss::V2_0::IAGnssCallback; +using IGnssBatching_V1_0 = android::hardware::gnss::V1_0::IGnssBatching; +using IGnssBatching_V2_0 = android::hardware::gnss::V2_0::IGnssBatching; +using IGnssBatchingCallback_V1_0 = android::hardware::gnss::V1_0::IGnssBatchingCallback; +using IGnssBatchingCallback_V2_0 = android::hardware::gnss::V2_0::IGnssBatchingCallback; using android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrections; using android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrectionsCallback; @@ -192,7 +194,8 @@ sp<IAGnssRil_V2_0> agnssRilIface_V2_0 = nullptr; sp<IGnssGeofencing> gnssGeofencingIface = nullptr; sp<IAGnss_V1_0> agnssIface = nullptr; sp<IAGnss_V2_0> agnssIface_V2_0 = nullptr; -sp<IGnssBatching> gnssBatchingIface = nullptr; +sp<IGnssBatching_V1_0> gnssBatchingIface = nullptr; +sp<IGnssBatching_V2_0> gnssBatchingIface_V2_0 = nullptr; sp<IGnssDebug_V1_0> gnssDebugIface = nullptr; sp<IGnssDebug_V2_0> gnssDebugIface_V2_0 = nullptr; sp<IGnssConfiguration_V1_0> gnssConfigurationIface = nullptr; @@ -1445,20 +1448,15 @@ Return<void> AGnssRilCallback::requestRefLocCb() { return Void(); } -/* - * GnssBatchingCallback interface implements the callback methods - * required by the IGnssBatching interface. - */ -struct GnssBatchingCallback : public IGnssBatchingCallback { - /* - * Methods from ::android::hardware::gps::V1_0::IGnssBatchingCallback - * follow. - */ - Return<void> gnssLocationBatchCb(const hidl_vec<GnssLocation_V1_0>& locations) override; +struct GnssBatchingCallbackUtil { + template<class T> + static Return<void> gnssLocationBatchCbImpl(const hidl_vec<T>& locations); +private: + GnssBatchingCallbackUtil() = delete; }; -Return<void> GnssBatchingCallback::gnssLocationBatchCb( - const hidl_vec<GnssLocation_V1_0>& locations) { +template<class T> +Return<void> GnssBatchingCallbackUtil::gnssLocationBatchCbImpl(const hidl_vec<T>& locations) { JNIEnv* env = getJniEnv(); jobjectArray jLocations = env->NewObjectArray(locations.size(), @@ -1478,6 +1476,28 @@ Return<void> GnssBatchingCallback::gnssLocationBatchCb( return Void(); } +/* + * GnssBatchingCallback_V1_0 class implements the callback methods required by the + * IGnssBatching 1.0 interface. + */ +struct GnssBatchingCallback_V1_0 : public IGnssBatchingCallback_V1_0 { + /** Methods from ::android::hardware::gps::V1_0::IGnssBatchingCallback follow. */ + Return<void> gnssLocationBatchCb(const hidl_vec<GnssLocation_V1_0>& locations) override { + return GnssBatchingCallbackUtil::gnssLocationBatchCbImpl(locations); + } +}; + +/* + * GnssBatchingCallback_V2_0 class implements the callback methods required by the + * IGnssBatching 2.0 interface. + */ +struct GnssBatchingCallback_V2_0 : public IGnssBatchingCallback_V2_0 { + /** Methods from ::android::hardware::gps::V2_0::IGnssBatchingCallback follow. */ + Return<void> gnssLocationBatchCb(const hidl_vec<GnssLocation_V2_0>& locations) override { + return GnssBatchingCallbackUtil::gnssLocationBatchCbImpl(locations); + } +}; + static void android_location_GnssLocationProvider_class_init_native(JNIEnv* env, jclass clazz) { gnssHal_V2_0 = IGnss_V2_0::getService(); if (gnssHal_V2_0 != nullptr) { @@ -1753,11 +1773,22 @@ static void android_location_GnssLocationProvider_init_once(JNIEnv* env, jclass gnssGeofencingIface = gnssGeofencing; } - auto gnssBatching = gnssHal->getExtensionGnssBatching(); - if (!gnssBatching.isOk()) { - ALOGD("Unable to get a handle to gnssBatching"); - } else { - gnssBatchingIface = gnssBatching; + // If IGnssBatching.hal@2.0 is not supported, use IGnssBatching.hal@1.0 + if (gnssHal_V2_0 != nullptr) { + auto gnssBatching_V2_0 = gnssHal_V2_0->getExtensionGnssBatching_2_0(); + if (!gnssBatching_V2_0.isOk()) { + ALOGD("Unable to get a handle to GnssBatching_V2_0"); + } else { + gnssBatchingIface_V2_0 = gnssBatching_V2_0; + } + } + if (gnssBatchingIface_V2_0 == nullptr ) { + auto gnssBatching_V1_0 = gnssHal->getExtensionGnssBatching(); + if (!gnssBatching_V1_0.isOk()) { + ALOGD("Unable to get a handle to GnssBatching"); + } else { + gnssBatchingIface = gnssBatching_V1_0; + } } if (gnssHal_V2_0 != nullptr) { @@ -2123,8 +2154,6 @@ struct AGnssDispatcher { private: AGnssDispatcher() = delete; - AGnssDispatcher(const AGnssDispatcher&) = delete; - AGnssDispatcher& operator=(const AGnssDispatcher&) = delete; }; void AGnssDispatcher::dataConnOpen(sp<IAGnss_V1_0> agnssIface, JNIEnv* env, jstring apn, @@ -2848,12 +2877,15 @@ static jint android_location_GnssBatchingProvider_get_batch_size(JNIEnv*, jclass } static jboolean android_location_GnssBatchingProvider_init_batching(JNIEnv*, jclass) { - if (gnssBatchingIface == nullptr) { + if (gnssBatchingIface_V2_0 != nullptr) { + sp<IGnssBatchingCallback_V2_0> gnssBatchingCbIface_V2_0 = new GnssBatchingCallback_V2_0(); + return static_cast<jboolean>(gnssBatchingIface_V2_0->init_2_0(gnssBatchingCbIface_V2_0)); + } else if (gnssBatchingIface != nullptr) { + sp<IGnssBatchingCallback_V1_0> gnssBatchingCbIface_V1_0 = new GnssBatchingCallback_V1_0(); + return static_cast<jboolean>(gnssBatchingIface->init(gnssBatchingCbIface_V1_0)); + } else { return JNI_FALSE; // batching not supported } - sp<IGnssBatchingCallback> gnssBatchingCbIface = new GnssBatchingCallback(); - - return static_cast<jboolean>(gnssBatchingIface->init(gnssBatchingCbIface)); } static void android_location_GnssBatchingProvider_cleanup_batching(JNIEnv*, jclass) { @@ -2869,10 +2901,10 @@ static jboolean android_location_GnssBatchingProvider_start_batch(JNIEnv*, jclas return JNI_FALSE; // batching not supported } - IGnssBatching::Options options; + IGnssBatching_V1_0::Options options; options.periodNanos = periodNanos; if (wakeOnFifoFull) { - options.flags = static_cast<uint8_t>(IGnssBatching::Flag::WAKEUP_ON_FIFO_FULL); + options.flags = static_cast<uint8_t>(IGnssBatching_V1_0::Flag::WAKEUP_ON_FIFO_FULL); } else { options.flags = 0; } diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp index 5ffed03c86ae..2cfaebf4632e 100644 --- a/services/core/jni/onload.cpp +++ b/services/core/jni/onload.cpp @@ -54,6 +54,7 @@ int register_android_server_GraphicsStatsService(JNIEnv* env); int register_android_hardware_display_DisplayViewport(JNIEnv* env); int register_android_server_net_NetworkStatsService(JNIEnv* env); int register_android_server_security_VerityUtils(JNIEnv* env); +int register_android_server_am_AppCompactor(JNIEnv* env); }; using namespace android; @@ -101,5 +102,6 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) register_android_hardware_display_DisplayViewport(env); register_android_server_net_NetworkStatsService(env); register_android_server_security_VerityUtils(env); + register_android_server_am_AppCompactor(env); return JNI_VERSION_1_4; } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index f6de82d8e237..4ff5d61b29d1 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -58,7 +58,14 @@ import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_HOME; import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_NOTIFICATIONS; import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW; import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_NONE; +import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC; +import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC; +import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK; import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_COMPLEX; +import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_MANAGED; +import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC; +import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX; +import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING; import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; import static android.app.admin.DevicePolicyManager.PRIVATE_DNS_MODE_OFF; import static android.app.admin.DevicePolicyManager.PRIVATE_DNS_MODE_OPPORTUNISTIC; @@ -3475,15 +3482,15 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { static void validateQualityConstant(int quality) { switch (quality) { - case DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED: - case DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK: - case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING: - case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC: - case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX: - case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC: - case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC: - case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX: - case DevicePolicyManager.PASSWORD_QUALITY_MANAGED: + case PASSWORD_QUALITY_UNSPECIFIED: + case PASSWORD_QUALITY_BIOMETRIC_WEAK: + case PASSWORD_QUALITY_SOMETHING: + case PASSWORD_QUALITY_NUMERIC: + case PASSWORD_QUALITY_NUMERIC_COMPLEX: + case PASSWORD_QUALITY_ALPHABETIC: + case PASSWORD_QUALITY_ALPHANUMERIC: + case PASSWORD_QUALITY_COMPLEX: + case PASSWORD_QUALITY_MANAGED: return; } throw new IllegalArgumentException("Invalid quality constant: 0x" @@ -4747,41 +4754,36 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { // setActivePasswordState has never been called for it. metrics = new PasswordMetrics(); } + return isPasswordSufficientForUserWithoutCheckpointLocked(metrics, userHandle, parent); } /** - * Returns {@code true} if the password represented by the {@code passwordMetrics} argument + * Returns {@code true} if the password represented by the {@code metrics} argument * sufficiently fulfills the password requirements for the user corresponding to - * {@code userHandle} (or its parent, if {@code parent} is set to {@code true}). + * {@code userId} (or its parent, if {@code parent} is set to {@code true}). */ private boolean isPasswordSufficientForUserWithoutCheckpointLocked( - PasswordMetrics passwordMetrics, int userHandle, boolean parent) { - final int requiredPasswordQuality = getPasswordQuality(null, userHandle, parent); + PasswordMetrics metrics, @UserIdInt int userId, boolean parent) { + final int requiredQuality = getPasswordQuality(null, userId, parent); - if (passwordMetrics.quality < requiredPasswordQuality) { - return false; - } - if (requiredPasswordQuality >= DevicePolicyManager.PASSWORD_QUALITY_NUMERIC - && passwordMetrics.length < getPasswordMinimumLength( - null, userHandle, parent)) { + if (requiredQuality >= PASSWORD_QUALITY_NUMERIC + && metrics.length < getPasswordMinimumLength(null, userId, parent)) { return false; } - if (requiredPasswordQuality != DevicePolicyManager.PASSWORD_QUALITY_COMPLEX) { - return true; + + // PASSWORD_QUALITY_COMPLEX doesn't represent actual password quality, it means that number + // of characters of each class should be checked instead of quality itself. + if (requiredQuality == PASSWORD_QUALITY_COMPLEX) { + return metrics.upperCase >= getPasswordMinimumUpperCase(null, userId, parent) + && metrics.lowerCase >= getPasswordMinimumLowerCase(null, userId, parent) + && metrics.letters >= getPasswordMinimumLetters(null, userId, parent) + && metrics.numeric >= getPasswordMinimumNumeric(null, userId, parent) + && metrics.symbols >= getPasswordMinimumSymbols(null, userId, parent) + && metrics.nonLetter >= getPasswordMinimumNonLetter(null, userId, parent); + } else { + return metrics.quality >= requiredQuality; } - return passwordMetrics.upperCase >= getPasswordMinimumUpperCase( - null, userHandle, parent) - && passwordMetrics.lowerCase >= getPasswordMinimumLowerCase( - null, userHandle, parent) - && passwordMetrics.letters >= getPasswordMinimumLetters( - null, userHandle, parent) - && passwordMetrics.numeric >= getPasswordMinimumNumeric( - null, userHandle, parent) - && passwordMetrics.symbols >= getPasswordMinimumSymbols( - null, userHandle, parent) - && passwordMetrics.nonLetter >= getPasswordMinimumNonLetter( - null, userHandle, parent); } @Override @@ -5042,14 +5044,13 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { int quality; synchronized (getLockObject()) { quality = getPasswordQuality(null, userHandle, /* parent */ false); - if (quality == DevicePolicyManager.PASSWORD_QUALITY_MANAGED) { + if (quality == PASSWORD_QUALITY_MANAGED) { quality = PASSWORD_QUALITY_UNSPECIFIED; } // TODO(b/120484642): remove getBytes() below final PasswordMetrics metrics = PasswordMetrics.computeForPassword(password.getBytes()); final int realQuality = metrics.quality; - if (realQuality < quality - && quality != DevicePolicyManager.PASSWORD_QUALITY_COMPLEX) { + if (realQuality < quality && quality != PASSWORD_QUALITY_COMPLEX) { Slog.w(LOG_TAG, "resetPassword: password quality 0x" + Integer.toHexString(realQuality) + " does not meet required quality 0x" @@ -5063,7 +5064,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { + " does not meet required length " + length); return false; } - if (quality == DevicePolicyManager.PASSWORD_QUALITY_COMPLEX) { + if (quality == PASSWORD_QUALITY_COMPLEX) { int neededLetters = getPasswordMinimumLetters(null, userHandle, /* parent */ false); if(metrics.letters < neededLetters) { Slog.w(LOG_TAG, "resetPassword: number of letters " + metrics.letters @@ -5132,11 +5133,14 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { final boolean result; try { if (token == null) { + // This is the legacy reset password for DPM. Here we want to be able to override + // the old device password without necessarily knowing it. if (!TextUtils.isEmpty(password)) { mLockPatternUtils.saveLockPassword(password.getBytes(), null, quality, - userHandle); + userHandle, /*allowUntrustedChange */true); } else { - mLockPatternUtils.clearLock(null, userHandle); + mLockPatternUtils.clearLock(null, userHandle, + /*allowUntrustedChange */ true); } result = true; } else { diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 419f52cff578..d4ccb0b77bca 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -849,7 +849,7 @@ public final class SystemServer { private void startOtherServices() { final Context context = mSystemContext; VibratorService vibrator = null; - DynamicAndroidService dynamicAndroid = null; + DynamicSystemService dynamicSystem = null; IStorageManager storageManager = null; NetworkManagementService networkManagement = null; IpSecService ipSecService = null; @@ -968,9 +968,9 @@ public final class SystemServer { ServiceManager.addService("vibrator", vibrator); traceEnd(); - traceBeginAndSlog("StartDynamicAndroidService"); - dynamicAndroid = new DynamicAndroidService(context); - ServiceManager.addService("dynamic_android", dynamicAndroid); + traceBeginAndSlog("StartDynamicSystemService"); + dynamicSystem = new DynamicSystemService(context); + ServiceManager.addService("dynamic_system", dynamicSystem); traceEnd(); if (!isWatch) { diff --git a/services/net/Android.bp b/services/net/Android.bp index 486d15d918bf..9e1d44b9faff 100644 --- a/services/net/Android.bp +++ b/services/net/Android.bp @@ -1,3 +1,61 @@ +// AIDL interfaces between the core system and the networking mainline module. +aidl_interface { + name: "ipmemorystore-aidl-interfaces", + local_include_dir: "java", + srcs: [ + // TODO: Define and use a filegroup for these files, since they're also used in + // networkstack-aidl-interfaces. This does not appear to work at the moment. + "java/android/net/IIpMemoryStore.aidl", + "java/android/net/IIpMemoryStoreCallbacks.aidl", + "java/android/net/ipmemorystore/**/*.aidl", + ], + backend: { + ndk: { + enabled: false, + }, + cpp: { + enabled: false, + }, + }, + api_dir: "aidl/networkstack", +} + +aidl_interface { + name: "networkstack-aidl-interfaces", + local_include_dir: "java", + include_dirs: ["frameworks/base/core/java"], // For framework parcelables. + srcs: [ + "java/android/net/ApfCapabilitiesParcelable.aidl", + "java/android/net/DhcpResultsParcelable.aidl", + "java/android/net/IIpMemoryStore.aidl", + "java/android/net/IIpMemoryStoreCallbacks.aidl", + "java/android/net/INetworkMonitor.aidl", + "java/android/net/INetworkMonitorCallbacks.aidl", + "java/android/net/INetworkStackConnector.aidl", + "java/android/net/INetworkStackStatusCallback.aidl", + "java/android/net/InitialConfigurationParcelable.aidl", + "java/android/net/PrivateDnsConfigParcel.aidl", + "java/android/net/ProvisioningConfigurationParcelable.aidl", + "java/android/net/StaticIpConfigurationParcelable.aidl", + "java/android/net/TcpKeepalivePacketDataParcelable.aidl", + "java/android/net/dhcp/DhcpServingParamsParcel.aidl", + "java/android/net/dhcp/IDhcpServer.aidl", + "java/android/net/dhcp/IDhcpServerCallbacks.aidl", + "java/android/net/ip/IIpClient.aidl", + "java/android/net/ip/IIpClientCallbacks.aidl", + "java/android/net/ipmemorystore/**/*.aidl", + ], + backend: { + ndk: { + enabled: false, + }, + cpp: { + enabled: false, + }, + }, + api_dir: "aidl/networkstack", +} + java_library_static { name: "services.net", srcs: ["java/**/*.java"], diff --git a/core/java/android/net/ApfCapabilitiesParcelable.aidl b/services/net/java/android/net/ApfCapabilitiesParcelable.aidl index f0645d2782d2..f0645d2782d2 100644 --- a/core/java/android/net/ApfCapabilitiesParcelable.aidl +++ b/services/net/java/android/net/ApfCapabilitiesParcelable.aidl diff --git a/core/java/android/net/DhcpResultsParcelable.aidl b/services/net/java/android/net/DhcpResultsParcelable.aidl index cf5629b6f792..cf5629b6f792 100644 --- a/core/java/android/net/DhcpResultsParcelable.aidl +++ b/services/net/java/android/net/DhcpResultsParcelable.aidl diff --git a/core/java/android/net/IIpMemoryStore.aidl b/services/net/java/android/net/IIpMemoryStore.aidl index 6f88dec8dee9..6f88dec8dee9 100644 --- a/core/java/android/net/IIpMemoryStore.aidl +++ b/services/net/java/android/net/IIpMemoryStore.aidl diff --git a/core/java/android/net/IIpMemoryStoreCallbacks.aidl b/services/net/java/android/net/IIpMemoryStoreCallbacks.aidl index 53108dbca097..53108dbca097 100644 --- a/core/java/android/net/IIpMemoryStoreCallbacks.aidl +++ b/services/net/java/android/net/IIpMemoryStoreCallbacks.aidl diff --git a/core/java/android/net/INetworkMonitor.aidl b/services/net/java/android/net/INetworkMonitor.aidl index 5d1ab983c5fc..1b0e1d788ff3 100644 --- a/core/java/android/net/INetworkMonitor.aidl +++ b/services/net/java/android/net/INetworkMonitor.aidl @@ -41,7 +41,7 @@ oneway interface INetworkMonitor { void start(); void launchCaptivePortalApp(); void notifyCaptivePortalAppFinished(int response); - void notifyAcceptPartialConnectivity(); + void setAcceptPartialConnectivity(); void forceReevaluation(int uid); void notifyPrivateDnsChanged(in PrivateDnsConfigParcel config); void notifyDnsResponse(int returnCode); diff --git a/core/java/android/net/INetworkMonitorCallbacks.aidl b/services/net/java/android/net/INetworkMonitorCallbacks.aidl index 2c61511feb72..2c61511feb72 100644 --- a/core/java/android/net/INetworkMonitorCallbacks.aidl +++ b/services/net/java/android/net/INetworkMonitorCallbacks.aidl diff --git a/core/java/android/net/INetworkStackConnector.aidl b/services/net/java/android/net/INetworkStackConnector.aidl index 3751c36d6ee9..3751c36d6ee9 100644 --- a/core/java/android/net/INetworkStackConnector.aidl +++ b/services/net/java/android/net/INetworkStackConnector.aidl diff --git a/core/java/android/net/INetworkStackStatusCallback.aidl b/services/net/java/android/net/INetworkStackStatusCallback.aidl index 51032d80a172..51032d80a172 100644 --- a/core/java/android/net/INetworkStackStatusCallback.aidl +++ b/services/net/java/android/net/INetworkStackStatusCallback.aidl diff --git a/core/java/android/net/InitialConfigurationParcelable.aidl b/services/net/java/android/net/InitialConfigurationParcelable.aidl index 3fa88c377a64..3fa88c377a64 100644 --- a/core/java/android/net/InitialConfigurationParcelable.aidl +++ b/services/net/java/android/net/InitialConfigurationParcelable.aidl diff --git a/core/java/android/net/PrivateDnsConfigParcel.aidl b/services/net/java/android/net/PrivateDnsConfigParcel.aidl index b52fce643302..b52fce643302 100644 --- a/core/java/android/net/PrivateDnsConfigParcel.aidl +++ b/services/net/java/android/net/PrivateDnsConfigParcel.aidl diff --git a/core/java/android/net/ProvisioningConfigurationParcelable.aidl b/services/net/java/android/net/ProvisioningConfigurationParcelable.aidl index 5b46d7f55ee3..5b46d7f55ee3 100644 --- a/core/java/android/net/ProvisioningConfigurationParcelable.aidl +++ b/services/net/java/android/net/ProvisioningConfigurationParcelable.aidl diff --git a/core/java/android/net/StaticIpConfigurationParcelable.aidl b/services/net/java/android/net/StaticIpConfigurationParcelable.aidl index 6fffb423edb5..6fffb423edb5 100644 --- a/core/java/android/net/StaticIpConfigurationParcelable.aidl +++ b/services/net/java/android/net/StaticIpConfigurationParcelable.aidl diff --git a/services/net/java/android/net/TcpKeepalivePacketData.java b/services/net/java/android/net/TcpKeepalivePacketData.java index 398a6b31cbce..d79ad1fe41a9 100644 --- a/services/net/java/android/net/TcpKeepalivePacketData.java +++ b/services/net/java/android/net/TcpKeepalivePacketData.java @@ -25,8 +25,8 @@ import android.os.Parcel; import android.os.Parcelable; import android.system.OsConstants; -import java.net.Inet4Address; import java.net.InetAddress; +import java.net.UnknownHostException; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.Objects; @@ -56,10 +56,10 @@ public class TcpKeepalivePacketData extends KeepalivePacketData implements Parce // This should only be constructed via static factory methods, such as // tcpKeepalivePacket. - private TcpKeepalivePacketData(TcpSocketInfo tcpDetails, byte[] data) - throws InvalidPacketException { - super(tcpDetails.srcAddress, tcpDetails.srcPort, tcpDetails.dstAddress, - tcpDetails.dstPort, data); + private TcpKeepalivePacketData(final TcpKeepalivePacketDataParcelable tcpDetails, + final byte[] data) throws InvalidPacketException, UnknownHostException { + super(InetAddress.getByAddress(tcpDetails.srcAddress), tcpDetails.srcPort, + InetAddress.getByAddress(tcpDetails.dstAddress), tcpDetails.dstPort, data); tcpSeq = tcpDetails.seq; tcpAck = tcpDetails.ack; // In the packet, the window is shifted right by the window scale. @@ -71,17 +71,22 @@ public class TcpKeepalivePacketData extends KeepalivePacketData implements Parce * Factory method to create tcp keepalive packet structure. */ public static TcpKeepalivePacketData tcpKeepalivePacket( - TcpSocketInfo tcpDetails) throws InvalidPacketException { + TcpKeepalivePacketDataParcelable tcpDetails) throws InvalidPacketException { final byte[] packet; - if ((tcpDetails.srcAddress instanceof Inet4Address) - && (tcpDetails.dstAddress instanceof Inet4Address)) { - packet = buildV4Packet(tcpDetails); - } else { - // TODO: support ipv6 + try { + if ((tcpDetails.srcAddress != null) && (tcpDetails.dstAddress != null) + && (tcpDetails.srcAddress.length == 4 /* V4 IP length */) + && (tcpDetails.dstAddress.length == 4 /* V4 IP length */)) { + packet = buildV4Packet(tcpDetails); + } else { + // TODO: support ipv6 + throw new InvalidPacketException(ERROR_INVALID_IP_ADDRESS); + } + return new TcpKeepalivePacketData(tcpDetails, packet); + } catch (UnknownHostException e) { throw new InvalidPacketException(ERROR_INVALID_IP_ADDRESS); } - return new TcpKeepalivePacketData(tcpDetails, packet); } /** @@ -89,7 +94,7 @@ public class TcpKeepalivePacketData extends KeepalivePacketData implements Parce */ // TODO : if this code is ever moved to the network stack, factorize constants with the ones // over there. - private static byte[] buildV4Packet(TcpSocketInfo tcpDetails) { + private static byte[] buildV4Packet(TcpKeepalivePacketDataParcelable tcpDetails) { final int length = IPV4_HEADER_LENGTH + TCP_HEADER_LENGTH; ByteBuffer buf = ByteBuffer.allocate(length); buf.order(ByteOrder.BIG_ENDIAN); @@ -102,8 +107,8 @@ public class TcpKeepalivePacketData extends KeepalivePacketData implements Parce buf.put((byte) OsConstants.IPPROTO_TCP); final int ipChecksumOffset = buf.position(); buf.putShort((short) 0); // IP checksum - buf.put(tcpDetails.srcAddress.getAddress()); - buf.put(tcpDetails.dstAddress.getAddress()); + buf.put(tcpDetails.srcAddress); + buf.put(tcpDetails.dstAddress); buf.putShort((short) tcpDetails.srcPort); buf.putShort((short) tcpDetails.dstPort); buf.putInt(tcpDetails.seq); // Sequence Number @@ -122,31 +127,6 @@ public class TcpKeepalivePacketData extends KeepalivePacketData implements Parce // TODO: add buildV6Packet. - /** Represents tcp/ip information. */ - // TODO: Replace TcpSocketInfo with TcpKeepalivePacketDataParcelable. - public static class TcpSocketInfo { - public final InetAddress srcAddress; - public final InetAddress dstAddress; - public final int srcPort; - public final int dstPort; - public final int seq; - public final int ack; - public final int rcvWnd; - public final int rcvWndScale; - - public TcpSocketInfo(InetAddress sAddr, int sPort, InetAddress dAddr, - int dPort, int writeSeq, int readSeq, int rWnd, int rWndScale) { - srcAddress = sAddr; - dstAddress = dAddr; - srcPort = sPort; - dstPort = dPort; - seq = writeSeq; - ack = readSeq; - rcvWnd = rWnd; - rcvWndScale = rWndScale; - } - } - @Override public boolean equals(@Nullable final Object o) { if (!(o instanceof TcpKeepalivePacketData)) return false; @@ -218,6 +198,8 @@ public class TcpKeepalivePacketData extends KeepalivePacketData implements Parce parcel.dstPort = dstPort; parcel.seq = tcpSeq; parcel.ack = tcpAck; + parcel.rcvWnd = tcpWnd; + parcel.rcvWndScale = tcpWndScale; return parcel; } diff --git a/core/java/android/net/TcpKeepalivePacketDataParcelable.aidl b/services/net/java/android/net/TcpKeepalivePacketDataParcelable.aidl index 7329c63b09be..d66b6ae3ab54 100644 --- a/core/java/android/net/TcpKeepalivePacketDataParcelable.aidl +++ b/services/net/java/android/net/TcpKeepalivePacketDataParcelable.aidl @@ -23,4 +23,6 @@ parcelable TcpKeepalivePacketDataParcelable { int dstPort; int seq; int ack; + int rcvWnd; + int rcvWndScale; } diff --git a/core/java/android/net/dhcp/DhcpServingParamsParcel.aidl b/services/net/java/android/net/dhcp/DhcpServingParamsParcel.aidl index 7b8b9ee324bc..7b8b9ee324bc 100644 --- a/core/java/android/net/dhcp/DhcpServingParamsParcel.aidl +++ b/services/net/java/android/net/dhcp/DhcpServingParamsParcel.aidl diff --git a/core/java/android/net/dhcp/IDhcpServer.aidl b/services/net/java/android/net/dhcp/IDhcpServer.aidl index 559433b13962..559433b13962 100644 --- a/core/java/android/net/dhcp/IDhcpServer.aidl +++ b/services/net/java/android/net/dhcp/IDhcpServer.aidl diff --git a/core/java/android/net/dhcp/IDhcpServerCallbacks.aidl b/services/net/java/android/net/dhcp/IDhcpServerCallbacks.aidl index 7ab4dcdbe584..7ab4dcdbe584 100644 --- a/core/java/android/net/dhcp/IDhcpServerCallbacks.aidl +++ b/services/net/java/android/net/dhcp/IDhcpServerCallbacks.aidl diff --git a/core/java/android/net/ip/IIpClient.aidl b/services/net/java/android/net/ip/IIpClient.aidl index b834e45c6852..b834e45c6852 100644 --- a/core/java/android/net/ip/IIpClient.aidl +++ b/services/net/java/android/net/ip/IIpClient.aidl diff --git a/core/java/android/net/ip/IIpClientCallbacks.aidl b/services/net/java/android/net/ip/IIpClientCallbacks.aidl index 3681416611a9..3681416611a9 100644 --- a/core/java/android/net/ip/IIpClientCallbacks.aidl +++ b/services/net/java/android/net/ip/IIpClientCallbacks.aidl diff --git a/services/net/java/android/net/ip/IpServer.java b/services/net/java/android/net/ip/IpServer.java index 0e44f88d2389..fc1128b80499 100644 --- a/services/net/java/android/net/ip/IpServer.java +++ b/services/net/java/android/net/ip/IpServer.java @@ -506,7 +506,7 @@ public class IpServer extends StateMachine { if (v6only != null) { params = new RaParams(); params.mtu = v6only.getMtu(); - params.hasDefaultRoute = v6only.hasIPv6DefaultRoute(); + params.hasDefaultRoute = v6only.hasIpv6DefaultRoute(); if (params.hasDefaultRoute) params.hopLimit = getHopLimit(v6only.getInterfaceName()); diff --git a/core/java/android/net/ipmemorystore/Blob.aidl b/services/net/java/android/net/ipmemorystore/Blob.aidl index 9dbef117f8a4..9dbef117f8a4 100644 --- a/core/java/android/net/ipmemorystore/Blob.aidl +++ b/services/net/java/android/net/ipmemorystore/Blob.aidl diff --git a/core/java/android/net/ipmemorystore/IOnBlobRetrievedListener.aidl b/services/net/java/android/net/ipmemorystore/IOnBlobRetrievedListener.aidl index 4926feb06e55..4926feb06e55 100644 --- a/core/java/android/net/ipmemorystore/IOnBlobRetrievedListener.aidl +++ b/services/net/java/android/net/ipmemorystore/IOnBlobRetrievedListener.aidl diff --git a/core/java/android/net/ipmemorystore/IOnL2KeyResponseListener.aidl b/services/net/java/android/net/ipmemorystore/IOnL2KeyResponseListener.aidl index dea0cc4e2586..dea0cc4e2586 100644 --- a/core/java/android/net/ipmemorystore/IOnL2KeyResponseListener.aidl +++ b/services/net/java/android/net/ipmemorystore/IOnL2KeyResponseListener.aidl diff --git a/core/java/android/net/ipmemorystore/IOnNetworkAttributesRetrieved.aidl b/services/net/java/android/net/ipmemorystore/IOnNetworkAttributesRetrieved.aidl index fb4ca3b97895..fb4ca3b97895 100644 --- a/core/java/android/net/ipmemorystore/IOnNetworkAttributesRetrieved.aidl +++ b/services/net/java/android/net/ipmemorystore/IOnNetworkAttributesRetrieved.aidl diff --git a/core/java/android/net/ipmemorystore/IOnSameNetworkResponseListener.aidl b/services/net/java/android/net/ipmemorystore/IOnSameNetworkResponseListener.aidl index 294bd3bd4012..294bd3bd4012 100644 --- a/core/java/android/net/ipmemorystore/IOnSameNetworkResponseListener.aidl +++ b/services/net/java/android/net/ipmemorystore/IOnSameNetworkResponseListener.aidl diff --git a/core/java/android/net/ipmemorystore/IOnStatusListener.aidl b/services/net/java/android/net/ipmemorystore/IOnStatusListener.aidl index 5d0750449ec5..5d0750449ec5 100644 --- a/core/java/android/net/ipmemorystore/IOnStatusListener.aidl +++ b/services/net/java/android/net/ipmemorystore/IOnStatusListener.aidl diff --git a/core/java/android/net/ipmemorystore/NetworkAttributesParcelable.aidl b/services/net/java/android/net/ipmemorystore/NetworkAttributesParcelable.aidl index 0894d7260915..0894d7260915 100644 --- a/core/java/android/net/ipmemorystore/NetworkAttributesParcelable.aidl +++ b/services/net/java/android/net/ipmemorystore/NetworkAttributesParcelable.aidl diff --git a/core/java/android/net/ipmemorystore/SameL3NetworkResponseParcelable.aidl b/services/net/java/android/net/ipmemorystore/SameL3NetworkResponseParcelable.aidl index 71966998a68a..71966998a68a 100644 --- a/core/java/android/net/ipmemorystore/SameL3NetworkResponseParcelable.aidl +++ b/services/net/java/android/net/ipmemorystore/SameL3NetworkResponseParcelable.aidl diff --git a/core/java/android/net/ipmemorystore/StatusParcelable.aidl b/services/net/java/android/net/ipmemorystore/StatusParcelable.aidl index fb36ef4a56ff..fb36ef4a56ff 100644 --- a/core/java/android/net/ipmemorystore/StatusParcelable.aidl +++ b/services/net/java/android/net/ipmemorystore/StatusParcelable.aidl diff --git a/services/net/java/android/net/shared/InitialConfiguration.java b/services/net/java/android/net/shared/InitialConfiguration.java index e423d62da7c9..007c8ca93d5a 100644 --- a/services/net/java/android/net/shared/InitialConfiguration.java +++ b/services/net/java/android/net/shared/InitialConfiguration.java @@ -207,7 +207,7 @@ public class InitialConfiguration { } private static boolean isIPv6GUA(LinkAddress addr) { - return addr.isIPv6() && addr.isGlobalPreferred(); + return addr.isIpv6() && addr.isGlobalPreferred(); } // TODO: extract out into CollectionUtils. diff --git a/services/robotests/backup/src/com/android/server/backup/TransportManagerTest.java b/services/robotests/backup/src/com/android/server/backup/TransportManagerTest.java index 9a6e003c1317..42115d437ee0 100644 --- a/services/robotests/backup/src/com/android/server/backup/TransportManagerTest.java +++ b/services/robotests/backup/src/com/android/server/backup/TransportManagerTest.java @@ -554,7 +554,7 @@ public class TransportManagerTest { transportManager.getTransportCurrentDestinationString(mTransportA1.transportName); Intent dataManagementIntent = transportManager.getTransportDataManagementIntent(mTransportA1.transportName); - String dataManagementLabel = + CharSequence dataManagementLabel = transportManager.getTransportDataManagementLabel(mTransportA1.transportName); String transportDirName = transportManager.getTransportDirName(mTransportA1.transportName); String transportDirNameByComponent = diff --git a/services/robotests/backup/src/com/android/server/backup/testing/TransportData.java b/services/robotests/backup/src/com/android/server/backup/testing/TransportData.java index 77f5d9a48c18..3c2981067fe8 100644 --- a/services/robotests/backup/src/com/android/server/backup/testing/TransportData.java +++ b/services/robotests/backup/src/com/android/server/backup/testing/TransportData.java @@ -75,7 +75,7 @@ public class TransportData { @Nullable public Intent configurationIntent; @Nullable public String currentDestinationString; @Nullable public Intent dataManagementIntent; - @Nullable public String dataManagementLabel; + @Nullable public CharSequence dataManagementLabel; private TransportData( @TransportStatus int transportStatus, @@ -85,7 +85,7 @@ public class TransportData { Intent configurationIntent, String currentDestinationString, Intent dataManagementIntent, - String dataManagementLabel) { + CharSequence dataManagementLabel) { this.transportStatus = transportStatus; this.transportName = transportName; this.transportComponentShort = transportComponentShort; @@ -103,7 +103,7 @@ public class TransportData { Intent configurationIntent, String currentDestinationString, Intent dataManagementIntent, - String dataManagementLabel) { + CharSequence dataManagementLabel) { this( TransportStatus.REGISTERED_AVAILABLE, transportName, diff --git a/services/robotests/backup/src/com/android/server/backup/testing/TransportTestUtils.java b/services/robotests/backup/src/com/android/server/backup/testing/TransportTestUtils.java index f6ed6307c82f..7dd5be53157b 100644 --- a/services/robotests/backup/src/com/android/server/backup/testing/TransportTestUtils.java +++ b/services/robotests/backup/src/com/android/server/backup/testing/TransportTestUtils.java @@ -188,7 +188,8 @@ public class TransportTestUtils { when(transportBinder.currentDestinationString()) .thenReturn(transport.currentDestinationString); when(transportBinder.dataManagementIntent()).thenReturn(transport.dataManagementIntent); - when(transportBinder.dataManagementLabel()).thenReturn(transport.dataManagementLabel); + when(transportBinder.dataManagementIntentLabel()) + .thenReturn(transport.dataManagementLabel); } catch (RemoteException e) { fail("RemoteException?"); } diff --git a/services/tests/servicestests/src/com/android/server/DynamicAndroidServiceTest.java b/services/tests/servicestests/src/com/android/server/DynamicSystemServiceTest.java index 149428443fa1..4a9dd9776a1b 100644 --- a/services/tests/servicestests/src/com/android/server/DynamicAndroidServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/DynamicSystemServiceTest.java @@ -16,28 +16,28 @@ package com.android.server; -import android.os.IDynamicAndroidService; import android.os.ServiceManager; +import android.os.image.IDynamicSystemService; import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.LargeTest; -public class DynamicAndroidServiceTest extends AndroidTestCase { - private static final String TAG = "DynamicAndroidServiceTests"; - private IDynamicAndroidService mService; +public class DynamicSystemServiceTest extends AndroidTestCase { + private static final String TAG = "DynamicSystemServiceTests"; + private IDynamicSystemService mService; @Override protected void setUp() throws Exception { mService = - IDynamicAndroidService.Stub.asInterface( - ServiceManager.getService("dynamic_android")); + IDynamicSystemService.Stub.asInterface( + ServiceManager.getService("dynamic_system")); } @LargeTest public void test1() { - assertTrue("dynamic_android service available", mService != null); + assertTrue("dynamic_system service available", mService != null); try { mService.startInstallation(1 << 20, 8 << 30); - fail("DynamicAndroidService did not throw SecurityException as expected"); + fail("DynamicSystemService did not throw SecurityException as expected"); } catch (SecurityException e) { // expected } catch (Exception e) { diff --git a/services/tests/servicestests/src/com/android/server/am/MemoryStatUtilTest.java b/services/tests/servicestests/src/com/android/server/am/MemoryStatUtilTest.java index 71b43973ea14..5fb762eadb49 100644 --- a/services/tests/servicestests/src/com/android/server/am/MemoryStatUtilTest.java +++ b/services/tests/servicestests/src/com/android/server/am/MemoryStatUtilTest.java @@ -310,6 +310,8 @@ public class MemoryStatUtilTest { @Test public void testParseIonHeapSizeFromDebugfs_invalidValue() { assertEquals(0, parseIonHeapSizeFromDebugfs("<<no-value>>")); + + assertEquals(0, parseIonHeapSizeFromDebugfs("\ntotal 12345678901234567890\n")); } @Test diff --git a/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java b/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java index 3e5ce46e8e3a..dd79aad52fd2 100644 --- a/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java +++ b/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java @@ -82,7 +82,7 @@ public class TrampolineTest { private static final String CURRENT_PASSWORD = "current_password"; private static final String NEW_PASSWORD = "new_password"; private static final String ENCRYPTION_PASSWORD = "encryption_password"; - private static final String DATA_MANAGEMENT_LABEL = "data_management_label"; + private static final CharSequence DATA_MANAGEMENT_LABEL = "data_management_label"; private static final String DESTINATION_STRING = "destination_string"; private static final String[] PACKAGE_NAMES = new String[]{"some.package.name._1", "some.package.name._2"}; @@ -1104,8 +1104,8 @@ public class TrampolineTest { } @Test - public void getDataManagementLabel_calledBeforeInitialize_ignored() throws Exception { - assertNull(mTrampoline.getDataManagementLabel(TRANSPORT_NAME)); + public void getDataManagementLabelForUser_calledBeforeInitialize_ignored() throws Exception { + assertNull(mTrampoline.getDataManagementLabelForUser(mUserId, TRANSPORT_NAME)); verifyNoMoreInteractions(mBackupManagerServiceMock); } @@ -1122,17 +1122,6 @@ public class TrampolineTest { } @Test - public void getDataManagementLabel_forwarded() throws Exception { - TrampolineTestable.sCallingUserId = mUserId; - when(mBackupManagerServiceMock.getDataManagementLabel(mUserId, TRANSPORT_NAME)).thenReturn( - DATA_MANAGEMENT_LABEL); - mTrampoline.initializeService(); - - assertEquals(DATA_MANAGEMENT_LABEL, mTrampoline.getDataManagementLabel(TRANSPORT_NAME)); - verify(mBackupManagerServiceMock).getDataManagementLabel(mUserId, TRANSPORT_NAME); - } - - @Test public void beginRestoreSession_calledBeforeInitialize_ignored() throws Exception { mTrampoline.beginRestoreSessionForUser(mUserId, PACKAGE_NAME, TRANSPORT_NAME); verifyNoMoreInteractions(mBackupManagerServiceMock); diff --git a/services/tests/servicestests/src/com/android/server/backup/testutils/IPackageManagerStub.java b/services/tests/servicestests/src/com/android/server/backup/testutils/IPackageManagerStub.java index caf6c9cac509..4b3d9cf59487 100644 --- a/services/tests/servicestests/src/com/android/server/backup/testutils/IPackageManagerStub.java +++ b/services/tests/servicestests/src/com/android/server/backup/testutils/IPackageManagerStub.java @@ -1068,6 +1068,12 @@ public class IPackageManagerStub implements IPackageManager { } @Override + public ParceledListSlice getDeclaredSharedLibraries(String packageName, int flags, int userId) + throws RemoteException { + return null; + } + + @Override public boolean canRequestPackageInstalls(String packageName, int userId) throws RemoteException { return false; diff --git a/services/tests/servicestests/src/com/android/server/locksettings/CachedSyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/CachedSyntheticPasswordTests.java index 94d21ddeaa2b..ca4330fa7a5d 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/CachedSyntheticPasswordTests.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/CachedSyntheticPasswordTests.java @@ -61,12 +61,12 @@ public class CachedSyntheticPasswordTests extends SyntheticPasswordTests { long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID); // clear password mService.setLockCredential(null, LockPatternUtils.CREDENTIAL_TYPE_NONE, null, - PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID); + PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID, true); assertEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID)); // set a new password mService.setLockCredential(newPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null, - PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID); + PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false); assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(newPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID) .getResponseCode()); @@ -81,7 +81,7 @@ public class CachedSyntheticPasswordTests extends SyntheticPasswordTests { long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID); // Untrusted change password mService.setLockCredential(newPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null, - PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID); + PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, true); assertNotEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID)); assertNotEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID)); @@ -99,7 +99,7 @@ public class CachedSyntheticPasswordTests extends SyntheticPasswordTests { initializeCredentialUnderSP(password, PRIMARY_USER_ID); // Untrusted change password mService.setLockCredential(newPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null, - PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID); + PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, true); // Verify the password assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(newPassword, @@ -124,10 +124,12 @@ public class CachedSyntheticPasswordTests extends SyntheticPasswordTests { initializeCredentialUnderSP(password, PRIMARY_USER_ID); long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID); // Untrusted change password - assertExpectException(IllegalStateException.class, /* messageRegex= */ null, + assertExpectException( + IllegalStateException.class, + /* messageRegex= */ "Untrusted credential reset not possible without cached SP", () -> mService.setLockCredential(newPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null, - PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID)); + PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, true)); assertEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID)); // Verify the new password doesn't work but the old one still does diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java index 6e0ba3cb366c..255e694bffaf 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java @@ -85,9 +85,9 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests { try { mService.setLockCredential("newpwd".getBytes(), CREDENTIAL_TYPE_PASSWORD, - "badpwd".getBytes(), PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID); + "badpwd".getBytes(), PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false); fail("Did not fail when enrolling using incorrect credential"); - } catch (RemoteException expected) { + } catch (IllegalStateException expected) { assertTrue(expected.getMessage().equals(FAILED_MESSAGE)); } assertVerifyCredentials(PRIMARY_USER_ID, "password", CREDENTIAL_TYPE_PASSWORD, sid); @@ -97,7 +97,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests { final String PASSWORD = "password"; initializeStorageWithCredential(PRIMARY_USER_ID, PASSWORD, CREDENTIAL_TYPE_PASSWORD, 1234); mService.setLockCredential(null, CREDENTIAL_TYPE_NONE, PASSWORD.getBytes(), - PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID); + PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID, false); assertFalse(mService.havePassword(PRIMARY_USER_ID)); assertFalse(mService.havePattern(PRIMARY_USER_ID)); assertEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID)); @@ -108,7 +108,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests { final String secondUnifiedPassword = "testManagedProfileUnifiedChallenge-pwd-2"; mService.setLockCredential(firstUnifiedPassword.getBytes(), LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, - null, PASSWORD_QUALITY_COMPLEX, PRIMARY_USER_ID); + null, PASSWORD_QUALITY_COMPLEX, PRIMARY_USER_ID, false); mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null); final long primarySid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID); final long profileSid = mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID); @@ -143,15 +143,16 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests { mStorageManager.setIgnoreBadUnlock(true); // Change primary password and verify that profile SID remains mService.setLockCredential(secondUnifiedPassword.getBytes(), - LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, - firstUnifiedPassword.getBytes(), PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID); + LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, firstUnifiedPassword.getBytes(), + PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false); mStorageManager.setIgnoreBadUnlock(false); assertEquals(profileSid, mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID)); assertNull(mGateKeeperService.getAuthToken(TURNED_OFF_PROFILE_USER_ID)); // Clear unified challenge mService.setLockCredential(null, LockPatternUtils.CREDENTIAL_TYPE_NONE, - secondUnifiedPassword.getBytes(), PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID); + secondUnifiedPassword.getBytes(), PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID, + false); assertEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID)); assertEquals(0, mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID)); assertEquals(0, mGateKeeperService.getSecureUserId(TURNED_OFF_PROFILE_USER_ID)); @@ -162,7 +163,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests { final String profilePassword = "testManagedProfileSeparateChallenge-profile"; mService.setLockCredential(primaryPassword.getBytes(), LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null, - PASSWORD_QUALITY_COMPLEX, PRIMARY_USER_ID); + PASSWORD_QUALITY_COMPLEX, PRIMARY_USER_ID, false); /* Currently in LockSettingsService.setLockCredential, unlockUser() is called with the new * credential as part of verifyCredential() before the new credential is committed in * StorageManager. So we relax the check in our mock StorageManager to allow that. @@ -170,7 +171,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests { mStorageManager.setIgnoreBadUnlock(true); mService.setLockCredential(profilePassword.getBytes(), LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null, - PASSWORD_QUALITY_COMPLEX, MANAGED_PROFILE_USER_ID); + PASSWORD_QUALITY_COMPLEX, MANAGED_PROFILE_USER_ID, false); mStorageManager.setIgnoreBadUnlock(false); final long primarySid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID); @@ -197,7 +198,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests { // Change primary credential and make sure we don't affect profile mStorageManager.setIgnoreBadUnlock(true); mService.setLockCredential("pwd".getBytes(), LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, - primaryPassword.getBytes(), PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID); + primaryPassword.getBytes(), PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false); mStorageManager.setIgnoreBadUnlock(false); assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential( profilePassword.getBytes(), LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, @@ -208,7 +209,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests { private void testCreateCredential(int userId, String credential, int type, int quality) throws RemoteException { mService.setLockCredential(credential.getBytes(), type, null, quality, - userId); + userId, false); assertVerifyCredentials(userId, credential, type, -1); } @@ -218,7 +219,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests { try { mService.setLockCredential(credential.getBytes(), type, null, quality, - userId); + userId, false); fail("An exception should have been thrown."); } catch (UnsupportedOperationException e) { // Success - the exception was expected. @@ -233,7 +234,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests { final long sid = 1234; initializeStorageWithCredential(userId, oldCredential, oldType, sid); mService.setLockCredential(newCredential.getBytes(), newType, oldCredential.getBytes(), - quality, userId); + quality, userId, false); assertVerifyCredentials(userId, newCredential, newType, sid); } diff --git a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java index 6a07a45ed360..58055e58fce3 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java @@ -102,7 +102,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { disableSyntheticPassword(); mService.setLockCredential(password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null, - PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID); + PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false); long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID); final byte[] primaryStorageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID); enableSyntheticPassword(); @@ -127,7 +127,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { : PASSWORD_QUALITY_UNSPECIFIED; int type = password != null ? LockPatternUtils.CREDENTIAL_TYPE_PASSWORD : LockPatternUtils.CREDENTIAL_TYPE_NONE; - mService.setLockCredential(password, type, null, quality, userId); + mService.setLockCredential(password, type, null, quality, userId, false); } public void testSyntheticPasswordChangeCredential() throws RemoteException { @@ -137,7 +137,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { initializeCredentialUnderSP(password, PRIMARY_USER_ID); long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID); mService.setLockCredential(newPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, password, - PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID); + PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false); assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential( newPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID) .getResponseCode()); @@ -166,12 +166,12 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID); // clear password mService.setLockCredential(null, LockPatternUtils.CREDENTIAL_TYPE_NONE, password, - PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID); + PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID, false); assertEquals(0 ,mGateKeeperService.getSecureUserId(PRIMARY_USER_ID)); // set a new password mService.setLockCredential(badPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null, - PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID); + PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false); assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential( badPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID) .getResponseCode()); @@ -186,7 +186,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { initializeCredentialUnderSP(password, PRIMARY_USER_ID); mService.setLockCredential(badPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, password, - PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID); + PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false); assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential( badPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID) .getResponseCode()); @@ -245,7 +245,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { final byte[] password = "getASyntheticPassword".getBytes(); initializeCredentialUnderSP(password, PRIMARY_USER_ID); mService.setLockCredential(null, LockPatternUtils.CREDENTIAL_TYPE_NONE, password, - PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID); + PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID, false); reset(mAuthSecretService); mService.onUnlockUser(PRIMARY_USER_ID); @@ -257,7 +257,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { final byte[] UnifiedPassword = "testManagedProfileUnifiedChallengeMigration-pwd".getBytes(); disableSyntheticPassword(); mService.setLockCredential(UnifiedPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null, - PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID); + PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false); mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null); final long primarySid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID); final long profileSid = mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID); @@ -294,9 +294,9 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { "testManagedProfileSeparateChallengeMigration-profile".getBytes(); disableSyntheticPassword(); mService.setLockCredential(primaryPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null, - PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID); + PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false); mService.setLockCredential(profilePassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null, - PASSWORD_QUALITY_ALPHABETIC, MANAGED_PROFILE_USER_ID); + PASSWORD_QUALITY_ALPHABETIC, MANAGED_PROFILE_USER_ID, false); final long primarySid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID); final long profileSid = mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID); final byte[] primaryStorageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID); @@ -404,7 +404,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID)); mService.setLockCredential(pattern, LockPatternUtils.CREDENTIAL_TYPE_PATTERN, password, - PASSWORD_QUALITY_SOMETHING, PRIMARY_USER_ID); + PASSWORD_QUALITY_SOMETHING, PRIMARY_USER_ID, false); mLocalService.setLockCredentialWithToken(newPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, handle, token, @@ -443,7 +443,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { // Set up pre-SP user password disableSyntheticPassword(); mService.setLockCredential(password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null, - PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID); + PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false); enableSyntheticPassword(); long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null); @@ -491,12 +491,12 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { public void testgetHashFactorPrimaryUser() throws RemoteException { final byte[] password = "password".getBytes(); mService.setLockCredential(password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null, - PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID); + PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false); final byte[] hashFactor = mService.getHashFactor(password, PRIMARY_USER_ID); assertNotNull(hashFactor); mService.setLockCredential(null, LockPatternUtils.CREDENTIAL_TYPE_NONE, - password, PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID); + password, PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID, false); final byte[] newHashFactor = mService.getHashFactor(null, PRIMARY_USER_ID); assertNotNull(newHashFactor); // Hash factor should never change after password change/removal @@ -506,7 +506,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { public void testgetHashFactorManagedProfileUnifiedChallenge() throws RemoteException { final byte[] pattern = "1236".getBytes(); mService.setLockCredential(pattern, LockPatternUtils.CREDENTIAL_TYPE_PATTERN, - null, PASSWORD_QUALITY_SOMETHING, PRIMARY_USER_ID); + null, PASSWORD_QUALITY_SOMETHING, PRIMARY_USER_ID, false); mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null); assertNotNull(mService.getHashFactor(null, MANAGED_PROFILE_USER_ID)); } @@ -515,9 +515,9 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { final byte[] primaryPassword = "primary".getBytes(); final byte[] profilePassword = "profile".getBytes(); mService.setLockCredential(primaryPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null, - PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID); + PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false); mService.setLockCredential(profilePassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null, - PASSWORD_QUALITY_ALPHABETIC, MANAGED_PROFILE_USER_ID); + PASSWORD_QUALITY_ALPHABETIC, MANAGED_PROFILE_USER_ID, false); assertNotNull(mService.getHashFactor(profilePassword, MANAGED_PROFILE_USER_ID)); } diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java index 6f967593e6f1..a8da80efa35f 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -391,7 +391,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { mBinderService.createNotificationChannels( PKG, new ParceledListSlice(Arrays.asList(mTestNotificationChannel))); - assertNotNull(mBinderService.getNotificationChannel(PKG, TEST_CHANNEL_ID)); + assertNotNull(mBinderService.getNotificationChannel( + PKG, mContext.getUserId(), PKG, TEST_CHANNEL_ID)); } @After @@ -497,7 +498,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { mBinderService.createNotificationChannels(PKG, new ParceledListSlice(Arrays.asList(channel))); final NotificationChannel createdChannel = - mBinderService.getNotificationChannel(PKG, "id"); + mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id"); assertTrue(createdChannel != null); } @@ -520,8 +521,10 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { new NotificationChannel("id2", "name", IMPORTANCE_DEFAULT); mBinderService.createNotificationChannels(PKG, new ParceledListSlice(Arrays.asList(channel1, channel2))); - assertTrue(mBinderService.getNotificationChannel(PKG, "id1") != null); - assertTrue(mBinderService.getNotificationChannel(PKG, "id2") != null); + assertTrue(mBinderService.getNotificationChannel( + PKG, mContext.getUserId(), PKG, "id1") != null); + assertTrue(mBinderService.getNotificationChannel( + PKG, mContext.getUserId(), PKG, "id2") != null); } @Test @@ -538,7 +541,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { mBinderService.createNotificationChannels(PKG, new ParceledListSlice(Arrays.asList(dupeChannel))); final NotificationChannel createdChannel = - mBinderService.getNotificationChannel(PKG, "id"); + mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id"); assertEquals(IMPORTANCE_DEFAULT, createdChannel.getImportance()); } @@ -556,7 +559,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { mBinderService.createNotificationChannels(PKG, new ParceledListSlice(Arrays.asList(dupeChannel))); final NotificationChannel createdChannel = - mBinderService.getNotificationChannel(PKG, "id"); + mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id"); assertEquals(NotificationManager.IMPORTANCE_LOW, createdChannel.getImportance()); } @@ -579,7 +582,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { mBinderService.createNotificationChannels(PKG, new ParceledListSlice(Arrays.asList(dupeChannel))); final NotificationChannel createdChannel = - mBinderService.getNotificationChannel(PKG, "id"); + mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id"); assertEquals(IMPORTANCE_HIGH, createdChannel.getImportance()); } @@ -593,7 +596,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { mBinderService.createNotificationChannels(PKG, new ParceledListSlice(Arrays.asList(channel1, channel2))); final NotificationChannel createdChannel = - mBinderService.getNotificationChannel(PKG, "id"); + mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id"); assertEquals(IMPORTANCE_DEFAULT, createdChannel.getImportance()); } @@ -646,8 +649,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { assertEquals(1, mBinderService.getActiveNotifications(sbn.getPackageName()).length); assertEquals(IMPORTANCE_LOW, mService.getNotificationRecord(sbn.getKey()).getImportance()); - assertEquals(IMPORTANCE_LOW, - mBinderService.getNotificationChannel(PKG, channel.getId()).getImportance()); + assertEquals(IMPORTANCE_LOW, mBinderService.getNotificationChannel( + PKG, mContext.getUserId(), PKG, channel.getId()).getImportance()); } @Test @@ -664,8 +667,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { new NotificationChannel("blockedbyuser", "name", IMPORTANCE_NONE); mBinderService.updateNotificationChannelForPackage(PKG, mUid, update); waitForIdle(); - assertEquals(IMPORTANCE_NONE, - mBinderService.getNotificationChannel(PKG, channel.getId()).getImportance()); + assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel( + PKG, mContext.getUserId(), PKG, channel.getId()).getImportance()); StatusBarNotification sbn = generateNotificationRecord(channel).sbn; sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; @@ -677,8 +680,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { assertEquals(1, mBinderService.getActiveNotifications(sbn.getPackageName()).length); assertEquals(IMPORTANCE_LOW, mService.getNotificationRecord(sbn.getKey()).getImportance()); - assertEquals(IMPORTANCE_LOW, - mBinderService.getNotificationChannel(PKG, channel.getId()).getImportance()); + assertEquals(IMPORTANCE_LOW, mBinderService.getNotificationChannel( + PKG, mContext.getUserId(), PKG, channel.getId()).getImportance()); mBinderService.cancelNotificationWithTag(PKG, "tag", sbn.getId(), sbn.getUserId()); waitForIdle(); @@ -686,8 +689,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { update.setFgServiceShown(true); mBinderService.updateNotificationChannelForPackage(PKG, mUid, update); waitForIdle(); - assertEquals(IMPORTANCE_NONE, - mBinderService.getNotificationChannel(PKG, channel.getId()).getImportance()); + assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel( + PKG, mContext.getUserId(), PKG, channel.getId()).getImportance()); sbn = generateNotificationRecord(channel).sbn; sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; @@ -697,8 +700,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { // The second time it is shown, we keep the user's preference. assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length); assertNull(mService.getNotificationRecord(sbn.getKey())); - assertEquals(IMPORTANCE_NONE, - mBinderService.getNotificationChannel(PKG, channel.getId()).getImportance()); + assertEquals(IMPORTANCE_NONE, mBinderService.getNotificationChannel( + PKG, mContext.getUserId(), PKG, channel.getId()).getImportance()); } @Test @@ -2692,7 +2695,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { mService.getNotificationRecord(sbn.getKey()).getImportance()); NotificationChannel defaultChannel = mBinderService.getNotificationChannel( - preOPkg, NotificationChannel.DEFAULT_CHANNEL_ID); + preOPkg, mContext.getUserId(), preOPkg, NotificationChannel.DEFAULT_CHANNEL_ID); assertEquals(IMPORTANCE_UNSPECIFIED, defaultChannel.getImportance()); } @@ -4192,6 +4195,25 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { } @Test + public void testgetNotificationChannels_crossUser() throws Exception { + // same user no problem + mBinderService.getNotificationChannels("src", "target", mContext.getUserId()); + + // cross user, no permission, problem + try { + mBinderService.getNotificationChannels("src", "target", mContext.getUserId() + 1); + fail("Should not be callable cross user without cross user permission"); + } catch (SecurityException e) { + // good + } + + // cross user, with permission, no problem + TestablePermissions perms = mContext.getTestablePermissions(); + perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED); + mBinderService.getNotificationChannels("src", "target", mContext.getUserId() + 1); + } + + @Test public void setDefaultAssistantForUser_fromConfigXml() { clearDeviceConfig(); ComponentName xmlConfig = new ComponentName("config", "xml"); @@ -4264,4 +4286,18 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { componentName, false); } + + public void testGetAllowedAssistantCapabilities() throws Exception { + List<String> capabilities = mBinderService.getAllowedAssistantCapabilities(null); + assertNotNull(capabilities); + + for (int i = capabilities.size() - 1; i >= 0; i--) { + String capability = capabilities.get(i); + mBinderService.disallowAssistantCapability(capability); + assertEquals(i + 1, mBinderService.getAllowedAssistantCapabilities(null).size()); + List<String> currentCapabilities = mBinderService.getAllowedAssistantCapabilities(null); + assertNotNull(currentCapabilities); + assertFalse(currentCapabilities.contains(capability)); + } + } } diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java index 4279c4152836..03969dad67c5 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java @@ -50,6 +50,7 @@ import android.view.WindowManager; import androidx.test.filters.SmallTest; +import com.android.server.policy.WindowManagerPolicy; import com.android.server.wm.utils.WmDisplayCutout; import org.junit.Before; @@ -476,6 +477,28 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { } } + @Test + public void forceShowSystemBars_clearsSystemUIFlags() { + synchronized (mWm.mGlobalLock) { + mDisplayPolicy.mLastSystemUiFlags |= SYSTEM_UI_FLAG_FULLSCREEN; + mWindow.mAttrs.subtreeSystemUiVisibility |= SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; + mWindow.mAttrs.flags |= FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; + mWindow.mSystemUiVisibility = SYSTEM_UI_FLAG_FULLSCREEN; + mDisplayPolicy.setForceShowSystemBars(true); + addWindow(mWindow); + + mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); + mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); + // triggers updateSystemUiVisibilityLw which will reset the flags as needed + int finishPostLayoutPolicyLw = mDisplayPolicy.focusChangedLw(mWindow, mWindow); + + assertEquals(WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT, finishPostLayoutPolicyLw); + assertEquals(0, mDisplayPolicy.mLastSystemUiFlags); + assertEquals(0, mWindow.mAttrs.systemUiVisibility); + assertInsetByTopBottom(mWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); + } + } + /** * Asserts that {@code actual} is inset by the given amounts from the full display rect. * diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java index a03d28b47057..e392353a8875 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java @@ -20,17 +20,23 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.view.Display.DEFAULT_DISPLAY; +import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; import static com.android.dx.mockito.inline.extended.ExtendedMockito.atLeast; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verifyNoMoreInteractions; import static com.android.dx.mockito.inline.extended.ExtendedMockito.when; import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_IN_PLACE; import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_ORIGINAL_POSITION; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.eq; import android.os.Binder; @@ -67,7 +73,11 @@ public class RecentsAnimationControllerTest extends WindowTestsBase { @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); - + synchronized (mWm.mGlobalLock) { + // Hold the lock to protect the stubbing from being accessed by other threads. + spyOn(mWm.mRoot); + doNothing().when(mWm.mRoot).performSurfacePlacement(anyBoolean()); + } when(mMockRunner.asBinder()).thenReturn(new Binder()); mController = new RecentsAnimationController(mWm, mMockRunner, mAnimationCallbacks, DEFAULT_DISPLAY); @@ -88,7 +98,7 @@ public class RecentsAnimationControllerTest extends WindowTestsBase { // Verify that the finish callback to reparent the leash is called verify(mFinishedCallback).onAnimationFinished(eq(adapter)); // Verify the animation canceled callback to the app was made - verify(mMockRunner).onAnimationCanceled(); + verify(mMockRunner).onAnimationCanceled(false); verifyNoMoreInteractionsExceptAsBinder(mMockRunner); } @@ -131,6 +141,31 @@ public class RecentsAnimationControllerTest extends WindowTestsBase { assertFalse(mController.isAnimatingTask(hiddenAppWindow.getTask())); } + @Test + public void testCancelAnimationWithScreenShot() throws Exception { + mWm.setRecentsAnimationController(mController); + final AppWindowToken appWindow = createAppWindowToken(mDisplayContent, + WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD); + final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, appWindow, "win1"); + appWindow.addWindow(win1); + assertEquals(appWindow.getTask().getTopVisibleAppToken(), appWindow); + assertEquals(appWindow.findMainWindow(), win1); + + mController.addAnimation(appWindow.getTask(), false /* isRecentTaskInvisible */); + assertTrue(mController.isAnimatingTask(appWindow.getTask())); + + mController.setCancelWithDeferredScreenshotLocked(true); + mController.cancelAnimationWithScreenShot(); + verify(mMockRunner).onAnimationCanceled(true /* deferredWithScreenshot */); + assertNotNull(mController.mRecentScreenshotAnimator); + assertTrue(mController.mRecentScreenshotAnimator.isAnimating()); + + // Assume IRecentsAnimationController#cleanupScreenshot called to finish screenshot + // animation. + mController.mRecentScreenshotAnimator.cancelAnimation(); + verify(mAnimationCallbacks).onAnimationFinished(REORDER_KEEP_IN_PLACE, true); + } + private static void verifyNoMoreInteractionsExceptAsBinder(IInterface binder) { verify(binder, atLeast(0)).asBinder(); verifyNoMoreInteractions(binder); diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java index 5f3a29032c22..5625ea42726f 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java @@ -20,7 +20,6 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; -import static com.android.dx.mockito.inline.extended.ExtendedMockito.any; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; @@ -29,6 +28,8 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.times; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_IN_PLACE; +import static org.mockito.ArgumentMatchers.any; + import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -51,11 +52,15 @@ public class RecentsAnimationTest extends ActivityTestsBase { private Context mContext = InstrumentationRegistry.getContext(); private ComponentName mRecentsComponent; + private RecentsAnimationController mRecentsAnimationController; @Before public void setUp() throws Exception { mRecentsComponent = new ComponentName(mContext.getPackageName(), "RecentsActivity"); mService = new TestActivityTaskManagerService(mContext); + mRecentsAnimationController = mock(RecentsAnimationController.class); + doReturn(mRecentsAnimationController).when( + mService.mWindowManager).getRecentsAnimationController(); final RecentTasks recentTasks = mService.getRecentTasks(); spyOn(recentTasks); @@ -96,9 +101,18 @@ public class RecentsAnimationTest extends ActivityTestsBase { fullscreenStack.moveToFront("Activity start"); - // Ensure that the recents animation was canceled + // Ensure that the recents animation was canceled by cancelAnimationSynchronously(). verify(mService.mWindowManager, times(1)).cancelRecentsAnimationSynchronously( eq(REORDER_KEEP_IN_PLACE), any()); + + // Assume recents animation already started, set a state that cancel recents animation + // with screenshot. + doReturn(true).when(mRecentsAnimationController).shouldCancelWithDeferredScreenshot(); + // Start another fullscreen activity. + fullscreenStack2.moveToFront("Activity start"); + + // Ensure that the recents animation was canceled by cancelOnNextTransitionStart(). + verify(mRecentsAnimationController, times(1)).cancelOnNextTransitionStart(); } @Test @@ -137,5 +151,6 @@ public class RecentsAnimationTest extends ActivityTestsBase { // Ensure that the recents animation was NOT canceled verify(mService.mWindowManager, times(0)).cancelRecentsAnimationSynchronously( eq(REORDER_KEEP_IN_PLACE), any()); + verify(mRecentsAnimationController, times(0)).cancelOnNextTransitionStart(); } } diff --git a/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java b/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java index c5df85c554f4..83aa620b9573 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java +++ b/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java @@ -38,7 +38,7 @@ public class TestIWindow extends IWindow.Stub { @Override public void resized(Rect frame, Rect overscanInsets, Rect contentInsets, Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw, MergedConfiguration mergedConfig, - Rect backDropFrame, boolean forceLayout, boolean alwaysConsumeNavBar, int displayId, + Rect backDropFrame, boolean forceLayout, boolean alwaysConsumeSystemBars, int displayId, DisplayCutout.ParcelableWrapper displayCutout) throws RemoteException { } diff --git a/startop/view_compiler/Android.bp b/startop/view_compiler/Android.bp index f5b4308a1b50..92ea872f04fc 100644 --- a/startop/view_compiler/Android.bp +++ b/startop/view_compiler/Android.bp @@ -22,7 +22,6 @@ cc_defaults { ], shared_libs: [ "libbase", - "libz", "slicer", ], static_libs: [ diff --git a/telecomm/java/android/telecom/Log.java b/telecomm/java/android/telecom/Log.java index 16791a4b8680..7d4ee7686512 100644 --- a/telecomm/java/android/telecom/Log.java +++ b/telecomm/java/android/telecom/Log.java @@ -16,6 +16,7 @@ package android.telecom; +import android.annotation.UnsupportedAppUsage; import android.content.Context; import android.net.Uri; import android.os.Build; @@ -97,6 +98,7 @@ public class Log { } } + @UnsupportedAppUsage public static void i(String prefix, String format, Object... args) { if (INFO) { android.util.Slog.i(TAG, buildMessage(prefix, format, args)); @@ -127,6 +129,7 @@ public class Log { } } + @UnsupportedAppUsage public static void w(String prefix, String format, Object... args) { if (WARN) { android.util.Slog.w(TAG, buildMessage(prefix, format, args)); diff --git a/telephony/java/android/telephony/AccessNetworkConstants.java b/telephony/java/android/telephony/AccessNetworkConstants.java index 81553a3bc0f8..afa35b4d4de3 100644 --- a/telephony/java/android/telephony/AccessNetworkConstants.java +++ b/telephony/java/android/telephony/AccessNetworkConstants.java @@ -18,6 +18,7 @@ package android.telephony; import android.annotation.IntDef; import android.annotation.SystemApi; +import android.annotation.TestApi; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -51,6 +52,7 @@ public final class AccessNetworkConstants { * @hide */ @SystemApi + @TestApi public static final int TRANSPORT_TYPE_WWAN = 1; /** @@ -58,6 +60,7 @@ public final class AccessNetworkConstants { * @hide */ @SystemApi + @TestApi public static final int TRANSPORT_TYPE_WLAN = 2; /** @hide */ diff --git a/telephony/java/android/telephony/CellIdentityTdscdma.java b/telephony/java/android/telephony/CellIdentityTdscdma.java index 10ffb804c8d0..19b11b666018 100644 --- a/telephony/java/android/telephony/CellIdentityTdscdma.java +++ b/telephony/java/android/telephony/CellIdentityTdscdma.java @@ -16,6 +16,7 @@ package android.telephony; +import android.annotation.NonNull; import android.annotation.Nullable; import android.os.Parcel; import android.telephony.gsm.GsmCellLocation; @@ -205,6 +206,12 @@ public final class CellIdentityTdscdma extends CellIdentity { /** Implement the Parcelable interface */ @Override + public int describeContents() { + return 0; + } + + /** Implement the Parcelable interface */ + @Override public void writeToParcel(Parcel dest, int flags) { if (DBG) log("writeToParcel(Parcel, int): " + toString()); super.writeToParcel(dest, CellInfo.TYPE_TDSCDMA); @@ -226,16 +233,17 @@ public final class CellIdentityTdscdma extends CellIdentity { /** Implement the Parcelable interface */ @SuppressWarnings("hiding") - public static final @android.annotation.NonNull Creator<CellIdentityTdscdma> CREATOR = + @NonNull + public static final Creator<CellIdentityTdscdma> CREATOR = new Creator<CellIdentityTdscdma>() { @Override - public CellIdentityTdscdma createFromParcel(Parcel in) { + public @NonNull CellIdentityTdscdma createFromParcel(Parcel in) { in.readInt(); // skip return createFromParcelBody(in); } @Override - public CellIdentityTdscdma[] newArray(int size) { + public @NonNull CellIdentityTdscdma[] newArray(int size) { return new CellIdentityTdscdma[size]; } }; diff --git a/telephony/java/android/telephony/CellInfoTdscdma.java b/telephony/java/android/telephony/CellInfoTdscdma.java index 93baabf34c16..1830086ba448 100644 --- a/telephony/java/android/telephony/CellInfoTdscdma.java +++ b/telephony/java/android/telephony/CellInfoTdscdma.java @@ -16,6 +16,7 @@ package android.telephony; +import android.annotation.NonNull; import android.os.Parcel; import android.os.Parcelable; @@ -24,7 +25,9 @@ import java.util.Objects; /** * A {@link CellInfo} representing a TD-SCDMA cell that provides identity and measurement info. * - * @hide + * @see android.telephony.CellInfo + * @see android.telephony.CellSignalStrengthTdscdma + * @see android.telephony.CellIdentityTdscdma */ public final class CellInfoTdscdma extends CellInfo implements Parcelable { @@ -72,18 +75,21 @@ public final class CellInfoTdscdma extends CellInfo implements Parcelable { mCellSignalStrengthTdscdma = new CellSignalStrengthTdscdma(cit.signalStrengthTdscdma); } - @Override public CellIdentityTdscdma getCellIdentity() { + @Override + public @NonNull CellIdentityTdscdma getCellIdentity() { return mCellIdentityTdscdma; } + /** @hide */ public void setCellIdentity(CellIdentityTdscdma cid) { mCellIdentityTdscdma = cid; } @Override - public CellSignalStrengthTdscdma getCellSignalStrength() { + public @NonNull CellSignalStrengthTdscdma getCellSignalStrength() { return mCellSignalStrengthTdscdma; } + /** @hide */ public void setCellSignalStrength(CellSignalStrengthTdscdma css) { mCellSignalStrengthTdscdma = css; @@ -149,15 +155,16 @@ public final class CellInfoTdscdma extends CellInfo implements Parcelable { } /** Implement the Parcelable interface */ - public static final @android.annotation.NonNull Creator<CellInfoTdscdma> CREATOR = new Creator<CellInfoTdscdma>() { + @NonNull + public static final Creator<CellInfoTdscdma> CREATOR = new Creator<CellInfoTdscdma>() { @Override - public CellInfoTdscdma createFromParcel(Parcel in) { + public @NonNull CellInfoTdscdma createFromParcel(Parcel in) { in.readInt(); // Skip past token, we know what it is return createFromParcelBody(in); } @Override - public CellInfoTdscdma[] newArray(int size) { + public @NonNull CellInfoTdscdma[] newArray(int size) { return new CellInfoTdscdma[size]; } }; diff --git a/telephony/java/android/telephony/CellSignalStrengthTdscdma.java b/telephony/java/android/telephony/CellSignalStrengthTdscdma.java index e79643fbf709..ddbd851bbce5 100644 --- a/telephony/java/android/telephony/CellSignalStrengthTdscdma.java +++ b/telephony/java/android/telephony/CellSignalStrengthTdscdma.java @@ -16,6 +16,7 @@ package android.telephony; +import android.annotation.NonNull; import android.os.Parcel; import android.os.Parcelable; import android.os.PersistableBundle; @@ -25,7 +26,8 @@ import java.util.Objects; /** * Tdscdma signal strength related information. * - * @hide + * This class provides signal strength and signal quality information for the TD-SCDMA air + * interface. For more information see 3gpp 25.225. */ public final class CellSignalStrengthTdscdma extends CellSignalStrength implements Parcelable { @@ -59,7 +61,9 @@ public final class CellSignalStrengthTdscdma extends CellSignalStrength implemen * @param rssi in dBm [-113, -51] or UNAVAILABLE * @param ber [0-7], 99 or UNAVAILABLE * @param rscp in dBm [-120, -24] or UNAVAILABLE - * @hide */ + * + * @hide + */ public CellSignalStrengthTdscdma(int rssi, int ber, int rscp) { mRssi = inRangeOrUnavailable(rssi, -113, -51); mBitErrorRate = inRangeOrUnavailable(ber, 0, 7, 99); @@ -148,8 +152,7 @@ public final class CellSignalStrengthTdscdma extends CellSignalStrength implemen } /** - * Get the RSCP as dBm - * @hide + * Get the RSCP as dBm value -120..-24dBm or {@link CellInfo#UNAVAILABLE UNAVAILABLE}. */ public int getRscp() { return mRscp; @@ -160,7 +163,7 @@ public final class CellSignalStrengthTdscdma extends CellSignalStrength implemen * * Asu is calculated based on 3GPP RSRP. Refer to 3GPP 27.007 (Ver 10.3.0) Sec 8.69 * - * @return RSCP in ASU 0..96, 255, or UNAVAILABLE + * @return RSCP in ASU 0..96, 255, or {@link CellInfo#UNAVAILABLE UNAVAILABLE}. */ @Override public int getAsuLevel() { @@ -237,15 +240,16 @@ public final class CellSignalStrengthTdscdma extends CellSignalStrength implemen /** Implement the Parcelable interface */ @SuppressWarnings("hiding") - public static final @android.annotation.NonNull Parcelable.Creator<CellSignalStrengthTdscdma> CREATOR = + @NonNull + public static final Parcelable.Creator<CellSignalStrengthTdscdma> CREATOR = new Parcelable.Creator<CellSignalStrengthTdscdma>() { @Override - public CellSignalStrengthTdscdma createFromParcel(Parcel in) { + public @NonNull CellSignalStrengthTdscdma createFromParcel(Parcel in) { return new CellSignalStrengthTdscdma(in); } @Override - public CellSignalStrengthTdscdma[] newArray(int size) { + public @NonNull CellSignalStrengthTdscdma[] newArray(int size) { return new CellSignalStrengthTdscdma[size]; } }; diff --git a/telephony/java/android/telephony/DataSpecificRegistrationStates.java b/telephony/java/android/telephony/DataSpecificRegistrationInfo.java index 8eb345ac258a..fbf488e590fd 100644 --- a/telephony/java/android/telephony/DataSpecificRegistrationStates.java +++ b/telephony/java/android/telephony/DataSpecificRegistrationInfo.java @@ -1,7 +1,24 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package android.telephony; import android.annotation.NonNull; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.os.Parcel; import android.os.Parcelable; @@ -13,7 +30,8 @@ import java.util.Objects; * @hide */ @SystemApi -public final class DataSpecificRegistrationStates implements Parcelable{ +@TestApi +public final class DataSpecificRegistrationInfo implements Parcelable { /** * @hide * The maximum number of simultaneous Data Calls that @@ -53,27 +71,27 @@ public final class DataSpecificRegistrationStates implements Parcelable{ /** * Provides network support info for LTE VoPS and LTE Emergency bearer support */ - private final LteVopsSupportInfo lteVopsSupportInfo; + private final LteVopsSupportInfo mLteVopsSupportInfo; /** * @hide */ - DataSpecificRegistrationStates( + DataSpecificRegistrationInfo( int maxDataCalls, boolean isDcNrRestricted, boolean isNrAvailable, boolean isEnDcAvailable, LteVopsSupportInfo lteVops) { this.maxDataCalls = maxDataCalls; this.isDcNrRestricted = isDcNrRestricted; this.isNrAvailable = isNrAvailable; this.isEnDcAvailable = isEnDcAvailable; - this.lteVopsSupportInfo = lteVops; + this.mLteVopsSupportInfo = lteVops; } - private DataSpecificRegistrationStates(Parcel source) { + private DataSpecificRegistrationInfo(Parcel source) { maxDataCalls = source.readInt(); isDcNrRestricted = source.readBoolean(); isNrAvailable = source.readBoolean(); isEnDcAvailable = source.readBoolean(); - lteVopsSupportInfo = LteVopsSupportInfo.CREATOR.createFromParcel(source); + mLteVopsSupportInfo = LteVopsSupportInfo.CREATOR.createFromParcel(source); } @Override @@ -82,7 +100,7 @@ public final class DataSpecificRegistrationStates implements Parcelable{ dest.writeBoolean(isDcNrRestricted); dest.writeBoolean(isNrAvailable); dest.writeBoolean(isEnDcAvailable); - lteVopsSupportInfo.writeToParcel(dest, flags); + mLteVopsSupportInfo.writeToParcel(dest, flags); } @Override @@ -98,7 +116,7 @@ public final class DataSpecificRegistrationStates implements Parcelable{ .append(" isDcNrRestricted = " + isDcNrRestricted) .append(" isNrAvailable = " + isNrAvailable) .append(" isEnDcAvailable = " + isEnDcAvailable) - .append(lteVopsSupportInfo.toString()) + .append(mLteVopsSupportInfo.toString()) .append(" }") .toString(); } @@ -106,41 +124,41 @@ public final class DataSpecificRegistrationStates implements Parcelable{ @Override public int hashCode() { return Objects.hash(maxDataCalls, isDcNrRestricted, isNrAvailable, isEnDcAvailable, - lteVopsSupportInfo); + mLteVopsSupportInfo); } @Override public boolean equals(Object o) { if (this == o) return true; - if (!(o instanceof DataSpecificRegistrationStates)) return false; + if (!(o instanceof DataSpecificRegistrationInfo)) return false; - DataSpecificRegistrationStates other = (DataSpecificRegistrationStates) o; + DataSpecificRegistrationInfo other = (DataSpecificRegistrationInfo) o; return this.maxDataCalls == other.maxDataCalls && this.isDcNrRestricted == other.isDcNrRestricted && this.isNrAvailable == other.isNrAvailable && this.isEnDcAvailable == other.isEnDcAvailable - && this.lteVopsSupportInfo.equals(other.lteVopsSupportInfo); + && this.mLteVopsSupportInfo.equals(other.mLteVopsSupportInfo); } - public static final @android.annotation.NonNull Parcelable.Creator<DataSpecificRegistrationStates> CREATOR = - new Parcelable.Creator<DataSpecificRegistrationStates>() { + public static final @NonNull Parcelable.Creator<DataSpecificRegistrationInfo> CREATOR = + new Parcelable.Creator<DataSpecificRegistrationInfo>() { @Override - public DataSpecificRegistrationStates createFromParcel(Parcel source) { - return new DataSpecificRegistrationStates(source); + public DataSpecificRegistrationInfo createFromParcel(Parcel source) { + return new DataSpecificRegistrationInfo(source); } @Override - public DataSpecificRegistrationStates[] newArray(int size) { - return new DataSpecificRegistrationStates[size]; + public DataSpecificRegistrationInfo[] newArray(int size) { + return new DataSpecificRegistrationInfo[size]; } }; /** - * @return LteVopsSupportInfo + * @return The LTE VOPS (Voice over Packet Switched) support information */ @NonNull public LteVopsSupportInfo getLteVopsSupportInfo() { - return lteVopsSupportInfo; + return mLteVopsSupportInfo; } } diff --git a/telephony/java/android/telephony/INetworkService.aidl b/telephony/java/android/telephony/INetworkService.aidl index 67e5650ab359..3a9c3a5bd45d 100644 --- a/telephony/java/android/telephony/INetworkService.aidl +++ b/telephony/java/android/telephony/INetworkService.aidl @@ -25,7 +25,7 @@ oneway interface INetworkService { void createNetworkServiceProvider(int slotId); void removeNetworkServiceProvider(int slotId); - void getNetworkRegistrationInfo(int slotId, int domain, INetworkServiceCallback callback); + void requestNetworkRegistrationInfo(int slotId, int domain, INetworkServiceCallback callback); void registerForNetworkRegistrationInfoChanged(int slotId, INetworkServiceCallback callback); void unregisterForNetworkRegistrationInfoChanged(int slotId, INetworkServiceCallback callback); } diff --git a/telephony/java/android/telephony/INetworkServiceCallback.aidl b/telephony/java/android/telephony/INetworkServiceCallback.aidl index 33b3ac0940b5..c35986c65f37 100644 --- a/telephony/java/android/telephony/INetworkServiceCallback.aidl +++ b/telephony/java/android/telephony/INetworkServiceCallback.aidl @@ -24,6 +24,6 @@ import android.telephony.NetworkRegistrationInfo; */ oneway interface INetworkServiceCallback { - void onGetNetworkRegistrationInfoComplete(int result, in NetworkRegistrationInfo state); + void onRequestNetworkRegistrationInfoComplete(int result, in NetworkRegistrationInfo state); void onNetworkStateChanged(); } diff --git a/telephony/java/android/telephony/JapanesePhoneNumberFormatter.java b/telephony/java/android/telephony/JapanesePhoneNumberFormatter.java index f5e53ef1ee5d..92a674c57688 100644 --- a/telephony/java/android/telephony/JapanesePhoneNumberFormatter.java +++ b/telephony/java/android/telephony/JapanesePhoneNumberFormatter.java @@ -16,6 +16,7 @@ package android.telephony; +import android.annotation.UnsupportedAppUsage; import android.text.Editable; /* @@ -154,6 +155,7 @@ import android.text.Editable; -35, -35, -35, -35, -35, -35, -35, -35, -35, -45, -26, -15, -15, -15, -15, -15, -15, -15, -15, -15}; + @UnsupportedAppUsage public static void format(Editable text) { // Here, "root" means the position of "'": // 0'3, 0'90, and +81'-90 diff --git a/telephony/java/android/telephony/LteVopsSupportInfo.java b/telephony/java/android/telephony/LteVopsSupportInfo.java index ee45f0761e0b..ec9f078367b8 100644 --- a/telephony/java/android/telephony/LteVopsSupportInfo.java +++ b/telephony/java/android/telephony/LteVopsSupportInfo.java @@ -18,6 +18,7 @@ package android.telephony; import android.annotation.IntDef; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.os.Parcel; import android.os.Parcelable; @@ -30,6 +31,7 @@ import java.util.Objects; * @hide */ @SystemApi +@TestApi public final class LteVopsSupportInfo implements Parcelable { /**@hide*/ diff --git a/telephony/java/android/telephony/NetworkRegistrationInfo.java b/telephony/java/android/telephony/NetworkRegistrationInfo.java index 9145b2532817..1dc29979dc61 100644 --- a/telephony/java/android/telephony/NetworkRegistrationInfo.java +++ b/telephony/java/android/telephony/NetworkRegistrationInfo.java @@ -20,6 +20,7 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.os.Parcel; import android.os.Parcelable; import android.telephony.AccessNetworkConstants.TransportType; @@ -38,6 +39,7 @@ import java.util.stream.Collectors; * @hide */ @SystemApi +@TestApi public final class NetworkRegistrationInfo implements Parcelable { /** * Network domain @@ -174,10 +176,10 @@ public final class NetworkRegistrationInfo implements Parcelable { private CellIdentity mCellIdentity; @Nullable - private VoiceSpecificRegistrationStates mVoiceSpecificStates; + private VoiceSpecificRegistrationInfo mVoiceSpecificInfo; @Nullable - private DataSpecificRegistrationStates mDataSpecificStates; + private DataSpecificRegistrationInfo mDataSpecificInfo; /** * @param domain Network domain. Must be a {@link Domain}. For transport type @@ -234,7 +236,7 @@ public final class NetworkRegistrationInfo implements Parcelable { this(domain, transportType, registrationState, accessNetworkTechnology, rejectCause, emergencyOnly, availableServices, cellIdentity); - mVoiceSpecificStates = new VoiceSpecificRegistrationStates(cssSupported, roamingIndicator, + mVoiceSpecificInfo = new VoiceSpecificRegistrationInfo(cssSupported, roamingIndicator, systemIsInPrl, defaultRoamingIndicator); } @@ -253,9 +255,9 @@ public final class NetworkRegistrationInfo implements Parcelable { this(domain, transportType, registrationState, accessNetworkTechnology, rejectCause, emergencyOnly, availableServices, cellIdentity); - mDataSpecificStates = new DataSpecificRegistrationStates( + mDataSpecificInfo = new DataSpecificRegistrationInfo( maxDataCalls, isDcNrRestricted, isNrAvailable, isEndcAvailable, lteVopsSupportInfo); - updateNrState(mDataSpecificStates); + updateNrState(mDataSpecificInfo); } private NetworkRegistrationInfo(Parcel source) { @@ -269,10 +271,10 @@ public final class NetworkRegistrationInfo implements Parcelable { mAvailableServices = new ArrayList<>(); source.readList(mAvailableServices, Integer.class.getClassLoader()); mCellIdentity = source.readParcelable(CellIdentity.class.getClassLoader()); - mVoiceSpecificStates = source.readParcelable( - VoiceSpecificRegistrationStates.class.getClassLoader()); - mDataSpecificStates = source.readParcelable( - DataSpecificRegistrationStates.class.getClassLoader()); + mVoiceSpecificInfo = source.readParcelable( + VoiceSpecificRegistrationInfo.class.getClassLoader()); + mDataSpecificInfo = source.readParcelable( + DataSpecificRegistrationInfo.class.getClassLoader()); mNrState = source.readInt(); } @@ -389,16 +391,16 @@ public final class NetworkRegistrationInfo implements Parcelable { * @hide */ @Nullable - public VoiceSpecificRegistrationStates getVoiceSpecificStates() { - return mVoiceSpecificStates; + public VoiceSpecificRegistrationInfo getVoiceSpecificInfo() { + return mVoiceSpecificInfo; } /** * @return Data registration related info */ @Nullable - public DataSpecificRegistrationStates getDataSpecificStates() { - return mDataSpecificStates; + public DataSpecificRegistrationInfo getDataSpecificInfo() { + return mDataSpecificInfo; } @Override @@ -474,8 +476,8 @@ public final class NetworkRegistrationInfo implements Parcelable { ? mAvailableServices.stream().map(type -> serviceTypeToString(type)) .collect(Collectors.joining(",")) : null) + "]") .append(" cellIdentity=").append(mCellIdentity) - .append(" voiceSpecificStates=").append(mVoiceSpecificStates) - .append(" dataSpecificStates=").append(mDataSpecificStates) + .append(" voiceSpecificInfo=").append(mVoiceSpecificInfo) + .append(" dataSpecificInfo=").append(mDataSpecificInfo) .append(" nrState=").append(nrStateToString(mNrState)) .append("}").toString(); } @@ -484,7 +486,7 @@ public final class NetworkRegistrationInfo implements Parcelable { public int hashCode() { return Objects.hash(mDomain, mTransportType, mRegistrationState, mRoamingType, mAccessNetworkTechnology, mRejectCause, mEmergencyOnly, mAvailableServices, - mCellIdentity, mVoiceSpecificStates, mDataSpecificStates, mNrState); + mCellIdentity, mVoiceSpecificInfo, mDataSpecificInfo, mNrState); } @Override @@ -505,8 +507,8 @@ public final class NetworkRegistrationInfo implements Parcelable { && mEmergencyOnly == other.mEmergencyOnly && mAvailableServices.equals(other.mAvailableServices) && Objects.equals(mCellIdentity, other.mCellIdentity) - && Objects.equals(mVoiceSpecificStates, other.mVoiceSpecificStates) - && Objects.equals(mDataSpecificStates, other.mDataSpecificStates) + && Objects.equals(mVoiceSpecificInfo, other.mVoiceSpecificInfo) + && Objects.equals(mDataSpecificInfo, other.mDataSpecificInfo) && mNrState == other.mNrState; } @@ -521,8 +523,8 @@ public final class NetworkRegistrationInfo implements Parcelable { dest.writeBoolean(mEmergencyOnly); dest.writeList(mAvailableServices); dest.writeParcelable(mCellIdentity, 0); - dest.writeParcelable(mVoiceSpecificStates, 0); - dest.writeParcelable(mDataSpecificStates, 0); + dest.writeParcelable(mVoiceSpecificInfo, 0); + dest.writeParcelable(mDataSpecificInfo, 0); dest.writeInt(mNrState); } @@ -543,7 +545,7 @@ public final class NetworkRegistrationInfo implements Parcelable { * * @param state data specific registration state contains the 5G NR indicators. */ - private void updateNrState(DataSpecificRegistrationStates state) { + private void updateNrState(DataSpecificRegistrationInfo state) { mNrState = NR_STATE_NONE; if (state.isEnDcAvailable) { if (!state.isDcNrRestricted && state.isNrAvailable) { diff --git a/telephony/java/android/telephony/NetworkService.java b/telephony/java/android/telephony/NetworkService.java index bc989dd8c5ad..8c5e10788b89 100644 --- a/telephony/java/android/telephony/NetworkService.java +++ b/telephony/java/android/telephony/NetworkService.java @@ -18,6 +18,7 @@ package android.telephony; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SdkConstant; import android.annotation.SystemApi; import android.app.Service; import android.content.Intent; @@ -54,7 +55,8 @@ public abstract class NetworkService extends Service { private final String TAG = NetworkService.class.getSimpleName(); - public static final String NETWORK_SERVICE_INTERFACE = "android.telephony.NetworkService"; + @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION) + public static final String SERVICE_INTERFACE = "android.telephony.NetworkService"; private static final int NETWORK_SERVICE_CREATE_NETWORK_SERVICE_PROVIDER = 1; private static final int NETWORK_SERVICE_REMOVE_NETWORK_SERVICE_PROVIDER = 2; @@ -104,13 +106,14 @@ public abstract class NetworkService extends Service { } /** - * API to get network registration info. The result will be passed to the callback. + * Request network registration info. The result will be passed to the callback. + * * @param domain Network domain * @param callback The callback for reporting network registration info */ - public void getNetworkRegistrationInfo(@Domain int domain, - @NonNull NetworkServiceCallback callback) { - callback.onGetNetworkRegistrationInfoComplete( + public void requestNetworkRegistrationInfo(@Domain int domain, + @NonNull NetworkServiceCallback callback) { + callback.onRequestNetworkRegistrationInfoComplete( NetworkServiceCallback.RESULT_ERROR_UNSUPPORTED, null); } @@ -192,7 +195,7 @@ public abstract class NetworkService extends Service { case NETWORK_SERVICE_GET_REGISTRATION_INFO: if (serviceProvider == null) break; int domainId = message.arg2; - serviceProvider.getNetworkRegistrationInfo(domainId, + serviceProvider.requestNetworkRegistrationInfo(domainId, new NetworkServiceCallback(callback)); break; @@ -231,14 +234,15 @@ public abstract class NetworkService extends Service { * will call this method after binding the network service for each active SIM slot id. * * @param slotIndex SIM slot id the network service associated with. - * @return Network service object + * @return Network service object. Null if failed to create the provider (e.g. invalid slot + * index) */ @Nullable public abstract NetworkServiceProvider onCreateNetworkServiceProvider(int slotIndex); @Override public IBinder onBind(Intent intent) { - if (intent == null || !NETWORK_SERVICE_INTERFACE.equals(intent.getAction())) { + if (intent == null || !SERVICE_INTERFACE.equals(intent.getAction())) { loge("Unexpected intent " + intent); return null; } @@ -280,8 +284,8 @@ public abstract class NetworkService extends Service { } @Override - public void getNetworkRegistrationInfo( - int slotIndex, int domain, INetworkServiceCallback callback) { + public void requestNetworkRegistrationInfo(int slotIndex, int domain, + INetworkServiceCallback callback) { mHandler.obtainMessage(NETWORK_SERVICE_GET_REGISTRATION_INFO, slotIndex, domain, callback).sendToTarget(); } diff --git a/telephony/java/android/telephony/NetworkServiceCallback.java b/telephony/java/android/telephony/NetworkServiceCallback.java index cc2524000091..1c64bcd28966 100644 --- a/telephony/java/android/telephony/NetworkServiceCallback.java +++ b/telephony/java/android/telephony/NetworkServiceCallback.java @@ -28,9 +28,9 @@ import java.lang.ref.WeakReference; /** * Network service callback. Object of this class is passed to NetworkServiceProvider upon - * calling getNetworkRegistrationInfo, to receive asynchronous feedback from NetworkServiceProvider - * upon onGetNetworkRegistrationInfoComplete. It's like a wrapper of INetworkServiceCallback - * because INetworkServiceCallback can't be a parameter type in public APIs. + * calling requestNetworkRegistrationInfo, to receive asynchronous feedback from + * NetworkServiceProvider upon onRequestNetworkRegistrationInfoComplete. It's like a wrapper of + * INetworkServiceCallback because INetworkServiceCallback can't be a parameter type in public APIs. * * @hide */ @@ -70,20 +70,20 @@ public class NetworkServiceCallback { /** * Called to indicate result of - * {@link NetworkServiceProvider#getNetworkRegistrationInfo(int, NetworkServiceCallback)} + * {@link NetworkServiceProvider#requestNetworkRegistrationInfo(int, NetworkServiceCallback)} * * @param result Result status like {@link NetworkServiceCallback#RESULT_SUCCESS} or - * {@link NetworkServiceCallback#RESULT_ERROR_UNSUPPORTED} + * {@link NetworkServiceCallback#RESULT_ERROR_UNSUPPORTED} * @param state The state information to be returned to callback. */ - public void onGetNetworkRegistrationInfoComplete(int result, - @Nullable NetworkRegistrationInfo state) { + public void onRequestNetworkRegistrationInfoComplete(int result, + @Nullable NetworkRegistrationInfo state) { INetworkServiceCallback callback = mCallback.get(); if (callback != null) { try { - callback.onGetNetworkRegistrationInfoComplete(result, state); + callback.onRequestNetworkRegistrationInfoComplete(result, state); } catch (RemoteException e) { - Rlog.e(mTag, "Failed to onGetNetworkRegistrationInfoComplete on the remote"); + Rlog.e(mTag, "Failed to onRequestNetworkRegistrationInfoComplete on the remote"); } } else { Rlog.e(mTag, "Weak reference of callback is null."); diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java index 30dcaa0091d2..49398ed881b9 100644 --- a/telephony/java/android/telephony/ServiceState.java +++ b/telephony/java/android/telephony/ServiceState.java @@ -1586,7 +1586,7 @@ public class ServiceState implements Parcelable { == NetworkRegistrationInfo.REGISTRATION_STATE_HOME) { // If the device is on IWLAN, return IWLAN as the network type. This is to simulate the // behavior of legacy mode device. In the future caller should use - // getNetworkRegistrationInfo() to retrieve the actual data network type on cellular + // requestNetworkRegistrationInfo() to retrieve the actual data network type on cellular // or on IWLAN. return iwlanRegState.getAccessNetworkTechnology(); } @@ -1855,6 +1855,7 @@ public class ServiceState implements Parcelable { /** * @hide */ + @TestApi public void addNetworkRegistrationInfo(NetworkRegistrationInfo regState) { if (regState == null) return; diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java index ac1194089758..ee28ca23be35 100644 --- a/telephony/java/android/telephony/SubscriptionInfo.java +++ b/telephony/java/android/telephony/SubscriptionInfo.java @@ -32,6 +32,7 @@ import android.graphics.Rect; import android.graphics.Typeface; import android.os.Build; import android.os.Parcel; +import android.os.ParcelUuid; import android.os.Parcelable; import android.text.TextUtils; import android.util.DisplayMetrics; @@ -154,11 +155,11 @@ public class SubscriptionInfo implements Parcelable { private boolean mIsOpportunistic; /** - * A UUID assigned to the subscription group. It returns - * null if not assigned. + * A UUID assigned to the subscription group. It returns null if not assigned. + * Check {@link SubscriptionManager#createSubscriptionGroup(List)} for more details. */ @Nullable - private String mGroupUUID; + private ParcelUuid mGroupUUID; /** * Whether group of the subscription is disabled. @@ -237,7 +238,7 @@ public class SubscriptionInfo implements Parcelable { this.mCardString = cardString; this.mCardId = cardId; this.mIsOpportunistic = isOpportunistic; - this.mGroupUUID = groupUUID; + this.mGroupUUID = groupUUID == null ? null : ParcelUuid.fromString(groupUUID); this.mIsGroupDisabled = isGroupDisabled; this.mCarrierId = carrierId; this.mProfileClass = profileClass; @@ -461,7 +462,7 @@ public class SubscriptionInfo implements Parcelable { * @return group UUID a String of group UUID if it belongs to a group. Otherwise * it will return null. */ - public @Nullable String getGroupUuid() { + public @Nullable ParcelUuid getGroupUuid() { return mGroupUUID; } @@ -643,7 +644,7 @@ public class SubscriptionInfo implements Parcelable { dest.writeString(mCardString); dest.writeInt(mCardId); dest.writeBoolean(mIsOpportunistic); - dest.writeString(mGroupUUID); + dest.writeString(mGroupUUID == null ? null : mGroupUUID.toString()); dest.writeBoolean(mIsGroupDisabled); dest.writeInt(mCarrierId); dest.writeInt(mProfileClass); diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java index 2edef838ff28..14eac87f1575 100644 --- a/telephony/java/android/telephony/SubscriptionManager.java +++ b/telephony/java/android/telephony/SubscriptionManager.java @@ -50,11 +50,12 @@ import android.os.Build; import android.os.Handler; import android.os.Looper; import android.os.Message; +import android.os.ParcelUuid; +import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; import android.telephony.euicc.EuiccManager; import android.telephony.ims.ImsMmTelManager; -import android.text.TextUtils; import android.util.DisplayMetrics; import android.util.Log; @@ -1752,6 +1753,10 @@ public class SubscriptionManager { Rlog.d(LOG_TAG, msg); } + private static void loge(String msg) { + Rlog.e(LOG_TAG, msg); + } + /** * Returns the system's default subscription id. * @@ -1991,24 +1996,6 @@ public class SubscriptionManager { } /** - * If a default is set to subscription which is not active, this will reset that default back to - * an invalid subscription id, i.e. < 0. - * @hide - */ - @UnsupportedAppUsage - public void clearDefaultsForInactiveSubIds() { - if (VDBG) logd("clearDefaultsForInactiveSubIds"); - try { - ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); - if (iSub != null) { - iSub.clearDefaultsForInactiveSubIds(); - } - } catch (RemoteException ex) { - // ignore it - } - } - - /** * Check if the supplied subscription ID is valid. * * <p>A valid subscription ID is not necessarily an active subscription ID @@ -2740,11 +2727,20 @@ public class SubscriptionManager { /** * Inform SubscriptionManager that subscriptions in the list are bundled - * as a group. Typically it's a primary subscription and an opportunistic - * subscription. It should only affect multi-SIM scenarios where primary - * and opportunistic subscriptions can be activated together. - * Being in the same group means they might be activated or deactivated - * together, some of them may be invisible to the users, etc. + * as a group. It can be multiple primary (non-opportunistic) subscriptions, + * or one or more primary plus one or more opportunistic subscriptions. + * + * This API will always create a new immutable group and assign group UUID to all the + * subscriptions, regardless whether they are in a group already or not. + * + * Grouped subscriptions will have below behaviors: + * 1) They will share the same user settings. + * 2) The opportunistic subscriptions in the group is considered invisible and will not + * return from {@link #getActiveSubscriptionInfoList()}, unless caller has carrier + * privilege permission of the subscriptions. + * 3) The opportunistic subscriptions in the group can't be active by itself. If all other + * non-opportunistic ones are deactivated (unplugged or disabled in Settings), + * the opportunistic ones will be deactivated automatically. * * Caller will either have {@link android.Manifest.permission#MODIFY_PHONE_STATE} * permission or had carrier privilege permission on the subscriptions: @@ -2755,34 +2751,94 @@ public class SubscriptionManager { * outlined above. * * @param subIdList list of subId that will be in the same group - * @return groupUUID a UUID assigned to the subscription group. It returns - * null if fails. + * @return groupUUID a UUID assigned to the subscription group. * */ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) - public @Nullable String setSubscriptionGroup(@NonNull int[] subIdList) { + public @NonNull ParcelUuid createSubscriptionGroup(@NonNull List<Integer> subIdList) { + Preconditions.checkNotNull(subIdList, "can't create group for null subId list"); String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>"; if (VDBG) { - logd("[setSubscriptionGroup]+ subIdList:" + Arrays.toString(subIdList)); + logd("[createSubscriptionGroup]"); } - String groupUUID = null; + ParcelUuid groupUuid = null; + int[] subIdArray = subIdList.stream().mapToInt(i->i).toArray(); try { ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); if (iSub != null) { - groupUUID = iSub.setSubscriptionGroup(subIdList, pkgForDebug); + groupUuid = iSub.createSubscriptionGroup(subIdArray, pkgForDebug); + } else { + if (!isSystemProcess()) { + throw new IllegalStateException("telephony service is null."); + } } } catch (RemoteException ex) { - // ignore it + loge("createSubscriptionGroup RemoteException " + ex); + if (!isSystemProcess()) { + ex.rethrowAsRuntimeException(); + } + } + + return groupUuid; + } + + /** + * Add a list of subscriptions into a group. + * See {@link #createSubscriptionGroup(List)} for more details. + * + * Caller will either have {@link android.Manifest.permission#MODIFY_PHONE_STATE} + * permission or had carrier privilege permission on the subscriptions: + * {@link TelephonyManager#hasCarrierPrivileges()} or + * {@link #canManageSubscription(SubscriptionInfo)} + * + * @throws SecurityException if the caller doesn't meet the requirements + * outlined above. + * @throws IllegalArgumentException if the some subscriptions in the list doesn't exist, + * or the groupUuid doesn't exist. + * + * @param subIdList list of subId that need adding into the group + * @param groupUuid the groupUuid the subscriptions are being added to. + * + */ + @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges + @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) + public void addSubscriptionsIntoGroup(@NonNull List<Integer> subIdList, + @NonNull ParcelUuid groupUuid) { + Preconditions.checkNotNull(subIdList, "subIdList can't be null."); + Preconditions.checkNotNull(groupUuid, "groupUuid can't be null."); + String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>"; + if (VDBG) { + logd("[addSubscriptionsIntoGroup]"); + } + + int[] subIdArray = subIdList.stream().mapToInt(i->i).toArray(); + + try { + ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); + if (iSub != null) { + iSub.addSubscriptionsIntoGroup(subIdArray, groupUuid, pkgForDebug); + } else { + if (!isSystemProcess()) { + throw new IllegalStateException("telephony service is null."); + } + } + } catch (RemoteException ex) { + loge("addSubscriptionsIntoGroup RemoteException " + ex); + if (!isSystemProcess()) { + ex.rethrowAsRuntimeException(); + } } + } - return groupUUID; + private boolean isSystemProcess() { + return Process.myUid() == Process.SYSTEM_UID; } /** * Remove a list of subscriptions from their subscription group. - * See {@link #setSubscriptionGroup(int[])} for more details. + * See {@link #createSubscriptionGroup(List)} for more details. * * Caller will either have {@link android.Manifest.permission#MODIFY_PHONE_STATE} * permission or had carrier privilege permission on the subscriptions: @@ -2791,34 +2847,45 @@ public class SubscriptionManager { * * @throws SecurityException if the caller doesn't meet the requirements * outlined above. + * @throws IllegalArgumentException if the some subscriptions in the list doesn't belong + * the specified group. * * @param subIdList list of subId that need removing from their groups. - * @return whether the operation succeeds. * */ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) - public boolean removeSubscriptionsFromGroup(@NonNull int[] subIdList) { + public void removeSubscriptionsFromGroup(@NonNull List<Integer> subIdList, + @NonNull ParcelUuid groupUuid) { + Preconditions.checkNotNull(subIdList, "subIdList can't be null."); + Preconditions.checkNotNull(groupUuid, "groupUuid can't be null."); String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>"; if (VDBG) { - logd("[removeSubscriptionsFromGroup]+ subIdList:" + Arrays.toString(subIdList)); + logd("[removeSubscriptionsFromGroup]"); } + int[] subIdArray = subIdList.stream().mapToInt(i->i).toArray(); + try { ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); if (iSub != null) { - return iSub.removeSubscriptionsFromGroup(subIdList, pkgForDebug); + iSub.removeSubscriptionsFromGroup(subIdArray, groupUuid, pkgForDebug); + } else { + if (!isSystemProcess()) { + throw new IllegalStateException("telephony service is null."); + } } } catch (RemoteException ex) { - // ignore it + loge("removeSubscriptionsFromGroup RemoteException " + ex); + if (!isSystemProcess()) { + ex.rethrowAsRuntimeException(); + } } - - return false; } /** * Get subscriptionInfo list of subscriptions that are in the same group of given subId. - * See {@link #setSubscriptionGroup(int[])} for more details. + * See {@link #createSubscriptionGroup(List)} for more details. * * Caller will either have {@link android.Manifest.permission#READ_PHONE_STATE} * permission or had carrier privilege permission on the subscription. @@ -2827,28 +2894,35 @@ public class SubscriptionManager { * @throws SecurityException if the caller doesn't meet the requirements * outlined above. * - * @param subId of which list of subInfo from the same group will be returned. + * @param groupUuid of which list of subInfo will be returned. * @return list of subscriptionInfo that belong to the same group, including the given - * subscription itself. It will return null if the subscription doesn't exist or it - * doesn't belong to any group. + * subscription itself. It will return an empty list if no subscription belongs to the group. * */ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges @RequiresPermission(Manifest.permission.READ_PHONE_STATE) - public @Nullable List<SubscriptionInfo> getSubscriptionsInGroup(int subId) { + public @NonNull List<SubscriptionInfo> getSubscriptionsInGroup(@NonNull ParcelUuid groupUuid) { + Preconditions.checkNotNull(groupUuid, "groupUuid can't be null"); String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>"; if (VDBG) { - logd("[getSubscriptionsInGroup]+ subId:" + subId); + logd("[getSubscriptionsInGroup]+ groupUuid:" + groupUuid); } List<SubscriptionInfo> result = null; try { ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); if (iSub != null) { - result = iSub.getSubscriptionsInGroup(subId, pkgForDebug); + result = iSub.getSubscriptionsInGroup(groupUuid, pkgForDebug); + } else { + if (!isSystemProcess()) { + throw new IllegalStateException("telephony service is null."); + } } } catch (RemoteException ex) { - // ignore it + loge("removeSubscriptionsFromGroup RemoteException " + ex); + if (!isSystemProcess()) { + ex.rethrowAsRuntimeException(); + } } return result; @@ -2868,7 +2942,7 @@ public class SubscriptionManager { if (info == null) return false; // If subscription is NOT grouped opportunistic subscription, it's visible. - if (TextUtils.isEmpty(info.getGroupUuid()) || !info.isOpportunistic()) return true; + if (info.getGroupUuid() == null || !info.isOpportunistic()) return true; // If the caller is the carrier app and owns the subscription, it should be visible // to the caller. @@ -2898,14 +2972,14 @@ public class SubscriptionManager { // It should be the current active primary subscription if any, or any // primary subscription. List<SubscriptionInfo> selectableList = new ArrayList<>(); - Map<String, SubscriptionInfo> groupMap = new HashMap<>(); + Map<ParcelUuid, SubscriptionInfo> groupMap = new HashMap<>(); for (SubscriptionInfo info : availableList) { // Opportunistic subscriptions are considered invisible // to users so they should never be returned. if (!isSubscriptionVisible(info)) continue; - String groupUuid = info.getGroupUuid(); + ParcelUuid groupUuid = info.getGroupUuid(); if (groupUuid == null) { // Doesn't belong to any group. Add in the list. selectableList.add(info); diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 282b1ff2f801..0d4d654ae25c 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -1428,6 +1428,70 @@ public class TelephonyManager { public static final String EXTRA_ANOMALY_DESCRIPTION = "android.telephony.extra.ANOMALY_DESCRIPTION"; + /** + * Broadcast intent sent to indicate primary (non-opportunistic) subscription list has changed. + * + * @hide + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_PRIMARY_SUBSCRIPTION_LIST_CHANGED = + "android.telephony.action.PRIMARY_SUBSCRIPTION_LIST_CHANGED"; + + /** + * Integer intent extra to be used with {@link #ACTION_PRIMARY_SUBSCRIPTION_LIST_CHANGED} + * to indicate whether a SIM selection is needed to choose default subscription. + * + * @hide + */ + public static final String EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE = + "android.telephony.extra.DEFAULT_SUBSCRIPTION_SELECT_TYPE"; + + /** + * Used as an int value for {@link #EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE} + * to indicate there's no need to re-select any default subscription. + * @hide + */ + public static final int EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_NONE = 0; + + /** + * Used as an int value for {@link #EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE} + * to indicate there's a need to select default data subscription. + * @hide + */ + public static final int EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_DATA = 1; + + /** + * Used as an int value for {@link #EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE} + * to indicate there's a need to select default voice call subscription. + * @hide + */ + public static final int EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_VOICE = 2; + + /** + * Used as an int value for {@link #EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE} + * to indicate there's a need to select default sms subscription. + * @hide + */ + public static final int EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_SMS = 3; + + /** + * Used as an int value for {@link #EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE} + * to indicate user to decide whether current SIM should be preferred for all + * data / voice / sms. + * @hide + */ + public static final int EXTRA_DEFAULT_SUBSCRIPTION_SELECT_FOR_ALL_TYPES = 4; + + /** + * Integer intent extra to be used with + * {@link #EXTRA_DEFAULT_SUBSCRIPTION_SELECT_FOR_ALL_TYPES} + * to indicate which SIM is being selected. + * + * @hide + */ + public static final String EXTRA_DEFAULT_SUBSCRIPTION_ID = + "android.telephony.extra.DEFAULT_SUBSCRIPTION_ID"; + // // // Device Info @@ -5296,7 +5360,6 @@ public class TelephonyManager { */ @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) @SystemApi - @Nullable public boolean iccCloseLogicalChannelBySlot(int slotIndex, int channel) { try { ITelephony telephony = getITelephony(); @@ -5373,8 +5436,8 @@ public class TelephonyManager { * @param p3 P3 value of the APDU command. If p3 is negative a 4 byte APDU * is sent to the SIM. * @param data Data to be sent with the APDU. - * @return The APDU response from the ICC card with the status appended at - * the end. + * @return The APDU response from the ICC card with the status appended at the end, or null if + * there is an issue connecting to the Telephony service. * @hide */ @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) @@ -10193,6 +10256,24 @@ public class TelephonyManager { } /** + * Determine whether the emergency assistance feature is available on the device. + * <p> + * Requires permission: {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE} + * + * @return whether the emergency assistance feature is available on the device + * + * @hide + */ + @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + @SystemApi + public boolean isEmergencyAssistanceEnabled() { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, + "isEmergencyAssistanceEnabled"); + return EMERGENCY_ASSISTANCE_ENABLED; + } + + /** * Get the emergency number list based on current locale, sim, default, modem and network. * * <p>In each returned list, the emergency number {@link EmergencyNumber} coming from higher @@ -10609,45 +10690,77 @@ public class TelephonyManager { * <p>Note: the API does not prevent access to the SIM cards for operations that don't require * access to the network. * - * @param isMultisimCarrierRestricted true if usage of multiple SIMs is restricted, false + * @param isMultiSimCarrierRestricted true if usage of multiple SIMs is restricted, false * otherwise. * * @hide */ @SystemApi @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) - public void setMultisimCarrierRestriction(boolean isMultisimCarrierRestricted) { + public void setMultiSimCarrierRestriction(boolean isMultiSimCarrierRestricted) { try { ITelephony service = getITelephony(); if (service != null) { - service.setMultisimCarrierRestriction(isMultisimCarrierRestricted); + service.setMultiSimCarrierRestriction(isMultiSimCarrierRestricted); } } catch (RemoteException e) { - Log.e(TAG, "setMultisimCarrierRestriction RemoteException", e); + Log.e(TAG, "setMultiSimCarrierRestriction RemoteException", e); } } /** + * The usage of multiple SIM cards at the same time to register on the network (e.g. Dual + * Standby or Dual Active) is supported. + */ + public static final int MULTISIM_ALLOWED = 0; + + /** + * The usage of multiple SIM cards at the same time to register on the network (e.g. Dual + * Standby or Dual Active) is not supported by the hardware. + */ + public static final int MULTISIM_NOT_SUPPORTED_BY_HARDWARE = 1; + + /** + * The usage of multiple SIM cards at the same time to register on the network (e.g. Dual + * Standby or Dual Active) is supported by the hardware, but restricted by the carrier. + */ + public static final int MULTISIM_NOT_SUPPORTED_BY_CARRIER = 2; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = {"MULTISIM_"}, + value = { + MULTISIM_ALLOWED, + MULTISIM_NOT_SUPPORTED_BY_HARDWARE, + MULTISIM_NOT_SUPPORTED_BY_CARRIER + }) + public @interface IsMultiSimSupportedResult {} + + /** * Returns if the usage of multiple SIM cards at the same time to register on the network * (e.g. Dual Standby or Dual Active) is supported by the device and by the carrier. * * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}). * - * @return true if usage of multiple SIMs is supported, false otherwise. + * @return {@link #MULTISIM_ALLOWED} if the device supports multiple SIMs. + * {@link #MULTISIM_NOT_SUPPORTED_BY_HARDWARE} if the device does not support multiple SIMs. + * {@link #MULTISIM_NOT_SUPPORTED_BY_CARRIER} in the device supports multiple SIMs, but the + * functionality is restricted by the carrier. */ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) - public boolean isMultisimSupported() { + @IsMultiSimSupportedResult + public int isMultiSimSupported() { try { ITelephony service = getITelephony(); if (service != null) { - return service.isMultisimSupported(getOpPackageName()); + return service.isMultiSimSupported(getOpPackageName()); } } catch (RemoteException e) { - Log.e(TAG, "isMultisimSupported RemoteException", e); + Log.e(TAG, "isMultiSimSupported RemoteException", e); } - return false; + return MULTISIM_NOT_SUPPORTED_BY_HARDWARE; } /** diff --git a/telephony/java/android/telephony/VoiceSpecificRegistrationStates.java b/telephony/java/android/telephony/VoiceSpecificRegistrationInfo.java index d8ce5b43e4d6..18a533a46273 100644 --- a/telephony/java/android/telephony/VoiceSpecificRegistrationStates.java +++ b/telephony/java/android/telephony/VoiceSpecificRegistrationInfo.java @@ -1,5 +1,22 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package android.telephony; +import android.annotation.NonNull; import android.os.Parcel; import android.os.Parcelable; @@ -10,14 +27,14 @@ import java.util.Objects; * Class that stores information specific to voice network registration. * @hide */ -public class VoiceSpecificRegistrationStates implements Parcelable{ +public class VoiceSpecificRegistrationInfo implements Parcelable{ /** * oncurrent services support indicator. if * registered on a CDMA system. * false - Concurrent services not supported, * true - Concurrent services supported */ - public final boolean cssSupported; + public final boolean cssSupported; /** * TSB-58 Roaming Indicator if registered @@ -40,15 +57,15 @@ public class VoiceSpecificRegistrationStates implements Parcelable{ */ public final int defaultRoamingIndicator; - VoiceSpecificRegistrationStates(boolean cssSupported, int roamingIndicator, int systemIsInPrl, - int defaultRoamingIndicator) { + VoiceSpecificRegistrationInfo(boolean cssSupported, int roamingIndicator, int systemIsInPrl, + int defaultRoamingIndicator) { this.cssSupported = cssSupported; this.roamingIndicator = roamingIndicator; this.systemIsInPrl = systemIsInPrl; this.defaultRoamingIndicator = defaultRoamingIndicator; } - private VoiceSpecificRegistrationStates(Parcel source) { + private VoiceSpecificRegistrationInfo(Parcel source) { this.cssSupported = source.readBoolean(); this.roamingIndicator = source.readInt(); this.systemIsInPrl = source.readInt(); @@ -70,7 +87,7 @@ public class VoiceSpecificRegistrationStates implements Parcelable{ @Override public String toString() { - return "VoiceSpecificRegistrationStates {" + return "VoiceSpecificRegistrationInfo {" + " mCssSupported=" + cssSupported + " mRoamingIndicator=" + roamingIndicator + " mSystemIsInPrl=" + systemIsInPrl @@ -87,11 +104,11 @@ public class VoiceSpecificRegistrationStates implements Parcelable{ public boolean equals(Object o) { if (this == o) return true; - if (o == null || !(o instanceof VoiceSpecificRegistrationStates)) { + if (o == null || !(o instanceof VoiceSpecificRegistrationInfo)) { return false; } - VoiceSpecificRegistrationStates other = (VoiceSpecificRegistrationStates) o; + VoiceSpecificRegistrationInfo other = (VoiceSpecificRegistrationInfo) o; return this.cssSupported == other.cssSupported && this.roamingIndicator == other.roamingIndicator && this.systemIsInPrl == other.systemIsInPrl @@ -99,16 +116,16 @@ public class VoiceSpecificRegistrationStates implements Parcelable{ } - public static final @android.annotation.NonNull Parcelable.Creator<VoiceSpecificRegistrationStates> CREATOR = - new Parcelable.Creator<VoiceSpecificRegistrationStates>() { + public static final @NonNull Parcelable.Creator<VoiceSpecificRegistrationInfo> CREATOR = + new Parcelable.Creator<VoiceSpecificRegistrationInfo>() { @Override - public VoiceSpecificRegistrationStates createFromParcel(Parcel source) { - return new VoiceSpecificRegistrationStates(source); + public VoiceSpecificRegistrationInfo createFromParcel(Parcel source) { + return new VoiceSpecificRegistrationInfo(source); } @Override - public VoiceSpecificRegistrationStates[] newArray(int size) { - return new VoiceSpecificRegistrationStates[size]; + public VoiceSpecificRegistrationInfo[] newArray(int size) { + return new VoiceSpecificRegistrationInfo[size]; } }; -}
\ No newline at end of file +} diff --git a/telephony/java/android/telephony/data/DataCallResponse.java b/telephony/java/android/telephony/data/DataCallResponse.java index 0622cddcbb99..17699d70cb18 100644 --- a/telephony/java/android/telephony/data/DataCallResponse.java +++ b/telephony/java/android/telephony/data/DataCallResponse.java @@ -17,16 +17,21 @@ package android.telephony.data; +import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.net.LinkAddress; import android.os.Parcel; import android.os.Parcelable; +import android.telephony.DataFailCause; +import android.telephony.DataFailCause.FailCause; import android.telephony.data.ApnSetting.ProtocolType; import com.android.internal.annotations.VisibleForTesting; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.net.InetAddress; import java.util.ArrayList; import java.util.List; @@ -39,83 +44,114 @@ import java.util.Objects; */ @SystemApi public final class DataCallResponse implements Parcelable { - private final int mStatus; + + /** {@hide} */ + @IntDef(prefix = "LINK_STATUS_", value = { + LINK_STATUS_UNKNOWN, + LINK_STATUS_INACTIVE, + LINK_STATUS_DORMANT, + LINK_STATUS_ACTIVE + }) + @Retention(RetentionPolicy.SOURCE) + public @interface LinkStatus {} + + /** Unknown status */ + public static final int LINK_STATUS_UNKNOWN = -1; + + /** Indicates the data connection is inactive. */ + public static final int LINK_STATUS_INACTIVE = 0; + + /** Indicates the data connection is active with physical link dormant. */ + public static final int LINK_STATUS_DORMANT = 1; + + /** Indicates the data connection is active with physical link up. */ + public static final int LINK_STATUS_ACTIVE = 2; + + private final @FailCause int mCause; private final int mSuggestedRetryTime; - private final int mCid; - private final int mActive; - private final int mProtocolType; - private final String mIfname; + private final int mId; + private final @LinkStatus int mLinkStatus; + private final @ProtocolType int mProtocolType; + private final String mInterfaceName; private final List<LinkAddress> mAddresses; - private final List<InetAddress> mDnses; - private final List<InetAddress> mGateways; - private final List<String> mPcscfs; + private final List<InetAddress> mDnsAddresses; + private final List<InetAddress> mGatewayAddresses; + private final List<InetAddress> mPcscfAddresses; private final int mMtu; /** - * @param status Data call fail cause. 0 indicates no error. + * @param cause Data call fail cause. {@link DataFailCause#NONE} indicates no error. * @param suggestedRetryTime The suggested data retry time in milliseconds. - * @param cid The unique id of the data connection. - * @param active Data connection active status. 0 = inactive, 1 = dormant, 2 = active. + * @param id The unique id of the data connection. + * @param linkStatus Data connection link status. * @param protocolType The connection protocol, should be one of the PDP_type values in 3GPP - * TS 27.007 section 10.1.1. For example, "IP", "IPV6", "IPV4V6", or "PPP". - * @param ifname The network interface name. + * TS 27.007 section 10.1.1. For example, "IP", "IPV6", "IPV4V6", or "PPP". + * @param interfaceName The network interface name. * @param addresses A list of addresses with optional "/" prefix length, e.g., - * "192.0.1.3" or "192.0.1.11/16 2001:db8::1/64". Typically 1 IPv4 or 1 IPv6 or - * one of each. If the prefix length is absent the addresses are assumed to be - * point to point with IPv4 having a prefix length of 32 and IPv6 128. - * @param dnses A list of DNS server addresses, e.g., "192.0.1.3" or - * "192.0.1.11 2001:db8::1". Null if no dns server addresses returned. - * @param gateways A list of default gateway addresses, e.g., "192.0.1.3" or - * "192.0.1.11 2001:db8::1". When null, the addresses represent point to point - * connections. - * @param pcscfs A list of Proxy Call State Control Function address via PCO(Protocol - * Configuration Option) for IMS client. - * @param mtu MTU (Maximum transmission unit) received from network Value <= 0 means network has - * either not sent a value or sent an invalid value. + * "192.0.1.3" or "192.0.1.11/16 2001:db8::1/64". Typically 1 IPv4 or 1 IPv6 or + * one of each. If the prefix length is absent the addresses are assumed to be + * point to point with IPv4 having a prefix length of 32 and IPv6 128. + * @param dnsAddresses A list of DNS server addresses, e.g., "192.0.1.3" or + * "192.0.1.11 2001:db8::1". Null if no dns server addresses returned. + * @param gatewayAddresses A list of default gateway addresses, e.g., "192.0.1.3" or + * "192.0.1.11 2001:db8::1". When null, the addresses represent point to point connections. + * @param pcscfAddresses A list of Proxy Call State Control Function address via PCO (Protocol + * Configuration Option) for IMS client. + * @param mtu MTU (maximum transmission unit) in bytes received from network. Zero or negative + * values means network has either not sent a value or sent an invalid value. + * either not sent a value or sent an invalid value. + * + * @removed Use the {@link Builder()} instead. */ - public DataCallResponse(int status, int suggestedRetryTime, int cid, int active, - @ProtocolType int protocolType, @Nullable String ifname, + public DataCallResponse(@FailCause int cause, int suggestedRetryTime, int id, + @LinkStatus int linkStatus, + @ProtocolType int protocolType, @Nullable String interfaceName, @Nullable List<LinkAddress> addresses, - @Nullable List<InetAddress> dnses, - @Nullable List<InetAddress> gateways, - @Nullable List<String> pcscfs, int mtu) { - mStatus = status; + @Nullable List<InetAddress> dnsAddresses, + @Nullable List<InetAddress> gatewayAddresses, + @Nullable List<InetAddress> pcscfAddresses, int mtu) { + mCause = cause; mSuggestedRetryTime = suggestedRetryTime; - mCid = cid; - mActive = active; + mId = id; + mLinkStatus = linkStatus; mProtocolType = protocolType; - mIfname = (ifname == null) ? "" : ifname; - mAddresses = (addresses == null) ? new ArrayList<>() : addresses; - mDnses = (dnses == null) ? new ArrayList<>() : dnses; - mGateways = (gateways == null) ? new ArrayList<>() : gateways; - mPcscfs = (pcscfs == null) ? new ArrayList<>() : pcscfs; + mInterfaceName = (interfaceName == null) ? "" : interfaceName; + mAddresses = (addresses == null) + ? new ArrayList<>() : new ArrayList<>(addresses); + mDnsAddresses = (dnsAddresses == null) + ? new ArrayList<>() : new ArrayList<>(dnsAddresses); + mGatewayAddresses = (gatewayAddresses == null) + ? new ArrayList<>() : new ArrayList<>(gatewayAddresses); + mPcscfAddresses = (pcscfAddresses == null) + ? new ArrayList<>() : new ArrayList<>(pcscfAddresses); mMtu = mtu; } /** @hide */ @VisibleForTesting public DataCallResponse(Parcel source) { - mStatus = source.readInt(); + mCause = source.readInt(); mSuggestedRetryTime = source.readInt(); - mCid = source.readInt(); - mActive = source.readInt(); + mId = source.readInt(); + mLinkStatus = source.readInt(); mProtocolType = source.readInt(); - mIfname = source.readString(); + mInterfaceName = source.readString(); mAddresses = new ArrayList<>(); source.readList(mAddresses, LinkAddress.class.getClassLoader()); - mDnses = new ArrayList<>(); - source.readList(mDnses, InetAddress.class.getClassLoader()); - mGateways = new ArrayList<>(); - source.readList(mGateways, InetAddress.class.getClassLoader()); - mPcscfs = new ArrayList<>(); - source.readList(mPcscfs, InetAddress.class.getClassLoader()); + mDnsAddresses = new ArrayList<>(); + source.readList(mDnsAddresses, InetAddress.class.getClassLoader()); + mGatewayAddresses = new ArrayList<>(); + source.readList(mGatewayAddresses, InetAddress.class.getClassLoader()); + mPcscfAddresses = new ArrayList<>(); + source.readList(mPcscfAddresses, InetAddress.class.getClassLoader()); mMtu = source.readInt(); } /** - * @return Data call fail cause. 0 indicates no error. + * @return Data call fail cause. {@link DataFailCause#NONE} indicates no error. */ - public int getStatus() { return mStatus; } + @FailCause + public int getCause() { return mCause; } /** * @return The suggested data retry time in milliseconds. @@ -125,12 +161,12 @@ public final class DataCallResponse implements Parcelable { /** * @return The unique id of the data connection. */ - public int getCallId() { return mCid; } + public int getId() { return mId; } /** - * @return 0 = inactive, 1 = dormant, 2 = active. + * @return The link status */ - public int getActive() { return mActive; } + @LinkStatus public int getLinkStatus() { return mLinkStatus; } /** * @return The connection protocol type. @@ -139,13 +175,13 @@ public final class DataCallResponse implements Parcelable { public int getProtocolType() { return mProtocolType; } /** - * @return The network interface name. + * @return The network interface name (e.g. "rmnet_data1"). */ @NonNull - public String getIfname() { return mIfname; } + public String getInterfaceName() { return mInterfaceName; } /** - * @return A list of {@link LinkAddress} + * @return A list of addresses of this data connection. */ @NonNull public List<LinkAddress> getAddresses() { return mAddresses; } @@ -155,25 +191,25 @@ public final class DataCallResponse implements Parcelable { * "192.0.1.11 2001:db8::1". Empty list if no dns server addresses returned. */ @NonNull - public List<InetAddress> getDnses() { return mDnses; } + public List<InetAddress> getDnsAddresses() { return mDnsAddresses; } /** * @return A list of default gateway addresses, e.g., "192.0.1.3" or * "192.0.1.11 2001:db8::1". Empty list if the addresses represent point to point connections. */ @NonNull - public List<InetAddress> getGateways() { return mGateways; } + public List<InetAddress> getGatewayAddresses() { return mGatewayAddresses; } /** - * @return A list of Proxy Call State Control Function address via PCO(Protocol Configuration + * @return A list of Proxy Call State Control Function address via PCO (Protocol Configuration * Option) for IMS client. */ @NonNull - public List<String> getPcscfs() { return mPcscfs; } + public List<InetAddress> getPcscfAddresses() { return mPcscfAddresses; } /** - * @return MTU received from network Value <= 0 means network has either not sent a value or - * sent an invalid value + * @return MTU (maximum transmission unit) in bytes received from network. Zero or negative + * values means network has either not sent a value or sent an invalid value. */ public int getMtu() { return mMtu; } @@ -181,16 +217,16 @@ public final class DataCallResponse implements Parcelable { public String toString() { StringBuffer sb = new StringBuffer(); sb.append("DataCallResponse: {") - .append(" status=").append(mStatus) + .append(" cause=").append(mCause) .append(" retry=").append(mSuggestedRetryTime) - .append(" cid=").append(mCid) - .append(" active=").append(mActive) + .append(" cid=").append(mId) + .append(" linkStatus=").append(mLinkStatus) .append(" protocolType=").append(mProtocolType) - .append(" ifname=").append(mIfname) + .append(" ifname=").append(mInterfaceName) .append(" addresses=").append(mAddresses) - .append(" dnses=").append(mDnses) - .append(" gateways=").append(mGateways) - .append(" pcscf=").append(mPcscfs) + .append(" dnses=").append(mDnsAddresses) + .append(" gateways=").append(mGatewayAddresses) + .append(" pcscf=").append(mPcscfAddresses) .append(" mtu=").append(mMtu) .append("}"); return sb.toString(); @@ -200,32 +236,33 @@ public final class DataCallResponse implements Parcelable { public boolean equals (Object o) { if (this == o) return true; - if (o == null || !(o instanceof DataCallResponse)) { + if (!(o instanceof DataCallResponse)) { return false; } DataCallResponse other = (DataCallResponse) o; - return this.mStatus == other.mStatus + return this.mCause == other.mCause && this.mSuggestedRetryTime == other.mSuggestedRetryTime - && this.mCid == other.mCid - && this.mActive == other.mActive + && this.mId == other.mId + && this.mLinkStatus == other.mLinkStatus && this.mProtocolType == other.mProtocolType - && this.mIfname.equals(other.mIfname) + && this.mInterfaceName.equals(other.mInterfaceName) && mAddresses.size() == other.mAddresses.size() && mAddresses.containsAll(other.mAddresses) - && mDnses.size() == other.mDnses.size() - && mDnses.containsAll(other.mDnses) - && mGateways.size() == other.mGateways.size() - && mGateways.containsAll(other.mGateways) - && mPcscfs.size() == other.mPcscfs.size() - && mPcscfs.containsAll(other.mPcscfs) + && mDnsAddresses.size() == other.mDnsAddresses.size() + && mDnsAddresses.containsAll(other.mDnsAddresses) + && mGatewayAddresses.size() == other.mGatewayAddresses.size() + && mGatewayAddresses.containsAll(other.mGatewayAddresses) + && mPcscfAddresses.size() == other.mPcscfAddresses.size() + && mPcscfAddresses.containsAll(other.mPcscfAddresses) && mMtu == other.mMtu; } @Override public int hashCode() { - return Objects.hash(mStatus, mSuggestedRetryTime, mCid, mActive, mProtocolType, mIfname, - mAddresses, mDnses, mGateways, mPcscfs, mMtu); + return Objects.hash(mCause, mSuggestedRetryTime, mId, mLinkStatus, mProtocolType, + mInterfaceName, mAddresses, mDnsAddresses, mGatewayAddresses, mPcscfAddresses, + mMtu); } @Override @@ -235,16 +272,16 @@ public final class DataCallResponse implements Parcelable { @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(mStatus); + dest.writeInt(mCause); dest.writeInt(mSuggestedRetryTime); - dest.writeInt(mCid); - dest.writeInt(mActive); + dest.writeInt(mId); + dest.writeInt(mLinkStatus); dest.writeInt(mProtocolType); - dest.writeString(mIfname); + dest.writeString(mInterfaceName); dest.writeList(mAddresses); - dest.writeList(mDnses); - dest.writeList(mGateways); - dest.writeList(mPcscfs); + dest.writeList(mDnsAddresses); + dest.writeList(mGatewayAddresses); + dest.writeList(mPcscfAddresses); dest.writeInt(mMtu); } @@ -260,4 +297,183 @@ public final class DataCallResponse implements Parcelable { return new DataCallResponse[size]; } }; -}
\ No newline at end of file + + /** + * Provides a convenient way to set the fields of a {@link DataCallResponse} when creating a new + * instance. + * + * <p>The example below shows how you might create a new {@code DataCallResponse}: + * + * <pre><code> + * + * DataCallResponse response = new DataCallResponse.Builder() + * .setAddresses(Arrays.asList("192.168.1.2")) + * .setProtocolType(ApnSetting.PROTOCOL_IPV4V6) + * .build(); + * </code></pre> + */ + public static final class Builder { + private @FailCause int mCause; + + private int mSuggestedRetryTime; + + private int mId; + + private @LinkStatus int mLinkStatus; + + private @ProtocolType int mProtocolType; + + private String mInterfaceName; + + private List<LinkAddress> mAddresses; + + private List<InetAddress> mDnsAddresses; + + private List<InetAddress> mGatewayAddresses; + + private List<InetAddress> mPcscfAddresses; + + private int mMtu; + + /** + * Default constructor for Builder. + */ + public Builder() { + } + + /** + * Set data call fail cause. + * + * @param cause Data call fail cause. {@link DataFailCause#NONE} indicates no error. + * @return The same instance of the builder. + */ + public @NonNull Builder setCause(@FailCause int cause) { + mCause = cause; + return this; + } + + /** + * Set the suggested data retry time. + * + * @param suggestedRetryTime The suggested data retry time in milliseconds. + * @return The same instance of the builder. + */ + public @NonNull Builder setSuggestedRetryTime(int suggestedRetryTime) { + mSuggestedRetryTime = suggestedRetryTime; + return this; + } + + /** + * Set the unique id of the data connection. + * + * @param id The unique id of the data connection. + * @return The same instance of the builder. + */ + public @NonNull Builder setId(int id) { + mId = id; + return this; + } + + /** + * Set the link status + * + * @param linkStatus The link status + * @return The same instance of the builder. + */ + public @NonNull Builder setLinkStatus(@LinkStatus int linkStatus) { + mLinkStatus = linkStatus; + return this; + } + + /** + * Set the connection protocol type. + * + * @param protocolType The connection protocol type. + * @return The same instance of the builder. + */ + public @NonNull Builder setProtocolType(@ProtocolType int protocolType) { + mProtocolType = protocolType; + return this; + } + + /** + * Set the network interface name. + * + * @param interfaceName The network interface name (e.g. "rmnet_data1"). + * @return The same instance of the builder. + */ + public @NonNull Builder setInterfaceName(@NonNull String interfaceName) { + mInterfaceName = interfaceName; + return this; + } + + /** + * Set the addresses of this data connection. + * + * @param addresses The list of address of the data connection. + * @return The same instance of the builder. + */ + public @NonNull Builder setAddresses(@NonNull List<LinkAddress> addresses) { + mAddresses = addresses; + return this; + } + + /** + * Set the DNS addresses of this data connection + * + * @param dnsAddresses The list of DNS address of the data connection. + * @return The same instance of the builder. + */ + public @NonNull Builder setDnsAddresses(@NonNull List<InetAddress> dnsAddresses) { + mDnsAddresses = dnsAddresses; + return this; + } + + /** + * Set the gateway addresses of this data connection + * + * @param gatewayAddresses The list of gateway address of the data connection. + * @return The same instance of the builder. + */ + public @NonNull Builder setGatewayAddresses(@NonNull List<InetAddress> gatewayAddresses) { + mGatewayAddresses = gatewayAddresses; + return this; + } + + /** + * Set the Proxy Call State Control Function address via PCO(Protocol Configuration + * Option) for IMS client. + * + * @param pcscfAddresses The list of pcscf address of the data connection. + * @return The same instance of the builder. + */ + public @NonNull Builder setPcscfAddresses(@NonNull List<InetAddress> pcscfAddresses) { + mPcscfAddresses = pcscfAddresses; + return this; + } + + /** + * Set maximum transmission unit of the data connection. + * + * @param mtu MTU (maximum transmission unit) in bytes received from network. Zero or + * negative values means network has either not sent a value or sent an invalid value. + * + * @return The same instance of the builder. + */ + public @NonNull Builder setMtu(int mtu) { + mMtu = mtu; + return this; + } + + /** + * Build the DataCallResponse. + * + * @return the DataCallResponse object. + */ + public @NonNull DataCallResponse build() { + return new DataCallResponse(mCause, mSuggestedRetryTime, mId, mLinkStatus, + mProtocolType, mInterfaceName, mAddresses, mDnsAddresses, mGatewayAddresses, + mPcscfAddresses, mMtu); + } + } +} diff --git a/telephony/java/android/telephony/data/DataProfile.java b/telephony/java/android/telephony/data/DataProfile.java index bcb47f73cb4d..c53ade16cae4 100644 --- a/telephony/java/android/telephony/data/DataProfile.java +++ b/telephony/java/android/telephony/data/DataProfile.java @@ -34,6 +34,7 @@ import com.android.internal.telephony.RILConstants; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.Objects; /** * Description of a mobile data profile used for establishing @@ -50,7 +51,7 @@ public final class DataProfile implements Parcelable { TYPE_COMMON, TYPE_3GPP, TYPE_3GPP2}) - public @interface DataProfileType {} + public @interface Type {} /** Common data profile */ public static final int TYPE_COMMON = 0; @@ -75,25 +76,25 @@ public final class DataProfile implements Parcelable { private final String mPassword; - @DataProfileType + @Type private final int mType; - private final int mMaxConnsTime; + private final int mMaxConnectionsTime; - private final int mMaxConns; + private final int mMaxConnections; private final int mWaitTime; private final boolean mEnabled; @ApnType - private final int mSupportedApnTypesBitmap; + private final int mSupportedApnTypesBitmask; @ProtocolType private final int mRoamingProtocolType; @NetworkTypeBitMask - private final int mBearerBitmap; + private final int mBearerBitmask; private final int mMtu; @@ -102,11 +103,13 @@ public final class DataProfile implements Parcelable { private final boolean mPreferred; /** @hide */ - public DataProfile(int profileId, String apn, @ProtocolType int protocolType, int authType, - String userName, String password, int type, int maxConnsTime, int maxConns, - int waitTime, boolean enabled, @ApnType int supportedApnTypesBitmap, - @ProtocolType int roamingProtocolType, @NetworkTypeBitMask int bearerBitmap, - int mtu, boolean persistent, boolean preferred) { + private DataProfile(int profileId, String apn, @ProtocolType int protocolType, int authType, + String userName, String password, int type, int maxConnectionsTime, + int maxConnections, int waitTime, boolean enabled, + @ApnType int supportedApnTypesBitmask, + @ProtocolType int roamingProtocolType, + @NetworkTypeBitMask int bearerBitmask, int mtu, boolean persistent, + boolean preferred) { this.mProfileId = profileId; this.mApn = apn; this.mProtocolType = protocolType; @@ -118,21 +121,19 @@ public final class DataProfile implements Parcelable { this.mUserName = userName; this.mPassword = password; this.mType = type; - this.mMaxConnsTime = maxConnsTime; - this.mMaxConns = maxConns; + this.mMaxConnectionsTime = maxConnectionsTime; + this.mMaxConnections = maxConnections; this.mWaitTime = waitTime; this.mEnabled = enabled; - - this.mSupportedApnTypesBitmap = supportedApnTypesBitmap; + this.mSupportedApnTypesBitmask = supportedApnTypesBitmask; this.mRoamingProtocolType = roamingProtocolType; - this.mBearerBitmap = bearerBitmap; + this.mBearerBitmask = bearerBitmask; this.mMtu = mtu; this.mPersistent = persistent; this.mPreferred = preferred; } - /** @hide */ - public DataProfile(Parcel source) { + private DataProfile(Parcel source) { mProfileId = source.readInt(); mApn = source.readString(); mProtocolType = source.readInt(); @@ -140,13 +141,13 @@ public final class DataProfile implements Parcelable { mUserName = source.readString(); mPassword = source.readString(); mType = source.readInt(); - mMaxConnsTime = source.readInt(); - mMaxConns = source.readInt(); + mMaxConnectionsTime = source.readInt(); + mMaxConnections = source.readInt(); mWaitTime = source.readInt(); mEnabled = source.readBoolean(); - mSupportedApnTypesBitmap = source.readInt(); + mSupportedApnTypesBitmask = source.readInt(); mRoamingProtocolType = source.readInt(); - mBearerBitmap = source.readInt(); + mBearerBitmask = source.readInt(); mMtu = source.readInt(); mPersistent = source.readBoolean(); mPreferred = source.readBoolean(); @@ -158,7 +159,8 @@ public final class DataProfile implements Parcelable { public int getProfileId() { return mProfileId; } /** - * @return The APN to establish data connection. + * @return The APN (Access Point Name) to establish data connection. This is a string + * specifically defined by the carrier. */ @NonNull public String getApn() { return mApn; } @@ -166,7 +168,7 @@ public final class DataProfile implements Parcelable { /** * @return The connection protocol defined in 3GPP TS 27.007 section 10.1.1. */ - public @ProtocolType int getProtocol() { return mProtocolType; } + public @ProtocolType int getProtocolType() { return mProtocolType; } /** * @return The authentication protocol used for this PDP context. @@ -188,22 +190,28 @@ public final class DataProfile implements Parcelable { /** * @return The profile type. */ - public @DataProfileType int getType() { return mType; } + public @Type int getType() { return mType; } /** * @return The period in seconds to limit the maximum connections. + * + * @hide */ - public int getMaxConnsTime() { return mMaxConnsTime; } + public int getMaxConnectionsTime() { return mMaxConnectionsTime; } /** * @return The maximum connections allowed. + * + * @hide */ - public int getMaxConns() { return mMaxConns; } + public int getMaxConnections() { return mMaxConnections; } /** * @return The required wait time in seconds after a successful UE initiated disconnect of a * given PDN connection before the device can send a new PDN connection request for that given * PDN. + * + * @hide */ public int getWaitTime() { return mWaitTime; } @@ -213,19 +221,19 @@ public final class DataProfile implements Parcelable { public boolean isEnabled() { return mEnabled; } /** - * @return The supported APN types bitmap. + * @return The supported APN types bitmask. */ - public @ApnType int getSupportedApnTypesBitmap() { return mSupportedApnTypesBitmap; } + public @ApnType int getSupportedApnTypesBitmask() { return mSupportedApnTypesBitmask; } /** * @return The connection protocol on roaming network defined in 3GPP TS 27.007 section 10.1.1. */ - public @ProtocolType int getRoamingProtocol() { return mRoamingProtocolType; } + public @ProtocolType int getRoamingProtocolType() { return mRoamingProtocolType; } /** - * @return The bearer bitmap indicating the applicable networks for this data profile. + * @return The bearer bitmask indicating the applicable networks for this data profile. */ - public @NetworkTypeBitMask int getBearerBitmap() { return mBearerBitmap; } + public @NetworkTypeBitMask int getBearerBitmask() { return mBearerBitmask; } /** * @return The maximum transmission unit (MTU) size in bytes. @@ -239,7 +247,8 @@ public final class DataProfile implements Parcelable { /** * @return {@code true} if this data profile was used to bring up the last default - * (i.e internet) data connection successfully. + * (i.e internet) data connection successfully, or the one chosen by the user in Settings' + * APN editor. For one carrier there can be only one profiled preferred. */ public boolean isPreferred() { return mPreferred; } @@ -253,19 +262,13 @@ public final class DataProfile implements Parcelable { return "DataProfile=" + mProfileId + "/" + mProtocolType + "/" + mAuthType + "/" + (Build.IS_USER ? "***/***/***" : (mApn + "/" + mUserName + "/" + mPassword)) + "/" + mType + "/" - + mMaxConnsTime + "/" + mMaxConns + "/" - + mWaitTime + "/" + mEnabled + "/" + mSupportedApnTypesBitmap + "/" - + mRoamingProtocolType + "/" + mBearerBitmap + "/" + mMtu + "/" + mPersistent + "/" + + mMaxConnectionsTime + "/" + mMaxConnections + "/" + + mWaitTime + "/" + mEnabled + "/" + mSupportedApnTypesBitmask + "/" + + mRoamingProtocolType + "/" + mBearerBitmask + "/" + mMtu + "/" + mPersistent + "/" + mPreferred; } @Override - public boolean equals(Object o) { - if (o instanceof DataProfile == false) return false; - return (o == this || toString().equals(o.toString())); - } - - @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(mProfileId); dest.writeString(mApn); @@ -274,13 +277,13 @@ public final class DataProfile implements Parcelable { dest.writeString(mUserName); dest.writeString(mPassword); dest.writeInt(mType); - dest.writeInt(mMaxConnsTime); - dest.writeInt(mMaxConns); + dest.writeInt(mMaxConnectionsTime); + dest.writeInt(mMaxConnections); dest.writeInt(mWaitTime); dest.writeBoolean(mEnabled); - dest.writeInt(mSupportedApnTypesBitmap); + dest.writeInt(mSupportedApnTypesBitmask); dest.writeInt(mRoamingProtocolType); - dest.writeInt(mBearerBitmap); + dest.writeInt(mBearerBitmask); dest.writeInt(mMtu); dest.writeBoolean(mPersistent); dest.writeBoolean(mPreferred); @@ -298,4 +301,312 @@ public final class DataProfile implements Parcelable { return new DataProfile[size]; } }; + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + DataProfile that = (DataProfile) o; + return mProfileId == that.mProfileId + && mProtocolType == that.mProtocolType + && mAuthType == that.mAuthType + && mType == that.mType + && mMaxConnectionsTime == that.mMaxConnectionsTime + && mMaxConnections == that.mMaxConnections + && mWaitTime == that.mWaitTime + && mEnabled == that.mEnabled + && mSupportedApnTypesBitmask == that.mSupportedApnTypesBitmask + && mRoamingProtocolType == that.mRoamingProtocolType + && mBearerBitmask == that.mBearerBitmask + && mMtu == that.mMtu + && mPersistent == that.mPersistent + && mPreferred == that.mPreferred + && Objects.equals(mApn, that.mApn) + && Objects.equals(mUserName, that.mUserName) + && Objects.equals(mPassword, that.mPassword); + } + + @Override + public int hashCode() { + return Objects.hash(mProfileId, mApn, mProtocolType, mAuthType, mUserName, mPassword, mType, + mMaxConnectionsTime, mMaxConnections, mWaitTime, mEnabled, + mSupportedApnTypesBitmask, mRoamingProtocolType, mBearerBitmask, mMtu, mPersistent, + mPreferred); + } + + /** + * Provides a convenient way to set the fields of a {@link DataProfile} when creating a new + * instance. + * + * <p>The example below shows how you might create a new {@code DataProfile}: + * + * <pre><code> + * + * DataProfile dp = new DataProfile.Builder() + * .setApn("apn.xyz.com") + * .setProtocol(ApnSetting.PROTOCOL_IPV4V6) + * .build(); + * </code></pre> + */ + public static final class Builder { + private int mProfileId; + + private String mApn; + + @ProtocolType + private int mProtocolType; + + @AuthType + private int mAuthType; + + private String mUserName; + + private String mPassword; + + @Type + private int mType; + + private int mMaxConnectionsTime; + + private int mMaxConnections; + + private int mWaitTime; + + private boolean mEnabled; + + @ApnType + private int mSupportedApnTypesBitmask; + + @ProtocolType + private int mRoamingProtocolType; + + @NetworkTypeBitMask + private int mBearerBitmask; + + private int mMtu; + + private boolean mPersistent; + + private boolean mPreferred; + + /** + * Default constructor for Builder. + */ + public Builder() { + } + + /** + * Set profile id. Note that this is not a global unique id of the data profile. This id + * is only used by certain CDMA carriers to identify the type of data profile. + * + * @param profileId Network domain. + * @return The same instance of the builder. + */ + public @NonNull Builder setProfileId(int profileId) { + mProfileId = profileId; + return this; + } + + /** + * Set the APN (Access Point Name) to establish data connection. This is a string + * specifically defined by the carrier. + * + * @param apn Access point name + * @return The same instance of the builder. + */ + public @NonNull Builder setApn(@NonNull String apn) { + mApn = apn; + return this; + } + + /** + * Set the connection protocol type. + * + * @param protocolType The connection protocol defined in 3GPP TS 27.007 section 10.1.1. + * @return The same instance of the builder. + */ + public @NonNull Builder setProtocolType(@ProtocolType int protocolType) { + mProtocolType = protocolType; + return this; + } + + /** + * Set the authentication type. + * + * @param authType The authentication type + * @return The same instance of the builder. + */ + public @NonNull Builder setAuthType(@AuthType int authType) { + mAuthType = authType; + return this; + } + + /** + * Set the user name + * + * @param userName The user name + * @return The same instance of the builder. + */ + public @NonNull Builder setUserName(@NonNull String userName) { + mUserName = userName; + return this; + } + + /** + * Set the password + * + * @param password The password + * @return The same instance of the builder. + */ + public @NonNull Builder setPassword(@NonNull String password) { + mPassword = password; + return this; + } + + /** + * Set the type + * + * @param type The profile type + * @return The same instance of the builder. + */ + public @NonNull Builder setType(@Type int type) { + mType = type; + return this; + } + + /** + * Set the period in seconds to limit the maximum connections. + * + * @param maxConnectionsTime The profile type + * @return The same instance of the builder. + * + * @hide + */ + public @NonNull Builder setMaxConnectionsTime(int maxConnectionsTime) { + mMaxConnectionsTime = maxConnectionsTime; + return this; + } + + /** + * Set the maximum connections allowed. + * + * @param maxConnections The maximum connections allowed. + * @return The same instance of the builder. + * + * @hide + */ + public @NonNull Builder setMaxConnections(int maxConnections) { + mMaxConnections = maxConnections; + return this; + } + + /** + * Set the period in seconds to limit the maximum connections. + * + * @param waitTime The required wait time in seconds after a successful UE initiated + * disconnect of a given PDN connection before the device can send a new PDN connection + * request for that given PDN. + * + * @return The same instance of the builder. + * + * @hide + */ + public @NonNull Builder setWaitTime(int waitTime) { + mWaitTime = waitTime; + return this; + } + + /** + * Enable the data profile + * + * @param isEnabled {@code true} to enable the data profile, otherwise disable. + * @return The same instance of the builder. + */ + public @NonNull Builder enable(boolean isEnabled) { + mEnabled = isEnabled; + return this; + } + + /** + * Set the supported APN types bitmask. + * + * @param supportedApnTypesBitmask The supported APN types bitmask. + * @return The same instance of the builder. + */ + public @NonNull Builder setSupportedApnTypesBitmask(@ApnType int supportedApnTypesBitmask) { + mSupportedApnTypesBitmask = supportedApnTypesBitmask; + return this; + } + + /** + * Set the connection protocol type for roaming. + * + * @param protocolType The connection protocol defined in 3GPP TS 27.007 section 10.1.1. + * @return The same instance of the builder. + */ + public @NonNull Builder setRoamingProtocolType(@ProtocolType int protocolType) { + mRoamingProtocolType = protocolType; + return this; + } + + /** + * Set the bearer bitmask indicating the applicable networks for this data profile. + * + * @param bearerBitmask The bearer bitmask indicating the applicable networks for this data + * profile. + * @return The same instance of the builder. + */ + public @NonNull Builder setBearerBitmask(@NetworkTypeBitMask int bearerBitmask) { + mBearerBitmask = bearerBitmask; + return this; + } + + /** + * Set the maximum transmission unit (MTU) size in bytes. + * + * @param mtu The maximum transmission unit (MTU) size in bytes. + * @return The same instance of the builder. + */ + public @NonNull Builder setMtu(int mtu) { + mMtu = mtu; + return this; + } + + /** + * Set data profile as preferred/non-preferred. + * + * @param isPreferred {@code true} if this data profile was used to bring up the last + * default (i.e internet) data connection successfully, or the one chosen by the user in + * Settings' APN editor. For one carrier there can be only one profiled preferred. + * @return The same instance of the builder. + */ + public @NonNull Builder setPreferred(boolean isPreferred) { + mPreferred = isPreferred; + return this; + } + + /** + * Set data profile as persistent/non-persistent + * + * @param isPersistent {@code true} if this data profile was used to bring up the last + * default (i.e internet) data connection successfully. + * @return The same instance of the builder. + */ + public @NonNull Builder setPersistent(boolean isPersistent) { + mPersistent = isPersistent; + return this; + } + + /** + * Build the DataProfile object + * + * @return The data profile object + */ + public @NonNull DataProfile build() { + return new DataProfile(mProfileId, mApn, mProtocolType, mAuthType, mUserName, mPassword, + mType, mMaxConnectionsTime, mMaxConnections, mWaitTime, mEnabled, + mSupportedApnTypesBitmask, mRoamingProtocolType, mBearerBitmask, mMtu, + mPersistent, mPreferred); + } + } } diff --git a/telephony/java/android/telephony/data/DataService.java b/telephony/java/android/telephony/data/DataService.java index 59d1e1e7115a..372bdf1c0f81 100644 --- a/telephony/java/android/telephony/data/DataService.java +++ b/telephony/java/android/telephony/data/DataService.java @@ -19,6 +19,7 @@ package android.telephony.data; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SdkConstant; import android.annotation.SystemApi; import android.app.Service; import android.content.Intent; @@ -58,10 +59,12 @@ import java.util.List; public abstract class DataService extends Service { private static final String TAG = DataService.class.getSimpleName(); - public static final String DATA_SERVICE_INTERFACE = "android.telephony.data.DataService"; + @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION) + public static final String SERVICE_INTERFACE = "android.telephony.data.DataService"; /** {@hide} */ @IntDef(prefix = "REQUEST_REASON_", value = { + REQUEST_REASON_UNKNOWN, REQUEST_REASON_NORMAL, REQUEST_REASON_HANDOVER, }) @@ -70,6 +73,7 @@ public abstract class DataService extends Service { /** {@hide} */ @IntDef(prefix = "REQUEST_REASON_", value = { + REQUEST_REASON_UNKNOWN, REQUEST_REASON_NORMAL, REQUEST_REASON_SHUTDOWN, REQUEST_REASON_HANDOVER, @@ -77,6 +81,8 @@ public abstract class DataService extends Service { @Retention(RetentionPolicy.SOURCE) public @interface DeactivateDataReason {} + /** The reason of the data request is unknown */ + public static final int REQUEST_REASON_UNKNOWN = 0; /** The reason of the data request is normal */ public static final int REQUEST_REASON_NORMAL = 1; @@ -94,7 +100,7 @@ public abstract class DataService extends Service { private static final int DATA_SERVICE_REQUEST_DEACTIVATE_DATA_CALL = 5; private static final int DATA_SERVICE_REQUEST_SET_INITIAL_ATTACH_APN = 6; private static final int DATA_SERVICE_REQUEST_SET_DATA_PROFILE = 7; - private static final int DATA_SERVICE_REQUEST_GET_DATA_CALL_LIST = 8; + private static final int DATA_SERVICE_REQUEST_REQUEST_DATA_CALL_LIST = 8; private static final int DATA_SERVICE_REQUEST_REGISTER_DATA_CALL_LIST_CHANGED = 9; private static final int DATA_SERVICE_REQUEST_UNREGISTER_DATA_CALL_LIST_CHANGED = 10; private static final int DATA_SERVICE_INDICATION_DATA_CALL_LIST_CHANGED = 11; @@ -149,14 +155,13 @@ public abstract class DataService extends Service { * {@link #REQUEST_REASON_HANDOVER}. * @param linkProperties If {@code reason} is {@link #REQUEST_REASON_HANDOVER}, this is the * link properties of the existing data connection, otherwise null. - * @param callback The result callback for this request. Null if the client does not care - * about the result. + * @param callback The result callback for this request. */ public void setupDataCall(int accessNetworkType, @NonNull DataProfile dataProfile, boolean isRoaming, boolean allowRoaming, @SetupDataReason int reason, @Nullable LinkProperties linkProperties, - @Nullable DataServiceCallback callback) { + @NonNull DataServiceCallback callback) { // The default implementation is to return unsupported. if (callback != null) { callback.onSetupDataCallComplete(DataServiceCallback.RESULT_ERROR_UNSUPPORTED, @@ -190,11 +195,10 @@ public abstract class DataService extends Service { * * @param dataProfile Data profile used for data call setup. See {@link DataProfile}. * @param isRoaming True if the device is data roaming. - * @param callback The result callback for this request. Null if the client does not care - * about the result. + * @param callback The result callback for this request. */ public void setInitialAttachApn(@NonNull DataProfile dataProfile, boolean isRoaming, - @Nullable DataServiceCallback callback) { + @NonNull DataServiceCallback callback) { // The default implementation is to return unsupported. if (callback != null) { callback.onSetInitialAttachApnComplete( @@ -209,11 +213,10 @@ public abstract class DataService extends Service { * * @param dps A list of data profiles. * @param isRoaming True if the device is data roaming. - * @param callback The result callback for this request. Null if the client does not care - * about the result. + * @param callback The result callback for this request. */ public void setDataProfile(@NonNull List<DataProfile> dps, boolean isRoaming, - @Nullable DataServiceCallback callback) { + @NonNull DataServiceCallback callback) { // The default implementation is to return unsupported. if (callback != null) { callback.onSetDataProfileComplete(DataServiceCallback.RESULT_ERROR_UNSUPPORTED); @@ -225,9 +228,10 @@ public abstract class DataService extends Service { * * @param callback The result callback for this request. */ - public void getDataCallList(@NonNull DataServiceCallback callback) { + public void requestDataCallList(@NonNull DataServiceCallback callback) { // The default implementation is to return unsupported. - callback.onGetDataCallListComplete(DataServiceCallback.RESULT_ERROR_UNSUPPORTED, null); + callback.onRequestDataCallListComplete(DataServiceCallback.RESULT_ERROR_UNSUPPORTED, + null); } private void registerForDataCallListChanged(IDataServiceCallback callback) { @@ -409,10 +413,10 @@ public abstract class DataService extends Service { ? new DataServiceCallback(setDataProfileRequest.callback) : null); break; - case DATA_SERVICE_REQUEST_GET_DATA_CALL_LIST: + case DATA_SERVICE_REQUEST_REQUEST_DATA_CALL_LIST: if (serviceProvider == null) break; - serviceProvider.getDataCallList(new DataServiceCallback( + serviceProvider.requestDataCallList(new DataServiceCallback( (IDataServiceCallback) message.obj)); break; case DATA_SERVICE_REQUEST_REGISTER_DATA_CALL_LIST_CHANGED: @@ -455,14 +459,14 @@ public abstract class DataService extends Service { * will call this method after binding the data service for each active SIM slot id. * * @param slotIndex SIM slot id the data service associated with. - * @return Data service object + * @return Data service object. Null if failed to create the provider (e.g. invalid slot index) */ @Nullable public abstract DataServiceProvider onCreateDataServiceProvider(int slotIndex); @Override public IBinder onBind(Intent intent) { - if (intent == null || !DATA_SERVICE_INTERFACE.equals(intent.getAction())) { + if (intent == null || !SERVICE_INTERFACE.equals(intent.getAction())) { loge("Unexpected intent " + intent); return null; } @@ -531,12 +535,12 @@ public abstract class DataService extends Service { } @Override - public void getDataCallList(int slotIndex, IDataServiceCallback callback) { + public void requestDataCallList(int slotIndex, IDataServiceCallback callback) { if (callback == null) { - loge("getDataCallList: callback is null"); + loge("requestDataCallList: callback is null"); return; } - mHandler.obtainMessage(DATA_SERVICE_REQUEST_GET_DATA_CALL_LIST, slotIndex, 0, + mHandler.obtainMessage(DATA_SERVICE_REQUEST_REQUEST_DATA_CALL_LIST, slotIndex, 0, callback).sendToTarget(); } diff --git a/telephony/java/android/telephony/data/DataServiceCallback.java b/telephony/java/android/telephony/data/DataServiceCallback.java index 2d0cfe80366c..5d8d79367ba4 100644 --- a/telephony/java/android/telephony/data/DataServiceCallback.java +++ b/telephony/java/android/telephony/data/DataServiceCallback.java @@ -140,21 +140,21 @@ public class DataServiceCallback { } /** - * Called to indicate result for the request {@link DataServiceProvider#getDataCallList( + * Called to indicate result for the request {@link DataServiceProvider#requestDataCallList( * DataServiceCallback)}. * * @param result The result code. Must be one of the {@link ResultCode}. * @param dataCallList List of the current active data connection. If no data call is presented, * set it to an empty list. */ - public void onGetDataCallListComplete(@ResultCode int result, - @NonNull List<DataCallResponse> dataCallList) { + public void onRequestDataCallListComplete(@ResultCode int result, + @NonNull List<DataCallResponse> dataCallList) { IDataServiceCallback callback = mCallback.get(); if (callback != null) { try { - callback.onGetDataCallListComplete(result, dataCallList); + callback.onRequestDataCallListComplete(result, dataCallList); } catch (RemoteException e) { - Rlog.e(TAG, "Failed to onGetDataCallListComplete on the remote"); + Rlog.e(TAG, "Failed to onRequestDataCallListComplete on the remote"); } } } diff --git a/telephony/java/android/telephony/data/IDataService.aidl b/telephony/java/android/telephony/data/IDataService.aidl index d4d9be85ffa8..9c74dcccec54 100644 --- a/telephony/java/android/telephony/data/IDataService.aidl +++ b/telephony/java/android/telephony/data/IDataService.aidl @@ -35,7 +35,7 @@ oneway interface IDataService IDataServiceCallback callback); void setDataProfile(int slotId, in List<DataProfile> dps, boolean isRoaming, IDataServiceCallback callback); - void getDataCallList(int slotId, IDataServiceCallback callback); + void requestDataCallList(int slotId, IDataServiceCallback callback); void registerForDataCallListChanged(int slotId, IDataServiceCallback callback); void unregisterForDataCallListChanged(int slotId, IDataServiceCallback callback); } diff --git a/telephony/java/android/telephony/data/IDataServiceCallback.aidl b/telephony/java/android/telephony/data/IDataServiceCallback.aidl index 856185b2974f..cec757d23988 100644 --- a/telephony/java/android/telephony/data/IDataServiceCallback.aidl +++ b/telephony/java/android/telephony/data/IDataServiceCallback.aidl @@ -28,6 +28,6 @@ oneway interface IDataServiceCallback void onDeactivateDataCallComplete(int result); void onSetInitialAttachApnComplete(int result); void onSetDataProfileComplete(int result); - void onGetDataCallListComplete(int result, in List<DataCallResponse> dataCallList); + void onRequestDataCallListComplete(int result, in List<DataCallResponse> dataCallList); void onDataCallListChanged(in List<DataCallResponse> dataCallList); } diff --git a/telephony/java/android/telephony/data/IQualifiedNetworksService.aidl b/telephony/java/android/telephony/data/IQualifiedNetworksService.aidl index 9c80cb77e435..3bf09bc19788 100644 --- a/telephony/java/android/telephony/data/IQualifiedNetworksService.aidl +++ b/telephony/java/android/telephony/data/IQualifiedNetworksService.aidl @@ -23,6 +23,6 @@ import android.telephony.data.IQualifiedNetworksServiceCallback; */ interface IQualifiedNetworksService { - oneway void createNetworkAvailabilityUpdater(int slotId, IQualifiedNetworksServiceCallback callback); - oneway void removeNetworkAvailabilityUpdater(int slotId); + oneway void createNetworkAvailabilityProvider(int slotId, IQualifiedNetworksServiceCallback callback); + oneway void removeNetworkAvailabilityProvider(int slotId); } diff --git a/telephony/java/android/telephony/data/QualifiedNetworksService.java b/telephony/java/android/telephony/data/QualifiedNetworksService.java index c38f2788ca92..0e1751d50949 100644 --- a/telephony/java/android/telephony/data/QualifiedNetworksService.java +++ b/telephony/java/android/telephony/data/QualifiedNetworksService.java @@ -17,7 +17,6 @@ package android.telephony.data; import android.annotation.NonNull; -import android.annotation.Nullable; import android.annotation.SystemApi; import android.app.Service; import android.content.Intent; @@ -34,14 +33,21 @@ import android.util.SparseArray; import com.android.internal.annotations.VisibleForTesting; +import java.util.List; + /** - * Base class of the qualified networks service. Services that extend QualifiedNetworksService must - * register the service in their AndroidManifest to be detected by the framework. They must be - * protected by the permission "android.permission.BIND_TELEPHONY_QUALIFIED_NETWORKS_SERVICE". - * The qualified networks service definition in the manifest must follow the following format: + * Base class of the qualified networks service, which is a vendor service providing up-to-date + * qualified network information to the frameworks for data handover control. A qualified network + * is defined as an access network that is ready for bringing up data connection for given APN + * types. + * + * Services that extend QualifiedNetworksService must register the service in their AndroidManifest + * to be detected by the framework. They must be protected by the permission + * "android.permission.BIND_TELEPHONY_DATA_SERVICE". The qualified networks service definition in + * the manifest must follow the following format: * ... * <service android:name=".xxxQualifiedNetworksService" - * android:permission="android.permission.BIND_TELEPHONY_QUALIFIED_NETWORKS_SERVICE" > + * android:permission="android.permission.BIND_TELEPHONY_DATA_SERVICE" > * <intent-filter> * <action android:name="android.telephony.data.QualifiedNetworksService" /> * </intent-filter> @@ -55,28 +61,28 @@ public abstract class QualifiedNetworksService extends Service { public static final String QUALIFIED_NETWORKS_SERVICE_INTERFACE = "android.telephony.data.QualifiedNetworksService"; - private static final int QNS_CREATE_NETWORK_AVAILABILITY_UPDATER = 1; - private static final int QNS_REMOVE_NETWORK_AVAILABILITY_UPDATER = 2; - private static final int QNS_REMOVE_ALL_NETWORK_AVAILABILITY_UPDATERS = 3; + private static final int QNS_CREATE_NETWORK_AVAILABILITY_PROVIDER = 1; + private static final int QNS_REMOVE_NETWORK_AVAILABILITY_PROVIDER = 2; + private static final int QNS_REMOVE_ALL_NETWORK_AVAILABILITY_PROVIDERS = 3; private static final int QNS_UPDATE_QUALIFIED_NETWORKS = 4; private final HandlerThread mHandlerThread; private final QualifiedNetworksServiceHandler mHandler; - private final SparseArray<NetworkAvailabilityUpdater> mUpdaters = new SparseArray<>(); + private final SparseArray<NetworkAvailabilityProvider> mProviders = new SparseArray<>(); /** @hide */ @VisibleForTesting public final IQualifiedNetworksServiceWrapper mBinder = new IQualifiedNetworksServiceWrapper(); /** - * The abstract class of the network availability updater implementation. The vendor qualified + * The abstract class of the network availability provider implementation. The vendor qualified * network service must extend this class to report the available networks for data - * connection setup. Note that each instance of network availability updater is associated with + * connection setup. Note that each instance of network availability provider is associated with * one physical SIM slot. */ - public abstract class NetworkAvailabilityUpdater implements AutoCloseable { + public abstract class NetworkAvailabilityProvider implements AutoCloseable { private final int mSlotIndex; private IQualifiedNetworksServiceCallback mCallback; @@ -89,14 +95,14 @@ public abstract class QualifiedNetworksService extends Service { /** * Constructor - * @param slotIndex SIM slot index the network availability updater associated with. + * @param slotIndex SIM slot index the network availability provider associated with. */ - public NetworkAvailabilityUpdater(int slotIndex) { + public NetworkAvailabilityProvider(int slotIndex) { mSlotIndex = slotIndex; } /** - * @return SIM slot index the network availability updater associated with. + * @return SIM slot index the network availability provider associated with. */ public final int getSlotIndex() { return mSlotIndex; @@ -121,7 +127,7 @@ public abstract class QualifiedNetworksService extends Service { } /** - * Update the qualified networks list. Network availability updater must invoke this method + * Update the qualified networks list. Network availability provider must invoke this method * whenever the qualified networks changes. If this method is never invoked for certain * APN types, then frameworks will always use the default (i.e. cellular) data and network * service. @@ -129,14 +135,16 @@ public abstract class QualifiedNetworksService extends Service { * @param apnTypes APN types of the qualified networks. This must be a bitmask combination * of {@link ApnSetting.ApnType}. * @param qualifiedNetworkTypes List of network types which are qualified for data - * connection setup for {@link @apnType} in the preferred order. Each element in the array - * is a {@link AccessNetworkType}. An empty list or null indicates no networks are qualified + * connection setup for {@link @apnType} in the preferred order. Each element in the list + * is a {@link AccessNetworkType}. An empty list indicates no networks are qualified * for data setup. */ - public final void updateQualifiedNetworkTypes(@ApnType int apnTypes, - @Nullable int[] qualifiedNetworkTypes) { + public final void updateQualifiedNetworkTypes( + @ApnType int apnTypes, @NonNull List<Integer> qualifiedNetworkTypes) { + int[] qualifiedNetworkTypesArray = + qualifiedNetworkTypes.stream().mapToInt(i->i).toArray(); mHandler.obtainMessage(QNS_UPDATE_QUALIFIED_NETWORKS, mSlotIndex, apnTypes, - qualifiedNetworkTypes).sendToTarget(); + qualifiedNetworkTypesArray).sendToTarget(); } private void onUpdateQualifiedNetworkTypes(@ApnType int apnTypes, @@ -152,7 +160,7 @@ public abstract class QualifiedNetworksService extends Service { } /** - * Called when the qualified networks updater is removed. The extended class should + * Called when the qualified networks provider is removed. The extended class should * implement this method to perform cleanup works. */ @Override @@ -168,48 +176,48 @@ public abstract class QualifiedNetworksService extends Service { public void handleMessage(Message message) { IQualifiedNetworksServiceCallback callback; final int slotIndex = message.arg1; - NetworkAvailabilityUpdater updater = mUpdaters.get(slotIndex); + NetworkAvailabilityProvider provider = mProviders.get(slotIndex); switch (message.what) { - case QNS_CREATE_NETWORK_AVAILABILITY_UPDATER: - if (mUpdaters.get(slotIndex) != null) { - loge("Network availability updater for slot " + slotIndex + case QNS_CREATE_NETWORK_AVAILABILITY_PROVIDER: + if (mProviders.get(slotIndex) != null) { + loge("Network availability provider for slot " + slotIndex + " already existed."); return; } - updater = createNetworkAvailabilityUpdater(slotIndex); - if (updater != null) { - mUpdaters.put(slotIndex, updater); + provider = onCreateNetworkAvailabilityProvider(slotIndex); + if (provider != null) { + mProviders.put(slotIndex, provider); callback = (IQualifiedNetworksServiceCallback) message.obj; - updater.registerForQualifiedNetworkTypesChanged(callback); + provider.registerForQualifiedNetworkTypesChanged(callback); } else { - loge("Failed to create network availability updater. slot index = " + loge("Failed to create network availability provider. slot index = " + slotIndex); } break; - case QNS_REMOVE_NETWORK_AVAILABILITY_UPDATER: - if (updater != null) { - updater.close(); - mUpdaters.remove(slotIndex); + case QNS_REMOVE_NETWORK_AVAILABILITY_PROVIDER: + if (provider != null) { + provider.close(); + mProviders.remove(slotIndex); } break; - case QNS_REMOVE_ALL_NETWORK_AVAILABILITY_UPDATERS: - for (int i = 0; i < mUpdaters.size(); i++) { - updater = mUpdaters.get(i); - if (updater != null) { - updater.close(); + case QNS_REMOVE_ALL_NETWORK_AVAILABILITY_PROVIDERS: + for (int i = 0; i < mProviders.size(); i++) { + provider = mProviders.get(i); + if (provider != null) { + provider.close(); } } - mUpdaters.clear(); + mProviders.clear(); break; case QNS_UPDATE_QUALIFIED_NETWORKS: - if (updater == null) break; - updater.onUpdateQualifiedNetworkTypes(message.arg2, (int[]) message.obj); + if (provider == null) break; + provider.onUpdateQualifiedNetworkTypes(message.arg2, (int[]) message.obj); break; } } @@ -227,8 +235,8 @@ public abstract class QualifiedNetworksService extends Service { } /** - * Create the instance of {@link NetworkAvailabilityUpdater}. Vendor qualified network service - * must override this method to facilitate the creation of {@link NetworkAvailabilityUpdater} + * Create the instance of {@link NetworkAvailabilityProvider}. Vendor qualified network service + * must override this method to facilitate the creation of {@link NetworkAvailabilityProvider} * instances. The system will call this method after binding the qualified networks service for * each active SIM slot index. * @@ -236,7 +244,7 @@ public abstract class QualifiedNetworksService extends Service { * @return Qualified networks service instance */ @NonNull - public abstract NetworkAvailabilityUpdater createNetworkAvailabilityUpdater(int slotIndex); + public abstract NetworkAvailabilityProvider onCreateNetworkAvailabilityProvider(int slotIndex); /** @hide */ @Override @@ -251,7 +259,7 @@ public abstract class QualifiedNetworksService extends Service { /** @hide */ @Override public boolean onUnbind(Intent intent) { - mHandler.obtainMessage(QNS_REMOVE_ALL_NETWORK_AVAILABILITY_UPDATERS).sendToTarget(); + mHandler.obtainMessage(QNS_REMOVE_ALL_NETWORK_AVAILABILITY_PROVIDERS).sendToTarget(); return false; } @@ -267,15 +275,15 @@ public abstract class QualifiedNetworksService extends Service { */ private class IQualifiedNetworksServiceWrapper extends IQualifiedNetworksService.Stub { @Override - public void createNetworkAvailabilityUpdater(int slotIndex, - IQualifiedNetworksServiceCallback callback) { - mHandler.obtainMessage(QNS_CREATE_NETWORK_AVAILABILITY_UPDATER, slotIndex, 0, + public void createNetworkAvailabilityProvider(int slotIndex, + IQualifiedNetworksServiceCallback callback) { + mHandler.obtainMessage(QNS_CREATE_NETWORK_AVAILABILITY_PROVIDER, slotIndex, 0, callback).sendToTarget(); } @Override - public void removeNetworkAvailabilityUpdater(int slotIndex) { - mHandler.obtainMessage(QNS_REMOVE_NETWORK_AVAILABILITY_UPDATER, slotIndex, 0) + public void removeNetworkAvailabilityProvider(int slotIndex) { + mHandler.obtainMessage(QNS_REMOVE_NETWORK_AVAILABILITY_PROVIDER, slotIndex, 0) .sendToTarget(); } } diff --git a/telephony/java/android/telephony/ims/feature/ImsFeature.java b/telephony/java/android/telephony/ims/feature/ImsFeature.java index b55866b5c1c8..5e3f3983b0a1 100644 --- a/telephony/java/android/telephony/ims/feature/ImsFeature.java +++ b/telephony/java/android/telephony/ims/feature/ImsFeature.java @@ -210,6 +210,7 @@ public abstract class ImsFeature { /** * Contains the capabilities defined and supported by an ImsFeature in the form of a bit mask. * @hide + * @deprecated Use {@link MmTelFeature.MmTelCapabilities} instead. */ @SystemApi // SystemApi only because it was leaked through type usage in a previous release. public static class Capabilities { diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl index 3bbf7a41eebf..01fdae800972 100755 --- a/telephony/java/com/android/internal/telephony/ISub.aidl +++ b/telephony/java/com/android/internal/telephony/ISub.aidl @@ -17,6 +17,7 @@ package com.android.internal.telephony; import android.telephony.SubscriptionInfo; +import android.os.ParcelUuid; import com.android.internal.telephony.ISetOpportunisticDataCallback; interface ISub { @@ -202,7 +203,7 @@ interface ISub { * null if fails. * */ - String setSubscriptionGroup(in int[] subIdList, String callingPackage); + ParcelUuid createSubscriptionGroup(in int[] subIdList, String callingPackage); /** * Set which subscription is preferred for cellular data. It's @@ -234,9 +235,13 @@ interface ISub { */ List<SubscriptionInfo> getOpportunisticSubscriptions(String callingPackage); - boolean removeSubscriptionsFromGroup(in int[] subIdList, String callingPackage); + void removeSubscriptionsFromGroup(in int[] subIdList, in ParcelUuid groupUuid, + String callingPackage); - List<SubscriptionInfo> getSubscriptionsInGroup(int subId, String callingPackage); + void addSubscriptionsIntoGroup(in int[] subIdList, in ParcelUuid groupUuid, + String callingPackage); + + List<SubscriptionInfo> getSubscriptionsInGroup(in ParcelUuid groupUuid, String callingPackage); int getSlotIndex(int subId); @@ -264,8 +269,6 @@ interface ISub { void setDefaultSmsSubId(int subId); - void clearDefaultsForInactiveSubIds(); - int[] getActiveSubIdList(boolean visibleOnly); int setSubscriptionProperty(int subId, String propKey, String propValue); diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index c2c31ccee795..10cc99e3e98e 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -1919,15 +1919,18 @@ interface ITelephony { * Indicate if the enablement of multi SIM functionality is restricted. * @hide */ - void setMultisimCarrierRestriction(boolean isMultisimCarrierRestricted); + void setMultiSimCarrierRestriction(boolean isMultiSimCarrierRestricted); /** * Returns if the usage of multiple SIM cards at the same time is supported. * * @param callingPackage The package making the call. - * @return true if multisim is supported, false otherwise. + * @return {@link #MULTISIM_ALLOWED} if the device supports multiple SIMs. + * {@link #MULTISIM_NOT_SUPPORTED_BY_HARDWARE} if the device does not support multiple SIMs. + * {@link #MULTISIM_NOT_SUPPORTED_BY_CARRIER} in the device supports multiple SIMs, but the + * functionality is restricted by the carrier. */ - boolean isMultisimSupported(String callingPackage); + int isMultiSimSupported(String callingPackage); /** * Switch configs to enable multi-sim or switch back to single-sim diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java index 52919df1cf0a..834743d7ffed 100644 --- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java +++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java @@ -39,7 +39,6 @@ import android.util.Log; import androidx.test.InstrumentationRegistry; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -531,7 +530,6 @@ public class RollbackTest { /** * Test rollback of apks involving splits. */ - @Ignore("b/127520966 build issues with splits need to be sorted out") @Test public void testRollbackWithSplits() throws Exception { try { @@ -827,6 +825,7 @@ public class RollbackTest { RollbackTestUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES, + Manifest.permission.MANAGE_ROLLBACKS, Manifest.permission.TEST_MANAGE_ROLLBACKS, Manifest.permission.KILL_BACKGROUND_PROCESSES, Manifest.permission.RESTART_PACKAGES); diff --git a/tests/net/java/android/net/LinkAddressTest.java b/tests/net/java/android/net/LinkAddressTest.java index be7bd1b108b0..d462441b22fa 100644 --- a/tests/net/java/android/net/LinkAddressTest.java +++ b/tests/net/java/android/net/LinkAddressTest.java @@ -81,14 +81,14 @@ public class LinkAddressTest { assertEquals(25, address.getPrefixLength()); assertEquals(0, address.getFlags()); assertEquals(RT_SCOPE_UNIVERSE, address.getScope()); - assertTrue(address.isIPv4()); + assertTrue(address.isIpv4()); address = new LinkAddress(V6_ADDRESS, 127); assertEquals(V6_ADDRESS, address.getAddress()); assertEquals(127, address.getPrefixLength()); assertEquals(0, address.getFlags()); assertEquals(RT_SCOPE_UNIVERSE, address.getScope()); - assertTrue(address.isIPv6()); + assertTrue(address.isIpv6()); // Nonsensical flags/scopes or combinations thereof are acceptable. address = new LinkAddress(V6 + "/64", IFA_F_DEPRECATED | IFA_F_PERMANENT, RT_SCOPE_LINK); @@ -96,14 +96,14 @@ public class LinkAddressTest { assertEquals(64, address.getPrefixLength()); assertEquals(IFA_F_DEPRECATED | IFA_F_PERMANENT, address.getFlags()); assertEquals(RT_SCOPE_LINK, address.getScope()); - assertTrue(address.isIPv6()); + assertTrue(address.isIpv6()); address = new LinkAddress(V4 + "/23", 123, 456); assertEquals(V4_ADDRESS, address.getAddress()); assertEquals(23, address.getPrefixLength()); assertEquals(123, address.getFlags()); assertEquals(456, address.getScope()); - assertTrue(address.isIPv4()); + assertTrue(address.isIpv4()); // InterfaceAddress doesn't have a constructor. Fetch some from an interface. List<InterfaceAddress> addrs = NetworkInterface.getByName("lo").getInterfaceAddresses(); diff --git a/tests/net/java/android/net/LinkPropertiesTest.java b/tests/net/java/android/net/LinkPropertiesTest.java index 9a7d48723e8c..417729150be8 100644 --- a/tests/net/java/android/net/LinkPropertiesTest.java +++ b/tests/net/java/android/net/LinkPropertiesTest.java @@ -405,8 +405,8 @@ public class LinkPropertiesTest { LinkProperties lp = new LinkProperties(); // No addresses. - assertFalse(lp.hasIPv4Address()); - assertFalse(lp.hasGlobalIPv6Address()); + assertFalse(lp.hasIpv4Address()); + assertFalse(lp.hasGlobalIpv6Address()); // Addresses on stacked links don't count. LinkProperties stacked = new LinkProperties(); @@ -414,53 +414,53 @@ public class LinkPropertiesTest { lp.addStackedLink(stacked); stacked.addLinkAddress(LINKADDRV4); stacked.addLinkAddress(LINKADDRV6); - assertTrue(stacked.hasIPv4Address()); - assertTrue(stacked.hasGlobalIPv6Address()); - assertFalse(lp.hasIPv4Address()); - assertFalse(lp.hasGlobalIPv6Address()); + assertTrue(stacked.hasIpv4Address()); + assertTrue(stacked.hasGlobalIpv6Address()); + assertFalse(lp.hasIpv4Address()); + assertFalse(lp.hasGlobalIpv6Address()); lp.removeStackedLink("stacked"); - assertFalse(lp.hasIPv4Address()); - assertFalse(lp.hasGlobalIPv6Address()); + assertFalse(lp.hasIpv4Address()); + assertFalse(lp.hasGlobalIpv6Address()); // Addresses on the base link. - // Check the return values of hasIPvXAddress and ensure the add/remove methods return true + // Check the return values of hasIpvXAddress and ensure the add/remove methods return true // iff something changes. assertEquals(0, lp.getLinkAddresses().size()); assertTrue(lp.addLinkAddress(LINKADDRV6)); assertEquals(1, lp.getLinkAddresses().size()); - assertFalse(lp.hasIPv4Address()); - assertTrue(lp.hasGlobalIPv6Address()); + assertFalse(lp.hasIpv4Address()); + assertTrue(lp.hasGlobalIpv6Address()); assertTrue(lp.removeLinkAddress(LINKADDRV6)); assertEquals(0, lp.getLinkAddresses().size()); assertTrue(lp.addLinkAddress(LINKADDRV6LINKLOCAL)); assertEquals(1, lp.getLinkAddresses().size()); - assertFalse(lp.hasGlobalIPv6Address()); + assertFalse(lp.hasGlobalIpv6Address()); assertTrue(lp.addLinkAddress(LINKADDRV4)); assertEquals(2, lp.getLinkAddresses().size()); - assertTrue(lp.hasIPv4Address()); - assertFalse(lp.hasGlobalIPv6Address()); + assertTrue(lp.hasIpv4Address()); + assertFalse(lp.hasGlobalIpv6Address()); assertTrue(lp.addLinkAddress(LINKADDRV6)); assertEquals(3, lp.getLinkAddresses().size()); - assertTrue(lp.hasIPv4Address()); - assertTrue(lp.hasGlobalIPv6Address()); + assertTrue(lp.hasIpv4Address()); + assertTrue(lp.hasGlobalIpv6Address()); assertTrue(lp.removeLinkAddress(LINKADDRV6LINKLOCAL)); assertEquals(2, lp.getLinkAddresses().size()); - assertTrue(lp.hasIPv4Address()); - assertTrue(lp.hasGlobalIPv6Address()); + assertTrue(lp.hasIpv4Address()); + assertTrue(lp.hasGlobalIpv6Address()); // Adding an address twice has no effect. // Removing an address that's not present has no effect. assertFalse(lp.addLinkAddress(LINKADDRV4)); assertEquals(2, lp.getLinkAddresses().size()); - assertTrue(lp.hasIPv4Address()); + assertTrue(lp.hasIpv4Address()); assertTrue(lp.removeLinkAddress(LINKADDRV4)); assertEquals(1, lp.getLinkAddresses().size()); - assertFalse(lp.hasIPv4Address()); + assertFalse(lp.hasIpv4Address()); assertFalse(lp.removeLinkAddress(LINKADDRV4)); assertEquals(1, lp.getLinkAddresses().size()); @@ -546,8 +546,8 @@ public class LinkPropertiesTest { assertFalse("v4only:addr+dns", lp4.isProvisioned()); lp4.addRoute(new RouteInfo(GATEWAY1)); assertTrue("v4only:addr+dns+route", lp4.isProvisioned()); - assertTrue("v4only:addr+dns+route", lp4.isIPv4Provisioned()); - assertFalse("v4only:addr+dns+route", lp4.isIPv6Provisioned()); + assertTrue("v4only:addr+dns+route", lp4.isIpv4Provisioned()); + assertFalse("v4only:addr+dns+route", lp4.isIpv6Provisioned()); LinkProperties lp6 = new LinkProperties(); assertFalse("v6only:empty", lp6.isProvisioned()); @@ -558,11 +558,11 @@ public class LinkPropertiesTest { lp6.addRoute(new RouteInfo(GATEWAY61)); assertFalse("v6only:fe80+dns+route", lp6.isProvisioned()); lp6.addLinkAddress(LINKADDRV6); - assertTrue("v6only:fe80+global+dns+route", lp6.isIPv6Provisioned()); + assertTrue("v6only:fe80+global+dns+route", lp6.isIpv6Provisioned()); assertTrue("v6only:fe80+global+dns+route", lp6.isProvisioned()); lp6.removeLinkAddress(LINKADDRV6LINKLOCAL); - assertFalse("v6only:global+dns+route", lp6.isIPv4Provisioned()); - assertTrue("v6only:global+dns+route", lp6.isIPv6Provisioned()); + assertFalse("v6only:global+dns+route", lp6.isIpv4Provisioned()); + assertTrue("v6only:global+dns+route", lp6.isIpv6Provisioned()); assertTrue("v6only:global+dns+route", lp6.isProvisioned()); LinkProperties lp46 = new LinkProperties(); @@ -572,12 +572,12 @@ public class LinkPropertiesTest { lp46.addDnsServer(DNS6); assertFalse("dualstack:missing-routes", lp46.isProvisioned()); lp46.addRoute(new RouteInfo(GATEWAY1)); - assertTrue("dualstack:v4-provisioned", lp46.isIPv4Provisioned()); - assertFalse("dualstack:v4-provisioned", lp46.isIPv6Provisioned()); + assertTrue("dualstack:v4-provisioned", lp46.isIpv4Provisioned()); + assertFalse("dualstack:v4-provisioned", lp46.isIpv6Provisioned()); assertTrue("dualstack:v4-provisioned", lp46.isProvisioned()); lp46.addRoute(new RouteInfo(GATEWAY61)); - assertTrue("dualstack:both-provisioned", lp46.isIPv4Provisioned()); - assertTrue("dualstack:both-provisioned", lp46.isIPv6Provisioned()); + assertTrue("dualstack:both-provisioned", lp46.isIpv4Provisioned()); + assertTrue("dualstack:both-provisioned", lp46.isIpv6Provisioned()); assertTrue("dualstack:both-provisioned", lp46.isProvisioned()); // A link with an IPv6 address and default route, but IPv4 DNS server. @@ -585,8 +585,8 @@ public class LinkPropertiesTest { mixed.addLinkAddress(LINKADDRV6); mixed.addDnsServer(DNS1); mixed.addRoute(new RouteInfo(GATEWAY61)); - assertFalse("mixed:addr6+route6+dns4", mixed.isIPv4Provisioned()); - assertFalse("mixed:addr6+route6+dns4", mixed.isIPv6Provisioned()); + assertFalse("mixed:addr6+route6+dns4", mixed.isIpv4Provisioned()); + assertFalse("mixed:addr6+route6+dns4", mixed.isIpv6Provisioned()); assertFalse("mixed:addr6+route6+dns4", mixed.isProvisioned()); } @@ -617,16 +617,16 @@ public class LinkPropertiesTest { v6lp.addLinkAddress(LINKADDRV6); v6lp.addRoute(new RouteInfo(GATEWAY61)); v6lp.addDnsServer(DNS6); - assertFalse(v6lp.isIPv4Provisioned()); - assertTrue(v6lp.isIPv6Provisioned()); + assertFalse(v6lp.isIpv4Provisioned()); + assertTrue(v6lp.isIpv6Provisioned()); assertTrue(v6lp.isProvisioned()); LinkProperties v46lp = new LinkProperties(v6lp); v46lp.addLinkAddress(LINKADDRV4); v46lp.addRoute(new RouteInfo(GATEWAY1)); v46lp.addDnsServer(DNS1); - assertTrue(v46lp.isIPv4Provisioned()); - assertTrue(v46lp.isIPv6Provisioned()); + assertTrue(v46lp.isIpv4Provisioned()); + assertTrue(v46lp.isIpv6Provisioned()); assertTrue(v46lp.isProvisioned()); assertEquals(ProvisioningChange.STILL_PROVISIONED, diff --git a/tests/net/java/android/net/TcpKeepalivePacketDataTest.java b/tests/net/java/android/net/TcpKeepalivePacketDataTest.java index 1f2dd275bb7b..372ffcd057b4 100644 --- a/tests/net/java/android/net/TcpKeepalivePacketDataTest.java +++ b/tests/net/java/android/net/TcpKeepalivePacketDataTest.java @@ -21,12 +21,9 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import android.net.SocketKeepalive.InvalidPacketException; -import android.net.TcpKeepalivePacketData.TcpSocketInfo; import com.android.internal.util.TestUtils; -import libcore.net.InetAddressUtils; - import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -37,14 +34,14 @@ import java.nio.ByteBuffer; @RunWith(JUnit4.class) public final class TcpKeepalivePacketDataTest { + private static final byte[] IPV4_KEEPALIVE_SRC_ADDR = {10, 0, 0, 1}; + private static final byte[] IPV4_KEEPALIVE_DST_ADDR = {10, 0, 0, 5}; @Before public void setUp() {} @Test - public void testV4TcpKeepalivePacket() { - final InetAddress srcAddr = InetAddressUtils.parseNumericAddress("192.168.0.1"); - final InetAddress dstAddr = InetAddressUtils.parseNumericAddress("192.168.0.10"); + public void testV4TcpKeepalivePacket() throws Exception { final int srcPort = 1234; final int dstPort = 4321; final int seq = 0x11111111; @@ -52,20 +49,28 @@ public final class TcpKeepalivePacketDataTest { final int wnd = 8000; final int wndScale = 2; TcpKeepalivePacketData resultData = null; - TcpSocketInfo testInfo = new TcpSocketInfo( - srcAddr, srcPort, dstAddr, dstPort, seq, ack, wnd, wndScale); + final TcpKeepalivePacketDataParcelable testInfo = new TcpKeepalivePacketDataParcelable(); + testInfo.srcAddress = IPV4_KEEPALIVE_SRC_ADDR; + testInfo.srcPort = srcPort; + testInfo.dstAddress = IPV4_KEEPALIVE_DST_ADDR; + testInfo.dstPort = dstPort; + testInfo.seq = seq; + testInfo.ack = ack; + testInfo.rcvWnd = wnd; + testInfo.rcvWndScale = wndScale; try { resultData = TcpKeepalivePacketData.tcpKeepalivePacket(testInfo); } catch (InvalidPacketException e) { fail("InvalidPacketException: " + e); } - assertEquals(testInfo.srcAddress, resultData.srcAddress); - assertEquals(testInfo.dstAddress, resultData.dstAddress); + assertEquals(InetAddress.getByAddress(testInfo.srcAddress), resultData.srcAddress); + assertEquals(InetAddress.getByAddress(testInfo.dstAddress), resultData.dstAddress); assertEquals(testInfo.srcPort, resultData.srcPort); assertEquals(testInfo.dstPort, resultData.dstPort); assertEquals(testInfo.seq, resultData.tcpSeq); assertEquals(testInfo.ack, resultData.tcpAck); + assertEquals(testInfo.rcvWnd, resultData.tcpWnd); assertEquals(testInfo.rcvWndScale, resultData.tcpWndScale); TestUtils.assertParcelingIsLossless(resultData, TcpKeepalivePacketData.CREATOR); @@ -78,11 +83,11 @@ public final class TcpKeepalivePacketDataTest { byte[] ip = new byte[4]; buf = ByteBuffer.wrap(packet, 12, 4); buf.get(ip); - assertArrayEquals(ip, srcAddr.getAddress()); + assertArrayEquals(ip, IPV4_KEEPALIVE_SRC_ADDR); // Destination IP address. buf = ByteBuffer.wrap(packet, 16, 4); buf.get(ip); - assertArrayEquals(ip, dstAddr.getAddress()); + assertArrayEquals(ip, IPV4_KEEPALIVE_DST_ADDR); buf = ByteBuffer.wrap(packet, 20, 12); // Source port. @@ -102,25 +107,32 @@ public final class TcpKeepalivePacketDataTest { @Test public void testParcel() throws Exception { - final InetAddress srcAddr = InetAddresses.parseNumericAddress("192.168.0.1"); - final InetAddress dstAddr = InetAddresses.parseNumericAddress("192.168.0.10"); final int srcPort = 1234; final int dstPort = 4321; final int sequence = 0x11111111; final int ack = 0x22222222; final int wnd = 48_000; final int wndScale = 2; + final TcpKeepalivePacketDataParcelable testInfo = new TcpKeepalivePacketDataParcelable(); + testInfo.srcAddress = IPV4_KEEPALIVE_SRC_ADDR; + testInfo.srcPort = srcPort; + testInfo.dstAddress = IPV4_KEEPALIVE_DST_ADDR; + testInfo.dstPort = dstPort; + testInfo.seq = sequence; + testInfo.ack = ack; + testInfo.rcvWnd = wnd; + testInfo.rcvWndScale = wndScale; TcpKeepalivePacketData testData = null; TcpKeepalivePacketDataParcelable resultData = null; - TcpSocketInfo testInfo = new TcpSocketInfo( - srcAddr, srcPort, dstAddr, dstPort, sequence, ack, wnd, wndScale); testData = TcpKeepalivePacketData.tcpKeepalivePacket(testInfo); resultData = testData.toStableParcelable(); - assertArrayEquals(resultData.srcAddress, srcAddr.getAddress()); - assertArrayEquals(resultData.dstAddress, dstAddr.getAddress()); + assertArrayEquals(resultData.srcAddress, IPV4_KEEPALIVE_SRC_ADDR); + assertArrayEquals(resultData.dstAddress, IPV4_KEEPALIVE_DST_ADDR); assertEquals(resultData.srcPort, srcPort); assertEquals(resultData.dstPort, dstPort); assertEquals(resultData.seq, sequence); assertEquals(resultData.ack, ack); + assertEquals(resultData.rcvWnd, wnd); + assertEquals(resultData.rcvWndScale, wndScale); } } diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 3263ef9f28cf..9dfe4362e838 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -495,7 +495,7 @@ public class ConnectivityServiceTest { try { doAnswer(validateAnswer).when(mNetworkMonitor).notifyNetworkConnected(); doAnswer(validateAnswer).when(mNetworkMonitor).forceReevaluation(anyInt()); - doAnswer(validateAnswer).when(mNetworkMonitor).notifyAcceptPartialConnectivity(); + doAnswer(validateAnswer).when(mNetworkMonitor).setAcceptPartialConnectivity(); } catch (RemoteException e) { fail(e.getMessage()); } @@ -2550,7 +2550,7 @@ public class ConnectivityServiceTest { verifyActiveNetwork(TRANSPORT_CELLULAR); } - // TODO: deflake and re-enable + // TODO(b/128426024): deflake and re-enable // @Test public void testPartialConnectivity() { // Register network callback. @@ -2585,7 +2585,7 @@ public class ConnectivityServiceTest { waitForIdle(); try { verify(mWiFiNetworkAgent.mNetworkMonitor, - timeout(TIMEOUT_MS).times(1)).notifyAcceptPartialConnectivity(); + timeout(TIMEOUT_MS).times(1)).setAcceptPartialConnectivity(); } catch (RemoteException e) { fail(e.getMessage()); } @@ -2641,7 +2641,7 @@ public class ConnectivityServiceTest { waitForIdle(); try { verify(mWiFiNetworkAgent.mNetworkMonitor, - timeout(TIMEOUT_MS).times(1)).notifyAcceptPartialConnectivity(); + timeout(TIMEOUT_MS).times(1)).setAcceptPartialConnectivity(); } catch (RemoteException e) { fail(e.getMessage()); } diff --git a/tests/net/java/com/android/server/NetworkManagementServiceTest.java b/tests/net/java/com/android/server/NetworkManagementServiceTest.java index 6fb322554d48..968b3071bf1d 100644 --- a/tests/net/java/com/android/server/NetworkManagementServiceTest.java +++ b/tests/net/java/com/android/server/NetworkManagementServiceTest.java @@ -16,6 +16,7 @@ package com.android.server; +import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.reset; @@ -23,11 +24,11 @@ import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; +import android.annotation.NonNull; import android.content.Context; import android.net.INetd; +import android.net.INetdUnsolicitedEventListener; import android.net.LinkAddress; -import android.net.LocalServerSocket; -import android.net.LocalSocket; import android.os.BatteryStats; import android.os.Binder; import android.os.IBinder; @@ -43,12 +44,11 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; -import java.io.IOException; -import java.io.OutputStream; - /** * Tests for {@link NetworkManagementService}. */ @@ -56,16 +56,16 @@ import java.io.OutputStream; @SmallTest public class NetworkManagementServiceTest { - private static final String SOCKET_NAME = "__test__NetworkManagementServiceTest"; private NetworkManagementService mNMService; - private LocalServerSocket mServerSocket; - private LocalSocket mSocket; - private OutputStream mOutputStream; @Mock private Context mContext; @Mock private IBatteryStats.Stub mBatteryStatsService; @Mock private INetd.Stub mNetdService; + @NonNull + @Captor + private ArgumentCaptor<INetdUnsolicitedEventListener> mUnsolListenerCaptor; + private final SystemServices mServices = new SystemServices() { @Override public IBinder getService(String name) { @@ -88,32 +88,15 @@ public class NetworkManagementServiceTest { @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); - - // Set up a sheltered test environment. - mServerSocket = new LocalServerSocket(SOCKET_NAME); - + doNothing().when(mNetdService) + .registerUnsolicitedEventListener(mUnsolListenerCaptor.capture()); // Start the service and wait until it connects to our socket. - mNMService = NetworkManagementService.create(mContext, SOCKET_NAME, mServices); - mSocket = mServerSocket.accept(); - mOutputStream = mSocket.getOutputStream(); + mNMService = NetworkManagementService.create(mContext, mServices); } @After public void tearDown() throws Exception { mNMService.shutdown(); - // Once NetworkManagementService#shutdown() actually does something and shutdowns - // the underlying NativeDaemonConnector, the block below should be uncommented. - // if (mOutputStream != null) mOutputStream.close(); - // if (mSocket != null) mSocket.close(); - // if (mServerSocket != null) mServerSocket.close(); - } - - /** - * Sends a message on the netd socket and gives the events some time to make it back. - */ - private void sendMessage(String message) throws IOException { - // Strings are null-terminated, so add "\0" at the end. - mOutputStream.write((message + "\0").getBytes()); } private static <T> T expectSoon(T mock) { @@ -131,125 +114,78 @@ public class NetworkManagementServiceTest { // Forget everything that happened to the mock so far, so we can explicitly verify // everything that happens and does not happen to it from now on. - reset(observer); - // Now send NetworkManagementService messages and ensure that the observer methods are - // called. After every valid message we expect a callback soon after; to ensure that + INetdUnsolicitedEventListener unsolListener = mUnsolListenerCaptor.getValue(); + reset(observer); + // Now call unsolListener methods and ensure that the observer methods are + // called. After every method we expect a callback soon after; to ensure that // invalid messages don't cause any callbacks, we call verifyNoMoreInteractions at the end. /** * Interface changes. */ - sendMessage("600 Iface added rmnet12"); + unsolListener.onInterfaceAdded("rmnet12"); expectSoon(observer).interfaceAdded("rmnet12"); - sendMessage("600 Iface removed eth1"); + unsolListener.onInterfaceRemoved("eth1"); expectSoon(observer).interfaceRemoved("eth1"); - sendMessage("607 Iface removed eth1"); - // Invalid code. - - sendMessage("600 Iface borked lo down"); - // Invalid event. - - sendMessage("600 Iface changed clat4 up again"); - // Extra tokens. - - sendMessage("600 Iface changed clat4 up"); + unsolListener.onInterfaceChanged("clat4", true); expectSoon(observer).interfaceStatusChanged("clat4", true); - sendMessage("600 Iface linkstate rmnet0 down"); + unsolListener.onInterfaceLinkStateChanged("rmnet0", false); expectSoon(observer).interfaceLinkStateChanged("rmnet0", false); - sendMessage("600 IFACE linkstate clat4 up"); - // Invalid group. - /** * Bandwidth control events. */ - sendMessage("601 limit alert data rmnet_usb0"); + unsolListener.onQuotaLimitReached("data", "rmnet_usb0"); expectSoon(observer).limitReached("data", "rmnet_usb0"); - sendMessage("601 invalid alert data rmnet0"); - // Invalid group. - - sendMessage("601 limit increased data rmnet0"); - // Invalid event. - - /** * Interface class activity. */ - - sendMessage("613 IfaceClass active 1 1234 10012"); + unsolListener.onInterfaceClassActivityChanged(true, 1, 1234, 0); expectSoon(observer).interfaceClassDataActivityChanged("1", true, 1234); - sendMessage("613 IfaceClass idle 9 5678"); + unsolListener.onInterfaceClassActivityChanged(false, 9, 5678, 0); expectSoon(observer).interfaceClassDataActivityChanged("9", false, 5678); - sendMessage("613 IfaceClass reallyactive 9 4321"); + unsolListener.onInterfaceClassActivityChanged(false, 9, 4321, 0); expectSoon(observer).interfaceClassDataActivityChanged("9", false, 4321); - sendMessage("613 InterfaceClass reallyactive 1"); - // Invalid group. - - /** * IP address changes. */ - sendMessage("614 Address updated fe80::1/64 wlan0 128 253"); + unsolListener.onInterfaceAddressUpdated("fe80::1/64", "wlan0", 128, 253); expectSoon(observer).addressUpdated("wlan0", new LinkAddress("fe80::1/64", 128, 253)); - // There is no "added", so we take this as "removed". - sendMessage("614 Address added fe80::1/64 wlan0 128 253"); + unsolListener.onInterfaceAddressRemoved("fe80::1/64", "wlan0", 128, 253); expectSoon(observer).addressRemoved("wlan0", new LinkAddress("fe80::1/64", 128, 253)); - sendMessage("614 Address removed 2001:db8::1/64 wlan0 1 0"); + unsolListener.onInterfaceAddressRemoved("2001:db8::1/64", "wlan0", 1, 0); expectSoon(observer).addressRemoved("wlan0", new LinkAddress("2001:db8::1/64", 1, 0)); - sendMessage("614 Address removed 2001:db8::1/64 wlan0 1"); - // Not enough arguments. - - sendMessage("666 Address removed 2001:db8::1/64 wlan0 1 0"); - // Invalid code. - - /** * DNS information broadcasts. */ - sendMessage("615 DnsInfo servers rmnet_usb0 3600 2001:db8::1"); + unsolListener.onInterfaceDnsServerInfo("rmnet_usb0", 3600, new String[]{"2001:db8::1"}); expectSoon(observer).interfaceDnsServerInfo("rmnet_usb0", 3600, new String[]{"2001:db8::1"}); - sendMessage("615 DnsInfo servers wlan0 14400 2001:db8::1,2001:db8::2"); + unsolListener.onInterfaceDnsServerInfo("wlan0", 14400, + new String[]{"2001:db8::1", "2001:db8::2"}); expectSoon(observer).interfaceDnsServerInfo("wlan0", 14400, new String[]{"2001:db8::1", "2001:db8::2"}); // We don't check for negative lifetimes, only for parse errors. - sendMessage("615 DnsInfo servers wlan0 -3600 ::1"); + unsolListener.onInterfaceDnsServerInfo("wlan0", -3600, new String[]{"::1"}); expectSoon(observer).interfaceDnsServerInfo("wlan0", -3600, new String[]{"::1"}); - sendMessage("615 DnsInfo servers wlan0 SIXHUNDRED ::1"); - // Non-numeric lifetime. - - sendMessage("615 DnsInfo servers wlan0 2001:db8::1"); - // Missing lifetime. - - sendMessage("615 DnsInfo servers wlan0 3600"); - // No servers. - - sendMessage("615 DnsInfo servers 3600 wlan0 2001:db8::1,2001:db8::2"); - // Non-numeric lifetime. - - sendMessage("615 DnsInfo wlan0 7200 2001:db8::1,2001:db8::2"); - // Invalid tokens. - - sendMessage("666 DnsInfo servers wlan0 5400 2001:db8::1"); - // Invalid code. - // No syntax checking on the addresses. - sendMessage("615 DnsInfo servers wlan0 600 ,::,,foo,::1,"); + unsolListener.onInterfaceDnsServerInfo("wlan0", 600, + new String[]{"", "::", "", "foo", "::1"}); expectSoon(observer).interfaceDnsServerInfo("wlan0", 600, new String[]{"", "::", "", "foo", "::1"}); diff --git a/tests/net/java/com/android/server/connectivity/TetheringTest.java b/tests/net/java/com/android/server/connectivity/TetheringTest.java index fdba72333f0b..6c42ac398b47 100644 --- a/tests/net/java/com/android/server/connectivity/TetheringTest.java +++ b/tests/net/java/com/android/server/connectivity/TetheringTest.java @@ -550,7 +550,7 @@ public class TetheringTest { mTetheringDependencies.ipv6CoordinatorNotifyList) { NetworkState ipv6OnlyState = buildMobileUpstreamState(false, true, false); ipSrv.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, 0, 0, - upstreamState.linkProperties.isIPv6Provisioned() + upstreamState.linkProperties.isIpv6Provisioned() ? ipv6OnlyState.linkProperties : null); } diff --git a/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectableClassModel.java b/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectableClassModel.java index 147f054b1abb..04710e436ffb 100644 --- a/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectableClassModel.java +++ b/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectableClassModel.java @@ -39,7 +39,6 @@ import java.util.Optional; public final class InspectableClassModel { private final @NonNull ClassName mClassName; private final @NonNull Map<String, Property> mPropertyMap; - private @NonNull Optional<String> mNodeName = Optional.empty(); /** * @param className The name of the modeled class @@ -54,15 +53,6 @@ public final class InspectableClassModel { return mClassName; } - @NonNull - public Optional<String> getNodeName() { - return mNodeName; - } - - public void setNodeName(@NonNull Optional<String> nodeName) { - mNodeName = nodeName; - } - /** * Add a property to the model, replacing an existing property of the same name. * diff --git a/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectableNodeNameProcessor.java b/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectableNodeNameProcessor.java deleted file mode 100644 index 64a60fbc9179..000000000000 --- a/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectableNodeNameProcessor.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 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.processor.view.inspector; - -import androidx.annotation.NonNull; - -import java.util.Optional; - -import javax.annotation.processing.ProcessingEnvironment; -import javax.lang.model.element.AnnotationMirror; -import javax.lang.model.element.Element; - -/** - * Process {@code @InspectableNodeName} annotations. - * - * @see android.view.inspector.InspectableNodeName - */ -public final class InspectableNodeNameProcessor implements ModelProcessor { - private final @NonNull String mQualifiedName; - private final @NonNull ProcessingEnvironment mProcessingEnv; - private final @NonNull AnnotationUtils mAnnotationUtils; - - /** - * @param annotationQualifiedName The qualified name of the annotation to process - * @param processingEnv The processing environment from the parent processor - */ - public InspectableNodeNameProcessor( - @NonNull String annotationQualifiedName, - @NonNull ProcessingEnvironment processingEnv) { - mQualifiedName = annotationQualifiedName; - mProcessingEnv = processingEnv; - mAnnotationUtils = new AnnotationUtils(processingEnv); - } - - /** - * Set the node name on the model if one is supplied. - * - * If the model already has a different node name, the node name will not be updated, and - * the processor will print an error the the messager. - * - * @param element The annotated element to operate on - * @param model The model this element should be merged into - */ - @Override - public void process(@NonNull Element element, @NonNull InspectableClassModel model) { - try { - final AnnotationMirror mirror = - mAnnotationUtils.exactlyOneMirror(mQualifiedName, element); - final Optional<String> nodeName = mAnnotationUtils - .typedValueByName("value", String.class, element, mirror); - - if (!model.getNodeName().isPresent() || model.getNodeName().equals(nodeName)) { - model.setNodeName(nodeName); - } else { - final String message = String.format( - "Node name was already set to \"%s\", refusing to change it to \"%s\".", - model.getNodeName().get(), - nodeName); - throw new ProcessingException(message, element, mirror); - } - } catch (ProcessingException processingException) { - processingException.print(mProcessingEnv.getMessager()); - } - } -} diff --git a/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectablePropertyProcessor.java b/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectablePropertyProcessor.java index 7f5f9ca8a8f8..2bd867c235c7 100644 --- a/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectablePropertyProcessor.java +++ b/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectablePropertyProcessor.java @@ -46,7 +46,7 @@ import javax.lang.model.type.TypeMirror; * * @see android.view.inspector.InspectableProperty */ -public final class InspectablePropertyProcessor implements ModelProcessor { +public final class InspectablePropertyProcessor { private final @NonNull String mQualifiedName; private final @NonNull ProcessingEnvironment mProcessingEnv; private final @NonNull AnnotationUtils mAnnotationUtils; @@ -139,7 +139,6 @@ public final class InspectablePropertyProcessor implements ModelProcessor { mAnnotationUtils = new AnnotationUtils(processingEnv); } - @Override public void process(@NonNull Element element, @NonNull InspectableClassModel model) { try { final AnnotationMirror annotation = @@ -608,7 +607,7 @@ public final class InspectablePropertyProcessor implements ModelProcessor { * Build a model of an {@code int} enumeration mapping from annotation values. * * This method only handles the one-to-one mapping of mirrors of - * {@link android.view.inspector.InspectableProperty.EnumMap} annotations into + * {@link android.view.inspector.InspectableProperty.EnumEntry} annotations into * {@link IntEnumEntry} objects. Further validation should be handled elsewhere * * @see android.view.inspector.InspectableProperty#enumMapping() @@ -656,7 +655,7 @@ public final class InspectablePropertyProcessor implements ModelProcessor { * Build a model of an {@code int} flag mapping from annotation values. * * This method only handles the one-to-one mapping of mirrors of - * {@link android.view.inspector.InspectableProperty.FlagMap} annotations into + * {@link android.view.inspector.InspectableProperty.FlagEntry} annotations into * {@link IntFlagEntry} objects. Further validation should be handled elsewhere * * @see android.view.inspector.IntFlagMapping diff --git a/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectionCompanionGenerator.java b/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectionCompanionGenerator.java index c428a4613c95..6e38c245c70e 100644 --- a/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectionCompanionGenerator.java +++ b/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectionCompanionGenerator.java @@ -163,8 +163,6 @@ public final class InspectionCompanionGenerator { .addMethod(generateMapProperties(properties, fields)) .addMethod(generateReadProperties(properties, fields, model.getClassName())); - model.getNodeName().ifPresent(name -> builder.addMethod(generateGetNodeName(name))); - return builder.build(); } @@ -451,31 +449,6 @@ public final class InspectionCompanionGenerator { } /** - * Generate an implementation of - * {@link android.view.inspector.InspectionCompanion#getNodeName()}. - * - * Example: - * <pre> - * @Override - * public String getNodeName() { - * return "nodeName"; - * } - * </pre> - * - * @param nodeName The name of this node - * @return A method definition that returns the node name - */ - @NonNull - private MethodSpec generateGetNodeName(@NonNull String nodeName) { - return MethodSpec.methodBuilder("getNodeName") - .addAnnotation(Override.class) - .addModifiers(Modifier.PUBLIC) - .returns(String.class) - .addStatement("return $S", nodeName) - .build(); - } - - /** * Generate the final class name for the inspection companion from the model's class name. * * The generated class is added to the same package as the source class. If the class in the diff --git a/tools/processors/view_inspector/src/java/android/processor/view/inspector/ModelProcessor.java b/tools/processors/view_inspector/src/java/android/processor/view/inspector/ModelProcessor.java deleted file mode 100644 index ab38f4c9e1b0..000000000000 --- a/tools/processors/view_inspector/src/java/android/processor/view/inspector/ModelProcessor.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 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.processor.view.inspector; - -import androidx.annotation.NonNull; - -import javax.lang.model.element.Element; - -/** - * An interface for annotation processors that operate on a single element and a class model. - */ -public interface ModelProcessor { - /** - * Process the supplied element, mutating the model as needed. - * - * @param element The annotated element to operate on - * @param model The model this element should be merged into - */ - void process(@NonNull Element element, @NonNull InspectableClassModel model); -} diff --git a/tools/processors/view_inspector/src/java/android/processor/view/inspector/PlatformInspectableProcessor.java b/tools/processors/view_inspector/src/java/android/processor/view/inspector/PlatformInspectableProcessor.java index d9ed1fb9f343..80d37273b422 100644 --- a/tools/processors/view_inspector/src/java/android/processor/view/inspector/PlatformInspectableProcessor.java +++ b/tools/processors/view_inspector/src/java/android/processor/view/inspector/PlatformInspectableProcessor.java @@ -38,25 +38,18 @@ import javax.lang.model.element.Modifier; import javax.lang.model.element.TypeElement; import javax.lang.model.util.ElementFilter; - /** * An annotation processor for the platform inspectable annotations. * - * It mostly delegates to {@link ModelProcessor} and {@link InspectionCompanionGenerator}. This - * modular architecture allows the core generation code to be reused for comparable annotations - * outside the platform, such as in AndroidX. + * It mostly delegates to {@link InspectablePropertyProcessor} and + * {@link InspectionCompanionGenerator}. This modular architecture allows the core generation code + * to be reused for comparable annotations outside the platform. * - * @see android.view.inspector.InspectableNodeName * @see android.view.inspector.InspectableProperty */ -@SupportedAnnotationTypes({ - PlatformInspectableProcessor.NODE_NAME_QUALIFIED_NAME, - PlatformInspectableProcessor.PROPERTY_QUALIFIED_NAME -}) +@SupportedAnnotationTypes({PlatformInspectableProcessor.ANNOTATION_QUALIFIED_NAME}) public final class PlatformInspectableProcessor extends AbstractProcessor { - static final String NODE_NAME_QUALIFIED_NAME = - "android.view.inspector.InspectableNodeName"; - static final String PROPERTY_QUALIFIED_NAME = + static final String ANNOTATION_QUALIFIED_NAME = "android.view.inspector.InspectableProperty"; @Override @@ -71,18 +64,8 @@ public final class PlatformInspectableProcessor extends AbstractProcessor { final Map<String, InspectableClassModel> modelMap = new HashMap<>(); for (TypeElement annotation : annotations) { - if (annotation.getQualifiedName().contentEquals(NODE_NAME_QUALIFIED_NAME)) { - runModelProcessor( - roundEnv.getElementsAnnotatedWith(annotation), - new InspectableNodeNameProcessor(NODE_NAME_QUALIFIED_NAME, processingEnv), - modelMap); - - } else if (annotation.getQualifiedName().contentEquals(PROPERTY_QUALIFIED_NAME)) { - runModelProcessor( - roundEnv.getElementsAnnotatedWith(annotation), - new InspectablePropertyProcessor(PROPERTY_QUALIFIED_NAME, processingEnv), - modelMap); - + if (annotation.getQualifiedName().contentEquals(ANNOTATION_QUALIFIED_NAME)) { + processProperties(roundEnv.getElementsAnnotatedWith(annotation), modelMap); } else { fail("Unexpected annotation type", annotation); } @@ -106,16 +89,17 @@ public final class PlatformInspectableProcessor extends AbstractProcessor { } /** - * Run a {@link ModelProcessor} for a set of elements + * Runs {@link PlatformInspectableProcessor} on a set of annotated elements. * - * @param elements Elements to process, should be annotated correctly - * @param processor The processor to use - * @param modelMap A map of qualified class names to models + * @param elements A set of annotated elements to process + * @param modelMap A map of qualified class names to class models to update */ - private void runModelProcessor( + private void processProperties( @NonNull Set<? extends Element> elements, - @NonNull ModelProcessor processor, @NonNull Map<String, InspectableClassModel> modelMap) { + final InspectablePropertyProcessor processor = + new InspectablePropertyProcessor(ANNOTATION_QUALIFIED_NAME, processingEnv); + for (Element element : elements) { final Optional<TypeElement> classElement = enclosingClassElement(element); diff --git a/tools/processors/view_inspector/test/java/android/processor/view/inspector/InspectionCompanionGeneratorTest.java b/tools/processors/view_inspector/test/java/android/processor/view/inspector/InspectionCompanionGeneratorTest.java index 3ec620a1a4bf..c6e6018869ac 100644 --- a/tools/processors/view_inspector/test/java/android/processor/view/inspector/InspectionCompanionGeneratorTest.java +++ b/tools/processors/view_inspector/test/java/android/processor/view/inspector/InspectionCompanionGeneratorTest.java @@ -36,7 +36,6 @@ import org.junit.Test; import java.io.IOException; import java.net.URL; import java.util.Arrays; -import java.util.Optional; /** * Tests for {@link InspectionCompanionGenerator} @@ -56,12 +55,6 @@ public class InspectionCompanionGeneratorTest { } @Test - public void testNodeName() { - mModel.setNodeName(Optional.of("NodeName")); - assertGeneratedFileEquals("NodeName"); - } - - @Test public void testNestedClass() { mModel = new InspectableClassModel( ClassName.get("com.android.node", "Outer", "Inner")); diff --git a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/NodeName.java.txt b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/NodeName.java.txt deleted file mode 100644 index ffa1f0be02d4..000000000000 --- a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/NodeName.java.txt +++ /dev/null @@ -1,37 +0,0 @@ -package com.android.node; - -import android.view.inspector.InspectionCompanion; -import android.view.inspector.PropertyMapper; -import android.view.inspector.PropertyReader; -import java.lang.Override; -import java.lang.String; - -/** - * Inspection companion for {@link TestNode}. - * - * Generated by {@link android.processor.view.inspector.InspectionCompanionGenerator} - * on behalf of {@link android.processor.view.inspector.InspectionCompanionGeneratorTest}. - */ -public final class TestNode$InspectionCompanion implements InspectionCompanion<TestNode> { - /** - * Guards against reading properties before mapping them. - */ - private boolean mPropertiesMapped = false; - - @Override - public void mapProperties(PropertyMapper propertyMapper) { - mPropertiesMapped = true; - } - - @Override - public void readProperties(TestNode node, PropertyReader propertyReader) { - if (!mPropertiesMapped) { - throw new InspectionCompanion.UninitializedPropertyMapException(); - } - } - - @Override - public String getNodeName() { - return "NodeName"; - } -} diff --git a/wifi/java/android/net/wifi/WifiUsabilityStatsEntry.java b/wifi/java/android/net/wifi/WifiUsabilityStatsEntry.java index 01176f223fe2..e59516485112 100644 --- a/wifi/java/android/net/wifi/WifiUsabilityStatsEntry.java +++ b/wifi/java/android/net/wifi/WifiUsabilityStatsEntry.java @@ -345,7 +345,7 @@ public final class WifiUsabilityStatsEntry implements Parcelable { } /** Whether the primary registered cell of current entry is same as that of previous entry */ - public boolean getIsSameRegisteredCell() { + public boolean isSameRegisteredCell() { return mIsSameRegisteredCell; } } diff --git a/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java b/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java index b2251163591b..daea601e9f96 100644 --- a/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java +++ b/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java @@ -18,6 +18,7 @@ package android.net.wifi.aware; import static android.net.wifi.aware.WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR; +import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.SystemApi; import android.net.NetworkSpecifier; @@ -302,12 +303,6 @@ public final class WifiAwareNetworkSpecifier extends NetworkSpecifier implements /** * A builder class for a Wi-Fi Aware network specifier to set up an Aware connection with a * peer. - * <p> - * Note that all Wi-Fi Aware connection specifier objects must call the - * {@link Builder#setDiscoverySession(DiscoverySession)} to specify the context - * within which the connection is created, and - * {@link Builder#setPeerHandle(PeerHandle)} to specify the peer to which the - * connection is created. */ public static final class Builder { private DiscoverySession mDiscoverySession; @@ -318,42 +313,27 @@ public final class WifiAwareNetworkSpecifier extends NetworkSpecifier implements private int mTransportProtocol = -1; // invalid value /** - * Configure the {@link PublishDiscoverySession} or {@link SubscribeDiscoverySession} - * discovery session in whose context the connection is created. - * <p> - * Note: this method must be called for any connection request! + * Create a builder for {@link WifiAwareNetworkSpecifier} used in requests to set up a + * Wi-Fi Aware connection with a peer. * - * @param discoverySession A Wi-Fi Aware discovery session. - * @return the current {@link Builder} builder, enabling chaining of builder - * methods. - */ - public @NonNull Builder setDiscoverySession(@NonNull DiscoverySession discoverySession) { - if (discoverySession == null) { - throw new IllegalArgumentException("Non-null discoverySession required"); - } - mDiscoverySession = discoverySession; - return this; - } - - /** - * Configure the {@link PeerHandle} of the peer to which the Wi-Fi Aware connection is - * requested. The peer is discovered through Wi-Fi Aware discovery, - * <p> - * Note: this method must be called for any connection request! - * - * @param peerHandle The peer's handle obtained through + * @param discoverySession A Wi-Fi Aware discovery session in whose context the connection + * is created. + * @param peerHandle The handle of the peer to which the Wi-Fi Aware connection is + * requested. The peer is discovered through Wi-Fi Aware discovery. The + * handle can be obtained through * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle, byte[], java.util.List)} * or * {@link DiscoverySessionCallback#onMessageReceived(PeerHandle, byte[])}. - * @return the current {@link Builder} builder, enabling chaining of builder - * methods. */ - public @NonNull Builder setPeerHandle(@NonNull PeerHandle peerHandle) { + public Builder(@NonNull DiscoverySession discoverySession, @NonNull PeerHandle peerHandle) { + if (discoverySession == null) { + throw new IllegalArgumentException("Non-null discoverySession required"); + } if (peerHandle == null) { throw new IllegalArgumentException("Non-null peerHandle required"); } + mDiscoverySession = discoverySession; mPeerHandle = peerHandle; - return this; } /** @@ -407,7 +387,7 @@ public final class WifiAwareNetworkSpecifier extends NetworkSpecifier implements * @return the current {@link Builder} builder, enabling chaining of builder * methods. */ - public @NonNull Builder setPort(int port) { + public @NonNull Builder setPort(@IntRange(from = 0, to = 65535) int port) { if (port <= 0 || port > 65535) { throw new IllegalArgumentException("The port must be a positive value (0, 65535]"); } @@ -432,7 +412,8 @@ public final class WifiAwareNetworkSpecifier extends NetworkSpecifier implements * @return the current {@link Builder} builder, enabling chaining of builder * methods. */ - public @NonNull Builder setTransportProtocol(int transportProtocol) { + public @NonNull + Builder setTransportProtocol(@IntRange(from = 0, to = 255) int transportProtocol) { if (transportProtocol < 0 || transportProtocol > 255) { throw new IllegalArgumentException( "The transport protocol must be in range [0, 255]"); @@ -460,6 +441,9 @@ public final class WifiAwareNetworkSpecifier extends NetworkSpecifier implements if (mDiscoverySession == null) { throw new IllegalStateException("Null discovery session!?"); } + if (mPeerHandle == null) { + throw new IllegalStateException("Null peerHandle!?"); + } if (mPskPassphrase != null & mPmk != null) { throw new IllegalStateException( "Can only specify a Passphrase or a PMK - not both!"); @@ -481,10 +465,6 @@ public final class WifiAwareNetworkSpecifier extends NetworkSpecifier implements } } - if (role == WIFI_AWARE_DATA_PATH_ROLE_INITIATOR && mPeerHandle == null) { - throw new IllegalStateException("Null peerHandle!?"); - } - return new WifiAwareNetworkSpecifier( WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB, role, mDiscoverySession.mClientId, mDiscoverySession.mSessionId, mPeerHandle.peerId, diff --git a/wifi/tests/src/android/net/wifi/WifiUsabilityStatsEntryTest.java b/wifi/tests/src/android/net/wifi/WifiUsabilityStatsEntryTest.java index cd60f029dcce..5184152bce34 100644 --- a/wifi/tests/src/android/net/wifi/WifiUsabilityStatsEntryTest.java +++ b/wifi/tests/src/android/net/wifi/WifiUsabilityStatsEntryTest.java @@ -116,6 +116,6 @@ public class WifiUsabilityStatsEntryTest { assertEquals(expected.getCellularSignalStrengthDbm(), actual.getCellularSignalStrengthDbm()); assertEquals(expected.getCellularSignalStrengthDb(), actual.getCellularSignalStrengthDb()); - assertEquals(expected.getIsSameRegisteredCell(), actual.getIsSameRegisteredCell()); + assertEquals(expected.isSameRegisteredCell(), actual.isSameRegisteredCell()); } } diff --git a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java index 657a3383612d..905540e081ed 100644 --- a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java +++ b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java @@ -958,8 +958,8 @@ public class WifiAwareManagerTest { WifiAwareNetworkSpecifier ns = (WifiAwareNetworkSpecifier) publishSession.getValue().createNetworkSpecifierOpen( peerHandle); - WifiAwareNetworkSpecifier nsb = new WifiAwareNetworkSpecifier.Builder().setDiscoverySession( - publishSession.getValue()).setPeerHandle(peerHandle).build(); + WifiAwareNetworkSpecifier nsb = new WifiAwareNetworkSpecifier.Builder( + publishSession.getValue(), peerHandle).build(); // validate format collector.checkThat("role", WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER, @@ -979,9 +979,8 @@ public class WifiAwareManagerTest { // (4) request an encrypted (PMK) network specifier from the session ns = (WifiAwareNetworkSpecifier) publishSession.getValue().createNetworkSpecifierPmk( peerHandle, pmk); - nsb = new WifiAwareNetworkSpecifier.Builder().setDiscoverySession( - publishSession.getValue()).setPeerHandle(peerHandle).setPmk(pmk).setPort( - port).setTransportProtocol(transportProtocol).build(); + nsb = new WifiAwareNetworkSpecifier.Builder(publishSession.getValue(), peerHandle).setPmk( + pmk).setPort(port).setTransportProtocol(transportProtocol).build(); // validate format collector.checkThat("role", WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER, @@ -1005,9 +1004,9 @@ public class WifiAwareManagerTest { (WifiAwareNetworkSpecifier) publishSession.getValue() .createNetworkSpecifierPassphrase( peerHandle, passphrase); - nsb = new WifiAwareNetworkSpecifier.Builder().setDiscoverySession( - publishSession.getValue()).setPeerHandle(peerHandle).setPskPassphrase( - passphrase).setPort(port).setTransportProtocol(transportProtocol).build(); + nsb = new WifiAwareNetworkSpecifier.Builder(publishSession.getValue(), + peerHandle).setPskPassphrase(passphrase).setPort(port).setTransportProtocol( + transportProtocol).build(); // validate format collector.checkThat("role", WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER, @@ -1255,16 +1254,15 @@ public class WifiAwareManagerTest { // (3) create network specifier if (doPmk) { if (useBuilder) { - new WifiAwareNetworkSpecifier.Builder().setDiscoverySession( - publishSession.getValue()).setPeerHandle(peerHandle).setPmk(pmk).build(); + new WifiAwareNetworkSpecifier.Builder(publishSession.getValue(), peerHandle).setPmk( + pmk).build(); } else { publishSession.getValue().createNetworkSpecifierPmk(peerHandle, pmk); } } else { if (useBuilder) { - new WifiAwareNetworkSpecifier.Builder().setDiscoverySession( - publishSession.getValue()).setPeerHandle(peerHandle).setPskPassphrase( - passphrase).build(); + new WifiAwareNetworkSpecifier.Builder(publishSession.getValue(), + peerHandle).setPskPassphrase(passphrase).build(); } else { publishSession.getValue().createNetworkSpecifierPassphrase(peerHandle, passphrase); } @@ -1353,8 +1351,8 @@ public class WifiAwareManagerTest { DiscoverySession publishSession = executeSessionStartup(true); - WifiAwareNetworkSpecifier nsb = new WifiAwareNetworkSpecifier.Builder().setDiscoverySession( - publishSession).setPeerHandle(peerHandle).setPmk(pmk).setPort(port).build(); + WifiAwareNetworkSpecifier nsb = new WifiAwareNetworkSpecifier.Builder(publishSession, + peerHandle).setPmk(pmk).setPort(port).build(); } /** @@ -1368,8 +1366,8 @@ public class WifiAwareManagerTest { DiscoverySession publishSession = executeSessionStartup(true); - WifiAwareNetworkSpecifier nsb = new WifiAwareNetworkSpecifier.Builder().setDiscoverySession( - publishSession).setPeerHandle(peerHandle).setPort(port).build(); + WifiAwareNetworkSpecifier nsb = new WifiAwareNetworkSpecifier.Builder(publishSession, + peerHandle).setPort(port).build(); } /** @@ -1383,8 +1381,8 @@ public class WifiAwareManagerTest { DiscoverySession subscribeSession = executeSessionStartup(false); - WifiAwareNetworkSpecifier nsb = new WifiAwareNetworkSpecifier.Builder().setDiscoverySession( - subscribeSession).setPeerHandle(peerHandle).setPort(port).build(); + WifiAwareNetworkSpecifier nsb = new WifiAwareNetworkSpecifier.Builder(subscribeSession, + peerHandle).setPort(port).build(); } /** @@ -1403,27 +1401,23 @@ public class WifiAwareManagerTest { DiscoverySession publishSession = executeSessionStartup(true); try { - WifiAwareNetworkSpecifier nsb = new WifiAwareNetworkSpecifier.Builder() - .setDiscoverySession(publishSession).setPeerHandle(peerHandle) - .setPmk(pmk).setTransportProtocol(tpNegative).build(); + WifiAwareNetworkSpecifier nsb = new WifiAwareNetworkSpecifier.Builder(publishSession, + peerHandle).setPmk(pmk).setTransportProtocol(tpNegative).build(); assertTrue("No exception on negative transport protocol!", false); } catch (IllegalArgumentException e) { // nop - exception is correct! } try { - WifiAwareNetworkSpecifier nsb = new WifiAwareNetworkSpecifier.Builder() - .setDiscoverySession(publishSession).setPeerHandle(peerHandle) - .setPmk(pmk).setTransportProtocol(tpTooLarge).build(); + WifiAwareNetworkSpecifier nsb = new WifiAwareNetworkSpecifier.Builder(publishSession, + peerHandle).setPmk(pmk).setTransportProtocol(tpTooLarge).build(); assertTrue("No exception on >255 transport protocol!", false); } catch (IllegalArgumentException e) { // nop - exception is correct! } - WifiAwareNetworkSpecifier nsb = new WifiAwareNetworkSpecifier.Builder() - .setDiscoverySession(publishSession).setPeerHandle(peerHandle) - .setPmk(pmk).setTransportProtocol(tpSmallest).build(); - nsb = new WifiAwareNetworkSpecifier.Builder().setDiscoverySession( - publishSession).setPeerHandle(peerHandle).setPmk(pmk).setTransportProtocol( - tpLargest).build(); + WifiAwareNetworkSpecifier nsb = new WifiAwareNetworkSpecifier.Builder(publishSession, + peerHandle).setPmk(pmk).setTransportProtocol(tpSmallest).build(); + nsb = new WifiAwareNetworkSpecifier.Builder(publishSession, peerHandle).setPmk( + pmk).setTransportProtocol(tpLargest).build(); } /** @@ -1437,9 +1431,8 @@ public class WifiAwareManagerTest { DiscoverySession publishSession = executeSessionStartup(true); - WifiAwareNetworkSpecifier nsb = new WifiAwareNetworkSpecifier.Builder() - .setDiscoverySession(publishSession).setPeerHandle(peerHandle) - .setTransportProtocol(transportProtocol).build(); + WifiAwareNetworkSpecifier nsb = new WifiAwareNetworkSpecifier.Builder(publishSession, + peerHandle).setTransportProtocol(transportProtocol).build(); } /** @@ -1453,9 +1446,8 @@ public class WifiAwareManagerTest { DiscoverySession subscribeSession = executeSessionStartup(false); - WifiAwareNetworkSpecifier nsb = new WifiAwareNetworkSpecifier.Builder() - .setDiscoverySession(subscribeSession).setPeerHandle(peerHandle) - .setTransportProtocol(transportProtocol).build(); + WifiAwareNetworkSpecifier nsb = new WifiAwareNetworkSpecifier.Builder(subscribeSession, + peerHandle).setTransportProtocol(transportProtocol).build(); } /* |