diff options
423 files changed, 8051 insertions, 6310 deletions
diff --git a/Android.bp b/Android.bp index 0acc3d69a597..035420f9ff50 100644 --- a/Android.bp +++ b/Android.bp @@ -768,7 +768,6 @@ java_defaults { "android.hardware.vibrator-V1.2-java", "android.hardware.vibrator-V1.3-java", "android.hardware.wifi-V1.0-java-constants", - "networkstack-aidl-framework-java", "devicepolicyprotosnano", ], @@ -1686,6 +1685,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 34c2c2942ded..14fb910d5134 100644 --- a/api/current.txt +++ b/api/current.txt @@ -11598,6 +11598,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); @@ -22810,6 +22811,7 @@ package android.location { field public static final int CONSTELLATION_GALILEO = 6; // 0x6 field public static final int CONSTELLATION_GLONASS = 3; // 0x3 field public static final int CONSTELLATION_GPS = 1; // 0x1 + field public static final int CONSTELLATION_IRNSS = 7; // 0x7 field public static final int CONSTELLATION_QZSS = 4; // 0x4 field public static final int CONSTELLATION_SBAS = 2; // 0x2 field public static final int CONSTELLATION_UNKNOWN = 0; // 0x0 @@ -23400,15 +23402,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 { @@ -23705,17 +23708,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); @@ -23782,10 +23774,18 @@ 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 setDataSource(@NonNull android.media.DataSourceCallback); + 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 { @@ -23990,21 +23990,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(); @@ -24425,9 +24410,10 @@ package android.media { field public static final int AV1Level71 = 2097152; // 0x200000 field public static final int AV1Level72 = 4194304; // 0x400000 field public static final int AV1Level73 = 8388608; // 0x800000 - field public static final int AV1Profile0 = 1; // 0x1 - field public static final int AV1Profile1 = 2; // 0x2 - field public static final int AV1Profile2 = 4; // 0x4 + field public static final int AV1ProfileMain10 = 2; // 0x2 + field public static final int AV1ProfileMain10HDR10 = 4096; // 0x1000 + field public static final int AV1ProfileMain10HDR10Plus = 8192; // 0x2000 + field public static final int AV1ProfileMain8 = 1; // 0x1 field public static final int AVCLevel1 = 1; // 0x1 field public static final int AVCLevel11 = 4; // 0x4 field public static final int AVCLevel12 = 8; // 0x8 @@ -24621,42 +24607,39 @@ package android.media { ctor public MediaCodecInfo.VideoCapabilities.PerformancePoint(int, int, int); method public boolean covers(@NonNull android.media.MediaFormat); method public boolean covers(@NonNull android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint); - field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_100; - field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_120; - field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_200; - field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_24; - field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_240; - field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_25; - field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_30; - field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_50; - field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_60; - field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_100; - field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_120; - field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_200; - field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_24; - field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_240; - field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_25; - field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_30; - field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_50; - field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_60; - field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint SD_24; - field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint SD_25; - field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint SD_30; - field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint SD_48; - field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint SD_50; - field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint SD_60; - field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_100; - field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_120; - field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_200; - field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_24; - field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_240; - field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_25; - field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_30; - field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_50; - field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_60; - field public final int frameRate; - field public final long macroBlockRate; - field public final int macroBlocks; + field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_100; + field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_120; + field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_200; + field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_24; + field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_240; + field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_25; + field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_30; + field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_50; + field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_60; + field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_100; + field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_120; + field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_200; + field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_24; + field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_240; + field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_25; + field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_30; + field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_50; + field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_60; + field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint SD_24; + field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint SD_25; + field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint SD_30; + field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint SD_48; + field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint SD_50; + field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint SD_60; + field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_100; + field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_120; + field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_200; + field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_24; + field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_240; + field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_25; + field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_30; + field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_50; + field @NonNull public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_60; } public final class MediaCodecList { @@ -24942,6 +24925,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 { @@ -25071,6 +25055,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"; @@ -25093,6 +25078,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"; @@ -26142,10 +26128,11 @@ 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; } @@ -26359,6 +26346,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; @@ -26419,10 +26408,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 { @@ -26473,6 +26460,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(); @@ -26513,6 +26501,7 @@ package android.media { } public final class TimedMetaData { + ctor public TimedMetaData(long, @NonNull byte[]); method public byte[] getMetaData(); method public long getTimestamp(); } @@ -26637,21 +26626,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); } @@ -28880,16 +28854,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; } @@ -28997,6 +28980,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); @@ -29025,6 +29009,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 @@ -29036,7 +29021,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(); @@ -30318,13 +30303,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 { @@ -34621,6 +34604,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 @@ -35434,6 +35418,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(); @@ -42500,12 +42485,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(); @@ -42570,7 +42555,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; @@ -44510,6 +44495,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(); @@ -44593,6 +44585,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(); @@ -45196,7 +45198,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(); @@ -45276,6 +45278,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 @@ -53502,7 +53507,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/system-current.txt b/api/system-current.txt index 220a79c7d68f..12a64c792ef3 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -339,6 +339,7 @@ package android.app { field public static final String OPSTR_GET_ACCOUNTS = "android:get_accounts"; field public static final String OPSTR_GPS = "android:gps"; field public static final String OPSTR_INSTANT_APP_START_FOREGROUND = "android:instant_app_start_foreground"; + field public static final String OPSTR_LEGACY_STORAGE = "android:legacy_storage"; field public static final String OPSTR_MANAGE_IPSEC_TUNNELS = "android:manage_ipsec_tunnels"; field public static final String OPSTR_MUTE_MICROPHONE = "android:mute_microphone"; field public static final String OPSTR_NEIGHBORING_CELLS = "android:neighboring_cells"; @@ -546,6 +547,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); @@ -743,7 +745,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(); @@ -757,7 +760,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 @@ -862,7 +866,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(); @@ -1424,14 +1429,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"; @@ -1619,7 +1625,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; @@ -1649,6 +1654,7 @@ package android.content.pm { field public static final String FEATURE_BROADCAST_RADIO = "android.hardware.broadcastradio"; field public static final String FEATURE_TELEPHONY_CARRIERLOCK = "android.hardware.telephony.carrierlock"; field public static final int FLAG_PERMISSION_GRANTED_BY_DEFAULT = 32; // 0x20 + field public static final int FLAG_PERMISSION_HIDDEN = 1024; // 0x400 field public static final int FLAG_PERMISSION_POLICY_FIXED = 4; // 0x4 field public static final int FLAG_PERMISSION_REVIEW_REQUIRED = 64; // 0x40 field public static final int FLAG_PERMISSION_REVOKE_ON_UPGRADE = 8; // 0x8 @@ -1719,7 +1725,7 @@ package android.content.pm { method public void onPermissionsChanged(int); } - @IntDef(prefix={"FLAG_PERMISSION_"}, value={android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET, android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED, android.content.pm.PackageManager.FLAG_PERMISSION_POLICY_FIXED, android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE, android.content.pm.PackageManager.FLAG_PERMISSION_SYSTEM_FIXED, android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT, android.content.pm.PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED, android.content.pm.PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface PackageManager.PermissionFlags { + @IntDef(prefix={"FLAG_PERMISSION_"}, value={android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET, android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED, android.content.pm.PackageManager.FLAG_PERMISSION_POLICY_FIXED, android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE, android.content.pm.PackageManager.FLAG_PERMISSION_SYSTEM_FIXED, android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT, android.content.pm.PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED, android.content.pm.PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED, android.content.pm.PackageManager.FLAG_PERMISSION_HIDDEN}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface PackageManager.PermissionFlags { } public class PermissionGroupInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable { @@ -3068,6 +3074,19 @@ package android.location { method public void onLocationBatch(java.util.List<android.location.Location>); } + public final class GnssCapabilities { + method public boolean hasCapability(int); + field public static final int GEOFENCING = 2; // 0x2 + field public static final int LOW_POWER_MODE = 0; // 0x0 + field public static final int MEASUREMENTS = 3; // 0x3 + field public static final int MEASUREMENT_CORRECTIONS = 5; // 0x5 + field public static final int MEASUREMENT_CORRECTIONS_EXCESS_PATH_LENGTH = 7; // 0x7 + field public static final int MEASUREMENT_CORRECTIONS_LOS_SATS = 6; // 0x6 + field public static final int MEASUREMENT_CORRECTIONS_REFLECTING_PLANE = 8; // 0x8 + field public static final int NAV_MESSAGES = 4; // 0x4 + field public static final int SATELLITE_BLACKLIST = 1; // 0x1 + } + public final class GnssMeasurementCorrections implements android.os.Parcelable { method public int describeContents(); method @FloatRange(from=-1000.0F, to=10000.0f) public double getAltitudeMeters(); @@ -3375,7 +3394,7 @@ package android.location { public class LocationManager { method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void flushGnssBatch(); method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public int getGnssBatchSize(); - method public int getGnssCapabilities(); + method @Nullable public android.location.GnssCapabilities getGnssCapabilities(); method @Nullable public String getLocationControllerExtraPackage(); method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public void injectGnssMeasurementCorrections(@NonNull android.location.GnssMeasurementCorrections); method public boolean isLocationControllerExtraPackageEnabled(); @@ -3559,13 +3578,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); @@ -3575,20 +3587,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 { @@ -3665,13 +3663,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 { @@ -4029,8 +4028,8 @@ 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); + ctor public CaptivePortal(@NonNull android.os.IBinder); + 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 @@ -4046,7 +4045,7 @@ package android.net { 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(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); @@ -4077,8 +4076,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 { @@ -4101,57 +4100,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 } @@ -4173,7 +4162,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 { @@ -4197,7 +4186,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 @@ -4237,18 +4226,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; } @@ -4286,8 +4275,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; @@ -4302,28 +4291,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); } @@ -4334,78 +4323,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 { @@ -4453,15 +4442,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 { @@ -4476,12 +4465,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); } } @@ -5494,7 +5483,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; } @@ -5732,10 +5721,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; } @@ -5888,6 +5877,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"; } @@ -5915,13 +5905,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); @@ -6117,6 +6100,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 @@ -6323,12 +6307,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"; @@ -6647,6 +6634,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); @@ -7730,19 +7718,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 @@ -8044,11 +8032,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); @@ -8068,7 +8057,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); @@ -8175,39 +8164,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(); @@ -8218,32 +8223,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); @@ -8256,15 +8281,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>); } } @@ -8356,6 +8381,7 @@ package android.telephony.euicc { field public static final String EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTIONS = "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTIONS"; field public static final String EXTRA_ENABLE_SUBSCRIPTION = "android.telephony.euicc.extra.ENABLE_SUBSCRIPTION"; field public static final String EXTRA_FORCE_PROVISION = "android.telephony.euicc.extra.FORCE_PROVISION"; + field public static final String EXTRA_FROM_SUBSCRIPTION_ID = "android.telephony.euicc.extra.FROM_SUBSCRIPTION_ID"; field public static final String EXTRA_SUBSCRIPTION_ID = "android.telephony.euicc.extra.SUBSCRIPTION_ID"; field public static final String EXTRA_SUBSCRIPTION_NICKNAME = "android.telephony.euicc.extra.SUBSCRIPTION_NICKNAME"; } @@ -8575,7 +8601,7 @@ package android.telephony.ims { field public final java.util.HashMap<java.lang.String,android.os.Bundle> mParticipants; } - public class ImsException extends java.lang.Exception { + public final class ImsException extends java.lang.Exception { ctor public ImsException(@Nullable String); ctor public ImsException(@Nullable String, int); ctor public ImsException(@Nullable String, int, @Nullable Throwable); @@ -9106,8 +9132,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 18d0ec02f077..9780d43624fa 100644 --- a/api/system-removed.txt +++ b/api/system-removed.txt @@ -60,14 +60,6 @@ package android.content { } -package android.content.pm { - - public static class PackageInstaller.SessionParams implements android.os.Parcelable { - method @Deprecated public void setEnableRollback(); - } - -} - package android.location { public class LocationManager { @@ -149,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 9e8b02ae63e8..417a9edf3720 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -134,16 +134,19 @@ package android.app { method @RequiresPermission("android.permission.MANAGE_APPOPS") public void addHistoricalOps(@NonNull android.app.AppOpsManager.HistoricalOps); method @RequiresPermission("android.permission.MANAGE_APPOPS") public void clearHistory(); method @RequiresPermission("android.permission.GET_APP_OPS_STATS") public void getHistoricalOps(@NonNull android.app.AppOpsManager.HistoricalOpsRequest, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.AppOpsManager.HistoricalOps>); - method @RequiresPermission("android.permission.GET_APP_OPS_STATS") public void getHistoricalOpsFromDiskRaw(@NonNull android.app.AppOpsManager.HistoricalOpsRequest, @Nullable java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.AppOpsManager.HistoricalOps>); + method @RequiresPermission("android.permission.MANAGE_APPOPS") public void getHistoricalOpsFromDiskRaw(@NonNull android.app.AppOpsManager.HistoricalOpsRequest, @Nullable java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.AppOpsManager.HistoricalOps>); method public static int getNumOps(); method public static String[] getOpStrs(); method public boolean isOperationActive(int, int, String); method @RequiresPermission("android.permission.MANAGE_APPOPS") public void offsetHistory(long); + method public static int opToDefaultMode(@NonNull String); method public static String opToPermission(int); method public static int permissionToOpCode(String); + method @RequiresPermission("android.permission.MANAGE_APPOPS") public void reloadNonHistoricalState(); method @RequiresPermission("android.permission.MANAGE_APPOPS") public void resetHistoryParameters(); method @RequiresPermission("android.permission.MANAGE_APPOPS") public void setHistoryParameters(int, long, int); method @RequiresPermission("android.permission.MANAGE_APP_OPS_MODES") public void setMode(int, int, String, int); + method @RequiresPermission("android.permission.MANAGE_APP_OPS_MODES") public void setMode(String, int, String, int); method @RequiresPermission("android.permission.MANAGE_APP_OPS_MODES") public void setUidMode(String, int, int); method public void startWatchingActive(@NonNull int[], @NonNull android.app.AppOpsManager.OnOpActiveChangedListener); method public void stopWatchingActive(@NonNull android.app.AppOpsManager.OnOpActiveChangedListener); @@ -169,6 +172,7 @@ package android.app { field public static final String OPSTR_GET_ACCOUNTS = "android:get_accounts"; field public static final String OPSTR_GPS = "android:gps"; field public static final String OPSTR_INSTANT_APP_START_FOREGROUND = "android:instant_app_start_foreground"; + field public static final String OPSTR_LEGACY_STORAGE = "android:legacy_storage"; field public static final String OPSTR_MANAGE_IPSEC_TUNNELS = "android:manage_ipsec_tunnels"; field public static final String OPSTR_MUTE_MICROPHONE = "android:mute_microphone"; field public static final String OPSTR_NEIGHBORING_CELLS = "android:neighboring_cells"; @@ -416,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); } @@ -656,6 +661,7 @@ package android.content.pm { method @RequiresPermission(anyOf={"android.permission.GRANT_RUNTIME_PERMISSIONS", "android.permission.REVOKE_RUNTIME_PERMISSIONS"}) public abstract void updatePermissionFlags(String, String, int, int, @NonNull android.os.UserHandle); field public static final String FEATURE_ADOPTABLE_STORAGE = "android.software.adoptable_storage"; field public static final String FEATURE_FILE_BASED_ENCRYPTION = "android.software.file_based_encryption"; + field public static final int FLAG_PERMISSION_HIDDEN = 1024; // 0x400 field public static final int FLAG_PERMISSION_REVIEW_REQUIRED = 64; // 0x40 field public static final int FLAG_PERMISSION_REVOKE_ON_UPGRADE = 8; // 0x8 field public static final int FLAG_PERMISSION_REVOKE_WHEN_REQUESTED = 128; // 0x80 @@ -1072,6 +1078,25 @@ package android.media { method public android.media.BufferingParams.Builder setResumePlaybackMarkMs(int); } + public class CallbackDataSourceDesc extends android.media.DataSourceDesc { + method @NonNull public android.media.DataSourceCallback getDataSourceCallback(); + } + + 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); + method public int getMaxFrameRate(); + method public long getMaxMacroBlockRate(); + method public int getMaxMacroBlocks(); + } + public class MediaPlayer2 implements android.media.AudioRouting java.lang.AutoCloseable { method public android.media.MediaPlayer2.DrmInfo getDrmInfo(@NonNull android.media.DataSourceDesc); method public android.media.MediaDrm.KeyRequest getDrmKeyRequest(@NonNull android.media.DataSourceDesc, @Nullable byte[], @Nullable byte[], @Nullable String, int, @Nullable java.util.Map<java.lang.String,java.lang.String>) throws android.media.MediaPlayer2.NoDrmSchemeException; @@ -1088,6 +1113,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); } @@ -1176,8 +1207,8 @@ 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); + ctor public CaptivePortal(@NonNull android.os.IBinder); + 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 @@ -1185,14 +1216,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 { @@ -1203,48 +1234,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 } @@ -1253,7 +1284,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 @@ -1262,18 +1293,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; } @@ -1310,8 +1341,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; @@ -1326,28 +1357,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); } @@ -1358,78 +1389,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 { @@ -1477,15 +1508,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 { @@ -1500,12 +1531,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); } } @@ -3172,10 +3203,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/idmap2/tests/data/overlay/AndroidManifest.xml b/cmds/idmap2/tests/data/overlay/AndroidManifest.xml index a7767a6d35e6..619bb6ce0f25 100644 --- a/cmds/idmap2/tests/data/overlay/AndroidManifest.xml +++ b/cmds/idmap2/tests/data/overlay/AndroidManifest.xml @@ -16,6 +16,7 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="test.overlay"> + <application android:hasCode="false"/> <overlay android:targetPackage="test.target" android:targetName="TestResources"/> diff --git a/cmds/idmap2/tests/data/signature-overlay/AndroidManifest.xml b/cmds/idmap2/tests/data/signature-overlay/AndroidManifest.xml index 5dacebded529..9e6a4536cb51 100644 --- a/cmds/idmap2/tests/data/signature-overlay/AndroidManifest.xml +++ b/cmds/idmap2/tests/data/signature-overlay/AndroidManifest.xml @@ -16,6 +16,7 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="test.overlay.system"> + <application android:hasCode="false"/> <overlay android:targetPackage="test.target" android:targetName="TestResources"/> diff --git a/cmds/idmap2/tests/data/system-overlay-invalid/AndroidManifest.xml b/cmds/idmap2/tests/data/system-overlay-invalid/AndroidManifest.xml index ae687d375e7f..c7b652cdb287 100644 --- a/cmds/idmap2/tests/data/system-overlay-invalid/AndroidManifest.xml +++ b/cmds/idmap2/tests/data/system-overlay-invalid/AndroidManifest.xml @@ -16,6 +16,7 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="test.overlay.system.invalid"> + <application android:hasCode="false"/> <overlay android:targetPackage="test.target" android:targetName="TestResources"/> diff --git a/cmds/idmap2/tests/data/system-overlay/AndroidManifest.xml b/cmds/idmap2/tests/data/system-overlay/AndroidManifest.xml index 5dacebded529..9e6a4536cb51 100644 --- a/cmds/idmap2/tests/data/system-overlay/AndroidManifest.xml +++ b/cmds/idmap2/tests/data/system-overlay/AndroidManifest.xml @@ -16,6 +16,7 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="test.overlay.system"> + <application android:hasCode="false"/> <overlay android:targetPackage="test.target" android:targetName="TestResources"/> diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto index 1dbbbc5595ba..1735b05148fa 100644 --- a/cmds/statsd/src/atoms.proto +++ b/cmds/statsd/src/atoms.proto @@ -2065,6 +2065,9 @@ message BluetoothClassicPairingEventReported { // HCI reason code associated with this event // Default: STATUS_UNKNOWN optional android.bluetooth.hci.StatusEnum reason_code = 6; + // A status value related to this specific event + // Default: 0 + optional int64 event_value = 7; } /** @@ -3419,7 +3422,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 { diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt index b3f003730c53..76d69cdce5cf 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; 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/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index 1066fc7598e9..5ed4428b729b 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -48,7 +48,6 @@ import android.util.LongSparseLongArray; import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; - import com.android.internal.annotations.Immutable; import com.android.internal.app.IAppOpsActiveCallback; import com.android.internal.app.IAppOpsCallback; @@ -1098,6 +1097,8 @@ public class AppOpsManager { /** @hide Write media of image type. */ public static final String OPSTR_WRITE_MEDIA_IMAGES = "android:write_media_images"; /** @hide Has a legacy (non-isolated) view of storage. */ + @TestApi + @SystemApi public static final String OPSTR_LEGACY_STORAGE = "android:legacy_storage"; /** @hide Interact with accessibility. */ @SystemApi @@ -2153,6 +2154,7 @@ public class AppOpsManager { * * @hide */ + @TestApi @SystemApi public static int opToDefaultMode(@NonNull String appOp) { return opToDefaultMode(strOpToOp(appOp)); @@ -4465,7 +4467,7 @@ public class AppOpsManager { * @hide */ @TestApi - @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) + @RequiresPermission(Manifest.permission.MANAGE_APPOPS) public void getHistoricalOpsFromDiskRaw(@NonNull HistoricalOpsRequest request, @Nullable Executor executor, @NonNull Consumer<HistoricalOps> callback) { Preconditions.checkNotNull(executor, "executor cannot be null"); @@ -4488,6 +4490,21 @@ public class AppOpsManager { } /** + * Reloads the non historical state to allow testing the read/write path. + * + * @hide + */ + @TestApi + @RequiresPermission(Manifest.permission.MANAGE_APPOPS) + public void reloadNonHistoricalState() { + try { + mService.reloadNonHistoricalState(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * Sets given app op in the specified mode for app ops in the UID. * This applies to all apps currently in the UID or installed in * this UID in the future. @@ -4570,6 +4587,7 @@ public class AppOpsManager { * be changed. * @hide */ + @TestApi @SystemApi @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES) public void setMode(String op, int uid, String packageName, @Mode int mode) { 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 523b2005fb72..7ba614685ad8 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; @@ -8707,12 +8709,25 @@ public class Notification implements Parcelable * <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..1aacf966fc14 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; @@ -715,12 +716,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 +733,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 +1193,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/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/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/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/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/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java index 33b9c724de21..3edd17a4bb1f 100644 --- a/core/java/android/content/pm/PackageInstaller.java +++ b/core/java/android/content/pm/PackageInstaller.java @@ -1448,19 +1448,6 @@ public class PackageInstaller { } /** - * Request that rollbacks be enabled for the given upgrade. - * - * @removed - * @deprecated use {@link #setEnableRollback(boolean)} instead. - * @hide - */ - @Deprecated - @SystemApi - public void setEnableRollback() { - installFlags |= PackageManager.INSTALL_ENABLE_ROLLBACK; - } - - /** * Request that rollbacks be enabled or disabled for the given upgrade. * * @param enable set to {@code true} to enable, {@code false} to disable diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 2f99879d43a6..73e6f679c984 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -3065,6 +3065,15 @@ public abstract class PackageManager { public static final int FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED = 1 << 9; /** + * Permission flag: The permission should not be shown in the UI. + * + * @hide + */ + @SystemApi + @TestApi + public static final int FLAG_PERMISSION_HIDDEN = 1 << 10; + + /** * Mask for all permission flags present in Android P * * @deprecated This constant does not contain useful information and should never have been @@ -3082,7 +3091,7 @@ public abstract class PackageManager { * * @hide */ - public static final int MASK_PERMISSION_FLAGS_ALL = 0x3FF; + public static final int MASK_PERMISSION_FLAGS_ALL = 0x7FF; /** * Injected activity in app that forwards user to setting activity of that app. @@ -3793,6 +3802,7 @@ public abstract class PackageManager { FLAG_PERMISSION_GRANTED_BY_DEFAULT, FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED, FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED, + FLAG_PERMISSION_HIDDEN, /* FLAG_PERMISSION_REVOKE_WHEN_REQUESED */ @@ -5643,7 +5653,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); @@ -5652,7 +5664,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); @@ -5669,7 +5683,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); @@ -5692,7 +5708,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, @@ -5707,7 +5725,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 @@ -5737,7 +5757,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 @@ -5763,7 +5785,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 @@ -5778,7 +5802,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 @@ -5799,7 +5825,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); @@ -5824,7 +5852,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, @@ -5891,9 +5921,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"); @@ -6586,6 +6615,7 @@ public abstract class PackageManager { case FLAG_PERMISSION_REVOKE_WHEN_REQUESTED: return "REVOKE_WHEN_REQUESTED"; case FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED: return "USER_SENSITIVE_WHEN_GRANTED"; case FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED: return "USER_SENSITIVE_WHEN_DENIED"; + case FLAG_PERMISSION_HIDDEN: return "HIDDEN"; default: return Integer.toString(flag); } } 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..3e4e35a8f16d 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; @@ -65,7 +66,7 @@ public class CaptivePortal implements Parcelable { /** @hide */ @SystemApi @TestApi - public CaptivePortal(IBinder binder) { + public CaptivePortal(@NonNull IBinder binder) { mBinder = binder; } @@ -142,7 +143,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..16322353add2 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) { diff --git a/core/java/android/net/INetworkMonitor.aidl b/core/java/android/net/INetworkMonitor.aidl index 5d1ab983c5fc..1b0e1d788ff3 100644 --- a/core/java/android/net/INetworkMonitor.aidl +++ b/core/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/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/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/TcpKeepalivePacketDataParcelable.aidl b/core/java/android/net/TcpKeepalivePacketDataParcelable.aidl index 7329c63b09be..d66b6ae3ab54 100644 --- a/core/java/android/net/TcpKeepalivePacketDataParcelable.aidl +++ b/core/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/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/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/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/Settings.java b/core/java/android/provider/Settings.java index 63235a1c17e7..7d66b9043b58 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -5613,6 +5613,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 +8587,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 +8958,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/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/euicc/GetEuiccProfileInfoListResult.java b/core/java/android/service/euicc/GetEuiccProfileInfoListResult.java index 7a9d8a05ab47..9add38e40d9b 100644 --- a/core/java/android/service/euicc/GetEuiccProfileInfoListResult.java +++ b/core/java/android/service/euicc/GetEuiccProfileInfoListResult.java @@ -97,9 +97,10 @@ public final class GetEuiccProfileInfoListResult implements Parcelable { if (this.result == EuiccService.RESULT_OK) { this.mProfiles = profiles; } else { - if (profiles != null) { + // For error case, profiles is either null or 0 size. + if (profiles != null && profiles.length > 0) { throw new IllegalArgumentException( - "Error result with non-null profiles: " + result); + "Error result with non-empty profiles: " + result); } this.mProfiles = null; } 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 c1504ae2a269..de10ffb80bee 100644 --- a/core/java/android/util/FeatureFlagUtils.java +++ b/core/java/android/util/FeatureFlagUtils.java @@ -51,7 +51,7 @@ public class FeatureFlagUtils { DEFAULT_FLAGS.put("settings_network_and_internet_v2", "true"); DEFAULT_FLAGS.put("settings_slice_injection", "true"); DEFAULT_FLAGS.put("settings_systemui_theme", "true"); - DEFAULT_FLAGS.put("settings_mainline_module", "false"); + DEFAULT_FLAGS.put("settings_mainline_module", "true"); DEFAULT_FLAGS.put("settings_dynamic_android", "false"); DEFAULT_FLAGS.put(SEAMLESS_TRANSFER, "false"); DEFAULT_FLAGS.put(HEARING_AID_SETTINGS, "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/GestureDetector.java b/core/java/android/view/GestureDetector.java index c1d122a1f9b1..c794a69d3680 100644 --- a/core/java/android/view/GestureDetector.java +++ b/core/java/android/view/GestureDetector.java @@ -16,20 +16,11 @@ package android.view; -import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DEEP_PRESS; -import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DOUBLE_TAP; -import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS; -import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SCROLL; -import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SINGLE_TAP; -import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION; - import android.annotation.UnsupportedAppUsage; import android.content.Context; import android.os.Build; import android.os.Handler; import android.os.Message; -import android.os.SystemClock; -import android.util.StatsLog; /** * Detects various gestures and events using the supplied {@link MotionEvent}s. @@ -260,12 +251,8 @@ public class GestureDetector { private boolean mAlwaysInTapRegion; private boolean mAlwaysInBiggerTapRegion; private boolean mIgnoreNextUpEvent; - // Whether a classification has been recorded by statsd for the current event stream. Reset on - // ACTION_DOWN. - private boolean mHasRecordedClassification; private MotionEvent mCurrentDownEvent; - private MotionEvent mCurrentMotionEvent; private MotionEvent mPreviousUpEvent; /** @@ -310,7 +297,6 @@ public class GestureDetector { break; case LONG_PRESS: - recordGestureClassification(msg.arg1); dispatchLongPress(); break; @@ -318,8 +304,6 @@ public class GestureDetector { // If the user's finger is still down, do not count it as a tap if (mDoubleTapListener != null) { if (!mStillDown) { - recordGestureClassification( - TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SINGLE_TAP); mDoubleTapListener.onSingleTapConfirmed(mCurrentDownEvent); } else { mDeferConfirmSingleTap = true; @@ -517,11 +501,6 @@ public class GestureDetector { final int action = ev.getAction(); - if (mCurrentMotionEvent != null) { - mCurrentMotionEvent.recycle(); - } - mCurrentMotionEvent = MotionEvent.obtain(ev); - if (mVelocityTracker == null) { mVelocityTracker = VelocityTracker.obtain(); } @@ -590,8 +569,6 @@ public class GestureDetector { && isConsideredDoubleTap(mCurrentDownEvent, mPreviousUpEvent, ev)) { // This is a second tap mIsDoubleTapping = true; - recordGestureClassification( - TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DOUBLE_TAP); // Give a callback with the first tap of the double-tap handled |= mDoubleTapListener.onDoubleTap(mCurrentDownEvent); // Give a callback with down event of the double-tap @@ -613,17 +590,11 @@ public class GestureDetector { mStillDown = true; mInLongPress = false; mDeferConfirmSingleTap = false; - mHasRecordedClassification = false; if (mIsLongpressEnabled) { mHandler.removeMessages(LONG_PRESS); - mHandler.sendMessageAtTime( - mHandler.obtainMessage( - LONG_PRESS, - TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS, - 0 /* arg2 */), - mCurrentDownEvent.getDownTime() - + ViewConfiguration.getLongPressTimeout()); + mHandler.sendEmptyMessageAtTime(LONG_PRESS, mCurrentDownEvent.getDownTime() + + ViewConfiguration.getLongPressTimeout()); } mHandler.sendEmptyMessageAtTime(SHOW_PRESS, mCurrentDownEvent.getDownTime() + TAP_TIMEOUT); @@ -642,8 +613,6 @@ public class GestureDetector { final float scrollY = mLastFocusY - focusY; if (mIsDoubleTapping) { // Give the move events of the double-tap - recordGestureClassification( - TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DOUBLE_TAP); handled |= mDoubleTapListener.onDoubleTapEvent(ev); } else if (mAlwaysInTapRegion) { final int deltaX = (int) (focusX - mDownFocusX); @@ -666,12 +635,8 @@ public class GestureDetector { // reschedule long press with a modified timeout. mHandler.removeMessages(LONG_PRESS); final long longPressTimeout = ViewConfiguration.getLongPressTimeout(); - mHandler.sendMessageAtTime( - mHandler.obtainMessage( - LONG_PRESS, - TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS, - 0 /* arg2 */), - ev.getDownTime() + (long) (longPressTimeout * multiplier)); + mHandler.sendEmptyMessageAtTime(LONG_PRESS, ev.getDownTime() + + (long) (longPressTimeout * multiplier)); } // Inhibit default scroll. If a gesture is ambiguous, we prevent scroll // until the gesture is resolved. @@ -681,8 +646,6 @@ public class GestureDetector { } if (distance > slopSquare) { - recordGestureClassification( - TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SCROLL); handled = mListener.onScroll(mCurrentDownEvent, ev, scrollX, scrollY); mLastFocusX = focusX; mLastFocusY = focusY; @@ -696,7 +659,6 @@ public class GestureDetector { mAlwaysInBiggerTapRegion = false; } } else if ((Math.abs(scrollX) >= 1) || (Math.abs(scrollY) >= 1)) { - recordGestureClassification(TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SCROLL); handled = mListener.onScroll(mCurrentDownEvent, ev, scrollX, scrollY); mLastFocusX = focusX; mLastFocusY = focusY; @@ -705,11 +667,7 @@ public class GestureDetector { motionClassification == MotionEvent.CLASSIFICATION_DEEP_PRESS; if (deepPress && hasPendingLongPress) { mHandler.removeMessages(LONG_PRESS); - mHandler.sendMessage( - mHandler.obtainMessage( - LONG_PRESS, - TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DEEP_PRESS, - 0 /* arg2 */)); + mHandler.sendEmptyMessage(LONG_PRESS); } break; @@ -718,15 +676,11 @@ public class GestureDetector { MotionEvent currentUpEvent = MotionEvent.obtain(ev); if (mIsDoubleTapping) { // Finally, give the up event of the double-tap - recordGestureClassification( - TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DOUBLE_TAP); handled |= mDoubleTapListener.onDoubleTapEvent(ev); } else if (mInLongPress) { mHandler.removeMessages(TAP); mInLongPress = false; } else if (mAlwaysInTapRegion && !mIgnoreNextUpEvent) { - recordGestureClassification( - TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SINGLE_TAP); handled = mListener.onSingleTapUp(ev); if (mDeferConfirmSingleTap && mDoubleTapListener != null) { mDoubleTapListener.onSingleTapConfirmed(ev); @@ -867,21 +821,4 @@ public class GestureDetector { mInLongPress = true; mListener.onLongPress(mCurrentDownEvent); } - - private void recordGestureClassification(int classification) { - if (mHasRecordedClassification - || classification - == TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION) { - // Only record the first classification for an event stream. - return; - } - StatsLog.write( - StatsLog.TOUCH_GESTURE_CLASSIFIED, - getClass().getName(), - classification, - (int) (SystemClock.uptimeMillis() - mCurrentMotionEvent.getDownTime()), - (float) Math.hypot(mCurrentMotionEvent.getRawX() - mCurrentDownEvent.getRawX(), - mCurrentMotionEvent.getRawY() - mCurrentDownEvent.getRawY())); - mHasRecordedClassification = true; - } } 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 bf0f4e29a4f3..2357db46771a 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -17,10 +17,6 @@ package android.view; import static android.content.res.Resources.ID_NULL; -import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DEEP_PRESS; -import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS; -import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SINGLE_TAP; -import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION; import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL; import static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED; @@ -100,7 +96,6 @@ import android.util.Property; import android.util.SparseArray; import android.util.SparseIntArray; import android.util.StateSet; -import android.util.StatsLog; import android.util.SuperNotCalledException; import android.util.TypedValue; import android.view.AccessibilityIterators.CharacterTextSegmentIterator; @@ -14546,12 +14541,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if (clickable) { setPressed(true, x, y); } - checkForLongClick( - ViewConfiguration.getLongPressTimeout(), - x, - y, - // This is not a touch gesture -- do not classify it as one. - TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION); + checkForLongClick(ViewConfiguration.getLongPressTimeout(), x, y); return true; } } @@ -15292,11 +15282,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, mHasPerformedLongPress = false; if (!clickable) { - checkForLongClick( - ViewConfiguration.getLongPressTimeout(), - x, - y, - TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS); + checkForLongClick(ViewConfiguration.getLongPressTimeout(), x, y); break; } @@ -15320,11 +15306,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } else { // Not inside a scrolling container, so show the feedback right away setPressed(true, x, y); - checkForLongClick( - ViewConfiguration.getLongPressTimeout(), - x, - y, - TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS); + checkForLongClick(ViewConfiguration.getLongPressTimeout(), x, y); } break; @@ -15361,11 +15343,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * ambiguousMultiplier); // Subtract the time already spent delay -= event.getEventTime() - event.getDownTime(); - checkForLongClick( - delay, - x, - y, - TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS); + checkForLongClick(delay, x, y); } touchSlop *= ambiguousMultiplier; } @@ -15387,11 +15365,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if (deepPress && hasPendingLongPressCallback()) { // process the long click action immediately removeLongPressCallback(); - checkForLongClick( - 0 /* send immediately */, - x, - y, - TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DEEP_PRESS); + checkForLongClick(0 /* send immediately */, x, y); } break; @@ -26056,7 +26030,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } } - private void checkForLongClick(long delay, float x, float y, int classification) { + private void checkForLongClick(long delay, float x, float y) { if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE || (mViewFlags & TOOLTIP) == TOOLTIP) { mHasPerformedLongPress = false; @@ -26066,7 +26040,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, mPendingCheckForLongPress.setAnchor(x, y); mPendingCheckForLongPress.rememberWindowAttachCount(); mPendingCheckForLongPress.rememberPressedState(); - mPendingCheckForLongPress.setClassification(classification); postDelayed(mPendingCheckForLongPress, delay); } } @@ -27624,17 +27597,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, private float mX; private float mY; private boolean mOriginalPressedState; - /** - * The classification of the long click being checked: one of the - * StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__* constants. - */ - private int mClassification; @Override public void run() { if ((mOriginalPressedState == isPressed()) && (mParent != null) && mOriginalWindowAttachCount == mWindowAttachCount) { - recordGestureClassification(mClassification); if (performLongClick(mX, mY)) { mHasPerformedLongPress = true; } @@ -27653,10 +27620,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, public void rememberPressedState() { mOriginalPressedState = isPressed(); } - - public void setClassification(int classification) { - mClassification = classification; - } } private final class CheckForTap implements Runnable { @@ -27669,28 +27632,17 @@ public class View implements Drawable.Callback, KeyEvent.Callback, setPressed(true, x, y); final long delay = ViewConfiguration.getLongPressTimeout() - ViewConfiguration.getTapTimeout(); - checkForLongClick(delay, x, y, TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS); + checkForLongClick(delay, x, y); } } private final class PerformClick implements Runnable { @Override public void run() { - recordGestureClassification(TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SINGLE_TAP); performClickInternal(); } } - /** Records a classification for the current event stream. */ - private void recordGestureClassification(int classification) { - if (classification == TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION) { - return; - } - // To avoid negatively impacting View performance, the latency and displacement metrics - // are omitted. - StatsLog.write(StatsLog.TOUCH_GESTURE_CLASSIFIED, getClass().getName(), classification); - } - /** * This method returns a ViewPropertyAnimator object, which can be used to animate * specific properties on this View. @@ -28248,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/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 8f1896d76b9c..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,10 @@ 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; + /** @hide */ public static final int DEFAULT_LOGGING_LEVEL = Build.IS_DEBUGGABLE ? AutofillManager.FLAG_ADD_CLIENT_DEBUG @@ -307,8 +310,8 @@ public final class AutofillManager { /** * Same as {@link #STATE_UNKNOWN}, but used on - * {@link AutofillManagerClient#setSessionFinished(int)} when the session was finished because - * the URL bar changed on client mode + * {@link AutofillManagerClient#setSessionFinished(int, List)} when the session was finished + * because the URL bar changed on client mode * * @hide */ @@ -316,8 +319,8 @@ public final class AutofillManager { /** * Same as {@link #STATE_UNKNOWN}, but used on - * {@link AutofillManagerClient#setSessionFinished(int)} when the session was finished because - * the service failed to fullfil a request. + * {@link AutofillManagerClient#setSessionFinished(int, List)} when the session was finished + * because the service failed to fullfil a request. * * @hide */ @@ -436,7 +439,7 @@ public final class AutofillManager { * There is currently no session running. * {@hide} */ - public static final int NO_SESSION = Integer.MIN_VALUE; + public static final int NO_SESSION = Integer.MAX_VALUE; private final IAutoFillManager mService; @@ -513,6 +516,17 @@ public final class AutofillManager { @Nullable private final AutofillOptions mOptions; + /** When set, session is only used for augmented autofill requests. */ + @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 { /** @@ -939,10 +953,9 @@ public final class AutofillManager { ensureServiceClientAddedIfNeededLocked(); - if (!mEnabled) { - if (sVerbose) { - Log.v(TAG, "ignoring notifyViewEntered(" + id + "): disabled"); - } + if (!mEnabled && !mEnabledForAugmentedAutofillOnly) { + if (sVerbose) Log.v(TAG, "ignoring notifyViewEntered(" + id + "): disabled"); + if (mCallback != null) { callback = mCallback; } @@ -982,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(); @@ -1025,6 +1038,12 @@ public final class AutofillManager { private void notifyViewVisibilityChangedInternal(@NonNull View view, int virtualId, boolean isVisible, boolean virtual) { synchronized (mLock) { + if (mForAugmentedAutofillOnly) { + if (sVerbose) { + Log.v(TAG, "notifyViewVisibilityChanged(): ignoring on augmented only mode"); + } + return; + } if (mEnabled && isActiveLocked()) { final AutofillId id = virtual ? getAutofillId(view, virtualId) : view.getAutofillId(); @@ -1092,7 +1111,7 @@ public final class AutofillManager { ensureServiceClientAddedIfNeededLocked(); - if (!mEnabled) { + if (!mEnabled && !mEnabledForAugmentedAutofillOnly) { if (sVerbose) { Log.v(TAG, "ignoring notifyViewEntered(" + id + "): disabled"); } @@ -1143,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); @@ -1168,6 +1187,10 @@ public final class AutofillManager { AutofillValue value = null; synchronized (mLock) { + if (mForAugmentedAutofillOnly) { + if (sVerbose) Log.v(TAG, "notifyValueChanged(): ignoring on augmented only mode"); + return; + } // If the session is gone some fields might still be highlighted, hence we have to // remove the isAutofilled property even if no sessions are active. if (mLastAutofilledData == null) { @@ -1221,6 +1244,10 @@ public final class AutofillManager { return; } synchronized (mLock) { + if (mForAugmentedAutofillOnly) { + if (sVerbose) Log.v(TAG, "notifyValueChanged(): ignoring on augmented only mode"); + return; + } if (!mEnabled || !isActiveLocked()) { if (sVerbose) { Log.v(TAG, "notifyValueChanged(" + view.getAutofillId() + ":" + virtualId @@ -1654,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) { @@ -1676,14 +1706,20 @@ public final class AutofillManager { if (client == null) return; // NOTE: getClient() already logged it.. final SyncResultReceiver receiver = new SyncResultReceiver(SYNC_CALLS_TIMEOUT_MS); + final ComponentName componentName = client.autofillClientGetComponentName(); mService.startSession(client.autofillClientGetActivityToken(), mServiceClient.asBinder(), id, bounds, value, mContext.getUserId(), - mCallback != null, flags, client.autofillClientGetComponentName(), + mCallback != null, flags, componentName, isCompatibilityModeEnabledLocked(), receiver); mSessionId = receiver.getIntResult(); if (mSessionId != NO_SESSION) { mState = STATE_ACTIVE; } + final int extraFlags = receiver.getOptionalExtraIntResult(0); + if ((extraFlags & FLAG_SESSION_FOR_AUGMENTED_AUTOFILL_ONLY) != 0) { + if (sDebug) Log.d(TAG, "startSession(" + componentName + "): for augmented only"); + mForAugmentedAutofillOnly = true; + } client.autofillClientResetableStateAvailable(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -1750,7 +1786,8 @@ public final class AutofillManager { @GuardedBy("mLock") private void ensureServiceClientAddedIfNeededLocked() { - if (getClient() == null) { + final AutofillClient client = getClient(); + if (client == null) { return; } @@ -1759,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, () -> { @@ -2380,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); @@ -2400,6 +2445,9 @@ public final class AutofillManager { pw.print(pfx); pw.print("entered ids for augmented autofill: "); pw.println(mEnteredForAugmentedAutofillIds); } + if (mForAugmentedAutofillOnly) { + pw.print(pfx); pw.println("For Augmented Autofill Only"); + } pw.print(pfx); pw.print("save trigger id: "); pw.println(mSaveTriggerId); pw.print(pfx); pw.print("save on finish(): "); pw.println(mSaveOnFinish); if (mOptions != null) { 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..f3aac1584725 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; @@ -1465,14 +1466,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 +1554,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 +1694,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; } diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl index c4af4c797d37..1c901823566a 100644 --- a/core/java/com/android/internal/app/IAppOpsService.aidl +++ b/core/java/com/android/internal/app/IAppOpsService.aidl @@ -79,4 +79,6 @@ interface IAppOpsService { void stopWatchingNoted(IAppOpsNotedCallback callback); int checkOperationRaw(int code, int uid, String packageName); + + void reloadNonHistoricalState(); } 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/util/SyncResultReceiver.java b/core/java/com/android/internal/util/SyncResultReceiver.java index 9a346ac93a8d..60af5117489b 100644 --- a/core/java/com/android/internal/util/SyncResultReceiver.java +++ b/core/java/com/android/internal/util/SyncResultReceiver.java @@ -96,6 +96,19 @@ public final class SyncResultReceiver extends IResultReceiver.Stub { return mBundle == null ? null : mBundle.getParcelable(EXTRA); } + /** + * Gets the optional result from an operation that returns an extra {@code int} (besides the + * result code). + * + * @return value set in the bundle, or {@code defaultValue} when not set. + */ + public int getOptionalExtraIntResult(int defaultValue) throws TimeoutException { + waitResult(); + if (mBundle == null || !mBundle.containsKey(EXTRA)) return defaultValue; + + return mBundle.getInt(EXTRA); + } + @Override public void send(int resultCode, Bundle resultData) { mResult = resultCode; @@ -136,6 +149,18 @@ public final class SyncResultReceiver extends IResultReceiver.Stub { return bundle; } + /** + * Creates a bundle for an {@code int} value so it can be retrieved by + * {@link #getParcelableResult()} - typically used to return an extra {@code int} (as the 1st + * is returned as the result code). + */ + @NonNull + public static Bundle bundleFor(int value) { + final Bundle bundle = new Bundle(); + bundle.putInt(EXTRA, value); + return bundle; + } + /** @hide */ public static final class TimeoutException extends RemoteException { private TimeoutException(String msg) { 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/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index 1965609ff959..30f4d6fe417a 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. */ @@ -915,9 +913,10 @@ 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); @@ -927,13 +926,25 @@ public class LockPatternUtils { return; } - updateEncryptionPasswordIfNeeded(password, - PasswordMetrics.computeForPassword(password).quality, userHandle); + updateEncryptionPasswordIfNeeded(password, passwordQuality, userHandle); updatePasswordHistory(password, userHandle); onAfterChangingPassword(userHandle); } /** + * 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; + } + + /** * Update device encryption password if calling user is USER_SYSTEM and device supports * encryption. */ @@ -1033,24 +1044,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 +1745,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_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/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index efc6ad017bb1..5427147aa32a 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -819,8 +819,7 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_sdcardRead" android:description="@string/permdesc_sdcardRead" - android:protectionLevel="dangerous" - android:permissionFlags="removed" /> + android:protectionLevel="dangerous" /> <!-- Allows an application to write to external storage. <p class="note"><strong>Note:</strong> If <em>both</em> your <a @@ -841,8 +840,7 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_sdcardWrite" android:description="@string/permdesc_sdcardWrite" - android:protectionLevel="dangerous" - android:permissionFlags="removed" /> + android:protectionLevel="dangerous" /> <!-- Runtime permission controlling access to the user's shared aural media collection. --> diff --git a/core/res/res/layout/resolve_grid_item.xml b/core/res/res/layout/resolve_grid_item.xml index 71c153fa6021..a24f8928d04a 100644 --- a/core/res/res/layout/resolve_grid_item.xml +++ b/core/res/res/layout/resolve_grid_item.xml @@ -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_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..4ab9edb8bbaa 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" /> @@ -2778,7 +2779,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 +2924,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 +3589,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 +3645,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/core/tests/overlaytests/device/test-apps/AppOverlayOne/AndroidManifest.xml b/core/tests/overlaytests/device/test-apps/AppOverlayOne/AndroidManifest.xml index 17191589e3f2..8ac6953b44e5 100644 --- a/core/tests/overlaytests/device/test-apps/AppOverlayOne/AndroidManifest.xml +++ b/core/tests/overlaytests/device/test-apps/AppOverlayOne/AndroidManifest.xml @@ -18,5 +18,6 @@ package="com.android.overlaytest.app_overlay_one" android:versionCode="1" android:versionName="1.0"> + <application android:hasCode="false" /> <overlay android:targetPackage="com.android.overlaytest" android:priority="1" /> </manifest> diff --git a/core/tests/overlaytests/device/test-apps/AppOverlayTwo/AndroidManifest.xml b/core/tests/overlaytests/device/test-apps/AppOverlayTwo/AndroidManifest.xml index ae8307c446c1..f3c39ccbb301 100644 --- a/core/tests/overlaytests/device/test-apps/AppOverlayTwo/AndroidManifest.xml +++ b/core/tests/overlaytests/device/test-apps/AppOverlayTwo/AndroidManifest.xml @@ -18,5 +18,6 @@ package="com.android.overlaytest.app_overlay_two" android:versionCode="1" android:versionName="1.0"> + <application android:hasCode="false" /> <overlay android:targetPackage="com.android.overlaytest" android:priority="2" /> </manifest> diff --git a/core/tests/overlaytests/device/test-apps/FrameworkOverlay/AndroidManifest.xml b/core/tests/overlaytests/device/test-apps/FrameworkOverlay/AndroidManifest.xml index 77ea16afff83..73a83e09d50d 100644 --- a/core/tests/overlaytests/device/test-apps/FrameworkOverlay/AndroidManifest.xml +++ b/core/tests/overlaytests/device/test-apps/FrameworkOverlay/AndroidManifest.xml @@ -18,5 +18,6 @@ package="com.android.overlaytest.framework" android:versionCode="1" android:versionName="1.0"> + <application android:hasCode="false" /> <overlay android:targetPackage="android" android:priority="1" /> </manifest> diff --git a/core/tests/overlaytests/host/src/com/android/server/om/hosttest/InstallOverlayTests.java b/core/tests/overlaytests/host/src/com/android/server/om/hosttest/InstallOverlayTests.java index 27986cce0835..f9672d27e129 100644 --- a/core/tests/overlaytests/host/src/com/android/server/om/hosttest/InstallOverlayTests.java +++ b/core/tests/overlaytests/host/src/com/android/server/om/hosttest/InstallOverlayTests.java @@ -155,12 +155,26 @@ public class InstallOverlayTests extends BaseHostJUnit4Test { } } + private void delay() { + try { + Thread.sleep(100); + } catch (InterruptedException e) { + } + } + + private void installPackage(String pkg) throws Exception { + super.installPackage(pkg); + delay(); + } + private void setPackageEnabled(String pkg, boolean enabled) throws Exception { getDevice().executeShellCommand("cmd package " + (enabled ? "enable " : "disable ") + pkg); + delay(); } private void setOverlayEnabled(String pkg, boolean enabled) throws Exception { getDevice().executeShellCommand("cmd overlay " + (enabled ? "enable " : "disable ") + pkg); + delay(); } private boolean overlayManagerContainsPackage(String pkg) throws Exception { diff --git a/core/tests/overlaytests/host/test-apps/SignatureOverlay/AndroidManifest.xml b/core/tests/overlaytests/host/test-apps/SignatureOverlay/AndroidManifest.xml index b08ac96aca68..26b3875caab6 100644 --- a/core/tests/overlaytests/host/test-apps/SignatureOverlay/AndroidManifest.xml +++ b/core/tests/overlaytests/host/test-apps/SignatureOverlay/AndroidManifest.xml @@ -16,5 +16,6 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.server.om.hosttest.signature_overlay"> + <application android:hasCode="false" /> <overlay android:targetPackage="android" /> </manifest> diff --git a/core/tests/overlaytests/host/test-apps/SignatureOverlay/static/AndroidManifest.xml b/core/tests/overlaytests/host/test-apps/SignatureOverlay/static/AndroidManifest.xml index 139dd9653b4a..8a664235ac3d 100644 --- a/core/tests/overlaytests/host/test-apps/SignatureOverlay/static/AndroidManifest.xml +++ b/core/tests/overlaytests/host/test-apps/SignatureOverlay/static/AndroidManifest.xml @@ -16,5 +16,6 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.server.om.hosttest.signature_overlay"> + <application android:hasCode="false" /> <overlay android:targetPackage="android" android:isStatic="true" /> </manifest> diff --git a/core/tests/overlaytests/host/test-apps/UpdateOverlay/app/v1/AndroidManifest.xml b/core/tests/overlaytests/host/test-apps/UpdateOverlay/app/v1/AndroidManifest.xml index 73804ebd211f..b6ff0c3c6725 100644 --- a/core/tests/overlaytests/host/test-apps/UpdateOverlay/app/v1/AndroidManifest.xml +++ b/core/tests/overlaytests/host/test-apps/UpdateOverlay/app/v1/AndroidManifest.xml @@ -16,5 +16,6 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.server.om.hosttest.app_overlay"> + <application android:hasCode="false" /> <overlay android:targetPackage="com.android.server.om.hosttest.update_overlay_test" /> </manifest> diff --git a/core/tests/overlaytests/host/test-apps/UpdateOverlay/app/v2/AndroidManifest.xml b/core/tests/overlaytests/host/test-apps/UpdateOverlay/app/v2/AndroidManifest.xml index 9ec7d06ce5d7..f1a39817af86 100644 --- a/core/tests/overlaytests/host/test-apps/UpdateOverlay/app/v2/AndroidManifest.xml +++ b/core/tests/overlaytests/host/test-apps/UpdateOverlay/app/v2/AndroidManifest.xml @@ -16,6 +16,7 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.server.om.hosttest.app_overlay"> + <application android:hasCode="false" /> <overlay android:targetPackage="com.android.server.om.hosttest.update_overlay_test" android:category="android.theme" /> </manifest> diff --git a/core/tests/overlaytests/host/test-apps/UpdateOverlay/framework/AndroidManifest.xml b/core/tests/overlaytests/host/test-apps/UpdateOverlay/framework/AndroidManifest.xml index 8c8fe9480961..025d1a26d4ce 100644 --- a/core/tests/overlaytests/host/test-apps/UpdateOverlay/framework/AndroidManifest.xml +++ b/core/tests/overlaytests/host/test-apps/UpdateOverlay/framework/AndroidManifest.xml @@ -16,5 +16,6 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.server.om.hosttest.framework_overlay"> + <application android:hasCode="false" /> <overlay android:targetPackage="android" /> </manifest> diff --git a/data/etc/platform.xml b/data/etc/platform.xml index 44d71e269a95..28d311ec065d 100644 --- a/data/etc/platform.xml +++ b/data/etc/platform.xml @@ -202,17 +202,15 @@ <new-permission name="android.permission.ACCESS_BACKGROUND_LOCATION" /> </split-permission> - <!-- Apps holding either the legacy READ or WRITE permissions will inherit - the ability to <em>read</em> new typed permissions in the Q release; they - won't gain the ability to <em>write</em> that content. --> - <!-- STOPSHIP(b/112545973): change targetSdk to Q when SDK version finalised --> + <!-- STOPSHIP: change targetSdk to Q when SDK version finalised --> + <!-- Old apps might not understand the modern permission model, hence their view needs to be expanded --> <split-permission name="android.permission.READ_EXTERNAL_STORAGE" targetSdk="10000"> <new-permission name="android.permission.READ_MEDIA_AUDIO" /> <new-permission name="android.permission.READ_MEDIA_VIDEO" /> <new-permission name="android.permission.READ_MEDIA_IMAGES" /> </split-permission> - <!-- STOPSHIP(b/112545973): change targetSdk to Q when SDK version finalised --> + <!-- STOPSHIP: change targetSdk to Q when SDK version finalised --> <split-permission name="android.permission.WRITE_EXTERNAL_STORAGE" targetSdk="10000"> <new-permission name="android.permission.READ_MEDIA_AUDIO" /> @@ -220,6 +218,20 @@ <new-permission name="android.permission.READ_MEDIA_IMAGES" /> </split-permission> + <!-- An app using the typed media permissions might be grandfathered and then uses the old storage model --> + <split-permission name="android.permission.READ_MEDIA_AUDIO"> + <new-permission name="android.permission.READ_EXTERNAL_STORAGE" /> + <new-permission name="android.permission.WRITE_EXTERNAL_STORAGE" /> + </split-permission> + <split-permission name="android.permission.READ_MEDIA_VIDEO"> + <new-permission name="android.permission.READ_EXTERNAL_STORAGE" /> + <new-permission name="android.permission.WRITE_EXTERNAL_STORAGE" /> + </split-permission> + <split-permission name="android.permission.READ_MEDIA_IMAGES"> + <new-permission name="android.permission.READ_EXTERNAL_STORAGE" /> + <new-permission name="android.permission.WRITE_EXTERNAL_STORAGE" /> + </split-permission> + <!-- This is a list of all the libraries available for application code to link against. --> diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml index fcd5d566f250..a0d14f94bdbe 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"> diff --git a/location/java/android/location/GnssCapabilities.java b/location/java/android/location/GnssCapabilities.java new file mode 100644 index 000000000000..6a35920e7fa2 --- /dev/null +++ b/location/java/android/location/GnssCapabilities.java @@ -0,0 +1,153 @@ +/* + * 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.IntDef; +import android.annotation.SystemApi; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * A container of supported GNSS chipset capabilities. + * + * @hide + */ +@SystemApi +public final class GnssCapabilities { + /** The GNSS chipset supports low power mode. */ + public static final int LOW_POWER_MODE = 0; + + /** The GNSS chipset supports blacklisting satellites. */ + public static final int SATELLITE_BLACKLIST = 1; + + /** The GNSS chipset supports geofencing. */ + public static final int GEOFENCING = 2; + + /** The GNSS chipset supports measurements.*/ + public static final int MEASUREMENTS = 3; + + /** The GNSS chipset supports navigation messages. */ + public static final int NAV_MESSAGES = 4; + + /** The GNSS chipset supports measurement corrections. */ + public static final int MEASUREMENT_CORRECTIONS = 5; + + /** The GNSS chipset supports line-of-sight satellite identification measurement corrections. */ + public static final int MEASUREMENT_CORRECTIONS_LOS_SATS = 6; + + /** The GNSS chipset supports per satellite excess-path-length measurement corrections. */ + public static final int MEASUREMENT_CORRECTIONS_EXCESS_PATH_LENGTH = 7; + + /** The GNSS chipset supports reflecting planes measurement corrections. */ + public static final int MEASUREMENT_CORRECTIONS_REFLECTING_PLANE = 8; + + private static final int MIN_CAPABILITY = 0; + private static final int MAX_CAPABILITY = MEASUREMENT_CORRECTIONS_REFLECTING_PLANE; + + /** + * GNSS capability. + * @hide + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({ + LOW_POWER_MODE, + SATELLITE_BLACKLIST, + GEOFENCING, + MEASUREMENTS, + NAV_MESSAGES, + MEASUREMENT_CORRECTIONS, + MEASUREMENT_CORRECTIONS_LOS_SATS, + MEASUREMENT_CORRECTIONS_EXCESS_PATH_LENGTH, + MEASUREMENT_CORRECTIONS_REFLECTING_PLANE + }) + public @interface Capability {} + + /** + * @hide + */ + public static final long INVALID_CAPABILITIES = -1; + + /** A bitmask of supported GNSS capabilities. */ + private final long mGnssCapabilities; + + static GnssCapabilities of(long gnssCapabilities) { + return new GnssCapabilities(gnssCapabilities); + } + + private GnssCapabilities(long gnssCapabilities) { + mGnssCapabilities = gnssCapabilities; + } + + /** + * Returns {@code true} if the {@code capability} is supported by the GNSS implementation. + */ + public boolean hasCapability(@Capability int capability) { + return isValidCapability(capability) && (mGnssCapabilities & (1 << capability)) != 0; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("GnssCapabilities: ("); + int capability = 0; + boolean addSeparator = false; + long gnssCapabilities = mGnssCapabilities; + while (gnssCapabilities != 0) { + if ((gnssCapabilities & 1) != 0) { + if (addSeparator) { + sb.append(' '); + } else { + addSeparator = true; + } + sb.append(toStringCapability(capability)); + } + gnssCapabilities >>= 1; + ++capability; + } + sb.append(")"); + return sb.toString(); + } + + private boolean isValidCapability(@Capability int capability) { + return capability >= MIN_CAPABILITY && capability <= MAX_CAPABILITY; + } + + private static String toStringCapability(@Capability int capability) { + switch (capability) { + case LOW_POWER_MODE: + return "LOW_POWER_MODE"; + case SATELLITE_BLACKLIST: + return "SATELLITE_BLACKLIST"; + case GEOFENCING: + return "GEOFENCING"; + case MEASUREMENTS: + return "MEASUREMENTS"; + case NAV_MESSAGES: + return "NAV_MESSAGES"; + case MEASUREMENT_CORRECTIONS: + return "MEASUREMENT_CORRECTIONS"; + case MEASUREMENT_CORRECTIONS_LOS_SATS: + return "MEASUREMENT_CORRECTIONS_LOS_SATS"; + case MEASUREMENT_CORRECTIONS_EXCESS_PATH_LENGTH: + return "MEASUREMENT_CORRECTIONS_EXCESS_PATH_LENGTH"; + case MEASUREMENT_CORRECTIONS_REFLECTING_PLANE: + return "MEASUREMENT_CORRECTIONS_REFLECTING_PLANE"; + default: + return "Unknown(" + capability + ")"; + } + } +} diff --git a/location/java/android/location/GnssMeasurementCallbackTransport.java b/location/java/android/location/GnssMeasurementCallbackTransport.java index 1188b13b7841..8cb8c0b78da1 100644 --- a/location/java/android/location/GnssMeasurementCallbackTransport.java +++ b/location/java/android/location/GnssMeasurementCallbackTransport.java @@ -63,7 +63,7 @@ class GnssMeasurementCallbackTransport measurementCorrections, getContext().getPackageName()); } - protected int getGnssCapabilities() throws RemoteException { + protected long getGnssCapabilities() throws RemoteException { return mLocationManager.getGnssCapabilities(getContext().getPackageName()); } diff --git a/location/java/android/location/GnssStatus.java b/location/java/android/location/GnssStatus.java index 60c7748a8dbf..ce464b7bda37 100644 --- a/location/java/android/location/GnssStatus.java +++ b/location/java/android/location/GnssStatus.java @@ -42,6 +42,8 @@ public final class GnssStatus { public static final int CONSTELLATION_BEIDOU = 5; /** Constellation type constant for Galileo. */ public static final int CONSTELLATION_GALILEO = 6; + /** Constellation type constant for IRNSS. */ + public static final int CONSTELLATION_IRNSS = 7; /** @hide */ public static final int GNSS_SV_FLAGS_NONE = 0; @@ -94,7 +96,7 @@ public final class GnssStatus { */ @Retention(RetentionPolicy.SOURCE) @IntDef({CONSTELLATION_UNKNOWN, CONSTELLATION_GPS, CONSTELLATION_SBAS, CONSTELLATION_GLONASS, - CONSTELLATION_QZSS, CONSTELLATION_BEIDOU, CONSTELLATION_GALILEO}) + CONSTELLATION_QZSS, CONSTELLATION_BEIDOU, CONSTELLATION_GALILEO, CONSTELLATION_IRNSS}) public @interface ConstellationType {} final int[] mSvidWithFlags; diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl index c371c5fa0448..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; @@ -66,7 +67,7 @@ interface ILocationManager boolean addGnssMeasurementsListener(in IGnssMeasurementsListener listener, in String packageName); void injectGnssMeasurementCorrections(in GnssMeasurementCorrections corrections, in String packageName); - int getGnssCapabilities(in String packageName); + long getGnssCapabilities(in String packageName); void removeGnssMeasurementsListener(in IGnssMeasurementsListener listener); boolean addGnssNavigationMessageListener( @@ -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/LocationManager.java b/location/java/android/location/LocationManager.java index 01f17986d88c..edf304ca69cd 100644 --- a/location/java/android/location/LocationManager.java +++ b/location/java/android/location/LocationManager.java @@ -1986,15 +1986,19 @@ public class LocationManager { } /** - * Returns the integer capability flags of the GNSS chipset as defined in {@code - * IGnssCallback.hal} + * Returns the supported capabilities of the GNSS chipset or {@code null} if there is an error + * in obtaining the capabilities. * * @hide */ @SystemApi - public int getGnssCapabilities() { + public @Nullable GnssCapabilities getGnssCapabilities() { try { - return mGnssMeasurementCallbackTransport.getGnssCapabilities(); + long gnssCapabilities = mGnssMeasurementCallbackTransport.getGnssCapabilities(); + if (gnssCapabilities == GnssCapabilities.INVALID_CAPABILITIES) { + return null; + } + return GnssCapabilities.of(gnssCapabilities); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } 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/apex/java/android/media/CallbackDataSourceDesc.java b/media/apex/java/android/media/CallbackDataSourceDesc.java index 9209ca94897f..d9db62e99126 100644 --- a/media/apex/java/android/media/CallbackDataSourceDesc.java +++ b/media/apex/java/android/media/CallbackDataSourceDesc.java @@ -17,7 +17,7 @@ package android.media; import android.annotation.NonNull; -import android.annotation.Nullable; +import android.annotation.TestApi; /** * Structure of data source descriptor for sources using callback. @@ -26,12 +26,16 @@ import android.annotation.Nullable; * {@link MediaPlayer2#setNextDataSources} to set data source for playback. * * <p>Users should use {@link Builder} to create {@link CallbackDataSourceDesc}. - * + * @hide */ +@TestApi public class CallbackDataSourceDesc extends DataSourceDesc { private DataSourceCallback mDataSourceCallback; - private CallbackDataSourceDesc() { + CallbackDataSourceDesc(String mediaId, long startPositionMs, long endPositionMs, + DataSourceCallback dataSourceCallback) { + super(mediaId, startPositionMs, endPositionMs); + mDataSourceCallback = dataSourceCallback; } /** @@ -41,75 +45,4 @@ public class CallbackDataSourceDesc extends DataSourceDesc { 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/DataSourceDesc.java b/media/apex/java/android/media/DataSourceDesc.java index e6fd120b6d5b..be80c2255844 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,48 @@ 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 static final int SOURCE_TYPE_CALLBACK = 3; + + 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; + + // For CallbackDataSourceDesc + private DataSourceCallback mDataSourceCallback; + /** * Constructs a new BuilderBase with the defaults. */ - BuilderBase() { + public Builder() { } /** @@ -115,33 +156,61 @@ 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 if (dsd instanceof CallbackDataSourceDesc) { + mSourceType = SOURCE_TYPE_CALLBACK; + mDataSourceCallback = ((CallbackDataSourceDesc) dsd).getDataSourceCallback(); + } 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 if (mSourceType == SOURCE_TYPE_CALLBACK) { + desc = new CallbackDataSourceDesc( + mMediaId, mStartPositionMs, mEndPositionMs, mDataSourceCallback); + } else { + throw new IllegalStateException("Unknown source type:" + mSourceType); + } + return desc; } /** @@ -150,9 +219,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 +233,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 +250,155 @@ 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 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. + */ + @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 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. + */ + @NonNull + public Builder setDataSource( + @NonNull ParcelFileDescriptor pfd, long offset, long length) { + setSourceType(SOURCE_TYPE_FILE); + Media2Utils.checkArgument(pfd != null, "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; + } + + /** + * 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) { + setSourceType(SOURCE_TYPE_CALLBACK); + Media2Utils.checkArgument(dscb != null, "data source cannot be null."); + mDataSourceCallback = dscb; + 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..68a46ed5b8b8 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(); @@ -899,7 +898,7 @@ public class MediaPlayer2 implements AutoCloseable UriDataSourceDesc uriDSD = (UriDataSourceDesc) dsd; handleDataSource(isCurrent, srcId, - uriDSD.getContext(), + mContext, uriDSD.getUri(), uriDSD.getHeaders(), uriDSD.getCookies(), @@ -1810,12 +1809,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; } @@ -2643,13 +2640,11 @@ 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(); + SubtitleData data = new SubtitleData( + in.next().getInt32Value(), // trackIndex + in.next().getInt64Value(), // startTimeUs + in.next().getInt64Value(), // durationUs + in.next().getBytesValue().toByteArray()); // data sendEvent(new EventNotifier() { @Override public void notify(EventCallback callback) { @@ -2673,11 +2668,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; } 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..802cca9a61a8 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; @@ -3307,7 +3308,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 +5443,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/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/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java index 2ec935598c1b..a687c141960f 100644 --- a/media/java/android/media/MediaCodecInfo.java +++ b/media/java/android/media/MediaCodecInfo.java @@ -21,6 +21,7 @@ import static android.media.Utils.sortDistinctRanges; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.TestApi; import android.annotation.UnsupportedAppUsage; import android.os.Build; import android.util.Log; @@ -31,6 +32,7 @@ import android.util.Size; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -1332,7 +1334,7 @@ public final class MediaCodecInfo { private Range<Rational> mBlockAspectRatioRange; private Range<Long> mBlocksPerSecondRange; private Map<Size, Range<Long>> mMeasuredFrameRates; - private Vector<PerformancePoint> mPerformancePoints; + private List<PerformancePoint> mPerformancePoints; private Range<Integer> mFrameRateRange; private int mBlockWidth; @@ -1620,45 +1622,136 @@ public final class MediaCodecInfo { * rate. */ public static final class PerformancePoint { + private Size mBlockSize; // codec block size in macroblocks + private int mWidth; // width in macroblocks + private int mHeight; // height in macroblocks + private int mMaxFrameRate; // max frames per second + private long mMaxMacroBlockRate; // max macro block rate + /** - * (Maximum) number of macroblocks in the frame. + * Maximum number of macroblocks in the frame. * * Video frames are conceptually divided into 16-by-16 pixel blocks called macroblocks. * Most coding standards operate on these 16-by-16 pixel blocks; thus, codec performance * is characterized using such blocks. + * + * @hide */ - public final int macroBlocks; + @TestApi + public int getMaxMacroBlocks() { + return saturateLongToInt(mWidth * (long)mHeight); + } /** - * (Maximum) frame rate in frames per second. + * Maximum frame rate in frames per second. + * + * @hide */ - public final int frameRate; + @TestApi + public int getMaxFrameRate() { + return mMaxFrameRate; + } + + /** + * Maximum number of macroblocks processed per second. + * + * @hide + */ + @TestApi + public long getMaxMacroBlockRate() { + return mMaxMacroBlockRate; + } + + /** Convert to a debug string */ + public String toString() { + int blockWidth = 16 * mBlockSize.getWidth(); + int blockHeight = 16 * mBlockSize.getHeight(); + int origRate = (int)Utils.divUp(mMaxMacroBlockRate, getMaxMacroBlocks()); + String info = (mWidth * 16) + "x" + (mHeight * 16) + "@" + origRate; + if (origRate < mMaxFrameRate) { + info += ", max " + mMaxFrameRate + "fps"; + } + if (blockWidth > 16 || blockHeight > 16) { + info += ", " + blockWidth + "x" + blockHeight + " blocks"; + } + return "PerformancePoint(" + info + ")"; + } /** - * (Maximum) number of macroblocks processed per second. + * Create a detailed performance point with custom max frame rate and macroblock size. + * + * @param width frame width in pixels + * @param height frame height in pixels + * @param frameRate frames per second for frame width and height + * @param maxFrameRate maximum frames per second for any frame size + * @param blockSize block size for codec implementation. Must be powers of two in both + * width and height. + * + * @throws IllegalArgumentException if the blockSize dimensions are not powers of two. + * + * @hide */ - public final long macroBlockRate; + @TestApi + public PerformancePoint( + int width, int height, int frameRate, int maxFrameRate, + @NonNull Size blockSize) { + checkPowerOfTwo(blockSize.getWidth(), "block width"); + checkPowerOfTwo(blockSize.getHeight(), "block height"); + + mBlockSize = new Size(Utils.divUp(blockSize.getWidth(), 16), + Utils.divUp(blockSize.getHeight(), 16)); + // these are guaranteed not to overflow as we decimate by 16 + mWidth = (int)(Utils.divUp(Math.max(1L, width), + Math.max(blockSize.getWidth(), 16)) + * mBlockSize.getWidth()); + mHeight = (int)(Utils.divUp(Math.max(1L, height), + Math.max(blockSize.getHeight(), 16)) + * mBlockSize.getHeight()); + mMaxFrameRate = Math.max(1, Math.max(frameRate, maxFrameRate)); + mMaxMacroBlockRate = Math.max(1, frameRate) * getMaxMacroBlocks(); + Log.i("PP", "Created " + this); + } - /* package private */ - PerformancePoint(int width_, int height_, int frameRate_, int maxFrameRate_) { - macroBlocks = saturateLongToInt( - ((Math.max(1, (long)width_) + 15) / 16) - * ((Math.max(1, (long)height_) + 15) / 16)); - frameRate = Math.max(1, frameRate_); - macroBlockRate = Math.max(maxFrameRate_, frameRate) * macroBlocks; + /** + * Convert a performance point to a larger blocksize. + * + * @param pp performance point + * @param blockSize block size for codec implementation + * + * @hide + */ + @TestApi + public PerformancePoint(@NonNull PerformancePoint pp, @NonNull Size newBlockSize) { + this( + pp.mWidth * 16, pp.mHeight * 16, + // guaranteed not to overflow as these were multiplied at construction + (int)Utils.divUp(pp.mMaxMacroBlockRate, pp.getMaxMacroBlocks()), + pp.mMaxFrameRate, + new Size(Math.max(newBlockSize.getWidth(), pp.mBlockSize.getWidth() * 16), + Math.max(newBlockSize.getHeight(), pp.mBlockSize.getHeight() * 16)) + ); + /* + // these are guaranteed not to overflow as size * blockSize is decimated by 16 + width = align(pp.width * pp.blockSize.getWidth(), blockSize.getWidth()); + height = align(pp.height * pp.blockSize.getHeight(), blockSize.getHeight()); + frameRate = pp.frameRate; + macroBlockRate = align(pp.macroBlockRate, blockSize.getWidth * blockSize.getHeight()); + */ + Log.i("PP", " from " + pp + " and " + newBlockSize); } /** * Create a performance point for a given frame size and frame rate. * - * @param width_ width of the frame in pixels - * @param height_ height of the frame in pixels - * @param frameRate_ frame rate in frames per second + * @param width width of the frame in pixels + * @param height height of the frame in pixels + * @param frameRate frame rate in frames per second */ - public PerformancePoint(int width_, int height_, int frameRate_) { - this(width_, height_, frameRate_, frameRate_ /* maxFrameRate */); + public PerformancePoint(int width, int height, int frameRate) { + this(width, height, frameRate, frameRate /* maxFrameRate */, new Size(16, 16)); } + /** Saturates a long value to int */ private int saturateLongToInt(long value) { if (value < Integer.MIN_VALUE) { return Integer.MIN_VALUE; @@ -1669,6 +1762,19 @@ public final class MediaCodecInfo { } } + /* This method may overflow */ + private int align(int value, int alignment) { + return Utils.divUp(value, alignment) * alignment; + } + + /** Checks that value is a power of two. */ + private void checkPowerOfTwo2(int value, @NonNull String description) { + if (value == 0 || (value & (value - 1)) != 0) { + throw new IllegalArgumentException( + description + " (" + value + ") must be a power of 2"); + } + } + /** * Checks whether the performance point covers a media format. * @@ -1680,7 +1786,7 @@ public final class MediaCodecInfo { PerformancePoint other = new PerformancePoint( format.getInteger(MediaFormat.KEY_WIDTH, 0), format.getInteger(MediaFormat.KEY_HEIGHT, 0), - // safely convert ceil(double) to int through float case and Math.round + // safely convert ceil(double) to int through float cast and Math.round Math.round((float)( Math.ceil(format.getNumber(MediaFormat.KEY_FRAME_RATE, 0) .doubleValue())))); @@ -1690,7 +1796,7 @@ public final class MediaCodecInfo { /** * Checks whether the performance point covers another performance point. Use this * method to determine if a performance point advertised by a codec covers the - * performance point required. This method can also be used for lose ordering as this + * performance point required. This method can also be used for loose ordering as this * method is transitive. * * @param other other performance point considered @@ -1698,91 +1804,139 @@ public final class MediaCodecInfo { * @return {@code true} if the performance point covers the other. */ public boolean covers(@NonNull PerformancePoint other) { - return (macroBlocks >= other.macroBlocks - && frameRate >= other.frameRate - && macroBlockRate >= other.macroBlockRate); + // convert performance points to common block size + Size commonSize = getCommonBlockSize(other); + PerformancePoint aligned = new PerformancePoint(this, commonSize); + PerformancePoint otherAligned = new PerformancePoint(other, commonSize); + + return (aligned.getMaxMacroBlocks() >= otherAligned.getMaxMacroBlocks() + && aligned.mMaxFrameRate >= otherAligned.mMaxFrameRate + && aligned.mMaxMacroBlockRate >= otherAligned.mMaxMacroBlockRate); } + private @NonNull Size getCommonBlockSize(@NonNull PerformancePoint other) { + return new Size( + Math.max(mBlockSize.getWidth(), other.mBlockSize.getWidth()) * 16, + Math.max(mBlockSize.getHeight(), other.mBlockSize.getHeight()) * 16); + } @Override public boolean equals(Object o) { if (o instanceof PerformancePoint) { + // convert performance points to common block size PerformancePoint other = (PerformancePoint)o; - return (macroBlocks == other.macroBlocks - && frameRate == other.frameRate - && macroBlockRate == other.macroBlockRate); + Size commonSize = getCommonBlockSize(other); + PerformancePoint aligned = new PerformancePoint(this, commonSize); + PerformancePoint otherAligned = new PerformancePoint(other, commonSize); + + return (aligned.getMaxMacroBlocks() == otherAligned.getMaxMacroBlocks() + && aligned.mMaxFrameRate == otherAligned.mMaxFrameRate + && aligned.mMaxMacroBlockRate == otherAligned.mMaxMacroBlockRate); } return false; } /** 480p 24fps */ + @NonNull public static final PerformancePoint SD_24 = new PerformancePoint(720, 480, 24); /** 576p 25fps */ + @NonNull public static final PerformancePoint SD_25 = new PerformancePoint(720, 576, 25); /** 480p 30fps */ + @NonNull public static final PerformancePoint SD_30 = new PerformancePoint(720, 480, 30); /** 480p 48fps */ + @NonNull public static final PerformancePoint SD_48 = new PerformancePoint(720, 480, 48); /** 576p 50fps */ + @NonNull public static final PerformancePoint SD_50 = new PerformancePoint(720, 576, 50); /** 480p 60fps */ + @NonNull public static final PerformancePoint SD_60 = new PerformancePoint(720, 480, 60); /** 720p 24fps */ + @NonNull public static final PerformancePoint HD_24 = new PerformancePoint(1280, 720, 24); /** 720p 25fps */ + @NonNull public static final PerformancePoint HD_25 = new PerformancePoint(1280, 720, 25); /** 720p 30fps */ + @NonNull public static final PerformancePoint HD_30 = new PerformancePoint(1280, 720, 30); /** 720p 50fps */ + @NonNull public static final PerformancePoint HD_50 = new PerformancePoint(1280, 720, 50); /** 720p 60fps */ + @NonNull public static final PerformancePoint HD_60 = new PerformancePoint(1280, 720, 60); /** 720p 100fps */ + @NonNull public static final PerformancePoint HD_100 = new PerformancePoint(1280, 720, 100); /** 720p 120fps */ + @NonNull public static final PerformancePoint HD_120 = new PerformancePoint(1280, 720, 120); /** 720p 200fps */ + @NonNull public static final PerformancePoint HD_200 = new PerformancePoint(1280, 720, 200); /** 720p 240fps */ + @NonNull public static final PerformancePoint HD_240 = new PerformancePoint(1280, 720, 240); /** 1080p 24fps */ + @NonNull public static final PerformancePoint FHD_24 = new PerformancePoint(1920, 1080, 24); /** 1080p 25fps */ + @NonNull public static final PerformancePoint FHD_25 = new PerformancePoint(1920, 1080, 25); /** 1080p 30fps */ + @NonNull public static final PerformancePoint FHD_30 = new PerformancePoint(1920, 1080, 30); /** 1080p 50fps */ + @NonNull public static final PerformancePoint FHD_50 = new PerformancePoint(1920, 1080, 50); /** 1080p 60fps */ + @NonNull public static final PerformancePoint FHD_60 = new PerformancePoint(1920, 1080, 60); /** 1080p 100fps */ + @NonNull public static final PerformancePoint FHD_100 = new PerformancePoint(1920, 1080, 100); /** 1080p 120fps */ + @NonNull public static final PerformancePoint FHD_120 = new PerformancePoint(1920, 1080, 120); /** 1080p 200fps */ + @NonNull public static final PerformancePoint FHD_200 = new PerformancePoint(1920, 1080, 200); /** 1080p 240fps */ + @NonNull public static final PerformancePoint FHD_240 = new PerformancePoint(1920, 1080, 240); /** 2160p 24fps */ + @NonNull public static final PerformancePoint UHD_24 = new PerformancePoint(3840, 2160, 24); /** 2160p 25fps */ + @NonNull public static final PerformancePoint UHD_25 = new PerformancePoint(3840, 2160, 25); /** 2160p 30fps */ + @NonNull public static final PerformancePoint UHD_30 = new PerformancePoint(3840, 2160, 30); /** 2160p 50fps */ + @NonNull public static final PerformancePoint UHD_50 = new PerformancePoint(3840, 2160, 50); /** 2160p 60fps */ + @NonNull public static final PerformancePoint UHD_60 = new PerformancePoint(3840, 2160, 60); /** 2160p 100fps */ + @NonNull public static final PerformancePoint UHD_100 = new PerformancePoint(3840, 2160, 100); /** 2160p 120fps */ + @NonNull public static final PerformancePoint UHD_120 = new PerformancePoint(3840, 2160, 120); /** 2160p 200fps */ + @NonNull public static final PerformancePoint UHD_200 = new PerformancePoint(3840, 2160, 200); /** 2160p 240fps */ + @NonNull public static final PerformancePoint UHD_240 = new PerformancePoint(3840, 2160, 240); } @@ -1803,10 +1957,7 @@ public final class MediaCodecInfo { */ @Nullable public List<PerformancePoint> getSupportedPerformancePoints() { - if (mPerformancePoints == null) { - return null; - } - return new ArrayList<PerformancePoint>(mPerformancePoints); + return mPerformancePoints; } /** @@ -1945,7 +2096,7 @@ public final class MediaCodecInfo { mSmallerDimensionUpperLimit = SIZE_RANGE.getUpper(); } - private @Nullable Vector<PerformancePoint> getPerformancePoints(Map<String, Object> map) { + private @Nullable List<PerformancePoint> getPerformancePoints(Map<String, Object> map) { Vector<PerformancePoint> ret = new Vector<>(); final String prefix = "performance-point-"; Set<String> keys = map.keySet(); @@ -1959,7 +2110,7 @@ public final class MediaCodecInfo { // This means that component knowingly did not publish performance points. // This is different from when the component forgot to publish performance // points. - return ret; + return Collections.unmodifiableList(ret); } String[] temp = key.split("-"); if (temp.length != 4) { @@ -1974,23 +2125,32 @@ public final class MediaCodecInfo { if (range == null || range.getLower() < 0 || range.getUpper() < 0) { continue; } - ret.add(new PerformancePoint( + PerformancePoint given = new PerformancePoint( size.getWidth(), size.getHeight(), range.getLower().intValue(), - range.getUpper().intValue())); + range.getUpper().intValue(), new Size(mBlockWidth, mBlockHeight)); + PerformancePoint rotated = new PerformancePoint( + size.getHeight(), size.getWidth(), range.getLower().intValue(), + range.getUpper().intValue(), new Size(mBlockWidth, mBlockHeight)); + ret.add(given); + if (!given.covers(rotated)) { + ret.add(rotated); + } } + // check if the component specified no performance point indication if (ret.size() == 0) { return null; } // sort reversed by area first, then by frame rate - ret.sort((a, b) -> -((a.macroBlocks != b.macroBlocks) ? - (a.macroBlocks < b.macroBlocks ? -1 : 1) : - (a.macroBlockRate != b.macroBlockRate) ? - (a.macroBlockRate < b.macroBlockRate ? -1 : 1) : - (a.frameRate != b.frameRate) ? - (a.frameRate < b.frameRate ? -1 : 1) : 0)); - return ret; + ret.sort((a, b) -> + -((a.getMaxMacroBlocks() != b.getMaxMacroBlocks()) ? + (a.getMaxMacroBlocks() < b.getMaxMacroBlocks() ? -1 : 1) : + (a.getMaxMacroBlockRate() != b.getMaxMacroBlockRate()) ? + (a.getMaxMacroBlockRate() < b.getMaxMacroBlockRate() ? -1 : 1) : + (a.getMaxFrameRate() != b.getMaxFrameRate()) ? + (a.getMaxFrameRate() < b.getMaxFrameRate() ? -1 : 1) : 0)); + return Collections.unmodifiableList(ret); } private Map<Size, Range<Long>> getMeasuredFrameRates(Map<String, Object> map) { @@ -3404,14 +3564,29 @@ public final class MediaCodecInfo { public static final int VP8ProfileMain = 0x01; + /** VP9 Profile 0 4:2:0 8-bit */ public static final int VP9Profile0 = 0x01; + + /** VP9 Profile 1 4:2:2 8-bit */ public static final int VP9Profile1 = 0x02; + + /** VP9 Profile 2 4:2:0 10-bit */ public static final int VP9Profile2 = 0x04; + + /** VP9 Profile 3 4:2:2 10-bit */ public static final int VP9Profile3 = 0x08; + // HDR profiles also support passing HDR metadata + /** VP9 Profile 2 4:2:0 10-bit HDR */ public static final int VP9Profile2HDR = 0x1000; + + /** VP9 Profile 3 4:2:2 10-bit HDR */ public static final int VP9Profile3HDR = 0x2000; + + /** VP9 Profile 2 4:2:0 10-bit HDR10Plus */ public static final int VP9Profile2HDR10Plus = 0x4000; + + /** VP9 Profile 3 4:2:2 10-bit HDR10Plus */ public static final int VP9Profile3HDR10Plus = 0x8000; public static final int VP9Level1 = 0x1; @@ -3489,35 +3664,34 @@ public final class MediaCodecInfo { public static final int DolbyVisionLevelUhd48 = 0x80; public static final int DolbyVisionLevelUhd60 = 0x100; - // Profiles and levels for AV1 Codec, corresponding to the - // definitions in + // Profiles and levels for AV1 Codec, corresponding to the definitions in // "AV1 Bitstream & Decoding Process Specification", Annex A - // found at - // https://aomedia.org/av1-bitstream-and-decoding-process-specification/ + // found at https://aomedia.org/av1-bitstream-and-decoding-process-specification/ /** - * AV1 Main profile. + * AV1 Main profile 4:2:0 8-bit + * * See definition in - * <a href="https://aomedia.org/av1-bitstream-and-decoding-process-specification/"> AV1 Bitstream and Decoding Process Specification</a> + * <a href="https://aomedia.org/av1-bitstream-and-decoding-process-specification/">AV1 Specification</a> * Annex A. */ - public static final int AV1Profile0 = 0x1; + public static final int AV1ProfileMain8 = 0x1; /** - * AV1 High profile. + * AV1 Main profile 4:2:0 10-bit + * * See definition in - * <a href="https://aomedia.org/av1-bitstream-and-decoding-process-specification/"> AV1 Bitstream and Decoding Process Specification</a> + * <a href="https://aomedia.org/av1-bitstream-and-decoding-process-specification/">AV1 Specification</a> * Annex A. */ - public static final int AV1Profile1 = 0x2; + public static final int AV1ProfileMain10 = 0x2; - /** - * AV1 Professional profile. - * See definition in - * <a href="https://aomedia.org/av1-bitstream-and-decoding-process-specification/"> AV1 Bitstream and Decoding Process Specification</a> - * Annex A. - */ - public static final int AV1Profile2 = 0x4; + + /** AV1 Main profile 4:2:0 10-bit with HDR10. */ + public static final int AV1ProfileMain10HDR10 = 0x1000; + + /** AV1 Main profile 4:2:0 10-bit with HDR10Plus. */ + public static final int AV1ProfileMain10HDR10Plus = 0x2000; public static final int AV1Level2 = 0x1; public static final int AV1Level21 = 0x2; 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/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/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/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/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/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/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..61dc966076a8 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 @@ -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..e73cba626f15 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; 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/EntityHeaderWidgets/res/values/styles.xml b/packages/SettingsLib/EntityHeaderWidgets/res/values/styles.xml index 0eefd4bff97f..7db6014c9f39 100644 --- a/packages/SettingsLib/EntityHeaderWidgets/res/values/styles.xml +++ b/packages/SettingsLib/EntityHeaderWidgets/res/values/styles.xml @@ -31,7 +31,7 @@ </style> <style name="AppEntitiesHeader.Text.Summary" - parent="@android:style/TextAppearance.Material.Body1"> + parent="@*android:style/TextAppearance.DeviceDefault.Body1"> <item name="android:textColor">?android:attr/textColorSecondary</item> <item name="android:textSize">14sp</item> </style> diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml index d3dde92a4b44..c6a995cb25f7 100644 --- a/packages/SettingsLib/res/values/strings.xml +++ b/packages/SettingsLib/res/values/strings.xml @@ -113,6 +113,9 @@ <!-- Summary for Connected wifi network without internet --> <string name="wifi_connected_no_internet">Connected, no internet</string> + <!-- Summary for connected wifi network with partial internet connectivity [CHAR LIMIT=50] --> + <string name="wifi_limited_connection">Limited connection</string> + <!-- Wi-Fi status indicating that the current network is connected, but has no internet access. --> <string name="wifi_status_no_internet">No internet</string> diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java index 800c4014313f..3acbcd3f6b41 100644 --- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java +++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java @@ -1424,6 +1424,9 @@ public class AccessPoint implements Comparable<AccessPoint> { int id = context.getResources() .getIdentifier("network_available_sign_in", "string", "android"); return context.getString(id); + } else if (nc.hasCapability( + NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY)) { + return context.getString(R.string.wifi_limited_connection); } else if (!nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)) { return context.getString(R.string.wifi_connected_no_internet); } diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java index 2ab369cc2065..5352936d7224 100644 --- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java +++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java @@ -11,6 +11,7 @@ package com.android.settingslib.wifi; import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL; +import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY; import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; import android.content.Context; @@ -158,6 +159,9 @@ public class WifiStatusTracker extends ConnectivityManager.NetworkCallback { if (networkCapabilities.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL)) { statusLabel = mContext.getString(R.string.wifi_status_sign_in_required); return; + } else if (networkCapabilities.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY)) { + statusLabel = mContext.getString(R.string.wifi_limited_connection); + return; } else if (!networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) { statusLabel = mContext.getString(R.string.wifi_status_no_internet); return; 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/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/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/quick_qs_status_icons.xml b/packages/SystemUI/res/layout/quick_qs_status_icons.xml index 74002ac38c02..fa74536532b8 100644 --- a/packages/SystemUI/res/layout/quick_qs_status_icons.xml +++ b/packages/SystemUI/res/layout/quick_qs_status_icons.xml @@ -26,7 +26,9 @@ 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/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..77e79c96b6a7 100644 --- a/packages/SystemUI/res/values-land/dimens.xml +++ b/packages/SystemUI/res/values-land/dimens.xml @@ -34,4 +34,7 @@ <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..27cebcc112ac 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -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 --> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index c6c2763f7801..f8bec4a309b8 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -447,6 +447,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 +1072,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 +1310,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 +2379,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..1c13750a1340 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> 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/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/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 e8b346ed97ab..14e910f41cab 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java @@ -94,6 +94,9 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList private boolean mActivityViewReady = false; private PendingIntent mBubbleIntent; + private boolean mKeyboardVisible; + private boolean mNeedsNewHeight; + private int mMinHeight; private int mHeaderHeight; private int mBubbleHeight; @@ -227,21 +230,15 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList true /* singleTaskInstance */); addView(mActivityView); - mActivityView.setOnApplyWindowInsetsListener((View view, WindowInsets insets) -> { - ActivityView activityView = (ActivityView) view; - // Here we assume that the position of the ActivityView on the screen - // remains regardless of IME status. When we move ActivityView, the - // forwardedInsets should be computed not against the current location - // and size, but against the post-moved location and size. - Point displaySize = new Point(); - view.getContext().getDisplay().getSize(displaySize); - int[] windowLocation = view.getLocationOnScreen(); - final int windowBottom = windowLocation[1] + view.getHeight(); + setOnApplyWindowInsetsListener((View view, WindowInsets insets) -> { + // Keep track of IME displaying because we should not make any adjustments that might + // cause a config change while the IME is displayed otherwise it'll loose focus. final int keyboardHeight = insets.getSystemWindowInsetBottom() - insets.getStableInsetBottom(); - final int insetsBottom = Math.max(0, - windowBottom + keyboardHeight - displaySize.y); - activityView.setForwardedInsets(Insets.of(0, 0, 0, insetsBottom)); + mKeyboardVisible = keyboardHeight != 0; + if (!mKeyboardVisible && mNeedsNewHeight) { + updateHeight(); + } return view.onApplyWindowInsets(insets); }); @@ -258,6 +255,34 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList } } + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + mKeyboardVisible = false; + mNeedsNewHeight = false; + if (mActivityView != null) { + mActivityView.setForwardedInsets(Insets.of(0, 0, 0, 0)); + } + } + + /** + * Called by {@link BubbleStackView} when the insets for the expanded state should be updated. + * This should be done post-move and post-animation. + */ + void updateInsets(WindowInsets insets) { + if (usingActivityView()) { + Point displaySize = new Point(); + mActivityView.getContext().getDisplay().getSize(displaySize); + int[] windowLocation = mActivityView.getLocationOnScreen(); + final int windowBottom = windowLocation[1] + mActivityView.getHeight(); + final int keyboardHeight = insets.getSystemWindowInsetBottom() + - insets.getStableInsetBottom(); + final int insetsBottom = Math.max(0, + windowBottom + keyboardHeight - displaySize.y); + mActivityView.setForwardedInsets(Insets.of(0, 0, 0, insetsBottom)); + } + } + /** * Creates a background with corners rounded based on how the view is configured to display */ @@ -385,6 +410,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); } @@ -448,9 +475,15 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList int height = Math.min(desiredHeight, max); height = Math.max(height, mMinHeight); LayoutParams lp = (LayoutParams) mActivityView.getLayoutParams(); - lp.height = height; - mBubbleHeight = height; - mActivityView.setLayoutParams(lp); + mNeedsNewHeight = lp.height != height; + if (!mKeyboardVisible) { + // If the keyboard is visible... don't adjust the height because that will cause + // a configuration change and the keyboard will be lost. + lp.height = height; + mBubbleHeight = height; + mActivityView.setLayoutParams(lp); + mNeedsNewHeight = false; + } } else { mBubbleHeight = mNotifRow != null ? mNotifRow.getIntrinsicHeight() : mMinHeight; } diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java index 461e79c671c4..580acb82ebc1 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java @@ -128,6 +128,7 @@ public class BubbleStackView extends FrameLayout { private Bubble mExpandedBubble; private boolean mIsExpanded; + private boolean mImeVisible; private BubbleTouchHandler mTouchHandler; private BubbleController.BubbleExpandListener mExpandListener; @@ -236,6 +237,28 @@ public class BubbleStackView extends FrameLayout { setClipChildren(false); setFocusable(true); mBubbleContainer.bringToFront(); + + setOnApplyWindowInsetsListener((View view, WindowInsets insets) -> { + final int keyboardHeight = insets.getSystemWindowInsetBottom() + - insets.getStableInsetBottom(); + if (!mIsExpanded) { + return view.onApplyWindowInsets(insets); + } + mImeVisible = keyboardHeight != 0; + + float newY = getYPositionForExpandedView(); + if (newY < 0) { + // TODO: This means our expanded content is too big to fit on screen. Right now + // we'll let it translate off but we should be clipping it & pushing the header + // down so that it always remains visible. + } + mExpandedViewYAnim.animateToFinalPosition(newY); + mExpandedAnimationController.updateYPosition( + // Update the insets after we're done translating otherwise position + // calculation for them won't be correct. + () -> mExpandedBubble.expandedView.updateInsets(insets)); + return view.onApplyWindowInsets(insets); + }); } /** @@ -646,15 +669,6 @@ public class BubbleStackView extends FrameLayout { } } - /** - * The width of the collapsed stack of bubbles. - */ - public int getStackWidth() { - return mBubblePadding * (mBubbleContainer.getChildCount() - 1) - + mBubbleSize + mBubbleContainer.getPaddingEnd() - + mBubbleContainer.getPaddingStart(); - } - private void notifyExpansionChanged(NotificationEntry entry, boolean expanded) { if (mExpandListener != null) { mExpandListener.onBubbleExpandChanged(expanded, entry != null ? entry.key : null); @@ -843,8 +857,13 @@ public class BubbleStackView extends FrameLayout { // calculation is correct) mExpandedBubble.expandedView.updateView(); final float y = getYPositionForExpandedView(); - mExpandedViewContainer.setTranslationY(y); - // Then update the view so that ActivityView knows we translated + if (!mExpandedViewYAnim.isRunning()) { + // We're not animating so set the value + mExpandedViewContainer.setTranslationY(y); + } else { + // We are animating so update the value + mExpandedViewYAnim.animateToFinalPosition(y); + } mExpandedBubble.expandedView.updateView(); } 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 1f29883b180a..40e08bed8352 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java @@ -198,6 +198,19 @@ public class ExpandedAnimationController } /** + * Animates the bubbles to {@link #getExpandedY()} position. Used in response to IME showing. + */ + 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); + } + } + + /** * Animates the bubbles, starting at the given index, to the left or right by the given number * of bubble widths. Passing zero for numBubbleWidths will animate the bubbles to their normal * positions. @@ -213,18 +226,25 @@ public class ExpandedAnimationController /** The Y value of the row of expanded bubbles. */ public float getExpandedY() { - boolean showOnTop = mLayout != null - && BubbleController.showBubblesAtTop(mLayout.getContext()); - final WindowInsets insets = mLayout != null ? mLayout.getRootWindowInsets() : null; - if (showOnTop && insets != null) { + if (mLayout == null || mLayout.getRootWindowInsets() == null) { + return 0; + } + final boolean showOnTop = BubbleController.showBubblesAtTop(mLayout.getContext()); + final WindowInsets insets = mLayout.getRootWindowInsets(); + if (showOnTop) { return mBubblePaddingPx + Math.max( mStatusBarHeight, insets.getDisplayCutout() != null ? insets.getDisplayCutout().getSafeInsetTop() : 0); } else { - int bottomInset = insets != null ? insets.getSystemWindowInsetBottom() : 0; - return mDisplaySize.y - mBubbleSizePx - (mPipDismissHeight - bottomInset); + int keyboardHeight = insets.getSystemWindowInsetBottom() + - insets.getStableInsetBottom(); + float bottomInset = keyboardHeight > 0 + ? keyboardHeight + : (mPipDismissHeight - insets.getStableInsetBottom()); + // Stable insets are excluded from display size, so we must subtract it + return mDisplaySize.y - mBubbleSizePx - mBubblePaddingPx - bottomInset; } } diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java index bc3f48dac769..031f56266ea4 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,6 +183,20 @@ 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) { final boolean near = !far; final DozeMachine.State state = mMachine.getState(); 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/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/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java index 4862b9eddc85..c897b9c3b467 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; @@ -561,11 +558,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..5a7df1f21bbd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java @@ -303,7 +303,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(); 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/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/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..5a1f24a44b2f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java @@ -313,7 +313,7 @@ public class NotificationTestHelper { .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 c5c4b5a7e85b..7447331b113d 100644 --- a/proto/src/metrics_constants/metrics_constants.proto +++ b/proto/src/metrics_constants/metrics_constants.proto @@ -7124,6 +7124,20 @@ message MetricsEvent { // OS: Q DIALOG_FACE_REMOVE = 1693; + // FIELD - Detailed reason in screen wake. One of WAKE_REASON_* in PowerManager. + // OS: Q + FIELD_SCREEN_WAKE_REASON = 1694; + + // FIELD - Detailed reason in screen sleep. One of GO_TO_SLEEP_REASON_* in PowerManager. + // 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; + // ---- 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/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java index c9172683b39c..76d464d2acfe 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java @@ -683,6 +683,14 @@ public final class AutofillManagerService send(receiver, value ? 1 : 0); } + private void send(@NonNull IResultReceiver receiver, int value1, int value2) { + try { + receiver.send(value1, SyncResultReceiver.bundleFor(value2)); + } catch (RemoteException e) { + Slog.w(TAG, "Error async reporting result to client: " + e); + } + } + @Nullable @VisibleForTesting static Map<String, String[]> getWhitelistedCompatModePackages(String setting) { @@ -934,12 +942,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; @@ -1003,14 +1013,20 @@ public final class AutofillManagerService // TODO(b/113281366): add a callback method on AM to be notified when a task is finished // so we can clean up sessions kept alive final int taskId = mAm.getTaskIdForActivity(activityToken, false); - final int sessionId; + final long result; synchronized (mLock) { final AutofillManagerServiceImpl service = getServiceForUserLocked(userId); - sessionId = service.startSessionLocked(activityToken, taskId, getCallingUid(), + result = service.startSessionLocked(activityToken, taskId, getCallingUid(), appCallback, autofillId, bounds, value, hasCallback, componentName, compatMode, mAllowInstantService, flags); } - send(receiver, sessionId); + final int sessionId = (int) result; + final int resultFlags = (int) (result >> 32); + if (resultFlags != 0) { + send(receiver, sessionId, resultFlags); + } else { + send(receiver, sessionId); + } } @Override diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java index dd3efa0b4afa..ad5e6895ebf3 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java @@ -18,6 +18,9 @@ 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; import static com.android.server.autofill.Helper.sDebug; @@ -222,7 +225,7 @@ final class AutofillManagerServiceImpl session.removeSelfLocked(); } } - sendStateToClients(false); + sendStateToClients(/* resetClient= */ false); } updateRemoteAugmentedAutofillService(); return enabledChanged; @@ -240,13 +243,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") @@ -279,58 +297,91 @@ final class AutofillManagerServiceImpl } } + /** + * Starts a new session. + * + * @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 AutofillManager#FLAG_SESSION_FOR_AUGMENTED_AUTOFILL_ONLY}). + */ @GuardedBy("mLock") - int startSessionLocked(@NonNull IBinder activityToken, int taskId, int uid, + long startSessionLocked(@NonNull IBinder activityToken, int taskId, int uid, @NonNull IBinder appCallbackToken, @NonNull AutofillId autofillId, @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(); + 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(" + componentName + "): disabled by service but " + + "whitelisted for augmented autofill"); + } + forAugmentedAutofillOnly = true; - if (isAutofillDisabledLocked(componentName)) { - if (sDebug) { - Slog.d(TAG, "startSession(" + shortComponentName - + "): ignored because disabled by service"); - } + } else { + if (sDebug) { + Slog.d(TAG, "startSession(" + componentName + "): ignored because " + + "disabled by service and not whitelisted for augmented autofill"); + } + final IAutoFillManagerClient client = IAutoFillManagerClient.Stub + .asInterface(appCallbackToken); + try { + client.setSessionFinished(AutofillManager.STATE_DISABLED_BY_SERVICE, + /* autofillableIds= */ null); + } catch (RemoteException e) { + Slog.w(TAG, + "Could not notify " + componentName + " that it's disabled: " + e); + } - final IAutoFillManagerClient client = IAutoFillManagerClient.Stub - .asInterface(appCallbackToken); - try { - client.setSessionFinished(AutofillManager.STATE_DISABLED_BY_SERVICE, - /* autofillableIds= */ null); - } catch (RemoteException e) { - Slog.w(TAG, "Could not notify " + shortComponentName + " that it's disabled: " + e); + return NO_SESSION; } - - return NO_SESSION; } - if (sVerbose) Slog.v(TAG, "startSession(): token=" + activityToken + ", flags=" + flags); + if (sVerbose) { + Slog.v(TAG, "startSession(): token=" + activityToken + ", flags=" + flags + + ", forAugmentedAutofillOnly=" + forAugmentedAutofillOnly); + } // Occasionally clean up abandoned sessions pruneAbandonedSessionsLocked(); final Session newSession = createSessionByTokenLocked(activityToken, taskId, uid, appCallbackToken, hasCallback, componentName, compatMode, - bindInstantServiceAllowed, flags); + bindInstantServiceAllowed, forAugmentedAutofillOnly, flags); if (newSession == null) { 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; + + " hc=" + hasCallback + " f=" + flags + " aa=" + forAugmentedAutofillOnly; mMaster.logRequestLocked(historyItem); newSession.updateLocked(autofillId, virtualBounds, value, ACTION_START_SESSION, flags); - return newSession.id; + if (forAugmentedAutofillOnly) { + // Must embed the flag in the response, at the high-end side of the long. + // (session is always positive, so we don't have to worry about the signal bit) + final long extraFlags = ((long) FLAG_SESSION_FOR_AUGMENTED_AUTOFILL_ONLY) << 32; + final long result = extraFlags | newSession.id; + return result; + } else { + return newSession.id; + } } /** @@ -436,7 +487,7 @@ final class AutofillManagerServiceImpl private Session createSessionByTokenLocked(@NonNull IBinder activityToken, int taskId, int uid, @NonNull IBinder appCallbackToken, boolean hasCallback, @NonNull ComponentName componentName, boolean compatMode, - boolean bindInstantServiceAllowed, int flags) { + boolean bindInstantServiceAllowed, boolean forAugmentedAutofillOnly, int flags) { // use random ids so that one app cannot know that another app creates sessions int sessionId; int tries = 0; @@ -447,15 +498,20 @@ final class AutofillManagerServiceImpl return null; } - sessionId = sRandom.nextInt(); - } while (sessionId == NO_SESSION || mSessions.indexOfKey(sessionId) >= 0); + sessionId = Math.abs(sRandom.nextInt()); + } while (sessionId == 0 || sessionId == NO_SESSION + || mSessions.indexOfKey(sessionId) >= 0); 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(), - componentName, compatMode, bindInstantServiceAllowed, flags); + mUiLatencyHistory, mWtfHistory, serviceComponentName, + componentName, compatMode, bindInstantServiceAllowed, forAugmentedAutofillOnly, + flags); mSessions.put(newSession.id, newSession); return newSession; @@ -635,7 +691,7 @@ final class AutofillManagerServiceImpl remoteFillServices.valueAt(i).destroy(); } - sendStateToClients(true); + sendStateToClients(/* resetclient=*/ true); if (mClients != null) { mClients.kill(); mClients = null; diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java index ea47033f7141..ac8f61b50192 100644 --- a/services/autofill/java/com/android/server/autofill/Session.java +++ b/services/autofill/java/com/android/server/autofill/Session.java @@ -138,7 +138,11 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState private static AtomicInteger sIdCounter = new AtomicInteger(); - /** ID of the session */ + /** + * ID of the session. + * + * <p>It's always a positive number, to make it easier to embed it in a long. + */ public final int id; /** uid the session is for */ @@ -181,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") @@ -277,11 +287,23 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState private ArraySet<AutofillId> mAugmentedAutofillableIds; /** + * When {@code true}, the session was created only to handle Augmented Autofill requests (i.e., + * the session would not have existed otherwsie). + */ + @GuardedBy("mLock") + private boolean mForAugmentedAutofillOnly; + + /** * Receiver of assist data from the app's {@link Activity}. */ 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"); @@ -516,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 @@ -538,11 +565,12 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState */ @GuardedBy("mLock") private void requestNewFillResponseLocked(int flags) { - - if ((flags & FLAG_AUGMENTED_AUTOFILL_REQUEST) != 0) { + if (mForAugmentedAutofillOnly || (flags & FLAG_AUGMENTED_AUTOFILL_REQUEST) != 0) { // TODO(b/122858578): log metrics if (sVerbose) { - Slog.v(TAG, "requestNewFillResponse(): triggering augmented autofill instead"); + Slog.v(TAG, "requestNewFillResponse(): triggering augmented autofill instead " + + "(mForAugmentedAutofillOnly=" + mForAugmentedAutofillOnly + + ", flags=" + flags + ")"); } triggerAugmentedAutofillLocked(); return; @@ -564,8 +592,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState mRequestLogs.put(requestId, log); if (sVerbose) { - Slog.v(TAG, "Requesting structure for request #" + ordinal + " ,requestId=" - + requestId + ", flags=" + flags); + Slog.v(TAG, "Requesting structure for request #" + ordinal + " ,requestId=" + requestId + + ", flags=" + flags); } // If the focus changes very quickly before the first request is returned each focus change @@ -596,9 +624,12 @@ 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, int flags) { + boolean bindInstantServiceAllowed, boolean forAugmentedAutofillOnly, int flags) { + if (sessionId < 0) { + wtf(null, "Non-positive sessionId: %s", sessionId); + } id = sessionId; mFlags = flags; this.taskId = taskId; @@ -608,14 +639,16 @@ 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; mWtfHistory = wtfHistory; mComponentName = componentName; mCompatMode = compatMode; + mForAugmentedAutofillOnly = forAugmentedAutofillOnly; setClientLocked(client); mMetricsLogger.write(newLogMaker(MetricsEvent.AUTOFILL_SESSION_STARTED) @@ -727,14 +760,6 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState final long disableDuration = response.getDisableDuration(); if (disableDuration > 0) { final int flags = response.getFlags(); - if (sDebug) { - final StringBuilder message = new StringBuilder("Service disabled autofill for ") - .append(mComponentName) - .append(": flags=").append(flags) - .append(", duration="); - TimeUtils.formatDuration(disableDuration, message); - Slog.d(TAG, message.toString()); - } if ((flags & FillResponse.FLAG_DISABLE_ACTIVITY_ONLY) != 0) { mService.disableAutofillForActivity(mComponentName, disableDuration, id, mCompatMode); @@ -742,6 +767,23 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState mService.disableAutofillForApp(mComponentName.getPackageName(), disableDuration, id, mCompatMode); } + // Although "standard" autofill is disabled, it might still trigger augmented autofill + if (triggerAugmentedAutofillLocked() != null) { + mForAugmentedAutofillOnly = true; + if (sDebug) { + Slog.d(TAG, "Service disabled autofill for " + mComponentName + + ", but session is kept for augmented autofill only"); + } + return; + } + if (sDebug) { + final StringBuilder message = new StringBuilder("Service disabled autofill for ") + .append(mComponentName) + .append(": flags=").append(flags) + .append(", duration="); + TimeUtils.formatDuration(disableDuration, message); + Slog.d(TAG, message.toString()); + } sessionFinishedState = AutofillManager.STATE_DISABLED_BY_SERVICE; } @@ -2010,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); @@ -3005,6 +3052,9 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState pw.print(prefix); pw.print("mSaveOnAllViewsInvisible: "); pw.println( mSaveOnAllViewsInvisible); pw.print(prefix); pw.print("mSelectedDatasetIds: "); pw.println(mSelectedDatasetIds); + if (mForAugmentedAutofillOnly) { + pw.print(prefix); pw.println("For Augmented Autofill Only"); + } if (mAugmentedAutofillDestroyer != null) { pw.print(prefix); pw.println("has mAugmentedAutofillDestroyer"); } @@ -3017,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..ec5987e97ceb 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,11 @@ 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 = + final boolean partialConnectivityChanged = (partialConnectivity && !nai.partialConnectivity); final boolean valid = (msg.arg1 == NETWORK_TEST_RESULT_VALID); @@ -2584,17 +2576,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 +2605,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 +3359,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(); } @@ -3587,6 +3571,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; } @@ -6395,6 +6382,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/DynamicAndroidService.java index 8488941587fb..b02bfb111727 100644 --- a/services/core/java/com/android/server/DynamicAndroidService.java +++ b/services/core/java/com/android/server/DynamicAndroidService.java @@ -25,6 +25,7 @@ import android.os.IBinder.DeathRecipient; import android.os.IDynamicAndroidService; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.SystemProperties; import android.util.Slog; /** @@ -34,6 +35,7 @@ import android.util.Slog; public class DynamicAndroidService extends IDynamicAndroidService.Stub implements DeathRecipient { private static final String TAG = "DynamicAndroidService"; 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; @@ -66,12 +68,27 @@ public class DynamicAndroidService extends IDynamicAndroidService.Stub implement private IGsiService getGsiService() throws RemoteException { checkPermission(); - synchronized (this) { - if (mGsiService == null) { - mGsiService = connect(this); + if (!"running".equals(SystemProperties.get("init.svc.gsid"))) { + SystemProperties.set("ctl.start", "gsid"); + } + for (int sleepMs = 64; sleepMs <= (GSID_ROUGH_TIMEOUT_MS << 1); sleepMs <<= 1) { + try { + Thread.sleep(sleepMs); + } catch (InterruptedException e) { + Slog.e(TAG, "Interrupted when waiting for GSID"); + break; + } + if ("running".equals(SystemProperties.get("init.svc.gsid"))) { + synchronized (this) { + if (mGsiService == null) { + mGsiService = connect(this); + } + return mGsiService; + } } - return mGsiService; } + Slog.e(TAG, "Unable to start gsid"); + return null; } private void checkPermission() { diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java index 6ef5b547a353..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; @@ -1824,12 +1825,7 @@ public class LocationManagerService extends ILocationManager.Stub { @GuardedBy("mLock") private void removeProviderLocked(LocationProvider provider) { if (mProviders.remove(provider)) { - long identity = Binder.clearCallingIdentity(); - try { - provider.onUseableChangedLocked(false); - } finally { - Binder.restoreCallingIdentity(identity); - } + provider.onUseableChangedLocked(false); } } @@ -2108,7 +2104,9 @@ public class LocationManagerService extends ILocationManager.Stub { WorkSource worksource = new WorkSource(); ProviderRequest providerRequest = new ProviderRequest(); - if (records != null && !records.isEmpty()) { + // if provider is not active, it should not respond to requests + + if (mProviders.contains(provider) && records != null && !records.isEmpty()) { long backgroundThrottleInterval; long identity = Binder.clearCallingIdentity(); @@ -2698,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"); @@ -2943,7 +2954,7 @@ public class LocationManagerService extends ILocationManager.Stub { } @Override - public int getGnssCapabilities(String packageName) { + public long getGnssCapabilities(String packageName) { mContext.enforceCallingPermission( android.Manifest.permission.LOCATION_HARDWARE, "Location Hardware permission not granted to obtain GNSS chipset capabilities."); 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 8cb1ec73a00d..5bd0b89755d4 100644 --- a/services/core/java/com/android/server/StorageManagerService.java +++ b/services/core/java/com/android/server/StorageManagerService.java @@ -21,6 +21,9 @@ import static android.Manifest.permission.WRITE_MEDIA_STORAGE; import static android.app.AppOpsManager.MODE_ALLOWED; import static android.app.AppOpsManager.OP_LEGACY_STORAGE; import static android.app.AppOpsManager.OP_REQUEST_INSTALL_PACKAGES; +import static android.content.pm.PackageManager.FLAG_PERMISSION_HIDDEN; +import static android.content.pm.PackageManager.FLAG_PERMISSION_SYSTEM_FIXED; +import static android.content.pm.PackageManager.GET_PERMISSIONS; import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE; import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE; import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES; @@ -74,6 +77,7 @@ import android.content.res.ObbInfo; import android.database.ContentObserver; import android.net.Uri; import android.os.Binder; +import android.os.Build; import android.os.DropBoxManager; import android.os.Environment; import android.os.Environment.UserEnvironment; @@ -301,6 +305,19 @@ class StorageManagerService extends IStorageManager.Stub private static final String ATTR_LAST_TRIM_MILLIS = "lastTrimMillis"; private static final String ATTR_LAST_BENCH_MILLIS = "lastBenchMillis"; + private static final String[] LEGACY_STORAGE_PERMISSIONS = { + Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.WRITE_EXTERNAL_STORAGE + }; + + private static final String[] ALL_STORAGE_PERMISSIONS = { + Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.WRITE_EXTERNAL_STORAGE, + Manifest.permission.READ_MEDIA_AUDIO, + Manifest.permission.READ_MEDIA_VIDEO, + Manifest.permission.READ_MEDIA_IMAGES + }; + private final AtomicFile mSettingsFile; /** @@ -594,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) { @@ -607,6 +625,10 @@ class StorageManagerService extends IStorageManager.Stub handleSystemReady(); break; } + case H_BOOT_COMPLETED: { + handleBootCompleted(); + break; + } case H_DAEMON_CONNECTED: { handleDaemonConnected(); break; @@ -695,7 +717,7 @@ class StorageManagerService extends IStorageManager.Stub break; } case H_RESET: { - resetIfReadyAndConnected(); + resetIfBootedAndConnected(); break; } case H_RUN_IDLE_MAINT: { @@ -768,9 +790,6 @@ class StorageManagerService extends IStorageManager.Stub } private void handleSystemReady() { - initIfReadyAndConnected(); - resetIfReadyAndConnected(); - // Start scheduling nominally-daily fstrim operations MountServiceIdler.scheduleIdlePass(mContext); @@ -916,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 @@ -942,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); @@ -1104,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. @@ -1674,16 +1693,18 @@ class StorageManagerService extends IStorageManager.Stub synchronized (mLock) { final boolean thisIsolatedStorage = StorageManager.hasIsolatedStorage(); - if (mLastIsolatedStorage == thisIsolatedStorage) { - // Nothing changed since last boot; keep rolling forward - return; - } else if (thisIsolatedStorage) { - // This boot enables isolated storage; apply legacy behavior - applyLegacyStorage(); + if (mLastIsolatedStorage != thisIsolatedStorage) { + if (thisIsolatedStorage) { + // This boot enables isolated storage; apply legacy behavior + applyLegacyStorage(); + } + + // Always remember the new state we just booted with + writeSettingsLocked(); } - // Always remember the new state we just booted with - writeSettingsLocked(); + // Execute special logic to recover certain devices + recoverFrom128872367(); } } @@ -1691,23 +1712,27 @@ class StorageManagerService extends IStorageManager.Stub * If we're enabling isolated storage, we need to remember which existing * apps have already been using shared storage, and grant them legacy access * to keep them running smoothly. + * + * @see com.android.server.pm.permission.PermissionManagerService + * #applyLegacyStoragePermissionModel */ private void applyLegacyStorage() { final AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class); final UserManagerInternal um = LocalServices.getService(UserManagerInternal.class); for (int userId : um.getUserIds()) { + final UserHandle user = UserHandle.of(userId); final PackageManager pm; try { - pm = mContext.createPackageContextAsUser(mContext.getPackageName(), - 0, UserHandle.of(userId)).getPackageManager(); + pm = mContext.createPackageContextAsUser(mContext.getPackageName(), 0, + user).getPackageManager(); } catch (PackageManager.NameNotFoundException e) { throw new RuntimeException(e); } - final List<PackageInfo> pkgs = pm.getPackagesHoldingPermissions(new String[] { - android.Manifest.permission.READ_EXTERNAL_STORAGE, - android.Manifest.permission.WRITE_EXTERNAL_STORAGE - }, MATCH_UNINSTALLED_PACKAGES | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE); + final List<PackageInfo> pkgs = pm.getPackagesHoldingPermissions( + LEGACY_STORAGE_PERMISSIONS, + MATCH_UNINSTALLED_PACKAGES | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE + | GET_PERMISSIONS); for (PackageInfo pkg : pkgs) { final int uid = pkg.applicationInfo.uid; final String packageName = pkg.applicationInfo.packageName; @@ -1720,8 +1745,28 @@ class StorageManagerService extends IStorageManager.Stub Log.d(TAG, "Found " + uid + " " + packageName + " with granted storage access, last accessed " + lastAccess); if (lastAccess > 0) { - appOps.setMode(AppOpsManager.OP_LEGACY_STORAGE, - uid, packageName, AppOpsManager.MODE_ALLOWED); + appOps.setUidMode(AppOpsManager.OP_LEGACY_STORAGE, uid, + AppOpsManager.MODE_ALLOWED); + + // Grandfather pre-Q app by granting all permissions and fixing them. The user + // needs to uninstall the app to revoke the permissions. + // TODO: Deal with shard Uids + if (pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.Q) { + for (String perm : ALL_STORAGE_PERMISSIONS) { + if (ArrayUtils.contains(pkg.requestedPermissions, perm)) { + pm.grantRuntimePermission(packageName, perm, user); + + int flags = FLAG_PERMISSION_SYSTEM_FIXED; + if (!ArrayUtils.contains(LEGACY_STORAGE_PERMISSIONS, perm)) { + flags |= FLAG_PERMISSION_HIDDEN; + } + + pm.updatePermissionFlags(perm, packageName, + FLAG_PERMISSION_SYSTEM_FIXED | FLAG_PERMISSION_HIDDEN, + flags, user); + } + } + } } } } @@ -1740,6 +1785,69 @@ class StorageManagerService extends IStorageManager.Stub return maxTime; } + /** + * In b/128872367 we lost all app-ops on devices in the wild. This logic + * attempts to detect and recover from this by granting + * {@link AppOpsManager#OP_LEGACY_STORAGE} to any apps installed before + * isolated storage was enabled. + */ + private void recoverFrom128872367() { + // We're interested in packages that were installed or updated between + // 1/1/2014 and 12/17/2018 + final long START_TIMESTAMP = 1388534400000L; + final long END_TIMESTAMP = 1545004800000L; + + final PackageManager pm = mContext.getPackageManager(); + final AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class); + final UserManagerInternal um = LocalServices.getService(UserManagerInternal.class); + + boolean activeDuringWindow = false; + List<PackageInfo> pendingHolders = new ArrayList<>(); + + for (int userId : um.getUserIds()) { + final List<PackageInfo> pkgs = pm.getInstalledPackagesAsUser(MATCH_UNINSTALLED_PACKAGES + | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE, userId); + for (PackageInfo pkg : pkgs) { + // Determine if any apps on this device had been installed or + // updated during the period where the feature was disabled + activeDuringWindow |= (pkg.firstInstallTime > START_TIMESTAMP + && pkg.firstInstallTime < END_TIMESTAMP); + activeDuringWindow |= (pkg.lastUpdateTime > START_TIMESTAMP + && pkg.lastUpdateTime < END_TIMESTAMP); + + // This app should hold legacy op if they were installed before + // the cutoff; we only check the end boundary here so that + // include system apps, which are always installed on 1/1/2009. + final boolean shouldHold = (pkg.firstInstallTime < END_TIMESTAMP); + final boolean doesHold = (appOps.checkOpNoThrow(OP_LEGACY_STORAGE, + pkg.applicationInfo.uid, + pkg.applicationInfo.packageName) == MODE_ALLOWED); + + if (doesHold) { + Slog.d(TAG, "Found " + pkg + " holding legacy op; skipping recovery"); + return; + } else if (shouldHold) { + Slog.d(TAG, "Found " + pkg + " that should hold legacy op"); + pendingHolders.add(pkg); + } + } + } + + if (!activeDuringWindow) { + Slog.d(TAG, "No packages were active during the time window; skipping grants"); + return; + } + + // If we made it this far, nobody actually holds the legacy op, which + // means we probably lost the database, and we should grant the op to + // all the apps we identified. + for (PackageInfo pkg : pendingHolders) { + appOps.setMode(AppOpsManager.OP_LEGACY_STORAGE, + pkg.applicationInfo.uid, + pkg.applicationInfo.packageName, AppOpsManager.MODE_ALLOWED); + } + } + private void systemReady() { LocalServices.getService(ActivityTaskManagerInternal.class) .registerScreenObserver(this); @@ -1750,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() { 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/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/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java index 9c26526920a0..10b67c1047cf 100644 --- a/services/core/java/com/android/server/appop/AppOpsService.java +++ b/services/core/java/com/android/server/appop/AppOpsService.java @@ -1132,7 +1132,7 @@ public class AppOpsService extends IAppOpsService.Stub { .build(); Preconditions.checkNotNull(callback, "callback cannot be null"); - mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS, + mContext.enforcePermission(Manifest.permission.MANAGE_APPOPS, Binder.getCallingPid(), Binder.getCallingUid(), "getHistoricalOps"); final String[] opNamesArray = (opNames != null) @@ -1144,6 +1144,14 @@ public class AppOpsService extends IAppOpsService.Stub { } @Override + public void reloadNonHistoricalState() { + mContext.enforcePermission(Manifest.permission.MANAGE_APPOPS, + Binder.getCallingPid(), Binder.getCallingUid(), "reloadNonHistoricalState"); + writeState(); + readState(); + } + + @Override public List<AppOpsManager.PackageOps> getUidOps(int uid, int[] ops) { mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS, Binder.getCallingPid(), Binder.getCallingUid(), null); @@ -2998,6 +3006,7 @@ public class AppOpsService extends IAppOpsService.Stub { final LongSparseArray keys = op.collectKeys(); if (keys == null || keys.size() <= 0) { + out.endTag(null, "op"); continue; } 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/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java index 14b73012d126..d5883bb3befb 100644 --- a/services/core/java/com/android/server/job/JobSchedulerService.java +++ b/services/core/java/com/android/server/job/JobSchedulerService.java @@ -19,6 +19,7 @@ package com.android.server.job; import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED; import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER; +import android.annotation.NonNull; import android.annotation.UserIdInt; import android.app.Activity; import android.app.ActivityManager; @@ -2496,8 +2497,13 @@ public class JobSchedulerService extends com.android.server.SystemService // The expensive check: validate that the defined package+service is // still present & viable. + return isComponentUsable(job); + } + + private boolean isComponentUsable(@NonNull JobStatus job) { final ServiceInfo service; try { + // TODO: cache result until we're notified that something in the package changed. service = AppGlobals.getPackageManager().getServiceInfo( job.getServiceComponent(), PackageManager.MATCH_DEBUG_TRIAGED_MISSING, job.getUserId()); @@ -2507,7 +2513,7 @@ public class JobSchedulerService extends com.android.server.SystemService if (service == null) { if (DEBUG) { - Slog.v(TAG, "isReadyToBeExecutedLocked: " + job.toShortString() + Slog.v(TAG, "isComponentUsable: " + job.toShortString() + " component not present"); } return false; @@ -2515,10 +2521,8 @@ public class JobSchedulerService extends com.android.server.SystemService // Everything else checked out so far, so this is the final yes/no check final boolean appIsBad = mActivityManagerInternal.isAppBad(service.applicationInfo); - if (DEBUG) { - if (appIsBad) { - Slog.i(TAG, "App is bad for " + job.toShortString() + " so not runnable"); - } + if (DEBUG && appIsBad) { + Slog.i(TAG, "App is bad for " + job.toShortString() + " so not runnable"); } return !appIsBad; } @@ -2552,30 +2556,18 @@ public class JobSchedulerService extends com.android.server.SystemService return false; } + if (isJobThermalConstrainedLocked(job)) { + return false; + } + // Job pending/active doesn't affect the readiness of a job. - // Skipping the hearbeat check as this will only come into play when using the rolling + // Skipping the heartbeat check as this will only come into play when using the rolling // window quota management system. - // The expensive check last: validate that the defined package+service is + // The expensive check: validate that the defined package+service is // still present & viable. - final boolean componentPresent; - try { - // TODO: cache result until we're notified that something in the package changed. - componentPresent = (AppGlobals.getPackageManager().getServiceInfo( - job.getServiceComponent(), PackageManager.MATCH_DEBUG_TRIAGED_MISSING, - job.getUserId()) != null); - } catch (RemoteException e) { - throw e.rethrowAsRuntimeException(); - } - - if (DEBUG) { - Slog.v(TAG, "areComponentsInPlaceLocked: " + job.toShortString() - + " componentPresent=" + componentPresent); - } - - // Everything else checked out so far, so this is the final yes/no check - return componentPresent; + return isComponentUsable(job); } /** diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java index 293813add594..0c5fb7998c78 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,7 +323,7 @@ public class LockSettingsService extends ILockSettings.Stub { } Arrays.fill(newPasswordChars, '\u0000'); final int quality = DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC; - setLockCredentialInternal(newPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, + setLockCredentialInternal(newPassword, CREDENTIAL_TYPE_PASSWORD, managedUserPassword, quality, managedUserId); // 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 @@ -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,13 +1300,13 @@ 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); } 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, + setLockCredentialInternal(null, CREDENTIAL_TYPE_NONE, null, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, managedUserId); } mStorage.removeChildProfileLock(managedUserId); @@ -1345,7 +1346,7 @@ public class LockSettingsService extends ILockSettings.Stub { notifySeparateProfileChallengeChanged(userId); } - private void setLockCredentialInternal(byte[] credential, int credentialType, + private void setLockCredentialInternal(byte[] credential, @CredentialType int credentialType, byte[] savedCredential, int requestedQuality, int userId) throws RemoteException { // Normalize savedCredential and credential such that empty string is always represented // as null. @@ -1363,7 +1364,7 @@ public class LockSettingsService extends ILockSettings.Stub { } } - 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 +1374,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; } @@ -1431,8 +1432,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 +1688,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; @@ -1736,7 +1736,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 +1773,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 +1793,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); 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 +1823,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,7 +1835,7 @@ 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 */; @@ -1871,18 +1871,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 +1931,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 +1942,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 +2388,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 +2440,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 +2487,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 +2531,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()) { @@ -2571,8 +2568,7 @@ public class LockSettingsService extends ILockSettings.Stub { // If existing credential is provided, then it must match. if (savedCredential != null && auth == null) { throw new RemoteException("Failed to enroll " + - (credentialType == LockPatternUtils.CREDENTIAL_TYPE_PASSWORD ? "password" - : "pattern")); + (credentialType == CREDENTIAL_TYPE_PASSWORD ? "password" : "pattern")); } boolean untrustedReset = false; @@ -2660,7 +2656,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/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/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java index 897b885c5a3c..e36ac23d6473 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -17,14 +17,20 @@ package com.android.server.pm.permission; import static android.Manifest.permission.READ_EXTERNAL_STORAGE; +import static android.Manifest.permission.READ_MEDIA_AUDIO; +import static android.Manifest.permission.READ_MEDIA_IMAGES; +import static android.Manifest.permission.READ_MEDIA_VIDEO; import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE; import static android.app.AppOpsManager.MODE_ALLOWED; import static android.app.AppOpsManager.MODE_ERRORED; import static android.app.AppOpsManager.MODE_FOREGROUND; +import static android.app.AppOpsManager.MODE_IGNORED; +import static android.app.AppOpsManager.OP_LEGACY_STORAGE; import static android.app.AppOpsManager.OP_NONE; import static android.app.AppOpsManager.permissionToOp; import static android.app.AppOpsManager.permissionToOpCode; import static android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT; +import static android.content.pm.PackageManager.FLAG_PERMISSION_HIDDEN; import static android.content.pm.PackageManager.FLAG_PERMISSION_POLICY_FIXED; import static android.content.pm.PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED; import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE; @@ -1149,6 +1155,8 @@ public class PermissionManagerService { updatedUserIds); updatedUserIds = setInitialGrantForNewImplicitPermissionsLocked(origPermissions, permissionsState, pkg, updatedUserIds); + updatedUserIds = applyLegacyStoragePermissionModel(origPermissions, permissionsState, + pkg, updatedUserIds); setAppOpsLocked(permissionsState, pkg); } @@ -1468,6 +1476,179 @@ public class PermissionManagerService { } /** + * Pre-Q apps use READ/WRITE_EXTERNAL_STORAGE, post-Q apps use READ_MEDIA_AUDIO/VIDEO/IMAGES. + * + * <p>There is the special case of the grandfathered post-Q app that has all legacy and modern + * permissions system-fixed granted. The only way to remove these permissions is to uninstall + * the app. + * + * @param origPs The permission state of the package before the update + * @param ps The permissions state of the package + * @param pkg The package + * @param updatedUserIds The userIds we have already been updated before + * + * @return The userIds that have been updated + * + * @see com.android.server.StorageManagerService#applyLegacyStorage() + */ + private @NonNull int[] applyLegacyStoragePermissionModel(@NonNull PermissionsState origPs, + @NonNull PermissionsState ps, @NonNull PackageParser.Package pkg, + @NonNull int[] updatedUserIds) { + AppOpsManagerInternal appOpsManager = LocalServices.getService(AppOpsManagerInternal.class); + int[] users = UserManagerService.getInstance().getUserIds(); + + boolean isQApp = pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.Q; + boolean isPreMApp = pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M; + int appId = getAppId(pkg.applicationInfo.uid); + + int numRequestedPerms = pkg.requestedPermissions.size(); + for (int i = 0; i < numRequestedPerms; i++) { + String perm = pkg.requestedPermissions.get(i); + + boolean isLegacyStoragePermission = false; + boolean isModernStoragePermission = false; + switch (perm) { + case READ_EXTERNAL_STORAGE: + case WRITE_EXTERNAL_STORAGE: + isLegacyStoragePermission = true; + break; + case READ_MEDIA_AUDIO: + case READ_MEDIA_VIDEO: + case READ_MEDIA_IMAGES: + isModernStoragePermission = true; + break; + default: + // 'perm' is not a storage permission, skip it + continue; + } + + BasePermission bp = mSettings.getPermissionLocked(perm); + + for (int userId : users) { + boolean useLegacyStoragePermissionModel; + if (isQApp) { + useLegacyStoragePermissionModel = appOpsManager.checkOperationUnchecked( + OP_LEGACY_STORAGE, getUid(userId, appId), pkg.packageName) + == MODE_ALLOWED; + } else { + useLegacyStoragePermissionModel = true; + } + + int origCombinedLegacyFlags = + origPs.getPermissionFlags(READ_EXTERNAL_STORAGE, userId) + | origPs.getPermissionFlags(WRITE_EXTERNAL_STORAGE, userId); + + int origCombinedModernFlags = origPs.getPermissionFlags(READ_MEDIA_AUDIO, userId) + | origPs.getPermissionFlags(READ_MEDIA_VIDEO, userId) + | origPs.getPermissionFlags(READ_MEDIA_IMAGES, userId); + + boolean oldPermAreLegacyStorageModel = + (origCombinedLegacyFlags & FLAG_PERMISSION_HIDDEN) == 0; + boolean oldPermAreModernStorageModel = + (origCombinedModernFlags & FLAG_PERMISSION_HIDDEN) == 0; + + if (oldPermAreLegacyStorageModel && oldPermAreModernStorageModel) { + // This only happens after an platform upgrade from before Q + oldPermAreModernStorageModel = false; + } + + boolean shouldBeRestricted; + boolean shouldBeFixed; + boolean shouldBeGranted = false; + boolean shouldBeRevoked = false; + int userFlags = -1; + if (useLegacyStoragePermissionModel) { + shouldBeRestricted = isModernStoragePermission; + shouldBeFixed = isQApp || isModernStoragePermission; + + if (shouldBeFixed) { + userFlags = 0; + shouldBeGranted = true; + shouldBeRevoked = false; + } else if (oldPermAreModernStorageModel) { + // Inherit grant state on permission model change + userFlags = origCombinedModernFlags; + + shouldBeGranted = origPs.hasRuntimePermission(READ_MEDIA_AUDIO, userId) + || origPs.hasRuntimePermission(READ_MEDIA_VIDEO, userId) + || origPs.hasRuntimePermission(READ_MEDIA_IMAGES, userId); + + shouldBeRevoked = !shouldBeGranted; + } + } else { + shouldBeRestricted = isLegacyStoragePermission; + shouldBeFixed = isLegacyStoragePermission; + + if (shouldBeFixed) { + userFlags = 0; + shouldBeGranted = true; + shouldBeRevoked = false; + } else if (oldPermAreLegacyStorageModel) { + // Inherit grant state on permission model change + userFlags = origCombinedLegacyFlags; + + shouldBeGranted = origPs.hasRuntimePermission(READ_EXTERNAL_STORAGE, userId) + || origPs.hasRuntimePermission(WRITE_EXTERNAL_STORAGE, userId); + + if ((origCombinedLegacyFlags & FLAG_PERMISSION_REVOKE_ON_UPGRADE) != 0 + && !isPreMApp) { + shouldBeGranted = false; + } + + shouldBeRevoked = !shouldBeGranted; + } + } + + // Granted permissions can never be user fixed + if (shouldBeGranted & userFlags != -1) { + userFlags &= ~FLAG_PERMISSION_USER_FIXED; + } + + boolean changed = false; + synchronized (mLock) { + if (shouldBeGranted) { + if (isPreMApp) { + setAppOpMode(perm, pkg, userId, MODE_ALLOWED); + } else if (!ps.hasRuntimePermission(perm, userId)) { + ps.grantRuntimePermission(bp, userId); + changed = true; + } + } + + if (shouldBeRevoked) { + if (isPreMApp) { + setAppOpMode(perm, pkg, userId, MODE_IGNORED); + } else if (ps.hasRuntimePermission(perm, userId)) { + ps.revokeRuntimePermission(bp, userId); + changed = true; + } + } + + if (shouldBeFixed) { + changed |= ps.updatePermissionFlags(mSettings.getPermissionLocked(perm), + userId, FLAG_PERMISSION_SYSTEM_FIXED, FLAG_PERMISSION_SYSTEM_FIXED); + } + + if (userFlags != -1) { + changed |= ps.updatePermissionFlags(mSettings.getPermissionLocked(perm), + userId, USER_PERMISSION_FLAGS, userFlags); + } + + changed |= ps.updatePermissionFlags(mSettings.getPermissionLocked(perm), userId, + FLAG_PERMISSION_HIDDEN, + shouldBeRestricted ? FLAG_PERMISSION_HIDDEN : 0); + } + + if (changed) { + updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId); + } + } + } + + return updatedUserIds; + } + + /** * Fix app-op modes for runtime permissions. * * @param permsState The state of the permissions of the package diff --git a/services/core/java/com/android/server/pm/permission/TEST_MAPPING b/services/core/java/com/android/server/pm/permission/TEST_MAPPING index 2280d3fd9134..c610ed09a5a2 100644 --- a/services/core/java/com/android/server/pm/permission/TEST_MAPPING +++ b/services/core/java/com/android/server/pm/permission/TEST_MAPPING @@ -19,6 +19,9 @@ }, { "include-filter": "android.permission.cts.PermissionFlagsTest" + }, + { + "include-filter": "android.permission.cts.DualStoragePermissionModelTest" } ] }, diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index e7c9a0819896..5a32aa0539ec 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 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/Notifier.java b/services/core/java/com/android/server/power/Notifier.java index 1a82858147f4..b81d969a1bb2 100644 --- a/services/core/java/com/android/server/power/Notifier.java +++ b/services/core/java/com/android/server/power/Notifier.java @@ -486,6 +486,8 @@ public class Notifier { log.setType(MetricsEvent.TYPE_OPEN); log.setSubtype(why); log.setLatency(interactiveChangeLatency); + log.addTaggedData( + MetricsEvent.FIELD_SCREEN_WAKE_REASON, mInteractiveChangeReason); MetricsLogger.action(log); EventLogTags.writePowerScreenState(1, 0, 0, 0, interactiveChangeLatency); mPolicy.finishedWakingUp(why); @@ -513,6 +515,8 @@ public class Notifier { log.setType(MetricsEvent.TYPE_CLOSE); log.setSubtype(why); log.setLatency(interactiveChangeLatency); + log.addTaggedData( + MetricsEvent.FIELD_SCREEN_SLEEP_REASON, mInteractiveChangeReason); MetricsLogger.action(log); EventLogTags.writePowerScreenState(0, why, 0, 0, interactiveChangeLatency); mPolicy.finishedGoingToSleep(why); 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/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index 118eb5bea602..c91ee8e2f286 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -6493,8 +6493,10 @@ 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); + synchronized (mGlobalLock) { + return mRootActivityContainer.startHomeOnDisplay(userId, reason, displayId, + 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/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java index f63269571fc0..75e34fb0d453 100644 --- a/services/core/java/com/android/server/wm/AppTransitionController.java +++ b/services/core/java/com/android/server/wm/AppTransitionController.java @@ -19,6 +19,7 @@ package com.android.server.wm; import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; import static android.view.WindowManager.TRANSIT_ACTIVITY_CLOSE; import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN; +import static android.view.WindowManager.TRANSIT_ACTIVITY_RELAUNCH; import static android.view.WindowManager.TRANSIT_CRASHING_ACTIVITY_CLOSE; import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS; import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION; @@ -638,6 +639,39 @@ public class AppTransitionController { return transit; } + /** + * Identifies whether the current transition occurs within a single task or not. This is used + * to determine whether animations should be clipped to the task bounds instead of stack bounds. + */ + @VisibleForTesting + boolean isTransitWithinTask(int transit, Task task) { + if (task == null + || !mDisplayContent.mChangingApps.isEmpty()) { + // if there is no task, then we can't constrain to the task. + // if anything is changing, it can animate outside its task. + return false; + } + if (!(transit == TRANSIT_ACTIVITY_OPEN + || transit == TRANSIT_ACTIVITY_CLOSE + || transit == TRANSIT_ACTIVITY_RELAUNCH)) { + // only activity-level transitions will be within-task. + return false; + } + // check that all components are in the task. + for (AppWindowToken activity : mDisplayContent.mOpeningApps) { + Task activityTask = activity.getTask(); + if (activityTask != task) { + return false; + } + } + for (AppWindowToken activity : mDisplayContent.mClosingApps) { + if (activity.getTask() != task) { + return false; + } + } + return true; + } + private boolean canBeWallpaperTarget(ArraySet<AppWindowToken> apps) { for (int i = apps.size() - 1; i >= 0; i--) { if (apps.valueAt(i).windowsCanBeWallpaperTarget()) { diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java index ea3a7d5ca3b2..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. @@ -2705,16 +2711,21 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree // If the animation needs to be cropped then an animation bounds layer is created as a child // of the pinned stack or animation layer. The leash is then reparented to this new layer. if (mNeedsAnimationBoundsLayer) { - final TaskStack stack = getStack(); - if (stack == null) { - return; + mTmpRect.setEmpty(); + final Task task = getTask(); + if (getDisplayContent().mAppTransitionController.isTransitWithinTask( + getTransit(), task)) { + task.getBounds(mTmpRect); + } else { + final TaskStack stack = getStack(); + if (stack == null) { + return; + } + // Set clip rect to stack bounds. + stack.getBounds(mTmpRect); } mAnimationBoundsLayer = createAnimationBoundsLayer(t); - // Set clip rect to stack bounds. - mTmpRect.setEmpty(); - stack.getBounds(mTmpRect); - // Crop to stack bounds. t.setWindowCrop(mAnimationBoundsLayer, mTmpRect); 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/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..26df832bf316 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); } @@ -245,6 +269,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 +314,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 +458,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 +482,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 +565,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/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/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/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index f6de82d8e237..2d014718a47b 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 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/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/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/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/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/AppTransitionControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java index 81133d1052ec..9bd993070939 100644 --- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java @@ -17,12 +17,16 @@ package com.android.server.wm; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; +import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; +import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN; import static android.view.WindowManager.TRANSIT_TASK_CHANGE_WINDOWING_MODE; import static android.view.WindowManager.TRANSIT_TASK_CLOSE; import static android.view.WindowManager.TRANSIT_TASK_OPEN; import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertTrue; import android.platform.test.annotations.Presubmit; import android.view.WindowManager; @@ -95,4 +99,24 @@ public class AppTransitionControllerTest extends WindowTestsBase { TRANSIT_TASK_CHANGE_WINDOWING_MODE)); } } + + @Test + public void testTransitWithinTask() { + synchronized (mWm.mGlobalLock) { + final AppWindowToken opening = createAppWindowToken(mDisplayContent, + WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD); + opening.setFillsParent(false); + final AppWindowToken closing = createAppWindowToken(mDisplayContent, + WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD); + closing.setFillsParent(false); + Task task = opening.getTask(); + mDisplayContent.mOpeningApps.add(opening); + mDisplayContent.mClosingApps.add(closing); + assertFalse(mAppTransitionController.isTransitWithinTask(TRANSIT_ACTIVITY_OPEN, task)); + closing.getTask().removeChild(closing); + task.addChild(closing, 0); + assertTrue(mAppTransitionController.isTransitWithinTask(TRANSIT_ACTIVITY_OPEN, task)); + assertFalse(mAppTransitionController.isTransitWithinTask(TRANSIT_TASK_OPEN, task)); + } + } } 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/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/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/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..df31f50d28a4 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(); } diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 282b1ff2f801..d296b2fe4878 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -5296,7 +5296,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 +5372,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 +10192,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 +10626,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/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/euicc/EuiccManager.java b/telephony/java/android/telephony/euicc/EuiccManager.java index 875bd782d2cb..cde10ea7cd09 100644 --- a/telephony/java/android/telephony/euicc/EuiccManager.java +++ b/telephony/java/android/telephony/euicc/EuiccManager.java @@ -118,9 +118,9 @@ public class EuiccManager { /** * Intent action sent by system apps (such as the Settings app) to the Telephony framework to * enable or disable a subscription. Must be accompanied with {@link #EXTRA_SUBSCRIPTION_ID} and - * {@link #EXTRA_ENABLE_SUBSCRIPTION}. + * {@link #EXTRA_ENABLE_SUBSCRIPTION}, and optionally {@link #EXTRA_FROM_SUBSCRIPTION_ID}. * - * Requires the caller to be a privileged process with the + * <p>Requires the caller to be a privileged process with the * {@link android.permission#CALL_PRIVILEGED} permission for the intent to reach the Telephony * stack. * @@ -143,7 +143,7 @@ public class EuiccManager { * Intent action sent by system apps (such as the Settings app) to the Telephony framework to * delete a subscription. Must be accompanied with {@link #EXTRA_SUBSCRIPTION_ID}. * - * Requires the caller to be a privileged process with the + * <p>Requires the caller to be a privileged process with the * {@link android.permission#CALL_PRIVILEGED} permission for the intent to reach the Telephony * stack. * @@ -167,7 +167,7 @@ public class EuiccManager { * rename a subscription. Must be accompanied with {@link #EXTRA_SUBSCRIPTION_ID} and * {@link #EXTRA_SUBSCRIPTION_NICKNAME}. * - * Requires the caller to be a privileged process with the + * <p>Requires the caller to be a privileged process with the * {@link android.permission#CALL_PRIVILEGED} permission for the intent to reach the Telephony * stack. * @@ -318,6 +318,22 @@ public class EuiccManager { "android.telephony.euicc.extra.SUBSCRIPTION_NICKNAME"; /** + * Key for an extra set on {@link #ACTION_TOGGLE_SUBSCRIPTION_PRIVILEGED} providing the ID of + * the subscription we're toggling from. This extra is optional and is only used for UI + * purposes by the underlying eUICC service (i.e. the LPA app), such as displaying a dialog + * titled "Switch X with Y". If set, the provided subscription will be used as the "from" + * subscription in UI (the "X" in the dialog example). Otherwise, the currently active + * subscription that will be disabled is the "from" subscription. + * + * <p>Expected type of the extra data: int + * + * @hide + */ + @SystemApi + public static final String EXTRA_FROM_SUBSCRIPTION_ID = + "android.telephony.euicc.extra.FROM_SUBSCRIPTION_ID"; + + /** * Optional meta-data attribute for a carrier app providing an icon to use to represent the * carrier. If not provided, the app's launcher icon will be used as a fallback. */ diff --git a/telephony/java/android/telephony/ims/ImsException.java b/telephony/java/android/telephony/ims/ImsException.java index 02eddf67e25b..8c686f704967 100644 --- a/telephony/java/android/telephony/ims/ImsException.java +++ b/telephony/java/android/telephony/ims/ImsException.java @@ -31,7 +31,7 @@ import java.lang.annotation.RetentionPolicy; * @hide */ @SystemApi -public class ImsException extends Exception { +public final class ImsException extends Exception { /** * The operation has failed due to an unknown or unspecified error. diff --git a/telephony/java/android/telephony/ims/feature/ImsFeature.java b/telephony/java/android/telephony/ims/feature/ImsFeature.java index b55866b5c1c8..d2b41337e100 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 */ @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/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/aapt2/Android.bp b/tools/aapt2/Android.bp index 8bef221fe5ed..aca2be1da33d 100644 --- a/tools/aapt2/Android.bp +++ b/tools/aapt2/Android.bp @@ -198,3 +198,22 @@ cc_binary_host { static_libs: ["libaapt2"], defaults: ["aapt2_defaults"], } + +// ========================================================== +// Dist the protos +// ========================================================== +genrule { + name: "aapt2-protos", + tools: [":soong_zip"], + srcs: [ + "Configuration.proto", + "Resources.proto", + ], + out: ["aapt2-protos.zip"], + cmd: "mkdir $(genDir)/protos && " + + "cp $(in) $(genDir)/protos && " + + "$(location :soong_zip) -o $(out) -C $(genDir)/protos -D $(genDir)/protos", + dist: { + targets: ["sdk_repo"], + }, +} 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/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/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(); } /* |