diff options
296 files changed, 5642 insertions, 4065 deletions
diff --git a/Android.bp b/Android.bp index 05c7dbcba02e..035420f9ff50 100644 --- a/Android.bp +++ b/Android.bp @@ -384,6 +384,7 @@ java_defaults { "core/java/android/view/IRecentsAnimationRunner.aidl", "core/java/android/view/IRemoteAnimationFinishedCallback.aidl", "core/java/android/view/IRotationWatcher.aidl", + "core/java/android/view/ISystemGestureExclusionListener.aidl", "core/java/android/view/IWallpaperVisibilityListener.aidl", "core/java/android/view/IWindow.aidl", "core/java/android/view/IWindowFocusObserver.aidl", @@ -753,10 +754,6 @@ java_defaults { "android.hardware.radio-V1.2-java", "android.hardware.radio-V1.3-java", "android.hardware.radio-V1.4-java", - "android.hardware.radio.config-V1.0-java", - "android.hardware.radio.config-V1.1-java", - "android.hardware.radio.config-V1.2-java", - "android.hardware.radio.deprecated-V1.0-java", "android.hardware.thermal-V1.0-java-constants", "android.hardware.thermal-V1.0-java", "android.hardware.thermal-V1.1-java", @@ -771,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", ], @@ -1689,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 118eb4c7fb67..e7a8ae3b1cd5 100644 --- a/api/current.txt +++ b/api/current.txt @@ -11051,6 +11051,7 @@ package android.content.pm { method public void dump(android.util.Printer, String); method public static CharSequence getCategoryTitle(android.content.Context, int); method public boolean isProfileableByShell(); + method public boolean isResourceOverlay(); method public boolean isVirtualPreload(); method public CharSequence loadDescription(android.content.pm.PackageManager); field public static final int CATEGORY_AUDIO = 1; // 0x1 @@ -11676,7 +11677,6 @@ package android.content.pm { field public static final String FEATURE_FAKETOUCH_MULTITOUCH_DISTINCT = "android.hardware.faketouch.multitouch.distinct"; field public static final String FEATURE_FAKETOUCH_MULTITOUCH_JAZZHAND = "android.hardware.faketouch.multitouch.jazzhand"; field public static final String FEATURE_FINGERPRINT = "android.hardware.fingerprint"; - field public static final String FEATURE_FOLDABLE = "android.hardware.type.foldable"; field public static final String FEATURE_FREEFORM_WINDOW_MANAGEMENT = "android.software.freeform_window_management"; field public static final String FEATURE_GAMEPAD = "android.hardware.gamepad"; field public static final String FEATURE_HIFI_SENSORS = "android.hardware.sensor.hifi_sensors"; @@ -22810,6 +22810,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 +23401,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 { @@ -24425,9 +24427,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 +24624,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 { @@ -25083,6 +25083,7 @@ package android.media { field public static final String KEY_LANGUAGE = "language"; field public static final String KEY_LATENCY = "latency"; field public static final String KEY_LEVEL = "level"; + field public static final String KEY_MAX_BFRAMES = "max-bframes"; field public static final String KEY_MAX_FPS_TO_ENCODER = "max-fps-to-encoder"; field public static final String KEY_MAX_HEIGHT = "max-height"; field public static final String KEY_MAX_INPUT_SIZE = "max-input-size"; @@ -26142,10 +26143,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; } @@ -26473,6 +26475,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 +26516,7 @@ package android.media { } public final class TimedMetaData { + ctor public TimedMetaData(long, @NonNull byte[]); method public byte[] getMetaData(); method public long getTimestamp(); } @@ -30318,13 +30322,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 { @@ -35434,6 +35436,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 +42503,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 +42573,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; @@ -45196,7 +45199,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 +45279,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 @@ -45300,7 +45306,7 @@ package android.telephony { field public static final int PHONE_TYPE_GSM = 1; // 0x1 field public static final int PHONE_TYPE_NONE = 0; // 0x0 field public static final int PHONE_TYPE_SIP = 3; // 0x3 - field public static final int SET_OPPORTUNISTIC_SUB_INVALID_PARAMETER = 2; // 0x2 + field public static final int SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION = 2; // 0x2 field public static final int SET_OPPORTUNISTIC_SUB_SUCCESS = 0; // 0x0 field public static final int SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED = 1; // 0x1 field public static final int SIM_STATE_ABSENT = 1; // 0x1 @@ -50444,6 +50450,7 @@ package android.view { method protected float getLeftFadingEdgeStrength(); method protected int getLeftPaddingOffset(); method public final boolean getLocalVisibleRect(android.graphics.Rect); + method public void getLocationInSurface(@NonNull @Size(2) int[]); method public void getLocationInWindow(@Size(2) int[]); method public void getLocationOnScreen(@Size(2) int[]); method public android.graphics.Matrix getMatrix(); @@ -53501,7 +53508,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 f406879e6305..3e4ccb537235 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -186,6 +186,7 @@ package android { field public static final String SUBSTITUTE_NOTIFICATION_APP_NAME = "android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME"; field public static final String SUBSTITUTE_SHARE_TARGET_APP_NAME_AND_ICON = "android.permission.SUBSTITUTE_SHARE_TARGET_APP_NAME_AND_ICON"; field public static final String SUSPEND_APPS = "android.permission.SUSPEND_APPS"; + field public static final String TEST_MANAGE_ROLLBACKS = "android.permission.TEST_MANAGE_ROLLBACKS"; field public static final String TETHER_PRIVILEGED = "android.permission.TETHER_PRIVILEGED"; field public static final String TV_INPUT_HARDWARE = "android.permission.TV_INPUT_HARDWARE"; field public static final String TV_VIRTUAL_REMOTE_CONTROLLER = "android.permission.TV_VIRTUAL_REMOTE_CONTROLLER"; @@ -338,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"; @@ -545,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); @@ -742,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(); @@ -756,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 @@ -861,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(); @@ -1478,6 +1484,7 @@ package android.content.om { } public class OverlayManager { + method @Nullable public android.content.om.OverlayInfo getOverlayInfo(@NonNull String, @NonNull android.os.UserHandle); method public java.util.List<android.content.om.OverlayInfo> getOverlayInfosForTarget(@Nullable String, int); method public boolean setEnabled(@Nullable String, boolean, int); method public boolean setEnabledExclusiveInCategory(@Nullable String, int); @@ -1647,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 @@ -1717,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 { @@ -1836,9 +1844,9 @@ package android.content.rollback { } public final class RollbackManager { - method @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) public void commitRollback(int, @NonNull java.util.List<android.content.pm.VersionedPackage>, @NonNull android.content.IntentSender); - method @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) @NonNull public java.util.List<android.content.rollback.RollbackInfo> getAvailableRollbacks(); - method @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) @NonNull public java.util.List<android.content.rollback.RollbackInfo> getRecentlyCommittedRollbacks(); + method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, android.Manifest.permission.TEST_MANAGE_ROLLBACKS}) public void commitRollback(int, @NonNull java.util.List<android.content.pm.VersionedPackage>, @NonNull android.content.IntentSender); + method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, android.Manifest.permission.TEST_MANAGE_ROLLBACKS}) @NonNull public java.util.List<android.content.rollback.RollbackInfo> getAvailableRollbacks(); + method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, android.Manifest.permission.TEST_MANAGE_ROLLBACKS}) @NonNull public java.util.List<android.content.rollback.RollbackInfo> getRecentlyCommittedRollbacks(); field public static final String EXTRA_STATUS = "android.content.rollback.extra.STATUS"; field public static final String EXTRA_STATUS_MESSAGE = "android.content.rollback.extra.STATUS_MESSAGE"; field public static final int STATUS_FAILURE = 1; // 0x1 @@ -3066,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(); @@ -3373,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(); @@ -3557,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); @@ -3573,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 { @@ -4027,8 +4027,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 @@ -4235,18 +4235,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; } @@ -4300,28 +4300,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); } @@ -4332,78 +4332,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 { @@ -4474,12 +4474,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); } } @@ -5492,7 +5492,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; } @@ -5884,7 +5884,9 @@ package android.provider { field public static final String NAMESPACE_RUNTIME_NATIVE = "runtime_native"; field public static final String NAMESPACE_RUNTIME_NATIVE_BOOT = "runtime_native_boot"; 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"; } @@ -5912,18 +5914,6 @@ package android.provider { method @Nullable public String getString(@NonNull String, @Nullable String); } - public static interface DeviceConfig.Storage { - field public static final String ISOLATED_STORAGE_ENABLED = "isolated_storage_enabled"; - field public static final String NAMESPACE = "storage"; - } - - 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); @@ -6118,6 +6108,8 @@ package android.provider { field public static final String LOCATION_PERMISSIONS_UPGRADE_TO_Q_MODE = "location_permissions_upgrade_to_q_mode"; 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 @@ -6428,6 +6420,7 @@ package android.service.contentcapture { method public int getEventType(); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.service.contentcapture.ActivityEvent> CREATOR; + field public static final int TYPE_ACTIVITY_DESTROYED = 24; // 0x18 field public static final int TYPE_ACTIVITY_PAUSED = 2; // 0x2 field public static final int TYPE_ACTIVITY_RESUMED = 1; // 0x1 field public static final int TYPE_ACTIVITY_STOPPED = 23; // 0x17 @@ -6446,6 +6439,7 @@ package android.service.contentcapture { method public void onUserDataRemovalRequest(@NonNull android.view.contentcapture.UserDataRemovalRequest); method public final void setContentCaptureWhitelist(@Nullable java.util.Set<java.lang.String>, @Nullable java.util.Set<android.content.ComponentName>); field public static final String SERVICE_INTERFACE = "android.service.contentcapture.ContentCaptureService"; + field public static final String SERVICE_META_DATA = "android.content_capture"; } public final class SnapshotData implements android.os.Parcelable { @@ -6646,6 +6640,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); @@ -8067,7 +8062,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); @@ -8355,6 +8350,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"; } @@ -8574,7 +8570,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); diff --git a/api/system-removed.txt b/api/system-removed.txt index 18d0ec02f077..7e044698c72c 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 { diff --git a/api/test-current.txt b/api/test-current.txt index f3095284cee7..5e9b405a75a9 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -14,6 +14,7 @@ package android { field public static final String MANAGE_ROLLBACKS = "android.permission.MANAGE_ROLLBACKS"; field public static final String READ_CELL_BROADCASTS = "android.permission.READ_CELL_BROADCASTS"; field public static final String REMOVE_TASKS = "android.permission.REMOVE_TASKS"; + field public static final String TEST_MANAGE_ROLLBACKS = "android.permission.TEST_MANAGE_ROLLBACKS"; field public static final String WRITE_DEVICE_CONFIG = "android.permission.WRITE_DEVICE_CONFIG"; field public static final String WRITE_MEDIA_STORAGE = "android.permission.WRITE_MEDIA_STORAGE"; field public static final String WRITE_OBB = "android.permission.WRITE_OBB"; @@ -133,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); @@ -168,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"; @@ -415,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); } @@ -655,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 @@ -720,11 +727,11 @@ package android.content.rollback { } public final class RollbackManager { - method @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) public void commitRollback(int, @NonNull java.util.List<android.content.pm.VersionedPackage>, @NonNull android.content.IntentSender); - method @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) public void expireRollbackForPackage(@NonNull String); - method @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) @NonNull public java.util.List<android.content.rollback.RollbackInfo> getAvailableRollbacks(); - method @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) @NonNull public java.util.List<android.content.rollback.RollbackInfo> getRecentlyCommittedRollbacks(); - method @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) public void reloadPersistedData(); + method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, android.Manifest.permission.TEST_MANAGE_ROLLBACKS}) public void commitRollback(int, @NonNull java.util.List<android.content.pm.VersionedPackage>, @NonNull android.content.IntentSender); + method @RequiresPermission(android.Manifest.permission.TEST_MANAGE_ROLLBACKS) public void expireRollbackForPackage(@NonNull String); + method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, android.Manifest.permission.TEST_MANAGE_ROLLBACKS}) @NonNull public java.util.List<android.content.rollback.RollbackInfo> getAvailableRollbacks(); + method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, android.Manifest.permission.TEST_MANAGE_ROLLBACKS}) @NonNull public java.util.List<android.content.rollback.RollbackInfo> getRecentlyCommittedRollbacks(); + method @RequiresPermission(android.Manifest.permission.TEST_MANAGE_ROLLBACKS) public void reloadPersistedData(); field public static final String EXTRA_STATUS = "android.content.rollback.extra.STATUS"; field public static final String EXTRA_STATUS_MESSAGE = "android.content.rollback.extra.STATUS_MESSAGE"; field public static final String PROPERTY_ROLLBACK_LIFETIME_MILLIS = "rollback_lifetime_in_millis"; @@ -1071,6 +1078,14 @@ package android.media { method public android.media.BufferingParams.Builder setResumePlaybackMarkMs(int); } + 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; @@ -1175,8 +1190,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 @@ -1261,18 +1276,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; } @@ -1325,28 +1340,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); } @@ -1357,78 +1372,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 { @@ -1499,12 +1514,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); } } @@ -2393,6 +2408,7 @@ package android.service.contentcapture { method public int getEventType(); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.service.contentcapture.ActivityEvent> CREATOR; + field public static final int TYPE_ACTIVITY_DESTROYED = 24; // 0x18 field public static final int TYPE_ACTIVITY_PAUSED = 2; // 0x2 field public static final int TYPE_ACTIVITY_RESUMED = 1; // 0x1 field public static final int TYPE_ACTIVITY_STOPPED = 23; // 0x17 @@ -2411,6 +2427,7 @@ package android.service.contentcapture { method public void onUserDataRemovalRequest(@NonNull android.view.contentcapture.UserDataRemovalRequest); method public final void setContentCaptureWhitelist(@Nullable java.util.Set<java.lang.String>, @Nullable java.util.Set<android.content.ComponentName>); field public static final String SERVICE_INTERFACE = "android.service.contentcapture.ContentCaptureService"; + field public static final String SERVICE_META_DATA = "android.content_capture"; } public final class SnapshotData implements android.os.Parcelable { @@ -3169,10 +3186,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/Commands.h b/cmds/idmap2/idmap2/Commands.h index dcc69b30743d..718e361b38ab 100644 --- a/cmds/idmap2/idmap2/Commands.h +++ b/cmds/idmap2/idmap2/Commands.h @@ -20,10 +20,12 @@ #include <string> #include <vector> -bool Create(const std::vector<std::string>& args, std::ostream& out_error); -bool Dump(const std::vector<std::string>& args, std::ostream& out_error); -bool Lookup(const std::vector<std::string>& args, std::ostream& out_error); -bool Scan(const std::vector<std::string>& args, std::ostream& out_error); -bool Verify(const std::vector<std::string>& args, std::ostream& out_error); +#include "idmap2/Result.h" + +android::idmap2::Result<android::idmap2::Unit> Create(const std::vector<std::string>& args); +android::idmap2::Result<android::idmap2::Unit> Dump(const std::vector<std::string>& args); +android::idmap2::Result<android::idmap2::Unit> Lookup(const std::vector<std::string>& args); +android::idmap2::Result<android::idmap2::Unit> Scan(const std::vector<std::string>& args); +android::idmap2::Result<android::idmap2::Unit> Verify(const std::vector<std::string>& args); #endif // IDMAP2_IDMAP2_COMMANDS_H_ diff --git a/cmds/idmap2/idmap2/Create.cpp b/cmds/idmap2/idmap2/Create.cpp index c416fa123b73..fdbb21044176 100644 --- a/cmds/idmap2/idmap2/Create.cpp +++ b/cmds/idmap2/idmap2/Create.cpp @@ -33,14 +33,17 @@ using android::ApkAssets; using android::idmap2::BinaryStreamVisitor; using android::idmap2::CommandLineOptions; +using android::idmap2::Error; using android::idmap2::Idmap; using android::idmap2::PoliciesToBitmask; using android::idmap2::PolicyBitmask; using android::idmap2::PolicyFlags; +using android::idmap2::Result; +using android::idmap2::Unit; using android::idmap2::utils::kIdmapFilePermissionMask; using android::idmap2::utils::UidHasWriteAccessToPath; -bool Create(const std::vector<std::string>& args, std::ostream& out_error) { +Result<Unit> Create(const std::vector<std::string>& args) { SYSTRACE << "Create " << args; std::string target_apk_path; std::string overlay_apk_path; @@ -63,15 +66,14 @@ bool Create(const std::vector<std::string>& args, std::ostream& out_error) { &policies) .OptionalFlag("--ignore-overlayable", "disables overlayable and policy checks", &ignore_overlayable); - if (!opts.Parse(args, out_error)) { - return false; + const auto opts_ok = opts.Parse(args); + if (!opts_ok) { + return opts_ok.GetError(); } const uid_t uid = getuid(); if (!UidHasWriteAccessToPath(uid, idmap_path)) { - out_error << "error: uid " << uid << " does not have write access to " << idmap_path - << std::endl; - return false; + return Error("uid %d does not have write access to %s", uid, idmap_path.c_str()); } PolicyBitmask fulfilled_policies = 0; @@ -79,8 +81,7 @@ bool Create(const std::vector<std::string>& args, std::ostream& out_error) { if (conv_result) { fulfilled_policies |= *conv_result; } else { - out_error << "error: " << conv_result.GetErrorMessage() << std::endl; - return false; + return conv_result.GetError(); } if (fulfilled_policies == 0) { @@ -89,36 +90,33 @@ bool Create(const std::vector<std::string>& args, std::ostream& out_error) { const std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path); if (!target_apk) { - out_error << "error: failed to load apk " << target_apk_path << std::endl; - return false; + return Error("failed to load apk %s", target_apk_path.c_str()); } const std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path); if (!overlay_apk) { - out_error << "error: failed to load apk " << overlay_apk_path << std::endl; - return false; + 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, out_error); + fulfilled_policies, !ignore_overlayable, stream); if (!idmap) { - return false; + return Error("failed to create idmap: %s", stream.str().c_str()); } umask(kIdmapFilePermissionMask); std::ofstream fout(idmap_path); if (fout.fail()) { - out_error << "failed to open idmap path " << idmap_path << std::endl; - return false; + return Error("failed to open idmap path %s", idmap_path.c_str()); } BinaryStreamVisitor visitor(fout); idmap->accept(&visitor); fout.close(); if (fout.fail()) { - out_error << "failed to write to idmap path " << idmap_path << std::endl; - return false; + return Error("failed to write to idmap path %s", idmap_path.c_str()); } - return true; + return Unit{}; } diff --git a/cmds/idmap2/idmap2/Dump.cpp b/cmds/idmap2/idmap2/Dump.cpp index 3947703fe8da..fd5822251188 100644 --- a/cmds/idmap2/idmap2/Dump.cpp +++ b/cmds/idmap2/idmap2/Dump.cpp @@ -17,6 +17,7 @@ #include <fstream> #include <iostream> #include <memory> +#include <sstream> #include <string> #include <vector> @@ -24,14 +25,18 @@ #include "idmap2/Idmap.h" #include "idmap2/PrettyPrintVisitor.h" #include "idmap2/RawPrintVisitor.h" +#include "idmap2/Result.h" #include "idmap2/SysTrace.h" using android::idmap2::CommandLineOptions; +using android::idmap2::Error; using android::idmap2::Idmap; using android::idmap2::PrettyPrintVisitor; using android::idmap2::RawPrintVisitor; +using android::idmap2::Result; +using android::idmap2::Unit; -bool Dump(const std::vector<std::string>& args, std::ostream& out_error) { +Result<Unit> Dump(const std::vector<std::string>& args) { SYSTRACE << "Dump " << args; std::string idmap_path; bool verbose; @@ -40,14 +45,16 @@ bool Dump(const std::vector<std::string>& args, std::ostream& out_error) { CommandLineOptions("idmap2 dump") .MandatoryOption("--idmap-path", "input: path to idmap file to pretty-print", &idmap_path) .OptionalFlag("--verbose", "annotate every byte of the idmap", &verbose); - if (!opts.Parse(args, out_error)) { - return false; + const auto opts_ok = opts.Parse(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, out_error); + const std::unique_ptr<const Idmap> idmap = Idmap::FromBinaryStream(fin, stream); fin.close(); if (!idmap) { - return false; + return Error("failed to load idmap: %s", stream.str().c_str()); } if (verbose) { @@ -58,5 +65,5 @@ bool Dump(const std::vector<std::string>& args, std::ostream& out_error) { idmap->accept(&visitor); } - return true; + return Unit{}; } diff --git a/cmds/idmap2/idmap2/Lookup.cpp b/cmds/idmap2/idmap2/Lookup.cpp index 83a40efee3f3..677c6fa155dd 100644 --- a/cmds/idmap2/idmap2/Lookup.cpp +++ b/cmds/idmap2/idmap2/Lookup.cpp @@ -57,6 +57,7 @@ using android::idmap2::Error; using android::idmap2::IdmapHeader; using android::idmap2::ResourceId; using android::idmap2::Result; +using android::idmap2::Unit; using android::idmap2::Xml; using android::idmap2::ZipFile; using android::util::Utf16ToUtf8; @@ -157,7 +158,7 @@ Result<std::string> GetTargetPackageNameFromManifest(const std::string& apk_path } } // namespace -bool Lookup(const std::vector<std::string>& args, std::ostream& out_error) { +Result<Unit> Lookup(const std::vector<std::string>& args) { SYSTRACE << "Lookup " << args; std::vector<std::string> idmap_paths; std::string config_str; @@ -172,14 +173,14 @@ bool Lookup(const std::vector<std::string>& args, std::ostream& out_error) { "'[package:]type/name') to look up", &resid_str); - if (!opts.Parse(args, out_error)) { - return false; + const auto opts_ok = opts.Parse(args); + if (!opts_ok) { + return opts_ok.GetError(); } ConfigDescription config; if (!ConfigDescription::Parse(config_str, &config)) { - out_error << "error: failed to parse config" << std::endl; - return false; + return Error("failed to parse config"); } std::vector<std::unique_ptr<const ApkAssets>> apk_assets; @@ -191,39 +192,33 @@ bool Lookup(const std::vector<std::string>& args, std::ostream& out_error) { auto idmap_header = IdmapHeader::FromBinaryStream(fin); fin.close(); if (!idmap_header) { - out_error << "error: failed to read idmap from " << idmap_path << std::endl; - return false; + return Error("failed to read idmap from %s", idmap_path.c_str()); } if (i == 0) { target_path = idmap_header->GetTargetPath().to_string(); auto target_apk = ApkAssets::Load(target_path); if (!target_apk) { - out_error << "error: failed to read target apk from " << target_path << std::endl; - return false; + return Error("failed to read target apk from %s", target_path.c_str()); } apk_assets.push_back(std::move(target_apk)); const Result<std::string> package_name = GetTargetPackageNameFromManifest(idmap_header->GetOverlayPath().to_string()); if (!package_name) { - out_error << "error: failed to parse android:targetPackage from overlay manifest" - << std::endl; - return false; + return Error("failed to parse android:targetPackage from overlay manifest"); } target_package_name = *package_name; } else if (target_path != idmap_header->GetTargetPath()) { - out_error << "error: different target APKs (expected target APK " << target_path << " but " - << idmap_path << " has target APK " << idmap_header->GetTargetPath() << ")" - << std::endl; - return false; + return Error("different target APKs (expected target APK %s but %s has target APK %s)", + target_path.c_str(), idmap_path.c_str(), + idmap_header->GetTargetPath().to_string().c_str()); } auto overlay_apk = ApkAssets::LoadOverlay(idmap_path); if (!overlay_apk) { - out_error << "error: failed to read overlay apk from " << idmap_header->GetOverlayPath() - << std::endl; - return false; + return Error("failed to read overlay apk from %s", + idmap_header->GetOverlayPath().to_string().c_str()); } apk_assets.push_back(std::move(overlay_apk)); } @@ -238,16 +233,14 @@ bool Lookup(const std::vector<std::string>& args, std::ostream& out_error) { const Result<ResourceId> resid = ParseResReference(am, resid_str, target_package_name); if (!resid) { - out_error << "error: failed to parse resource ID" << std::endl; - return false; + return Error(resid.GetError(), "failed to parse resource ID"); } const Result<std::string> value = GetValue(am, *resid); if (!value) { - out_error << StringPrintf("error: resource 0x%08x not found", *resid) << std::endl; - return false; + return Error(value.GetError(), "resource 0x%08x not found", *resid); } std::cout << *value << std::endl; - return true; + return Unit{}; } diff --git a/cmds/idmap2/idmap2/Main.cpp b/cmds/idmap2/idmap2/Main.cpp index a0ffccb26dfe..d8867fe8f497 100644 --- a/cmds/idmap2/idmap2/Main.cpp +++ b/cmds/idmap2/idmap2/Main.cpp @@ -24,14 +24,17 @@ #include <vector> #include "idmap2/CommandLineOptions.h" +#include "idmap2/Result.h" #include "idmap2/SysTrace.h" #include "Commands.h" using android::idmap2::CommandLineOptions; +using android::idmap2::Result; +using android::idmap2::Unit; using NameToFunctionMap = - std::map<std::string, std::function<bool(const std::vector<std::string>&, std::ostream&)>>; + std::map<std::string, std::function<Result<Unit>(const std::vector<std::string>&)>>; namespace { @@ -69,5 +72,10 @@ int main(int argc, char** argv) { PrintUsage(commands, std::cerr); return EXIT_FAILURE; } - return iter->second(*args, std::cerr) ? EXIT_SUCCESS : EXIT_FAILURE; + const auto result = iter->second(*args); + if (!result) { + std::cerr << "error: " << result.GetErrorMessage() << std::endl; + return EXIT_FAILURE; + } + return EXIT_SUCCESS; } diff --git a/cmds/idmap2/idmap2/Scan.cpp b/cmds/idmap2/idmap2/Scan.cpp index e85f132c6072..24331af9fd6d 100644 --- a/cmds/idmap2/idmap2/Scan.cpp +++ b/cmds/idmap2/idmap2/Scan.cpp @@ -30,6 +30,7 @@ #include "idmap2/FileUtils.h" #include "idmap2/Idmap.h" #include "idmap2/ResourceUtils.h" +#include "idmap2/Result.h" #include "idmap2/SysTrace.h" #include "idmap2/Xml.h" #include "idmap2/ZipFile.h" @@ -37,6 +38,7 @@ #include "Commands.h" using android::idmap2::CommandLineOptions; +using android::idmap2::Error; using android::idmap2::Idmap; using android::idmap2::kPolicyProduct; using android::idmap2::kPolicyPublic; @@ -45,6 +47,7 @@ using android::idmap2::kPolicyVendor; using android::idmap2::PolicyBitmask; using android::idmap2::PolicyFlags; using android::idmap2::Result; +using android::idmap2::Unit; using android::idmap2::utils::ExtractOverlayManifestInfo; using android::idmap2::utils::FindFiles; using android::idmap2::utils::OverlayManifestInfo; @@ -69,8 +72,8 @@ bool VendorIsQOrLater() { return version == "Q" || version == "q"; } -std::unique_ptr<std::vector<std::string>> FindApkFiles(const std::vector<std::string>& dirs, - bool recursive, std::ostream& out_error) { +Result<std::unique_ptr<std::vector<std::string>>> FindApkFiles(const std::vector<std::string>& dirs, + bool recursive) { SYSTRACE << "FindApkFiles " << dirs << " " << recursive; const auto predicate = [](unsigned char type, const std::string& path) -> bool { static constexpr size_t kExtLen = 4; // strlen(".apk") @@ -82,8 +85,7 @@ std::unique_ptr<std::vector<std::string>> FindApkFiles(const std::vector<std::st for (const auto& dir : dirs) { const auto apk_paths = FindFiles(dir, recursive, predicate); if (!apk_paths) { - out_error << "error: failed to open directory " << dir << std::endl; - return nullptr; + return Error("failed to open directory %s", dir.c_str()); } paths.insert(apk_paths->cbegin(), apk_paths->cend()); } @@ -110,7 +112,7 @@ std::vector<std::string> PoliciesForPath(const std::string& apk_path) { } // namespace -bool Scan(const std::vector<std::string>& args, std::ostream& out_error) { +Result<Unit> Scan(const std::vector<std::string>& args) { SYSTRACE << "Scan " << args; std::vector<std::string> input_directories; std::string target_package_name; @@ -135,22 +137,22 @@ bool Scan(const std::vector<std::string>& args, std::ostream& out_error) { "input: an overlayable policy this overlay fulfills " "(if none or supplied, the overlays will not have their policies overriden", &override_policies); - if (!opts.Parse(args, out_error)) { - return false; + const auto opts_ok = opts.Parse(args); + if (!opts_ok) { + return opts_ok.GetError(); } - const auto apk_paths = FindApkFiles(input_directories, recursive, out_error); + const auto apk_paths = FindApkFiles(input_directories, recursive); if (!apk_paths) { - return false; + return Error(apk_paths.GetError(), "failed to find apk files"); } std::vector<InputOverlay> interesting_apks; - for (const std::string& path : *apk_paths) { + for (const std::string& path : **apk_paths) { Result<OverlayManifestInfo> overlay_info = ExtractOverlayManifestInfo(path, /* assert_overlay */ false); if (!overlay_info) { - out_error << "error: " << overlay_info.GetErrorMessage() << std::endl; - return false; + return overlay_info.GetError(); } if (!overlay_info->is_static) { @@ -194,16 +196,13 @@ bool Scan(const std::vector<std::string>& args, std::ostream& out_error) { std::stringstream stream; for (const auto& overlay : interesting_apks) { - // Create the idmap for the overlay if it currently does not exist or if it is not up to date. - std::stringstream dev_null; - std::vector<std::string> verify_args = {"--idmap-path", overlay.idmap_path}; for (const std::string& policy : overlay.policies) { verify_args.emplace_back("--policy"); verify_args.emplace_back(policy); } - if (!Verify(std::vector<std::string>(verify_args), dev_null)) { + if (!Verify(std::vector<std::string>(verify_args))) { std::vector<std::string> create_args = {"--target-apk-path", target_apk_path, "--overlay-apk-path", overlay.apk_path, "--idmap-path", overlay.idmap_path}; @@ -216,8 +215,9 @@ bool Scan(const std::vector<std::string>& args, std::ostream& out_error) { create_args.emplace_back(policy); } - if (!Create(create_args, out_error)) { - return false; + const auto create_ok = Create(create_args); + if (!create_ok) { + return Error(create_ok.GetError(), "failed to create idmap"); } } @@ -226,5 +226,5 @@ bool Scan(const std::vector<std::string>& args, std::ostream& out_error) { std::cout << stream.str(); - return true; + return Unit{}; } diff --git a/cmds/idmap2/idmap2/Verify.cpp b/cmds/idmap2/idmap2/Verify.cpp index d8fe7aa0ed99..9cb67b33e6cf 100644 --- a/cmds/idmap2/idmap2/Verify.cpp +++ b/cmds/idmap2/idmap2/Verify.cpp @@ -21,29 +21,39 @@ #include "idmap2/CommandLineOptions.h" #include "idmap2/Idmap.h" +#include "idmap2/Result.h" #include "idmap2/SysTrace.h" using android::idmap2::CommandLineOptions; +using android::idmap2::Error; using android::idmap2::IdmapHeader; +using android::idmap2::Result; +using android::idmap2::Unit; -bool Verify(const std::vector<std::string>& args, std::ostream& out_error) { +Result<Unit> Verify(const std::vector<std::string>& args) { SYSTRACE << "Verify " << args; std::string idmap_path; const CommandLineOptions opts = CommandLineOptions("idmap2 verify") .MandatoryOption("--idmap-path", "input: path to idmap file to verify", &idmap_path); - if (!opts.Parse(args, out_error)) { - return false; + + const auto opts_ok = opts.Parse(args); + if (!opts_ok) { + return opts_ok.GetError(); } std::ifstream fin(idmap_path); const std::unique_ptr<const IdmapHeader> header = IdmapHeader::FromBinaryStream(fin); fin.close(); if (!header) { - out_error << "error: failed to parse idmap header" << std::endl; - return false; + return Error("failed to parse idmap header"); + } + + const auto header_ok = header->IsUpToDate(); + if (!header_ok) { + return Error(header_ok.GetError(), "idmap not up to date"); } - return header->IsUpToDate(out_error); + return Unit{}; } diff --git a/cmds/idmap2/idmap2d/Idmap2Service.cpp b/cmds/idmap2/idmap2d/Idmap2Service.cpp index fa944143e408..e03a9cc1032e 100644 --- a/cmds/idmap2/idmap2d/Idmap2Service.cpp +++ b/cmds/idmap2/idmap2d/Idmap2Service.cpp @@ -104,8 +104,7 @@ Status Idmap2Service::verifyIdmap(const std::string& overlay_apk_path, std::ifstream fin(idmap_path); const std::unique_ptr<const IdmapHeader> header = IdmapHeader::FromBinaryStream(fin); fin.close(); - std::stringstream dev_null; - *_aidl_return = header && header->IsUpToDate(dev_null); + *_aidl_return = header && header->IsUpToDate(); // TODO(b/119328308): Check that the set of fulfilled policies of the overlay has not changed diff --git a/cmds/idmap2/include/idmap2/CommandLineOptions.h b/cmds/idmap2/include/idmap2/CommandLineOptions.h index 6db6bf9ea8ad..52ac8181da02 100644 --- a/cmds/idmap2/include/idmap2/CommandLineOptions.h +++ b/cmds/idmap2/include/idmap2/CommandLineOptions.h @@ -23,6 +23,8 @@ #include <string> #include <vector> +#include "idmap2/Result.h" + namespace android::idmap2 { /* @@ -46,7 +48,7 @@ class CommandLineOptions { std::string* value); CommandLineOptions& OptionalOption(const std::string& name, const std::string& description, std::vector<std::string>* value); - bool Parse(const std::vector<std::string>& argv, std::ostream& outError) const; + Result<Unit> Parse(const std::vector<std::string>& argv) const; void Usage(std::ostream& out) const; private: diff --git a/cmds/idmap2/include/idmap2/Idmap.h b/cmds/idmap2/include/idmap2/Idmap.h index 1666dc8a3bbd..673d18d25907 100644 --- a/cmds/idmap2/include/idmap2/Idmap.h +++ b/cmds/idmap2/include/idmap2/Idmap.h @@ -115,7 +115,7 @@ class IdmapHeader { // Invariant: anytime the idmap data encoding is changed, the idmap version // field *must* be incremented. Because of this, we know that if the idmap // header is up-to-date the entire file is up-to-date. - bool IsUpToDate(std::ostream& out_error) const; + Result<Unit> IsUpToDate() const; void accept(Visitor* v) const; diff --git a/cmds/idmap2/libidmap2/CommandLineOptions.cpp b/cmds/idmap2/libidmap2/CommandLineOptions.cpp index a49a607091a4..d5fd2ce38b11 100644 --- a/cmds/idmap2/libidmap2/CommandLineOptions.cpp +++ b/cmds/idmap2/libidmap2/CommandLineOptions.cpp @@ -19,12 +19,14 @@ #include <iostream> #include <memory> #include <set> +#include <sstream> #include <string> #include <vector> #include "android-base/macros.h" #include "idmap2/CommandLineOptions.h" +#include "idmap2/Result.h" namespace android::idmap2 { @@ -77,7 +79,7 @@ CommandLineOptions& CommandLineOptions::OptionalOption(const std::string& name, return *this; } -bool CommandLineOptions::Parse(const std::vector<std::string>& argv, std::ostream& outError) const { +Result<Unit> CommandLineOptions::Parse(const std::vector<std::string>& argv) const { const auto pivot = std::partition(options_.begin(), options_.end(), [](const Option& opt) { return opt.count != Option::COUNT_OPTIONAL && opt.count != Option::COUNT_OPTIONAL_ONCE_OR_MORE; }); @@ -89,8 +91,9 @@ bool CommandLineOptions::Parse(const std::vector<std::string>& argv, std::ostrea for (size_t i = 0; i < argv_size; i++) { const std::string arg = argv[i]; if ("--help" == arg || "-h" == arg) { - Usage(outError); - return false; + std::stringstream stream; + Usage(stream); + return Error("%s", stream.str().c_str()); } bool match = false; for (const Option& opt : options_) { @@ -100,9 +103,9 @@ bool CommandLineOptions::Parse(const std::vector<std::string>& argv, std::ostrea if (opt.argument) { i++; if (i >= argv_size) { - outError << "error: " << opt.name << ": missing argument" << std::endl; - Usage(outError); - return false; + std::stringstream stream; + Usage(stream); + return Error("%s: missing argument\n%s", opt.name.c_str(), stream.str().c_str()); } } opt.action(argv[i]); @@ -111,20 +114,27 @@ bool CommandLineOptions::Parse(const std::vector<std::string>& argv, std::ostrea } } if (!match) { - outError << "error: " << arg << ": unknown option" << std::endl; - Usage(outError); - return false; + std::stringstream stream; + Usage(stream); + return Error("%s: unknown option\n%s", arg.c_str(), stream.str().c_str()); } } if (!mandatory_opts.empty()) { + std::stringstream stream; + bool separator = false; for (const auto& opt : mandatory_opts) { - outError << "error: " << opt << ": missing mandatory option" << std::endl; + if (separator) { + stream << ", "; + } + separator = true; + stream << opt << ": missing mandatory option"; } - Usage(outError); - return false; + stream << std::endl; + Usage(stream); + return Error("%s", stream.str().c_str()); } - return true; + return Unit{}; } void CommandLineOptions::Usage(std::ostream& out) const { diff --git a/cmds/idmap2/libidmap2/Idmap.cpp b/cmds/idmap2/libidmap2/Idmap.cpp index a7d180c90307..e8e19d801323 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_; } @@ -142,62 +142,46 @@ std::unique_ptr<const IdmapHeader> IdmapHeader::FromBinaryStream(std::istream& s return std::move(idmap_header); } -bool IdmapHeader::IsUpToDate(std::ostream& out_error) const { +Result<Unit> IdmapHeader::IsUpToDate() const { if (magic_ != kIdmapMagic) { - out_error << base::StringPrintf("error: bad magic: actual 0x%08x, expected 0x%08x", magic_, - kIdmapMagic) - << std::endl; - return false; + return Error("bad magic: actual 0x%08x, expected 0x%08x", magic_, kIdmapMagic); } if (version_ != kIdmapCurrentVersion) { - out_error << base::StringPrintf("error: bad version: actual 0x%08x, expected 0x%08x", version_, - kIdmapCurrentVersion) - << std::endl; - return false; + return Error("bad version: actual 0x%08x, expected 0x%08x", version_, kIdmapCurrentVersion); } const std::unique_ptr<const ZipFile> target_zip = ZipFile::Open(target_path_); if (!target_zip) { - out_error << "error: failed to open target " << target_path_ << std::endl; - return false; + return Error("failed to open target %s", GetTargetPath().to_string().c_str()); } Result<uint32_t> target_crc = GetCrc(*target_zip); if (!target_crc) { - out_error << "error: failed to get target crc" << std::endl; - return false; + return Error("failed to get target crc"); } if (target_crc_ != *target_crc) { - out_error << base::StringPrintf( - "error: bad target crc: idmap version 0x%08x, file system version 0x%08x", - target_crc_, *target_crc) - << std::endl; - return false; + return Error("bad target crc: idmap version 0x%08x, file system version 0x%08x", target_crc_, + *target_crc); } const std::unique_ptr<const ZipFile> overlay_zip = ZipFile::Open(overlay_path_); if (!overlay_zip) { - out_error << "error: failed to open overlay " << overlay_path_ << std::endl; - return false; + return Error("failed to open overlay %s", GetOverlayPath().to_string().c_str()); } Result<uint32_t> overlay_crc = GetCrc(*overlay_zip); if (!overlay_crc) { - out_error << "error: failed to get overlay crc" << std::endl; - return false; + return Error("failed to get overlay crc"); } if (overlay_crc_ != *overlay_crc) { - out_error << base::StringPrintf( - "error: bad overlay crc: idmap version 0x%08x, file system version 0x%08x", - overlay_crc_, *overlay_crc) - << std::endl; - return false; + return Error("bad overlay crc: idmap version 0x%08x, file system version 0x%08x", overlay_crc_, + *overlay_crc); } - return true; + return Unit{}; } std::unique_ptr<const IdmapData::Header> IdmapData::Header::FromBinaryStream(std::istream& stream) { @@ -452,7 +436,7 @@ std::unique_ptr<const Idmap> Idmap::FromApkAssets( continue; } - if (!enforce_overlayable) { + if (enforce_overlayable) { Result<Unit> success = CheckOverlayable(*target_pkg, *overlay_info, fulfilled_policies, target_resid); if (!success) { diff --git a/cmds/idmap2/tests/CommandLineOptionsTests.cpp b/cmds/idmap2/tests/CommandLineOptionsTests.cpp index 39f18d3336af..d567af64b16a 100644 --- a/cmds/idmap2/tests/CommandLineOptionsTests.cpp +++ b/cmds/idmap2/tests/CommandLineOptionsTests.cpp @@ -46,14 +46,13 @@ TEST(CommandLineOptionsTests, Flag) { CommandLineOptions opts = CommandLineOptions("test").OptionalFlag("--foo", "", &foo).OptionalFlag("--bar", "", &bar); - std::ostream fakeStdErr(nullptr); - bool success = opts.Parse({"--foo", "--bar"}, fakeStdErr); + auto success = opts.Parse({"--foo", "--bar"}); ASSERT_TRUE(success); ASSERT_TRUE(foo); ASSERT_TRUE(bar); foo = bar = false; - success = opts.Parse({"--foo"}, fakeStdErr); + success = opts.Parse({"--foo"}); ASSERT_TRUE(success); ASSERT_TRUE(foo); ASSERT_FALSE(bar); @@ -65,21 +64,19 @@ TEST(CommandLineOptionsTests, MandatoryOption) { CommandLineOptions opts = CommandLineOptions("test") .MandatoryOption("--foo", "", &foo) .MandatoryOption("--bar", "", &bar); - std::ostream fakeStdErr(nullptr); - bool success = opts.Parse({"--foo", "FOO", "--bar", "BAR"}, fakeStdErr); + auto success = opts.Parse({"--foo", "FOO", "--bar", "BAR"}); ASSERT_TRUE(success); ASSERT_EQ(foo, "FOO"); ASSERT_EQ(bar, "BAR"); - success = opts.Parse({"--foo"}, fakeStdErr); + success = opts.Parse({"--foo"}); ASSERT_FALSE(success); } TEST(CommandLineOptionsTests, MandatoryOptionMultipleArgsButExpectedOnce) { std::string foo; CommandLineOptions opts = CommandLineOptions("test").MandatoryOption("--foo", "", &foo); - std::ostream fakeStdErr(nullptr); - bool success = opts.Parse({"--foo", "FIRST", "--foo", "SECOND"}, fakeStdErr); + auto success = opts.Parse({"--foo", "FIRST", "--foo", "SECOND"}); ASSERT_TRUE(success); ASSERT_EQ(foo, "SECOND"); } @@ -87,8 +84,7 @@ TEST(CommandLineOptionsTests, MandatoryOptionMultipleArgsButExpectedOnce) { TEST(CommandLineOptionsTests, MandatoryOptionMultipleArgsAndExpectedOnceOrMore) { std::vector<std::string> args; CommandLineOptions opts = CommandLineOptions("test").MandatoryOption("--foo", "", &args); - std::ostream fakeStdErr(nullptr); - bool success = opts.Parse({"--foo", "FOO", "--foo", "BAR"}, fakeStdErr); + auto success = opts.Parse({"--foo", "FOO", "--foo", "BAR"}); ASSERT_TRUE(success); ASSERT_EQ(args.size(), 2U); ASSERT_EQ(args[0], "FOO"); @@ -101,23 +97,22 @@ TEST(CommandLineOptionsTests, OptionalOption) { CommandLineOptions opts = CommandLineOptions("test") .OptionalOption("--foo", "", &foo) .OptionalOption("--bar", "", &bar); - std::ostream fakeStdErr(nullptr); - bool success = opts.Parse({"--foo", "FOO", "--bar", "BAR"}, fakeStdErr); + auto success = opts.Parse({"--foo", "FOO", "--bar", "BAR"}); ASSERT_TRUE(success); ASSERT_EQ(foo, "FOO"); ASSERT_EQ(bar, "BAR"); - success = opts.Parse({"--foo", "BAZ"}, fakeStdErr); + success = opts.Parse({"--foo", "BAZ"}); ASSERT_TRUE(success); ASSERT_EQ(foo, "BAZ"); - success = opts.Parse({"--foo"}, fakeStdErr); + success = opts.Parse({"--foo"}); ASSERT_FALSE(success); - success = opts.Parse({"--foo", "--bar", "BAR"}, fakeStdErr); + success = opts.Parse({"--foo", "--bar", "BAR"}); ASSERT_FALSE(success); - success = opts.Parse({"--foo", "FOO", "--bar"}, fakeStdErr); + success = opts.Parse({"--foo", "FOO", "--bar"}); ASSERT_FALSE(success); } @@ -127,8 +122,7 @@ TEST(CommandLineOptionsTests, OptionalOptionList) { CommandLineOptions opts = CommandLineOptions("test") .OptionalOption("--foo", "", &foo) .OptionalOption("--bar", "", &bar); - std::ostream fakeStdErr(nullptr); - bool success = opts.Parse({"--foo", "FOO", "--bar", "BAR"}, fakeStdErr); + auto success = opts.Parse({"--foo", "FOO", "--bar", "BAR"}); ASSERT_TRUE(success); ASSERT_EQ(foo.size(), 1U); ASSERT_EQ(foo[0], "FOO"); @@ -137,7 +131,7 @@ TEST(CommandLineOptionsTests, OptionalOptionList) { foo.clear(); bar.clear(); - success = opts.Parse({"--foo", "BAZ"}, fakeStdErr); + success = opts.Parse({"--foo", "BAZ"}); ASSERT_TRUE(success); ASSERT_EQ(foo.size(), 1U); ASSERT_EQ(foo[0], "BAZ"); @@ -145,8 +139,7 @@ TEST(CommandLineOptionsTests, OptionalOptionList) { foo.clear(); bar.clear(); - success = - opts.Parse({"--foo", "BAZ", "--foo", "BIZ", "--bar", "FIZ", "--bar", "FUZZ"}, fakeStdErr); + success = opts.Parse({"--foo", "BAZ", "--foo", "BIZ", "--bar", "FIZ", "--bar", "FUZZ"}); ASSERT_TRUE(success); ASSERT_EQ(foo.size(), 2U); ASSERT_EQ(foo[0], "BAZ"); @@ -157,17 +150,17 @@ TEST(CommandLineOptionsTests, OptionalOptionList) { foo.clear(); bar.clear(); - success = opts.Parse({"--foo"}, fakeStdErr); + success = opts.Parse({"--foo"}); ASSERT_FALSE(success); foo.clear(); bar.clear(); - success = opts.Parse({"--foo", "--bar", "BAR"}, fakeStdErr); + success = opts.Parse({"--foo", "--bar", "BAR"}); ASSERT_FALSE(success); foo.clear(); bar.clear(); - success = opts.Parse({"--foo", "FOO", "--bar"}, fakeStdErr); + success = opts.Parse({"--foo", "FOO", "--bar"}); ASSERT_FALSE(success); } @@ -179,14 +172,13 @@ TEST(CommandLineOptionsTests, CornerCases) { .MandatoryOption("--foo", "", &foo) .OptionalFlag("--baz", "", &baz) .OptionalOption("--bar", "", &bar); - std::ostream fakeStdErr(nullptr); - bool success = opts.Parse({"--unexpected"}, fakeStdErr); + auto success = opts.Parse({"--unexpected"}); ASSERT_FALSE(success); - success = opts.Parse({"--bar", "BAR"}, fakeStdErr); + success = opts.Parse({"--bar", "BAR"}); ASSERT_FALSE(success); - success = opts.Parse({"--baz", "--foo", "FOO"}, fakeStdErr); + success = opts.Parse({"--baz", "--foo", "FOO"}); ASSERT_TRUE(success); ASSERT_TRUE(baz); ASSERT_EQ(foo, "FOO"); diff --git a/cmds/idmap2/tests/IdmapTests.cpp b/cmds/idmap2/tests/IdmapTests.cpp index 8d65428f134e..c20ae7b798a3 100644 --- a/cmds/idmap2/tests/IdmapTests.cpp +++ b/cmds/idmap2/tests/IdmapTests.cpp @@ -501,7 +501,7 @@ TEST(IdmapTests, IdmapHeaderIsUpToDate) { std::unique_ptr<const IdmapHeader> header = IdmapHeader::FromBinaryStream(stream); ASSERT_THAT(header, NotNull()); - ASSERT_TRUE(header->IsUpToDate(error)) << error.str(); + ASSERT_TRUE(header->IsUpToDate()); // magic: bytes (0x0, 0x03) std::string bad_magic_string(stream.str()); @@ -514,7 +514,7 @@ TEST(IdmapTests, IdmapHeaderIsUpToDate) { IdmapHeader::FromBinaryStream(bad_magic_stream); ASSERT_THAT(bad_magic_header, NotNull()); ASSERT_NE(header->GetMagic(), bad_magic_header->GetMagic()); - ASSERT_FALSE(bad_magic_header->IsUpToDate(error)); + ASSERT_FALSE(bad_magic_header->IsUpToDate()); // version: bytes (0x4, 0x07) std::string bad_version_string(stream.str()); @@ -527,7 +527,7 @@ TEST(IdmapTests, IdmapHeaderIsUpToDate) { IdmapHeader::FromBinaryStream(bad_version_stream); ASSERT_THAT(bad_version_header, NotNull()); ASSERT_NE(header->GetVersion(), bad_version_header->GetVersion()); - ASSERT_FALSE(bad_version_header->IsUpToDate(error)); + ASSERT_FALSE(bad_version_header->IsUpToDate()); // target crc: bytes (0x8, 0xb) std::string bad_target_crc_string(stream.str()); @@ -540,7 +540,7 @@ TEST(IdmapTests, IdmapHeaderIsUpToDate) { IdmapHeader::FromBinaryStream(bad_target_crc_stream); ASSERT_THAT(bad_target_crc_header, NotNull()); ASSERT_NE(header->GetTargetCrc(), bad_target_crc_header->GetTargetCrc()); - ASSERT_FALSE(bad_target_crc_header->IsUpToDate(error)); + ASSERT_FALSE(bad_target_crc_header->IsUpToDate()); // overlay crc: bytes (0xc, 0xf) std::string bad_overlay_crc_string(stream.str()); @@ -553,7 +553,7 @@ TEST(IdmapTests, IdmapHeaderIsUpToDate) { IdmapHeader::FromBinaryStream(bad_overlay_crc_stream); ASSERT_THAT(bad_overlay_crc_header, NotNull()); ASSERT_NE(header->GetOverlayCrc(), bad_overlay_crc_header->GetOverlayCrc()); - ASSERT_FALSE(bad_overlay_crc_header->IsUpToDate(error)); + ASSERT_FALSE(bad_overlay_crc_header->IsUpToDate()); // target path: bytes (0x10, 0x10f) std::string bad_target_path_string(stream.str()); @@ -563,7 +563,7 @@ TEST(IdmapTests, IdmapHeaderIsUpToDate) { IdmapHeader::FromBinaryStream(bad_target_path_stream); ASSERT_THAT(bad_target_path_header, NotNull()); ASSERT_NE(header->GetTargetPath(), bad_target_path_header->GetTargetPath()); - ASSERT_FALSE(bad_target_path_header->IsUpToDate(error)); + ASSERT_FALSE(bad_target_path_header->IsUpToDate()); // overlay path: bytes (0x110, 0x20f) std::string bad_overlay_path_string(stream.str()); @@ -573,7 +573,7 @@ TEST(IdmapTests, IdmapHeaderIsUpToDate) { IdmapHeader::FromBinaryStream(bad_overlay_path_stream); ASSERT_THAT(bad_overlay_path_header, NotNull()); ASSERT_NE(header->GetOverlayPath(), bad_overlay_path_header->GetOverlayPath()); - ASSERT_FALSE(bad_overlay_path_header->IsUpToDate(error)); + ASSERT_FALSE(bad_overlay_path_header->IsUpToDate()); } class TestVisitor : public Visitor { 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..d331c0f026f6 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; } /** 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/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index f6cfe4855070..e8d32932503b 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -340,4 +340,21 @@ public abstract class ActivityManagerInternal { * like persisting database etc. */ public abstract void prepareForPossibleShutdown(); + + /** + * Returns {@code true} if {@code uid} is running a foreground service of a specific + * {@code foregroundServiceType}. + */ + public abstract boolean hasRunningForegroundService(int uid, int foregroundServiceType); + + /** + * Registers the specified {@code processObserver} to be notified of future changes to + * process state. + */ + public abstract void registerProcessObserver(IProcessObserver processObserver); + + /** + * Unregisters the specified {@code processObserver}. + */ + public abstract void unregisterProcessObserver(IProcessObserver processObserver); } 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/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index a2260625a0c2..7a0639eef8cc 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -3054,9 +3054,9 @@ public class ApplicationPackageManager extends PackageManager { } @Override - public String getContentCaptureServicePackageName() { + public String getSystemCaptionsServicePackageName() { try { - return mPM.getContentCaptureServicePackageName(); + return mPM.getSystemCaptionsServicePackageName(); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } 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/IProcessObserver.aidl b/core/java/android/app/IProcessObserver.aidl index b436aa2bcd0f..7be3620f317b 100644 --- a/core/java/android/app/IProcessObserver.aidl +++ b/core/java/android/app/IProcessObserver.aidl @@ -19,5 +19,6 @@ package android.app; /** {@hide} */ oneway interface IProcessObserver { void onForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities); + void onForegroundServicesChanged(int pid, int uid, int serviceTypes); void onProcessDied(int pid, int uid); } 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/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/content/Intent.java b/core/java/android/content/Intent.java index efd9990f4ade..93a9daced987 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -2438,7 +2438,7 @@ public class Intent implements Parcelable, Cloneable { * Broadcast Action: A rollback has been committed. * * <p class="note">This is a protected intent that can only be sent - * by the system. + * by the system. The receiver must hold MANAGE_ROLLBACK permission. * * @hide */ diff --git a/core/java/android/content/om/OverlayManager.java b/core/java/android/content/om/OverlayManager.java index 8e72fa5e1cfd..ceea0435a254 100644 --- a/core/java/android/content/om/OverlayManager.java +++ b/core/java/android/content/om/OverlayManager.java @@ -16,12 +16,14 @@ package android.content.om; +import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.SystemService; import android.content.Context; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.UserHandle; import java.util.List; @@ -96,6 +98,28 @@ public class OverlayManager { } /** + * Returns information about the overlay with the given package name for + * the specified user. + * + * @param packageName The name of the package. + * @param userHandle The user to get the OverlayInfos for. + * @return An OverlayInfo object; if no overlays exist with the + * requested package name, null is returned. + * + * @hide + */ + @SystemApi + @Nullable + public OverlayInfo getOverlayInfo(@NonNull final String packageName, + @NonNull final UserHandle userHandle) { + try { + return mService.getOverlayInfo(packageName, userHandle.myUserId()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * Returns information about all overlays for the given target package for * the specified user. The returned list is ordered according to the * overlay priority with the highest priority at the end of the list. diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index 706cbbf560c5..068a93a253ff 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -671,6 +671,14 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { */ public static final int PRIVATE_FLAG_ALLOW_AUDIO_PLAYBACK_CAPTURE = 1 << 27; + /** + * Indicates whether this package is in fact a runtime resource overlay. + * + * @hide + */ + public static final int PRIVATE_FLAG_IS_RESOURCE_OVERLAY = 1 << 28; + + /** @hide */ @IntDef(flag = true, prefix = { "PRIVATE_FLAG_" }, value = { PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE, @@ -683,6 +691,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { PRIVATE_FLAG_HAS_DOMAIN_URLS, PRIVATE_FLAG_HIDDEN, PRIVATE_FLAG_INSTANT, + PRIVATE_FLAG_IS_RESOURCE_OVERLAY, PRIVATE_FLAG_ISOLATED_SPLIT_LOADING, PRIVATE_FLAG_OEM, PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE, @@ -2023,6 +2032,14 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { } /** + * Returns true if the package has declared in its manifest that it is a + * runtime resource overlay. + */ + public boolean isResourceOverlay() { + return (privateFlags & ApplicationInfo.PRIVATE_FLAG_IS_RESOURCE_OVERLAY) != 0; + } + + /** * @hide */ @Override protected ApplicationInfo getApplicationInfo() { diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index fd3529b05c35..464e866e0b31 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -742,7 +742,7 @@ interface IPackageManager { String getAppPredictionServicePackageName(); - String getContentCaptureServicePackageName(); + String getSystemCaptionsServicePackageName(); String getIncidentReportApproverPackageName(); 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 99324ba65f5c..fa5247c955d7 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -2589,14 +2589,6 @@ public abstract class PackageManager { public static final String FEATURE_PC = "android.hardware.type.pc"; /** - * Feature for {@link #getSystemAvailableFeatures} and - * {@link #hasSystemFeature}: This is a foldable device. Properties such as - * the display size may change in response to being folded. - */ - @SdkConstant(SdkConstantType.FEATURE) - public static final String FEATURE_FOLDABLE = "android.hardware.type.foldable"; - - /** * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}: * The device supports printing. */ @@ -3073,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 @@ -3090,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. @@ -3801,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 */ @@ -6594,6 +6596,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); } } @@ -6863,9 +6866,9 @@ public abstract class PackageManager { * * @hide */ - public String getContentCaptureServicePackageName() { + public String getSystemCaptionsServicePackageName() { throw new UnsupportedOperationException( - "getContentCaptureServicePackageName not implemented in subclass"); + "getSystemCaptionsServicePackageName not implemented in subclass"); } /** diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 9d0ece0220b4..743a302cc543 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -2108,6 +2108,9 @@ public class PackageParser { return null; } + pkg.applicationInfo.privateFlags |= + ApplicationInfo.PRIVATE_FLAG_IS_RESOURCE_OVERLAY; + XmlUtils.skipCurrentTag(parser); } else if (tagName.equals(TAG_KEY_SETS)) { diff --git a/core/java/android/content/pm/SharedLibraryInfo.java b/core/java/android/content/pm/SharedLibraryInfo.java index 13c49a072277..3488cc30892c 100644 --- a/core/java/android/content/pm/SharedLibraryInfo.java +++ b/core/java/android/content/pm/SharedLibraryInfo.java @@ -307,9 +307,9 @@ public final class SharedLibraryInfo implements Parcelable { @Override public String toString() { - return "SharedLibraryInfo[name:" + mName + ", type:" + typeToString(mType) + return "SharedLibraryInfo{name:" + mName + ", type:" + typeToString(mType) + ", version:" + mVersion + (!getDependentPackages().isEmpty() - ? " has dependents" : ""); + ? " has dependents" : "") + "}"; } @Override diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java index 67292426b248..6b8416d46601 100644 --- a/core/java/android/content/res/Resources.java +++ b/core/java/android/content/res/Resources.java @@ -191,9 +191,9 @@ public class Resources { /** * Return a global shared Resources object that provides access to only - * system resources (no application resources), and is not configured for - * the current screen (can not use dimension units, does not change based - * on orientation, etc). + * system resources (no application resources), is not configured for the + * current screen (can not use dimension units, does not change based on + * orientation, etc), and is not affected by Runtime Resource Overlay. */ public static Resources getSystem() { synchronized (sSync) { diff --git a/core/java/android/content/rollback/RollbackManager.java b/core/java/android/content/rollback/RollbackManager.java index 293c1e43086b..d54a6fe0a7b2 100644 --- a/core/java/android/content/rollback/RollbackManager.java +++ b/core/java/android/content/rollback/RollbackManager.java @@ -76,10 +76,12 @@ public final class RollbackManager { /** * Returns a list of all currently available rollbacks. * - * @throws SecurityException if the caller does not have the - * MANAGE_ROLLBACKS permission. + * @throws SecurityException if the caller does not have appropriate permissions. */ - @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) + @RequiresPermission(anyOf = { + android.Manifest.permission.MANAGE_ROLLBACKS, + android.Manifest.permission.TEST_MANAGE_ROLLBACKS + }) @NonNull public List<RollbackInfo> getAvailableRollbacks() { try { @@ -104,10 +106,12 @@ public final class RollbackManager { * rolled back from. * * @return the recently committed rollbacks - * @throws SecurityException if the caller does not have the - * MANAGE_ROLLBACKS permission. + * @throws SecurityException if the caller does not have appropriate permissions. */ - @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) + @RequiresPermission(anyOf = { + android.Manifest.permission.MANAGE_ROLLBACKS, + android.Manifest.permission.TEST_MANAGE_ROLLBACKS + }) public @NonNull List<RollbackInfo> getRecentlyCommittedRollbacks() { try { return mBinder.getRecentlyExecutedRollbacks().getList(); @@ -190,10 +194,12 @@ public final class RollbackManager { * @param statusReceiver where to deliver the results. Intents sent to * this receiver contain {@link #EXTRA_STATUS} * and {@link #EXTRA_STATUS_MESSAGE}. - * @throws SecurityException if the caller does not have the - * MANAGE_ROLLBACKS permission. + * @throws SecurityException if the caller does not have appropriate permissions. */ - @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) + @RequiresPermission(anyOf = { + android.Manifest.permission.MANAGE_ROLLBACKS, + android.Manifest.permission.TEST_MANAGE_ROLLBACKS + }) public void commitRollback(int rollbackId, @NonNull List<VersionedPackage> causePackages, @NonNull IntentSender statusReceiver) { try { @@ -210,12 +216,11 @@ public final class RollbackManager { * across device reboot, by simulating what happens on reboot without * actually rebooting the device. * - * @throws SecurityException if the caller does not have the - * MANAGE_ROLLBACKS permission. + * @throws SecurityException if the caller does not have appropriate permissions. * * @hide */ - @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) + @RequiresPermission(android.Manifest.permission.TEST_MANAGE_ROLLBACKS) @TestApi public void reloadPersistedData() { try { @@ -232,12 +237,11 @@ public final class RollbackManager { * recently committed rollbacks that contain the given package. * * @param packageName the name of the package to expire data for. - * @throws SecurityException if the caller does not have the - * MANAGE_ROLLBACKS permission. + * @throws SecurityException if the caller does not have appropriate permissions. * * @hide */ - @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) + @RequiresPermission(android.Manifest.permission.TEST_MANAGE_ROLLBACKS) @TestApi public void expireRollbackForPackage(@NonNull String packageName) { try { diff --git a/core/java/android/database/sqlite/SQLiteGlobal.java b/core/java/android/database/sqlite/SQLiteGlobal.java index d796003395f5..5e2875d02d90 100644 --- a/core/java/android/database/sqlite/SQLiteGlobal.java +++ b/core/java/android/database/sqlite/SQLiteGlobal.java @@ -176,6 +176,6 @@ public final class SQLiteGlobal { /** @hide */ public static boolean checkDbWipe() { - return true; + return false; } } diff --git a/core/java/android/net/CaptivePortal.java b/core/java/android/net/CaptivePortal.java index f2087248205c..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; @@ -29,15 +30,33 @@ import android.os.RemoteException; * {@code ACTION_CAPTIVE_PORTAL_SIGN_IN} activity. */ public class CaptivePortal implements Parcelable { - /** @hide */ + /** + * Response code from the captive portal application, indicating that the portal was dismissed + * and the network should be re-validated. + * @see ICaptivePortal#appResponse(int) + * @see android.net.INetworkMonitor#notifyCaptivePortalAppFinished(int) + * @hide + */ @SystemApi @TestApi public static final int APP_RETURN_DISMISSED = 0; - /** @hide */ + /** + * Response code from the captive portal application, indicating that the user did not login and + * does not want to use the captive portal network. + * @see ICaptivePortal#appResponse(int) + * @see android.net.INetworkMonitor#notifyCaptivePortalAppFinished(int) + * @hide + */ @SystemApi @TestApi public static final int APP_RETURN_UNWANTED = 1; - /** @hide */ + /** + * Response code from the captive portal application, indicating that the user does not wish to + * login but wants to use the captive portal network as-is. + * @see ICaptivePortal#appResponse(int) + * @see android.net.INetworkMonitor#notifyCaptivePortalAppFinished(int) + * @hide + */ @SystemApi @TestApi public static final int APP_RETURN_WANTED_AS_IS = 2; @@ -47,7 +66,7 @@ public class CaptivePortal implements Parcelable { /** @hide */ @SystemApi @TestApi - public CaptivePortal(IBinder binder) { + public CaptivePortal(@NonNull IBinder binder) { mBinder = binder; } @@ -124,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/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/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/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/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/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/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/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/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java index 7bd0fe23f1a3..4322a59cd3cd 100644 --- a/core/java/android/provider/DeviceConfig.java +++ b/core/java/android/provider/DeviceConfig.java @@ -225,6 +225,14 @@ public final class DeviceConfig { public static final String NAMESPACE_SCHEDULER = "scheduler"; /** + * Namespace for storage-related features. + * + * @hide + */ + @SystemApi + public static final String NAMESPACE_STORAGE = "storage"; + + /** * Namespace for System UI related features. * * @hide @@ -233,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 @@ -277,7 +293,6 @@ public final class DeviceConfig { * * @hide */ - @SystemApi public interface Telephony { String NAMESPACE = "telephony"; /** @@ -294,23 +309,6 @@ public final class DeviceConfig { String RAMPING_RINGER_VIBRATION_DURATION = "ramping_ringer_vibration_duration"; } - /** - * Namespace for storage-related features. - * - * @hide - */ - @SystemApi - public interface Storage { - String NAMESPACE = "storage"; - - /** - * If {@code 1}, enables the isolated storage feature. If {@code -1}, - * disables the isolated storage feature. If {@code 0}, uses the default - * value from the build system. - */ - String ISOLATED_STORAGE_ENABLED = "isolated_storage_enabled"; - } - private static final Object sLock = new Object(); @GuardedBy("sLock") private static ArrayMap<OnPropertyChangedListener, Pair<String, Executor>> sSingleListeners = diff --git a/core/java/android/provider/FontsContract.java b/core/java/android/provider/FontsContract.java index e931826d2455..8f772d4ec780 100644 --- a/core/java/android/provider/FontsContract.java +++ b/core/java/android/provider/FontsContract.java @@ -34,7 +34,6 @@ import android.graphics.fonts.FontFamily; import android.graphics.fonts.FontStyle; import android.graphics.fonts.FontVariationAxis; import android.net.Uri; -import android.os.Build.VERSION_CODES; import android.os.CancellationSignal; import android.os.Handler; import android.os.HandlerThread; @@ -652,17 +651,12 @@ public class FontsContract { if (familyBuilder == null) { familyBuilder = new FontFamily.Builder(font); } else { - try { - familyBuilder.addFont(font); - } catch (IllegalArgumentException e) { - if (context.getApplicationInfo().targetSdkVersion <= VERSION_CODES.P) { - // Surpress the IllegalArgumentException for keeping the backward - // compatibility. - continue; - } - throw e; - } + familyBuilder.addFont(font); } + } catch (IllegalArgumentException e) { + // To be a compatible behavior with API28 or before, catch IllegalArgumentExcetpion + // thrown by native code and returns null. + return null; } catch (IOException e) { continue; } diff --git a/core/java/android/provider/SearchIndexablesProvider.java b/core/java/android/provider/SearchIndexablesProvider.java index 1549c45478ed..d505f02468d0 100644 --- a/core/java/android/provider/SearchIndexablesProvider.java +++ b/core/java/android/provider/SearchIndexablesProvider.java @@ -25,6 +25,7 @@ import android.content.UriMatcher; import android.content.pm.ProviderInfo; import android.database.Cursor; import android.net.Uri; +import android.util.Log; /** * Base class for a search indexable provider. Such provider offers data to be indexed either @@ -112,19 +113,26 @@ public abstract class SearchIndexablesProvider extends ContentProvider { @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { - switch (mMatcher.match(uri)) { - case MATCH_RES_CODE: - return queryXmlResources(null); - case MATCH_RAW_CODE: - return queryRawData(null); - case MATCH_NON_INDEXABLE_KEYS_CODE: - return queryNonIndexableKeys(null); - case MATCH_SITE_MAP_PAIRS_CODE: - return querySiteMapPairs(); - case MATCH_SLICE_URI_PAIRS_CODE: - return querySliceUriPairs(); - default: - throw new UnsupportedOperationException("Unknown Uri " + uri); + try { + switch (mMatcher.match(uri)) { + case MATCH_RES_CODE: + return queryXmlResources(null); + case MATCH_RAW_CODE: + return queryRawData(null); + case MATCH_NON_INDEXABLE_KEYS_CODE: + return queryNonIndexableKeys(null); + case MATCH_SITE_MAP_PAIRS_CODE: + return querySiteMapPairs(); + case MATCH_SLICE_URI_PAIRS_CODE: + return querySliceUriPairs(); + default: + throw new UnsupportedOperationException("Unknown Uri " + uri); + } + } catch (UnsupportedOperationException e) { + throw e; + } catch (Exception e) { + Log.e(TAG, "Provider querying exception:", e); + return null; } } diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index b8174e66e8a6..7c80a0bff2f5 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -5607,11 +5607,23 @@ public final class Settings { * * @hide */ + @SystemApi public static final String ODI_CAPTIONS_ENABLED = "odi_captions_enabled"; 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. @@ -8978,6 +8990,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/service/autofill/augmented/AugmentedAutofillService.java b/core/java/android/service/autofill/augmented/AugmentedAutofillService.java index 34ced177fed1..96b861b46dd4 100644 --- a/core/java/android/service/autofill/augmented/AugmentedAutofillService.java +++ b/core/java/android/service/autofill/augmented/AugmentedAutofillService.java @@ -427,7 +427,7 @@ public abstract class AugmentedAutofillService extends Service { mFocusedValue = focusedValue; if (mCallback != null) { try { - if (mCallback.isCompleted()) { + if (!mCallback.isCompleted()) { mCallback.cancel(); } } catch (RemoteException e) { diff --git a/core/java/android/service/contentcapture/ActivityEvent.java b/core/java/android/service/contentcapture/ActivityEvent.java index 5407c1d9b832..fc781c2035f6 100644 --- a/core/java/android/service/contentcapture/ActivityEvent.java +++ b/core/java/android/service/contentcapture/ActivityEvent.java @@ -52,11 +52,17 @@ public final class ActivityEvent implements Parcelable { */ public static final int TYPE_ACTIVITY_STOPPED = Event.ACTIVITY_STOPPED; + /** + * The activity was destroyed. + */ + public static final int TYPE_ACTIVITY_DESTROYED = Event.ACTIVITY_DESTROYED; + /** @hide */ @IntDef(prefix = { "TYPE_" }, value = { TYPE_ACTIVITY_RESUMED, TYPE_ACTIVITY_PAUSED, - TYPE_ACTIVITY_STOPPED + TYPE_ACTIVITY_STOPPED, + TYPE_ACTIVITY_DESTROYED }) @Retention(RetentionPolicy.SOURCE) public @interface ActivityEventType{} @@ -81,7 +87,8 @@ public final class ActivityEvent implements Parcelable { /** * Gets the event type. * - * @return either {@link #TYPE_ACTIVITY_RESUMED} or {@value #TYPE_ACTIVITY_PAUSED}. + * @return either {@link #TYPE_ACTIVITY_RESUMED}, {@value #TYPE_ACTIVITY_PAUSED}, + * {@value #TYPE_ACTIVITY_STOPPED}, or {@value #TYPE_ACTIVITY_DESTROYED}. */ @ActivityEventType public int getEventType() { @@ -97,6 +104,8 @@ public final class ActivityEvent implements Parcelable { return "ACTIVITY_PAUSED"; case TYPE_ACTIVITY_STOPPED: return "ACTIVITY_STOPPED"; + case TYPE_ACTIVITY_DESTROYED: + return "ACTIVITY_DESTROYED"; default: return "UKNOWN_TYPE: " + type; } diff --git a/core/java/android/service/contentcapture/ContentCaptureService.java b/core/java/android/service/contentcapture/ContentCaptureService.java index 6f4114d1d81a..df113979bacf 100644 --- a/core/java/android/service/contentcapture/ContentCaptureService.java +++ b/core/java/android/service/contentcapture/ContentCaptureService.java @@ -78,6 +78,21 @@ public abstract class ContentCaptureService extends Service { public static final String SERVICE_INTERFACE = "android.service.contentcapture.ContentCaptureService"; + /** + * Name under which a ContentCaptureService component publishes information about itself. + * + * <p>This meta-data should reference an XML resource containing a + * <code><{@link + * android.R.styleable#ContentCaptureService content-capture-service}></code> tag. + * + * <p>This is a a sample XML file configuring a ContentCaptureService: + * <pre> <content-capture-service + * android:settingsActivity="foo.bar.SettingsActivity" + * . . . + * /></pre> + */ + public static final String SERVICE_META_DATA = "android.content_capture"; + private Handler mHandler; private IContentCaptureServiceCallback mCallback; diff --git a/core/java/android/service/contentcapture/ContentCaptureServiceInfo.java b/core/java/android/service/contentcapture/ContentCaptureServiceInfo.java new file mode 100644 index 000000000000..6ecd82f50fdb --- /dev/null +++ b/core/java/android/service/contentcapture/ContentCaptureServiceInfo.java @@ -0,0 +1,171 @@ +/* + * 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.service.contentcapture; + +import android.Manifest; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.UserIdInt; +import android.app.AppGlobals; +import android.content.ComponentName; +import android.content.Context; +import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; +import android.content.pm.ServiceInfo; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.content.res.XmlResourceParser; +import android.os.RemoteException; +import android.util.AttributeSet; +import android.util.Log; +import android.util.Slog; +import android.util.Xml; + +import com.android.internal.R; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.IOException; +import java.io.PrintWriter; + +/** + * {@link ServiceInfo} and meta-data about an {@link ContentCaptureService}. + * + * @hide + */ +public final class ContentCaptureServiceInfo { + + private static final String TAG = ContentCaptureServiceInfo.class.getSimpleName(); + private static final String XML_TAG_SERVICE = "content-capture-service"; + + private static ServiceInfo getServiceInfoOrThrow(ComponentName comp, boolean isTemp, + @UserIdInt int userId) throws PackageManager.NameNotFoundException { + int flags = PackageManager.GET_META_DATA; + if (!isTemp) { + flags |= PackageManager.MATCH_SYSTEM_ONLY; + } + + ServiceInfo si = null; + try { + si = AppGlobals.getPackageManager().getServiceInfo(comp, flags, userId); + } catch (RemoteException e) { + } + if (si == null) { + throw new NameNotFoundException("Could not get serviceInfo for " + + (isTemp ? " (temp)" : "(default system)") + + " " + comp.flattenToShortString()); + } + return si; + } + + @NonNull + private final ServiceInfo mServiceInfo; + + @Nullable + private final String mSettingsActivity; + + public ContentCaptureServiceInfo(@NonNull Context context, @NonNull ComponentName comp, + boolean isTemporaryService, @UserIdInt int userId) + throws PackageManager.NameNotFoundException { + this(context, getServiceInfoOrThrow(comp, isTemporaryService, userId)); + } + + private ContentCaptureServiceInfo(@NonNull Context context, @NonNull ServiceInfo si) { + // Check for permissions. + if (!Manifest.permission.BIND_CONTENT_CAPTURE_SERVICE.equals(si.permission)) { + Slog.w(TAG, "ContentCaptureService from '" + si.packageName + + "' does not require permission " + + Manifest.permission.BIND_CONTENT_CAPTURE_SERVICE); + throw new SecurityException("Service does not require permission " + + Manifest.permission.BIND_CONTENT_CAPTURE_SERVICE); + } + + mServiceInfo = si; + + // Get the metadata, if declared. + final XmlResourceParser parser = si.loadXmlMetaData(context.getPackageManager(), + ContentCaptureService.SERVICE_META_DATA); + if (parser == null) { + mSettingsActivity = null; + return; + } + + String settingsActivity = null; + + try { + final Resources resources = context.getPackageManager().getResourcesForApplication( + si.applicationInfo); + + int type = 0; + while (type != XmlPullParser.END_DOCUMENT && type != XmlPullParser.START_TAG) { + type = parser.next(); + } + + if (XML_TAG_SERVICE.equals(parser.getName())) { + final AttributeSet allAttributes = Xml.asAttributeSet(parser); + TypedArray afsAttributes = null; + try { + afsAttributes = resources.obtainAttributes(allAttributes, + com.android.internal.R.styleable.ContentCaptureService); + settingsActivity = afsAttributes.getString( + R.styleable.ContentCaptureService_settingsActivity); + } finally { + if (afsAttributes != null) { + afsAttributes.recycle(); + } + } + } else { + Log.e(TAG, "Meta-data does not start with content-capture-service tag"); + } + } catch (PackageManager.NameNotFoundException | IOException | XmlPullParserException e) { + Log.e(TAG, "Error parsing auto fill service meta-data", e); + } + + mSettingsActivity = settingsActivity; + } + + public ServiceInfo getServiceInfo() { + return mServiceInfo; + } + + @Nullable + public String getSettingsActivity() { + return mSettingsActivity; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append(getClass().getSimpleName()); + builder.append("[").append(mServiceInfo); + builder.append(", settings:").append(mSettingsActivity); + return builder.toString(); + } + + /** + * Dumps it! + */ + public void dump(@NonNull String prefix, @NonNull PrintWriter pw) { + pw.print(prefix); + pw.print("Component: "); + pw.println(getServiceInfo().getComponentName()); + pw.print(prefix); + pw.print("Settings: "); + pw.println(mSettingsActivity); + } +} 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/notification/StatusBarNotification.java b/core/java/android/service/notification/StatusBarNotification.java index cc74e1a329ed..8512a0bd8088 100644 --- a/core/java/android/service/notification/StatusBarNotification.java +++ b/core/java/android/service/notification/StatusBarNotification.java @@ -292,9 +292,9 @@ public class StatusBarNotification implements Parcelable { return uid; } - /** The package that posted the notification. - *<p> - * Might be different from {@link #getPackageName()} if the app owning the notification has + /** + * The package that posted the notification. + * <p> Might be different from {@link #getPackageName()} if the app owning the notification has * a {@link NotificationManager#setNotificationDelegate(String) notification delegate}. */ public @NonNull String getOpPkg() { diff --git a/core/java/android/text/style/LineHeightSpan.java b/core/java/android/text/style/LineHeightSpan.java index 7fb0f950f583..610cf2c7c784 100644 --- a/core/java/android/text/style/LineHeightSpan.java +++ b/core/java/android/text/style/LineHeightSpan.java @@ -70,7 +70,15 @@ public interface LineHeightSpan extends ParagraphStyle, WrapTogetherSpan { * Default implementation of the {@link LineHeightSpan}, which changes the line height of the * attached paragraph. * <p> - * LineHeightSpan will change the line height of the entire paragraph, even though it + * For example, a paragraph with its line height equal to 100px can be set like this: + * <pre> + * SpannableString string = new SpannableString("This is a multiline paragraph. This is a multiline paragraph."); + * string.setSpan(new LineHeightSpan.Standard(100), 0, string.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + * </pre> + * <img src="{@docRoot}reference/android/images/text/style/lineheightspan.png" /> + * <figcaption>Text with line height set to 100 pixels.</figcaption> + * <p> + * Notice that LineHeightSpan will change the line height of the entire paragraph, even though it * covers only part of the paragraph. * </p> */ 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/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/ISystemGestureExclusionListener.aidl b/core/java/android/view/ISystemGestureExclusionListener.aidl new file mode 100644 index 000000000000..a032625547d2 --- /dev/null +++ b/core/java/android/view/ISystemGestureExclusionListener.aidl @@ -0,0 +1,34 @@ +/** + * 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.view; + +import android.graphics.Region; + +/** + * Listener for changes to the system gesture exclusion region + * + * {@hide} + */ +oneway interface ISystemGestureExclusionListener { + /** + * Called when the system gesture exclusion for the given display changed. + * @param displayId the display whose system gesture exclusion changed + * @param systemGestureExclusion a {@code Region} where the app would like priority over the + * system gestures, in display coordinates. + */ + void onSystemGestureExclusionChanged(int displayId, in Region systemGestureExclusion); +}
\ No newline at end of file diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index 9ee6585d243f..b91b93f7e09c 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -40,6 +40,7 @@ import android.view.IOnKeyguardExitResult; import android.view.IPinnedStackListener; import android.view.RemoteAnimationAdapter; import android.view.IRotationWatcher; +import android.view.ISystemGestureExclusionListener; import android.view.IWallpaperVisibilityListener; import android.view.IWindowSession; import android.view.IWindowSessionCallback; @@ -281,6 +282,18 @@ interface IWindowManager int displayId); /** + * Registers a system gesture exclusion listener for a given display. + */ + void registerSystemGestureExclusionListener(ISystemGestureExclusionListener listener, + int displayId); + + /** + * Unregisters a system gesture exclusion listener for a given display. + */ + void unregisterSystemGestureExclusionListener(ISystemGestureExclusionListener listener, + int displayId); + + /** * Used only for assist -- request a screenshot of the current application. */ boolean requestAssistScreenshot(IAssistDataReceiver receiver); diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl index 1fcd4321cdde..87efb3fbf6c0 100644 --- a/core/java/android/view/IWindowSession.aidl +++ b/core/java/android/view/IWindowSession.aidl @@ -32,6 +32,8 @@ import android.view.InsetsState; import android.view.Surface; import android.view.SurfaceControl; +import java.util.List; + /** * System private per-application interface to the window manager. * @@ -265,4 +267,10 @@ interface IWindowSession { * that new state. */ void insetsModified(IWindow window, in InsetsState state); + + + /** + * Called when the system gesture exclusion has changed. + */ + void reportSystemGestureExclusionChanged(IWindow window, in List<Rect> exclusionRects); } diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index ab2cc6669631..75067d3668b3 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; @@ -11095,11 +11090,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * <p>Computes the coordinates of this view in its surface. The argument * must be an array of two integers. After the method returns, the array * contains the x and y location in that order.</p> - * @hide + * * @param location an array of two integers in which to hold the coordinates */ - @UnsupportedAppUsage - public void getLocationInSurface(@Size(2) int[] location) { + public void getLocationInSurface(@NonNull @Size(2) int[] location) { getLocationInWindow(location); if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) { location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left; @@ -14547,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; } } @@ -15293,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; } @@ -15321,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; @@ -15362,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; } @@ -15388,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; @@ -26057,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; @@ -26067,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); } } @@ -27625,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; } @@ -27654,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 { @@ -27670,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. diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index a28d6622c40f..6d04cd3187ef 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -3987,7 +3987,11 @@ public final class ViewRootImpl implements ViewParent, void systemGestureExclusionChanged() { final List<Rect> rectsForWindowManager = mGestureExclusionTracker.computeChangedRects(); if (rectsForWindowManager != null) { - // TODO Send to WM + try { + mWindowSession.reportSystemGestureExclusionChanged(mWindow, rectsForWindowManager); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } mAttachInfo.mTreeObserver .dispatchOnSystemGestureExclusionRectsChanged(rectsForWindowManager); } diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java index 8f1896d76b9c..8cb04cbdc994 100644 --- a/core/java/android/view/autofill/AutofillManager.java +++ b/core/java/android/view/autofill/AutofillManager.java @@ -228,6 +228,9 @@ 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_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,10 @@ public final class AutofillManager { @Nullable private final AutofillOptions mOptions; + /** When set, session is only used for augmented autofill requests. */ + @GuardedBy("mLock") + private boolean mForAugmentedAutofillOnly; + /** @hide */ public interface AutofillClient { /** @@ -940,9 +947,8 @@ public final class AutofillManager { ensureServiceClientAddedIfNeededLocked(); if (!mEnabled) { - if (sVerbose) { - Log.v(TAG, "ignoring notifyViewEntered(" + id + "): disabled"); - } + if (sVerbose) Log.v(TAG, "ignoring notifyViewEntered(" + id + "): disabled"); + if (mCallback != null) { callback = mCallback; } @@ -1025,6 +1031,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(); @@ -1168,6 +1180,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 +1237,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 @@ -1676,14 +1696,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(); @@ -2400,6 +2426,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/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/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java index 494eb0358ab9..a46580dcc539 100644 --- a/core/java/android/webkit/WebSettings.java +++ b/core/java/android/webkit/WebSettings.java @@ -245,10 +245,11 @@ public abstract class WebSettings { /** * Used with {@link #setForceDark} * - * Enable force dark, dependent on the state of the WebView parent. If the WebView parent view - * is being automatically rendered in dark mode, then WebView content will be rendered so as to - * emulate a dark theme. WebViews that are not attached to the view hierarchy will not be - * inverted. + * Enable force dark dependent on the state of the WebView parent view. If the WebView parent + * view is being automatically force darkened + * (see: {@link android.view.View#setForceDarkAllowed}), then WebView content will be rendered + * so as to emulate a dark theme. WebViews that are not attached to the view hierarchy will not + * be inverted. */ public static final int FORCE_DARK_AUTO = 1; @@ -1466,6 +1467,8 @@ public abstract class WebSettings { /** * Set the force dark mode for this WebView. + * + * @param forceDark the force dark mode to set. */ public void setForceDark(@ForceDark int forceDark) { // Stub implementation to satisfy Roboelectrc shadows that don't override this yet. @@ -1474,6 +1477,8 @@ public abstract class WebSettings { /** * Get the force dark mode for this WebView. * + * The default force dark mode is {@link #FORCE_DARK_AUTO} + * * @return the currently set force dark mode. */ public @ForceDark int getForceDark() { diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index b6ec5f936fbd..c9ef038b78de 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -4984,9 +4984,6 @@ public class Editor { if (magnifierTopLeft == null) { return; } - final Rect surfaceInsets = - mTextView.getViewRootImpl().mWindowAttributes.surfaceInsets; - magnifierTopLeft.offset(-surfaceInsets.left, -surfaceInsets.top); final Rect magnifierRect = new Rect(magnifierTopLeft.x, magnifierTopLeft.y, magnifierTopLeft.x + mMagnifierAnimator.mMagnifier.getWidth(), magnifierTopLeft.y + mMagnifierAnimator.mMagnifier.getHeight()); diff --git a/core/java/android/widget/Magnifier.java b/core/java/android/widget/Magnifier.java index 50e883679eb9..08799cfb5d4c 100644 --- a/core/java/android/widget/Magnifier.java +++ b/core/java/android/widget/Magnifier.java @@ -471,13 +471,13 @@ public final class Magnifier { } /** - * Returns the top left coordinates of the magnifier, relative to the surface of the - * main application window. They will be determined by the coordinates of the last - * {@link #show(float, float)} or {@link #show(float, float, float, float)} call, adjusted - * to take into account any potential clamping behavior. The method can be used immediately - * after a #show call to find out where the magnifier will be positioned. However, the - * position of the magnifier will not be updated in the same frame due to the async - * copying of the content copying and of the magnifier rendering. + * Returns the top left coordinates of the magnifier, relative to the main application + * window. They will be determined by the coordinates of the last {@link #show(float, float)} + * or {@link #show(float, float, float, float)} call, adjusted to take into account any + * potential clamping behavior. The method can be used immediately after a #show + * call to find out where the magnifier will be positioned. However, the position of the + * magnifier will not be updated visually in the same frame, due to the async nature of + * the content copying and of the magnifier rendering. * The method will return {@code null} if #show has not yet been called, or if the last * operation performed was a #dismiss. * @@ -488,15 +488,18 @@ public final class Magnifier { if (mWindow == null) { return null; } - return new Point(getCurrentClampedWindowCoordinates()); + final Point position = getCurrentClampedWindowCoordinates(); + position.offset(-mParentSurface.mInsets.left, -mParentSurface.mInsets.top); + return new Point(position); } /** * Returns the top left coordinates of the magnifier source (i.e. the view region going to - * be magnified and copied to the magnifier), relative to the surface the content is copied - * from. The content will be copied: + * be magnified and copied to the magnifier), relative to the window or surface the content + * is copied from. The content will be copied: * - if the magnified view is a {@link SurfaceView}, from the surface backing it - * - otherwise, from the surface of the main application window + * - otherwise, from the surface backing the main application window, and the coordinates + * returned will be relative to the main application window * The method will return {@code null} if #show has not yet been called, or if the last * operation performed was a #dismiss. * @@ -507,7 +510,9 @@ public final class Magnifier { if (mWindow == null) { return null; } - return new Point(mPixelCopyRequestRect.left, mPixelCopyRequestRect.top); + final Point position = new Point(mPixelCopyRequestRect.left, mPixelCopyRequestRect.top); + position.offset(-mContentCopySurface.mInsets.left, -mContentCopySurface.mInsets.top); + return new Point(position); } /** @@ -531,7 +536,7 @@ public final class Magnifier { viewRootImpl.getHeight() + surfaceInsets.top + surfaceInsets.bottom; validMainWindowSurface = new SurfaceInfo(viewRootImpl.getSurfaceControl(), mainWindowSurface, - surfaceWidth, surfaceHeight, true); + surfaceWidth, surfaceHeight, surfaceInsets, true); } } // Get the surface backing the magnified view, if it is a SurfaceView. @@ -544,7 +549,7 @@ public final class Magnifier { if (sc != null && sc.isValid()) { final Rect surfaceFrame = surfaceHolder.getSurfaceFrame(); validSurfaceViewSurface = new SurfaceInfo(sc, surfaceViewSurface, - surfaceFrame.right, surfaceFrame.bottom, false); + surfaceFrame.right, surfaceFrame.bottom, new Rect(), false); } } @@ -708,9 +713,13 @@ public final class Magnifier { final Rect windowBounds; if (mParentSurface.mIsMainWindowSurface) { final Insets systemInsets = mView.getRootWindowInsets().getSystemWindowInsets(); - windowBounds = new Rect(systemInsets.left, systemInsets.top, - mParentSurface.mWidth - systemInsets.right, - mParentSurface.mHeight - systemInsets.bottom); + windowBounds = new Rect( + systemInsets.left + mParentSurface.mInsets.left, + systemInsets.top + mParentSurface.mInsets.top, + mParentSurface.mWidth - systemInsets.right - mParentSurface.mInsets.right, + mParentSurface.mHeight - systemInsets.bottom + - mParentSurface.mInsets.bottom + ); } else { windowBounds = new Rect(0, 0, mParentSurface.mWidth, mParentSurface.mHeight); } @@ -725,21 +734,23 @@ public final class Magnifier { * Contains a surface and metadata corresponding to it. */ private static class SurfaceInfo { - public static final SurfaceInfo NULL = new SurfaceInfo(null, null, 0, 0, false); + public static final SurfaceInfo NULL = new SurfaceInfo(null, null, 0, 0, null, false); private Surface mSurface; private SurfaceControl mSurfaceControl; private int mWidth; private int mHeight; + private Rect mInsets; private boolean mIsMainWindowSurface; SurfaceInfo(final SurfaceControl surfaceControl, final Surface surface, - final int width, final int height, + final int width, final int height, final Rect insets, final boolean isMainWindowSurface) { mSurfaceControl = surfaceControl; mSurface = surface; mWidth = width; mHeight = height; + mInsets = insets; mIsMainWindowSurface = isMainWindowSurface; } } diff --git a/core/java/android/widget/TEST_MAPPING b/core/java/android/widget/TEST_MAPPING new file mode 100644 index 000000000000..ee378ff72218 --- /dev/null +++ b/core/java/android/widget/TEST_MAPPING @@ -0,0 +1,12 @@ +{ + "presubmit": [ + { + "name": "CtsWidgetTestCases", + "options": [ + { + "instrumentation-arg": "size:=small" + } + ] + } + ] +} 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/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/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/widget/PointerLocationView.java b/core/java/com/android/internal/widget/PointerLocationView.java index 4773e168fffa..3205b5aef281 100644 --- a/core/java/com/android/internal/widget/PointerLocationView.java +++ b/core/java/com/android/internal/widget/PointerLocationView.java @@ -20,12 +20,16 @@ import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Paint.FontMetricsInt; +import android.graphics.Path; import android.graphics.RectF; +import android.graphics.Region; import android.hardware.input.InputManager; import android.hardware.input.InputManager.InputDeviceListener; +import android.os.RemoteException; import android.os.SystemProperties; import android.util.Log; import android.util.Slog; +import android.view.ISystemGestureExclusionListener; import android.view.InputDevice; import android.view.KeyEvent; import android.view.MotionEvent; @@ -34,6 +38,7 @@ import android.view.VelocityTracker; import android.view.View; import android.view.ViewConfiguration; import android.view.WindowInsets; +import android.view.WindowManagerGlobal; import android.view.WindowManagerPolicyConstants.PointerEventListener; import java.util.ArrayList; @@ -124,12 +129,16 @@ public class PointerLocationView extends View implements InputDeviceListener, private int mActivePointerId; private final ArrayList<PointerState> mPointers = new ArrayList<PointerState>(); private final PointerCoords mTempCoords = new PointerCoords(); - + + private final Region mSystemGestureExclusion = new Region(); + private final Path mSystemGestureExclusionPath = new Path(); + private final Paint mSystemGestureExclusionPaint; + private final VelocityTracker mVelocity; private final VelocityTracker mAltVelocity; private final FasterStringBuilder mText = new FasterStringBuilder(); - + private boolean mPrintCoords = true; public PointerLocationView(Context c) { @@ -168,7 +177,11 @@ public class PointerLocationView extends View implements InputDeviceListener, mPathPaint.setARGB(255, 0, 96, 255); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeWidth(1); - + + mSystemGestureExclusionPaint = new Paint(); + mSystemGestureExclusionPaint.setARGB(25, 255, 0, 0); + mSystemGestureExclusionPaint.setStyle(Paint.Style.FILL_AND_STROKE); + PointerState ps = new PointerState(); mPointers.add(ps); mActivePointerId = 0; @@ -236,6 +249,12 @@ public class PointerLocationView extends View implements InputDeviceListener, final int NP = mPointers.size(); + if (!mSystemGestureExclusion.isEmpty()) { + mSystemGestureExclusionPath.reset(); + mSystemGestureExclusion.getBoundaryPath(mSystemGestureExclusionPath); + canvas.drawPath(mSystemGestureExclusionPath, mSystemGestureExclusionPaint); + } + // Labels if (mActivePointerId >= 0) { final PointerState ps = mPointers.get(mActivePointerId); @@ -719,6 +738,12 @@ public class PointerLocationView extends View implements InputDeviceListener, super.onAttachedToWindow(); mIm.registerInputDeviceListener(this, getHandler()); + try { + WindowManagerGlobal.getWindowManagerService().registerSystemGestureExclusionListener( + mSystemGestureExclusionListener, mContext.getDisplayId()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } logInputDevices(); } @@ -727,6 +752,12 @@ public class PointerLocationView extends View implements InputDeviceListener, super.onDetachedFromWindow(); mIm.unregisterInputDeviceListener(this); + try { + WindowManagerGlobal.getWindowManagerService().unregisterSystemGestureExclusionListener( + mSystemGestureExclusionListener, mContext.getDisplayId()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } @Override @@ -876,4 +907,17 @@ public class PointerLocationView extends View implements InputDeviceListener, return oldLength; } } + + private ISystemGestureExclusionListener mSystemGestureExclusionListener = + new ISystemGestureExclusionListener.Stub() { + @Override + public void onSystemGestureExclusionChanged(int displayId, Region systemGestureExclusion) { + Region exclusion = Region.obtain(systemGestureExclusion); + getHandler().post(() -> { + mSystemGestureExclusion.set(exclusion); + exclusion.recycle(); + invalidate(); + }); + } + }; } 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 7ad922312fa9..f03740725fe1 100644 --- a/core/proto/android/app/settings_enums.proto +++ b/core/proto/android/app/settings_enums.proto @@ -2305,4 +2305,8 @@ enum PageId { // Open: Settings > Special App Access > Do not disturb control for app ZEN_ACCESS_DETAIL = 1692; + + // OPEN: Settings > Face > Remove face + // OS: Q + DIALOG_FACE_REMOVE = 1693; } diff --git a/core/proto/android/service/notification.proto b/core/proto/android/service/notification.proto index c08d7cafd9cc..4ef26dd59240 100644 --- a/core/proto/android/service/notification.proto +++ b/core/proto/android/service/notification.proto @@ -66,6 +66,10 @@ message NotificationRecordProto { optional bool can_show_light = 8; optional string group_key = 9 [ (.android.privacy).dest = DEST_EXPLICIT ]; optional sint32 importance = 10; + // The package the notification was posted for. + optional string package = 11; + // The package that posted the notification. It might not be the same as package. + optional string delegate_package = 12; } message ListenersDisablingEffectsProto { diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index c7417bffb790..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. --> @@ -3929,6 +3927,10 @@ <permission android:name="android.permission.MANAGE_ROLLBACKS" android:protectionLevel="signature|verifier" /> + <!-- @SystemApi @TestApi @hide Allows testing apk level rollbacks. --> + <permission android:name="android.permission.TEST_MANAGE_ROLLBACKS" + android:protectionLevel="signature" /> + <!-- @SystemApi @hide Allows an application to mark other applications as harmful --> <permission android:name="android.permission.SET_HARMFUL_APP_WARNINGS" android:protectionLevel="signature|verifier" /> diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 743496fdffb5..9d48fe384f3f 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -8108,7 +8108,7 @@ <!-- Use <code>autofill-service</code> as the root tag of the XML resource that describes a {@link android.service.autofill.AutofillService}, which is referenced from its - {@link android.service.autofill#SERVICE_META_DATA} meta-data entry. + {@link android.service.autofill.AutofillService#SERVICE_META_DATA} meta-data entry. --> <declare-styleable name="AutofillService"> <!-- Fully qualified class name of an activity that allows the user to modify @@ -8134,6 +8134,23 @@ </declare-styleable> <!-- =============================== --> + <!-- Content Capture attributes --> + <!-- =============================== --> + <eat-comment /> + + <!-- Use <code>content-capture-service</code> as the root tag of the XML resource that describes + a {@link android.service.contentcapture.ContentCaptureService}, which is referenced from + its {@link android.service.contentcapture.ContentCaptureService#SERVICE_META_DATA} + meta-data entry. + @hide @SystemApi + --> + <declare-styleable name="ContentCaptureService"> + <!-- Fully qualified class name of an activity that allows the user to modify + the settings for this service. --> + <attr name="settingsActivity" /> + </declare-styleable> + + <!-- =============================== --> <!-- Contacts meta-data attributes --> <!-- =============================== --> <eat-comment /> diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java index 7322a5445e86..6fb4744f6a77 100644 --- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java +++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java @@ -656,6 +656,7 @@ 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, 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/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/assets/package-name.txt b/core/tests/overlaytests/device/assets/package-name.txt new file mode 100644 index 000000000000..809443818f06 --- /dev/null +++ b/core/tests/overlaytests/device/assets/package-name.txt @@ -0,0 +1 @@ +com.android.overlaytest diff --git a/core/tests/overlaytests/device/src/com/android/overlaytest/OverlayBaseTest.java b/core/tests/overlaytests/device/src/com/android/overlaytest/OverlayBaseTest.java index 91fcdbbb18ce..f86743a2fdbc 100644 --- a/core/tests/overlaytests/device/src/com/android/overlaytest/OverlayBaseTest.java +++ b/core/tests/overlaytests/device/src/com/android/overlaytest/OverlayBaseTest.java @@ -17,9 +17,12 @@ package com.android.overlaytest; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import android.app.UiAutomation; +import android.content.res.AssetManager; import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.XmlResourceParser; @@ -30,6 +33,8 @@ import android.util.Xml; import androidx.test.InstrumentationRegistry; +import com.android.internal.util.ArrayUtils; + import org.junit.Before; import org.junit.Ignore; import org.junit.Test; @@ -291,6 +296,33 @@ public abstract class OverlayBaseTest { assertEquals(getExpected(no, so, mo), actual); } + @Test + public void testAssetsNotPossibleToOverlay() throws Throwable { + final AssetManager am = mResources.getAssets(); + + // AssetManager#list will include assets from all loaded non-overlay + // APKs, including the framework; framework-res.apk contains at least + // assets/{images,webkit}. Rather than checking the list, verify that + // assets only present in overlays are never part of the list. + String[] files = am.list(""); + assertTrue(ArrayUtils.contains(files, "package-name.txt")); + assertFalse(ArrayUtils.contains(files, "foo.txt")); + assertFalse(ArrayUtils.contains(files, "bar.txt")); + + String contents = null; + try (InputStream is = am.open("package-name.txt")) { + final BufferedReader reader = new BufferedReader( + new InputStreamReader(is, StandardCharsets.UTF_8)); + StringBuilder str = new StringBuilder(); + String line; + while ((line = reader.readLine()) != null) { + str.append(line); + } + contents = str.toString(); + } + assertEquals("com.android.overlaytest", contents); + } + /* * testMatrix* tests * 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/AppOverlayOne/assets/foo.txt b/core/tests/overlaytests/device/test-apps/AppOverlayOne/assets/foo.txt new file mode 100644 index 000000000000..257cc5642cb1 --- /dev/null +++ b/core/tests/overlaytests/device/test-apps/AppOverlayOne/assets/foo.txt @@ -0,0 +1 @@ +foo diff --git a/core/tests/overlaytests/device/test-apps/AppOverlayOne/assets/package-name.txt b/core/tests/overlaytests/device/test-apps/AppOverlayOne/assets/package-name.txt new file mode 100644 index 000000000000..087cb96b767f --- /dev/null +++ b/core/tests/overlaytests/device/test-apps/AppOverlayOne/assets/package-name.txt @@ -0,0 +1 @@ +com.android.overlaytest.app_overlay_one 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/AppOverlayTwo/assets/bar.txt b/core/tests/overlaytests/device/test-apps/AppOverlayTwo/assets/bar.txt new file mode 100644 index 000000000000..5716ca5987cb --- /dev/null +++ b/core/tests/overlaytests/device/test-apps/AppOverlayTwo/assets/bar.txt @@ -0,0 +1 @@ +bar diff --git a/core/tests/overlaytests/device/test-apps/AppOverlayTwo/assets/package-name.txt b/core/tests/overlaytests/device/test-apps/AppOverlayTwo/assets/package-name.txt new file mode 100644 index 000000000000..13185654df21 --- /dev/null +++ b/core/tests/overlaytests/device/test-apps/AppOverlayTwo/assets/package-name.txt @@ -0,0 +1 @@ +com.android.overlaytest.app_overlay_two 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..94f69b8905d6 100644 --- a/data/etc/privapp-permissions-platform.xml +++ b/data/etc/privapp-permissions-platform.xml @@ -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/docs/html/reference/images/text/style/lineheightspan.png b/docs/html/reference/images/text/style/lineheightspan.png Binary files differnew file mode 100644 index 000000000000..18f575392b63 --- /dev/null +++ b/docs/html/reference/images/text/style/lineheightspan.png diff --git a/graphics/java/android/graphics/ColorSpace.java b/graphics/java/android/graphics/ColorSpace.java index 0d5233880674..9c4b5e8b0165 100644 --- a/graphics/java/android/graphics/ColorSpace.java +++ b/graphics/java/android/graphics/ColorSpace.java @@ -1809,6 +1809,45 @@ public abstract class ColorSpace { } /** + * <p>Computes the chromaticity coordinates of a specified correlated color + * temperature (CCT) on the Planckian locus. The specified CCT must be + * greater than 0. A meaningful CCT range is [1667, 25000].</p> + * + * <p>The transform is computed using the methods in Kang et + * al., <i>Design of Advanced Color - Temperature Control System for HDTV + * Applications</i>, Journal of Korean Physical Society 41, 865-871 + * (2002).</p> + * + * @param cct The correlated color temperature, in Kelvin + * @return Corresponding XYZ values + * @throws IllegalArgumentException If cct is invalid + * + * @hide + */ + @NonNull + @Size(3) + public static float[] cctToXyz(@IntRange(from = 1) int cct) { + if (cct < 1) { + throw new IllegalArgumentException("Temperature must be greater than 0"); + } + + final float icct = 1e3f / cct; + final float icct2 = icct * icct; + final float x = cct <= 4000.0f ? + 0.179910f + 0.8776956f * icct - 0.2343589f * icct2 - 0.2661239f * icct2 * icct : + 0.240390f + 0.2226347f * icct + 2.1070379f * icct2 - 3.0258469f * icct2 * icct; + + final float x2 = x * x; + final float y = cct <= 2222.0f ? + -0.20219683f + 2.18555832f * x - 1.34811020f * x2 - 1.1063814f * x2 * x : + cct <= 4000.0f ? + -0.16748867f + 2.09137015f * x - 1.37418593f * x2 - 0.9549476f * x2 * x : + -0.37001483f + 3.75112997f * x - 5.8733867f * x2 + 3.0817580f * x2 * x; + + return xyYToXyz(new float[] {x, y}); + } + + /** * <p>Computes the chromaticity coordinates of a CIE series D illuminant * from the specified correlated color temperature (CCT). The specified CCT * must be greater than 0. A meaningful CCT range is [4000, 25000].</p> diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java index 9995f1e73018..c8b361bbff2f 100644 --- a/graphics/java/android/graphics/Typeface.java +++ b/graphics/java/android/graphics/Typeface.java @@ -33,7 +33,6 @@ import android.graphics.fonts.FontStyle; import android.graphics.fonts.FontVariationAxis; import android.graphics.fonts.SystemFonts; import android.os.Build; -import android.os.Build.VERSION_CODES; import android.os.ParcelFileDescriptor; import android.provider.FontRequest; import android.provider.FontsContract; @@ -48,7 +47,6 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.Preconditions; import dalvik.annotation.optimization.CriticalNative; -import dalvik.system.VMRuntime; import libcore.util.NativeAllocationRegistry; @@ -266,16 +264,7 @@ public class Typeface { if (familyBuilder == null) { familyBuilder = new FontFamily.Builder(fontBuilder.build()); } else { - try { - familyBuilder.addFont(fontBuilder.build()); - } catch (IllegalArgumentException e) { - if (VMRuntime.getRuntime().getTargetSdkVersion() <= VERSION_CODES.P) { - // Surpress the IllegalArgumentException for keeping the backward - // compatibility. - continue; - } - throw e; - } + familyBuilder.addFont(fontBuilder.build()); } } if (familyBuilder == null) { @@ -297,6 +286,10 @@ public class Typeface { typeface = new Typeface.CustomFallbackBuilder(family) .setStyle(bestFont.getStyle()) .build(); + } catch (IllegalArgumentException e) { + // To be a compatible behavior with API28 or before, catch IllegalArgumentExcetpion + // thrown by native code and returns null. + return null; } catch (IOException e) { typeface = Typeface.DEFAULT; } diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp index d74f27cca200..951970464bfe 100644 --- a/libs/androidfw/AssetManager2.cpp +++ b/libs/androidfw/AssetManager2.cpp @@ -310,6 +310,9 @@ std::unique_ptr<AssetDir> AssetManager2::OpenDir(const std::string& dirname) con // Start from the back. for (auto iter = apk_assets_.rbegin(); iter != apk_assets_.rend(); ++iter) { const ApkAssets* apk_assets = *iter; + if (apk_assets->IsOverlay()) { + continue; + } auto func = [&](const StringPiece& name, FileType type) { AssetDir::FileInfo info; @@ -336,6 +339,13 @@ std::unique_ptr<Asset> AssetManager2::OpenNonAsset(const std::string& filename, Asset::AccessMode mode, ApkAssetsCookie* out_cookie) const { for (int32_t i = apk_assets_.size() - 1; i >= 0; i--) { + // Prevent RRO from modifying assets and other entries accessed by file + // path. Explicitly asking for a path in a given package (denoted by a + // cookie) is still OK. + if (apk_assets_[i]->IsOverlay()) { + continue; + } + std::unique_ptr<Asset> asset = apk_assets_[i]->Open(filename, mode); if (asset) { if (out_cookie != nullptr) { diff --git a/libs/androidfw/include/androidfw/ApkAssets.h b/libs/androidfw/include/androidfw/ApkAssets.h index db2d0382bcf6..35bbb5804df4 100644 --- a/libs/androidfw/include/androidfw/ApkAssets.h +++ b/libs/androidfw/include/androidfw/ApkAssets.h @@ -80,6 +80,10 @@ class ApkAssets { return loaded_arsc_.get(); } + inline bool IsOverlay() const { + return idmap_asset_.get() != nullptr; + } + private: DISALLOW_COPY_AND_ASSIGN(ApkAssets); diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h index 9298be65c5e8..5f43b488bcf2 100644 --- a/libs/hwui/renderthread/RenderThread.h +++ b/libs/hwui/renderthread/RenderThread.h @@ -41,6 +41,7 @@ namespace android { class Bitmap; +class AutoBackendTextureRelease; namespace uirenderer { @@ -135,6 +136,7 @@ private: friend class DispatchFrameCallbacks; friend class RenderProxy; friend class DummyVsyncSource; + friend class android::AutoBackendTextureRelease; friend class android::uirenderer::TestUtils; friend class android::uirenderer::WebViewFunctor; friend class android::uirenderer::skiapipeline::VkFunctorDrawHandler; diff --git a/libs/hwui/surfacetexture/ImageConsumer.cpp b/libs/hwui/surfacetexture/ImageConsumer.cpp index 077a8f73b0da..65d95ad36a6f 100644 --- a/libs/hwui/surfacetexture/ImageConsumer.cpp +++ b/libs/hwui/surfacetexture/ImageConsumer.cpp @@ -24,13 +24,17 @@ #include "renderthread/VulkanManager.h" #include "utils/Color.h" #include <GrAHardwareBufferUtils.h> +#include <GrBackendSurface.h> // Macro for including the SurfaceTexture name in log messages #define IMG_LOGE(x, ...) ALOGE("[%s] " x, st.mName.string(), ##__VA_ARGS__) +using namespace android::uirenderer::renderthread; + namespace android { void ImageConsumer::onFreeBufferLocked(int slotIndex) { + // This callback may be invoked on any thread. mImageSlots[slotIndex].clear(); } @@ -46,55 +50,141 @@ void ImageConsumer::onReleaseBufferLocked(int buf) { mImageSlots[buf].eglFence() = EGL_NO_SYNC_KHR; } +/** + * AutoBackendTextureRelease manages EglImage/VkImage lifetime. It is a ref-counted object + * that keeps GPU resources alive until the last SKImage object using them is destroyed. + */ +class AutoBackendTextureRelease { +public: + static void releaseProc(SkImage::ReleaseContext releaseContext); + + AutoBackendTextureRelease(GrContext* context, GraphicBuffer* buffer); + + const GrBackendTexture& getTexture() const { return mBackendTexture; } + + void ref() { mUsageCount++; } + + void unref(bool releaseImage); + + inline sk_sp<SkImage> getImage() { return mImage; } + + void makeImage(sp<GraphicBuffer>& graphicBuffer, android_dataspace dataspace, + GrContext* context); + +private: + // The only way to invoke dtor is with unref, when mUsageCount is 0. + ~AutoBackendTextureRelease() {} + + GrBackendTexture mBackendTexture; + GrAHardwareBufferUtils::DeleteImageProc mDeleteProc; + GrAHardwareBufferUtils::DeleteImageCtx mDeleteCtx; + + // Starting with refcount 1, because the first ref is held by SurfaceTexture. Additional refs + // are held by SkImages. + int mUsageCount = 1; + + // mImage is the SkImage created from mBackendTexture. + sk_sp<SkImage> mImage; +}; + +AutoBackendTextureRelease::AutoBackendTextureRelease(GrContext* context, GraphicBuffer* buffer) { + bool createProtectedImage = + 0 != (buffer->getUsage() & GraphicBuffer::USAGE_PROTECTED); + GrBackendFormat backendFormat = GrAHardwareBufferUtils::GetBackendFormat( + context, + reinterpret_cast<AHardwareBuffer*>(buffer), + buffer->getPixelFormat(), + false); + mBackendTexture = GrAHardwareBufferUtils::MakeBackendTexture( + context, + reinterpret_cast<AHardwareBuffer*>(buffer), + buffer->getWidth(), + buffer->getHeight(), + &mDeleteProc, + &mDeleteCtx, + createProtectedImage, + backendFormat, + false); +} + +void AutoBackendTextureRelease::unref(bool releaseImage) { + if (!RenderThread::isCurrent()) { + // EGLImage needs to be destroyed on RenderThread to prevent memory leak. + // ~SkImage dtor for both pipelines needs to be invoked on RenderThread, because it is not + // thread safe. + RenderThread::getInstance().queue().post([this, releaseImage]() { unref(releaseImage); }); + return; + } + + if (releaseImage) { + mImage.reset(); + } + + mUsageCount--; + if (mUsageCount <= 0) { + if (mBackendTexture.isValid()) { + mDeleteProc(mDeleteCtx); + mBackendTexture = {}; + } + delete this; + } +} + +void AutoBackendTextureRelease::releaseProc(SkImage::ReleaseContext releaseContext) { + AutoBackendTextureRelease* textureRelease = + reinterpret_cast<AutoBackendTextureRelease*>(releaseContext); + textureRelease->unref(false); +} + +void AutoBackendTextureRelease::makeImage(sp<GraphicBuffer>& graphicBuffer, + android_dataspace dataspace, GrContext* context) { + SkColorType colorType = GrAHardwareBufferUtils::GetSkColorTypeFromBufferFormat( + graphicBuffer->getPixelFormat()); + mImage = SkImage::MakeFromTexture(context, + mBackendTexture, + kTopLeft_GrSurfaceOrigin, + colorType, + kPremul_SkAlphaType, + uirenderer::DataSpaceToColorSpace(dataspace), + releaseProc, + this); + if (mImage.get()) { + // The following ref will be counteracted by releaseProc, when SkImage is discarded. + ref(); + } +} + void ImageConsumer::ImageSlot::createIfNeeded(sp<GraphicBuffer> graphicBuffer, android_dataspace dataspace, bool forceCreate, GrContext* context) { - if (!mImage.get() || dataspace != mDataspace || forceCreate) { + if (!mTextureRelease || !mTextureRelease->getImage().get() || dataspace != mDataspace + || forceCreate) { if (!graphicBuffer.get()) { clear(); return; } - if (!mBackendTexture.isValid()) { - clear(); - bool createProtectedImage = - 0 != (graphicBuffer->getUsage() & GraphicBuffer::USAGE_PROTECTED); - GrBackendFormat backendFormat = GrAHardwareBufferUtils::GetBackendFormat( - context, - reinterpret_cast<AHardwareBuffer*>(graphicBuffer.get()), - graphicBuffer->getPixelFormat(), - false); - mBackendTexture = GrAHardwareBufferUtils::MakeBackendTexture( - context, - reinterpret_cast<AHardwareBuffer*>(graphicBuffer.get()), - graphicBuffer->getWidth(), - graphicBuffer->getHeight(), - &mDeleteProc, - &mDeleteCtx, - createProtectedImage, - backendFormat, - false); + if (!mTextureRelease) { + mTextureRelease = new AutoBackendTextureRelease(context, graphicBuffer.get()); } + mDataspace = dataspace; - SkColorType colorType = GrAHardwareBufferUtils::GetSkColorTypeFromBufferFormat( - graphicBuffer->getPixelFormat()); - mImage = SkImage::MakeFromTexture(context, - mBackendTexture, - kTopLeft_GrSurfaceOrigin, - colorType, - kPremul_SkAlphaType, - uirenderer::DataSpaceToColorSpace(dataspace)); + mTextureRelease->makeImage(graphicBuffer, dataspace, context); } } void ImageConsumer::ImageSlot::clear() { - mImage.reset(); - if (mBackendTexture.isValid()) { - mDeleteProc(mDeleteCtx); - mBackendTexture = {}; + if (mTextureRelease) { + // The following unref counteracts the initial mUsageCount of 1, set by default initializer. + mTextureRelease->unref(true); + mTextureRelease = nullptr; } } +sk_sp<SkImage> ImageConsumer::ImageSlot::getImage() { + return mTextureRelease ? mTextureRelease->getImage() : nullptr; +} + sk_sp<SkImage> ImageConsumer::dequeueImage(bool* queueEmpty, SurfaceTexture& st, uirenderer::RenderState& renderState) { BufferItem item; diff --git a/libs/hwui/surfacetexture/ImageConsumer.h b/libs/hwui/surfacetexture/ImageConsumer.h index eee0a0ac3512..2fdece989876 100644 --- a/libs/hwui/surfacetexture/ImageConsumer.h +++ b/libs/hwui/surfacetexture/ImageConsumer.h @@ -25,7 +25,6 @@ #include <cutils/compiler.h> #include <gui/BufferItem.h> #include <system/graphics.h> -#include <GrBackendSurface.h> namespace GrAHardwareBufferUtils { typedef void* DeleteImageCtx; @@ -38,6 +37,7 @@ namespace uirenderer { class RenderState; } +class AutoBackendTextureRelease; class SurfaceTexture; /* @@ -81,16 +81,14 @@ private: void createIfNeeded(sp<GraphicBuffer> graphicBuffer, android_dataspace dataspace, bool forceCreate, GrContext* context); + void clear(); inline EGLSyncKHR& eglFence() { return mEglFence; } - inline sk_sp<SkImage> getImage() { return mImage; } + sk_sp<SkImage> getImage(); private: - // mImage is the SkImage created from mGraphicBuffer. - sk_sp<SkImage> mImage; - // the dataspace associated with the current image android_dataspace mDataspace; @@ -100,11 +98,11 @@ private: */ EGLSyncKHR mEglFence; - GrBackendTexture mBackendTexture; - - GrAHardwareBufferUtils::DeleteImageProc mDeleteProc; - - GrAHardwareBufferUtils::DeleteImageCtx mDeleteCtx; + /** + * mTextureRelease may outlive ImageConsumer, if the last ref is held by an SkImage. + * ImageConsumer holds one ref to mTextureRelease, which is decremented by "clear". + */ + AutoBackendTextureRelease* mTextureRelease = nullptr; }; /** 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/MediaPlayer2.java b/media/apex/java/android/media/MediaPlayer2.java index fbe184bf144f..13ff108b6e4f 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(); @@ -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/Session2Command.java b/media/apex/java/android/media/Session2Command.java index 20d6391526dd..6822ea56b5e8 100644 --- a/media/apex/java/android/media/Session2Command.java +++ b/media/apex/java/android/media/Session2Command.java @@ -32,6 +32,10 @@ import java.util.Objects; * If {@link #getCommandCode()} is {@link #COMMAND_CODE_CUSTOM}), it's custom command and * {@link #getCustomCommand()} shouldn't be {@code null}. * <p> + * Refer to the + * <a href="{@docRoot}reference/androidx/media2/SessionCommand2.html">AndroidX SessionCommand</a> + * class for the list of valid commands. + * <p> * This API is not generally intended for third party application developers. * Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a> * <a href="{@docRoot}reference/androidx/media2/package-summary.html">Media2 Library</a> 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/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/MediaFormat.java b/media/java/android/media/MediaFormat.java index 0e4fa14a41e4..8686c5905af7 100644 --- a/media/java/android/media/MediaFormat.java +++ b/media/java/android/media/MediaFormat.java @@ -1047,6 +1047,15 @@ public final class MediaFormat { */ public static final String KEY_CA_PRIVATE_DATA = "ca-private-data"; + /** + * A key describing the maximum number of B frames between I or P frames, + * to be used by a video encoder. + * The associated value is an integer. The default value is 0, which means + * that no B frames are allowed. Note that non-zero value does not guarantee + * B frames; it's up to the encoder to decide. + */ + public static final String KEY_MAX_BFRAMES = "max-bframes"; + /* package private */ MediaFormat(@NonNull Map<String, Object> map) { mMap = map; } 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/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/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java index a288d010e59b..bda5743d27f7 100644 --- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java +++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java @@ -52,6 +52,7 @@ import android.view.View; import android.webkit.CookieManager; import android.webkit.SslErrorHandler; import android.webkit.WebChromeClient; +import android.webkit.WebResourceRequest; import android.webkit.WebSettings; import android.webkit.WebView; import android.webkit.WebViewClient; @@ -409,8 +410,7 @@ public class CaptivePortalLoginActivity extends Activity { TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, getResources().getDisplayMetrics()); private int mPagesLoaded; - // the host of the page that this webview is currently loading. Can be null when undefined. - private String mHostname; + private String mMainFrameUrl; // If we haven't finished cleaning up the history, don't allow going back. public boolean allowBack() { @@ -436,7 +436,6 @@ public class CaptivePortalLoginActivity extends Activity { } final URL url = makeURL(urlString); Log.d(TAG, "onPageStarted: " + sanitizeURL(url)); - mHostname = host(url); // For internally generated pages, leave URL bar listing prior URL as this is the URL // the page refers to. if (!urlString.startsWith(INTERNAL_ASSETS)) { @@ -480,17 +479,28 @@ public class CaptivePortalLoginActivity extends Activity { return Integer.toString((int)dp) + "px"; } + // Check if webview is trying to load the main frame and record its url. + @Override + public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { + if (request.isForMainFrame()) { + mMainFrameUrl = request.getUrl().toString(); + } + return false; + } + // A web page consisting of a large broken lock icon to indicate SSL failure. @Override public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { - final URL url = makeURL(error.getUrl()); - final String host = host(url); + final URL errorUrl = makeURL(error.getUrl()); + final URL mainFrameUrl = makeURL(mMainFrameUrl); Log.d(TAG, String.format("SSL error: %s, url: %s, certificate: %s", - sslErrorName(error), sanitizeURL(url), error.getCertificate())); - if (url == null || !Objects.equals(host, mHostname)) { - // Ignore ssl errors for resources coming from a different hostname than the page - // that we are currently loading, and only cancel the request. + sslErrorName(error), sanitizeURL(errorUrl), error.getCertificate())); + if (errorUrl == null + // Ignore SSL errors from resources by comparing the main frame url with SSL + // error url. + || !errorUrl.equals(mainFrameUrl)) { + Log.d(TAG, "onReceivedSslError: mMainFrameUrl = " + mMainFrameUrl); handler.cancel(); return; } 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/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/bluetooth/BluetoothUtils.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java index 081f8a099cf5..bb8c8a6768ed 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java @@ -1,7 +1,6 @@ package com.android.settingslib.bluetooth; import android.bluetooth.BluetoothClass; -import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothProfile; import android.content.Context; import android.graphics.drawable.Drawable; @@ -10,7 +9,6 @@ import android.util.Pair; import androidx.annotation.DrawableRes; import com.android.settingslib.R; -import com.android.settingslib.graph.BluetoothDeviceLayerDrawable; import java.util.List; @@ -51,38 +49,29 @@ public class BluetoothUtils { public static Pair<Drawable, String> getBtClassDrawableWithDescription(Context context, CachedBluetoothDevice cachedDevice) { - return getBtClassDrawableWithDescription(context, cachedDevice, 1 /* iconScale */); - } - - public static Pair<Drawable, String> getBtClassDrawableWithDescription(Context context, - CachedBluetoothDevice cachedDevice, float iconScale) { BluetoothClass btClass = cachedDevice.getBtClass(); - final int level = cachedDevice.getBatteryLevel(); if (btClass != null) { switch (btClass.getMajorDeviceClass()) { case BluetoothClass.Device.Major.COMPUTER: return new Pair<>(getBluetoothDrawable(context, - com.android.internal.R.drawable.ic_bt_laptop, level, iconScale), + com.android.internal.R.drawable.ic_bt_laptop), context.getString(R.string.bluetooth_talkback_computer)); case BluetoothClass.Device.Major.PHONE: return new Pair<>( getBluetoothDrawable(context, - com.android.internal.R.drawable.ic_phone, level, - iconScale), + com.android.internal.R.drawable.ic_phone), context.getString(R.string.bluetooth_talkback_phone)); case BluetoothClass.Device.Major.PERIPHERAL: return new Pair<>( - getBluetoothDrawable(context, HidProfile.getHidClassDrawable(btClass), - level, iconScale), + getBluetoothDrawable(context, HidProfile.getHidClassDrawable(btClass)), context.getString(R.string.bluetooth_talkback_input_peripheral)); case BluetoothClass.Device.Major.IMAGING: return new Pair<>( getBluetoothDrawable(context, - com.android.internal.R.drawable.ic_settings_print, level, - iconScale), + com.android.internal.R.drawable.ic_settings_print), context.getString(R.string.bluetooth_talkback_imaging)); default: @@ -94,38 +83,33 @@ public class BluetoothUtils { for (LocalBluetoothProfile profile : profiles) { int resId = profile.getDrawableResource(btClass); if (resId != 0) { - return new Pair<>(getBluetoothDrawable(context, resId, level, iconScale), null); + return new Pair<>(getBluetoothDrawable(context, resId), null); } } if (btClass != null) { if (btClass.doesClassMatch(BluetoothClass.PROFILE_HEADSET)) { return new Pair<>( getBluetoothDrawable(context, - com.android.internal.R.drawable.ic_bt_headset_hfp, level, - iconScale), + com.android.internal.R.drawable.ic_bt_headset_hfp), context.getString(R.string.bluetooth_talkback_headset)); } if (btClass.doesClassMatch(BluetoothClass.PROFILE_A2DP)) { return new Pair<>( getBluetoothDrawable(context, - com.android.internal.R.drawable.ic_bt_headphones_a2dp, level, - iconScale), + com.android.internal.R.drawable.ic_bt_headphones_a2dp), context.getString(R.string.bluetooth_talkback_headphone)); } } return new Pair<>( getBluetoothDrawable(context, - com.android.internal.R.drawable.ic_settings_bluetooth, level, iconScale), + com.android.internal.R.drawable.ic_settings_bluetooth), context.getString(R.string.bluetooth_talkback_bluetooth)); } - public static Drawable getBluetoothDrawable(Context context, @DrawableRes int resId, - int batteryLevel, float iconScale) { - if (batteryLevel != BluetoothDevice.BATTERY_LEVEL_UNKNOWN) { - return BluetoothDeviceLayerDrawable.createLayerDrawable(context, resId, batteryLevel, - iconScale); - } else { - return context.getDrawable(resId); - } + /** + * Get bluetooth drawable by {@code resId} + */ + public static Drawable getBluetoothDrawable(Context context, @DrawableRes int resId) { + return context.getDrawable(resId); } } 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/bluetooth/BluetoothUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java index 7a71551bb367..b713e08eb67e 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java @@ -15,36 +15,55 @@ */ package com.android.settingslib.bluetooth; -import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; -import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothClass; +import android.content.Context; import android.graphics.drawable.Drawable; +import android.util.Pair; -import com.android.settingslib.graph.BluetoothDeviceLayerDrawable; - +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Answers; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; @RunWith(RobolectricTestRunner.class) public class BluetoothUtilsTest { + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private CachedBluetoothDevice mCachedBluetoothDevice; + private Context mContext; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + mContext = spy(RuntimeEnvironment.application); + } + @Test - public void testGetBluetoothDrawable_noBatteryLevel_returnSimpleDrawable() { - final Drawable drawable = BluetoothUtils.getBluetoothDrawable( - RuntimeEnvironment.application, com.android.internal.R.drawable.ic_bt_laptop, - BluetoothDevice.BATTERY_LEVEL_UNKNOWN, 1 /* iconScale */); + public void getBtClassDrawableWithDescription_typePhone_returnPhoneDrawable() { + when(mCachedBluetoothDevice.getBtClass().getMajorDeviceClass()).thenReturn( + BluetoothClass.Device.Major.PHONE); + final Pair<Drawable, String> pair = BluetoothUtils.getBtClassDrawableWithDescription( + mContext, mCachedBluetoothDevice); - assertThat(drawable).isNotInstanceOf(BluetoothDeviceLayerDrawable.class); + verify(mContext).getDrawable(com.android.internal.R.drawable.ic_phone); } @Test - public void testGetBluetoothDrawable_hasBatteryLevel_returnLayerDrawable() { - final Drawable drawable = BluetoothUtils.getBluetoothDrawable( - RuntimeEnvironment.application, com.android.internal.R.drawable.ic_bt_laptop, - 10 /* batteryLevel */, 1 /* iconScale */); + public void getBtClassDrawableWithDescription_typeComputer_returnComputerDrawable() { + when(mCachedBluetoothDevice.getBtClass().getMajorDeviceClass()).thenReturn( + BluetoothClass.Device.Major.COMPUTER); + final Pair<Drawable, String> pair = BluetoothUtils.getBtClassDrawableWithDescription( + mContext, mCachedBluetoothDevice); - assertThat(drawable).isInstanceOf(BluetoothDeviceLayerDrawable.class); + verify(mContext).getDrawable(com.android.internal.R.drawable.ic_bt_laptop); } -} +}
\ No newline at end of file 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 d639e5eca43d..441f88c193d6 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -86,6 +86,7 @@ <uses-permission android:name="android.permission.DELETE_CACHE_FILES" /> <uses-permission android:name="android.permission.DELETE_PACKAGES" /> <uses-permission android:name="android.permission.MANAGE_ROLLBACKS" /> + <uses-permission android:name="android.permission.TEST_MANAGE_ROLLBACKS" /> <uses-permission android:name="android.permission.ACCESS_SURFACE_FLINGER" /> <uses-permission android:name="android.permission.READ_FRAME_BUFFER" /> <uses-permission android:name="android.permission.DEVICE_POWER" /> @@ -178,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/res/layout/screen_record_dialog.xml b/packages/SystemUI/res/layout/screen_record_dialog.xml index 6c5c7fac3ed6..3d63b7d19c4f 100644 --- a/packages/SystemUI/res/layout/screen_record_dialog.xml +++ b/packages/SystemUI/res/layout/screen_record_dialog.xml @@ -5,26 +5,25 @@ android:clipChildren="false" android:clipToPadding="false" android:gravity="top" - android:orientation="vertical"> - - <Space - android:layout_width="match_parent" - android:layout_height="10dp"/> + android:orientation="vertical" + android:padding="@dimen/global_actions_padding" + android:background="@drawable/rounded_bg_full"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" - android:orientation="vertical" - android:background="@android:color/white"> + android:orientation="vertical"> <CheckBox android:id="@+id/checkbox_mic" android:layout_width="match_parent" android:layout_height="wrap_content" + android:textAppearance="?android:attr/textAppearanceMedium" android:text="@string/screenrecord_mic_label"/> <CheckBox android:id="@+id/checkbox_taps" android:layout_width="match_parent" android:layout_height="wrap_content" + android:textAppearance="?android:attr/textAppearanceMedium" android:text="@string/screenrecord_taps_label"/> <Button android:id="@+id/record_button" @@ -34,8 +33,4 @@ /> </LinearLayout> - <Space - android:layout_width="match_parent" - android:layout_height="10dp"/> - </LinearLayout> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index da433913bfa3..44fb1419c6c2 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -1069,10 +1069,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 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?</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> @@ -2370,12 +2370,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/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/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/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java index e0ed111d9cb0..4a2731e5437a 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java @@ -61,6 +61,7 @@ import com.android.systemui.statusbar.notification.NotificationInterruptionState import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag; import com.android.systemui.statusbar.phone.StatusBarWindowController; +import com.android.systemui.statusbar.policy.ConfigurationController; import java.lang.annotation.Retention; @@ -74,7 +75,8 @@ import javax.inject.Singleton; * The controller manages addition, removal, and visible state of bubbles on screen. */ @Singleton -public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListener { +public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListener, + ConfigurationController.ConfigurationListener { private static final String TAG = "BubbleController"; @@ -84,6 +86,7 @@ public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListe @IntDef({DISMISS_USER_GESTURE, DISMISS_AGED, DISMISS_TASK_FINISHED, DISMISS_BLOCKED, DISMISS_NOTIF_CANCEL, DISMISS_ACCESSIBILITY_ACTION}) @interface DismissReason {} + static final int DISMISS_USER_GESTURE = 1; static final int DISMISS_AGED = 2; static final int DISMISS_TASK_FINISHED = 3; @@ -151,6 +154,7 @@ public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListe public interface BubbleExpandListener { /** * Called when the expansion state of the bubble stack changes. + * * @param isExpanding whether it's expanding or collapsing * @param key the notification key associated with bubble being expanded */ @@ -179,13 +183,16 @@ public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListe @Inject public BubbleController(Context context, StatusBarWindowController statusBarWindowController, - BubbleData data) { - this(context, statusBarWindowController, data, null /* synchronizer */); + BubbleData data, ConfigurationController configurationController) { + this(context, statusBarWindowController, data, null /* synchronizer */, + configurationController); } public BubbleController(Context context, StatusBarWindowController statusBarWindowController, - BubbleData data, @Nullable BubbleStackView.SurfaceSynchronizer synchronizer) { + BubbleData data, @Nullable BubbleStackView.SurfaceSynchronizer synchronizer, + ConfigurationController configurationController) { mContext = context; + configurationController.addCallback(this /* configurationListener */); mNotificationEntryManager = Dependency.get(NotificationEntryManager.class); mNotificationEntryManager.addNotificationEntryListener(mEntryListener); @@ -215,6 +222,20 @@ public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListe mSurfaceSynchronizer = synchronizer; } + @Override + public void onUiModeChanged() { + if (mStackView != null) { + mStackView.onConfigChanged(); + } + } + + @Override + public void onOverlayChanged() { + if (mStackView != null) { + mStackView.onConfigChanged(); + } + } + /** * Set a listener to be notified when some states of the bubbles change. */ @@ -295,7 +316,7 @@ public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListe /** * Adds or updates a bubble associated with the provided notification entry. * - * @param notif the notification associated with this bubble. + * @param notif the notification associated with this bubble. * @param updatePosition whether this update should promote the bubble to the top of the stack. */ public void updateBubble(NotificationEntry notif, boolean updatePosition) { diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java index 856b9d6c27e4..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 */ @@ -354,6 +379,13 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList } } + /** + * Update bubble expanded view header when user toggles dark mode. + */ + void updateHeaderColor() { + mHeaderView.setBackgroundColor(mContext.getColor(R.attr.colorAccent)); + } + private void updateHeaderView() { mSettingsIcon.setContentDescription(getResources().getString( R.string.bubbles_settings_button_description, mAppName)); @@ -378,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); } @@ -441,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 1cc6b8789872..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,35 @@ 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); + }); + } + + /** + * Handle config changes. + */ + public void onConfigChanged() { + mExpandedBubble.expandedView.updateHeaderColor(); } @Override @@ -639,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); @@ -836,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/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/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/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/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..338886d735f2 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 @@ -346,14 +347,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/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java index 4e9d892dd809..63b66732c02e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java @@ -44,6 +44,7 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.statusbar.phone.StatusBarWindowController; +import com.android.systemui.statusbar.policy.ConfigurationController; import org.junit.Before; import org.junit.Test; @@ -66,6 +67,9 @@ public class BubbleControllerTest extends SysuiTestCase { private IActivityManager mActivityManager; @Mock private DozeParameters mDozeParameters; + @Mock + private ConfigurationController mConfigurationController; + private FrameLayout mStatusBarView; @Captor private ArgumentCaptor<NotificationEntryListener> mEntryListenerCaptor; @@ -97,6 +101,7 @@ public class BubbleControllerTest extends SysuiTestCase { mStatusBarView = new FrameLayout(mContext); mDependency.injectTestDependency(NotificationEntryManager.class, mNotificationEntryManager); + // Bubbles get added to status bar window view mStatusBarWindowController = new StatusBarWindowController(mContext, mWindowManager, mActivityManager, mDozeParameters); @@ -115,7 +120,7 @@ public class BubbleControllerTest extends SysuiTestCase { mBubbleData = new BubbleData(); mBubbleController = new TestableBubbleController(mContext, mStatusBarWindowController, - mBubbleData); + mBubbleData, mConfigurationController); mBubbleController.setBubbleStateChangeListener(mBubbleStateChangeListener); mBubbleController.setExpandListener(mBubbleExpandListener); @@ -331,8 +336,9 @@ public class BubbleControllerTest extends SysuiTestCase { static class TestableBubbleController extends BubbleController { // Let's assume surfaces can be synchronized immediately. TestableBubbleController(Context context, - StatusBarWindowController statusBarWindowController, BubbleData data) { - super(context, statusBarWindowController, data, Runnable::run); + StatusBarWindowController statusBarWindowController, BubbleData data, + ConfigurationController configurationController) { + super(context, statusBarWindowController, data, Runnable::run, configurationController); } @Override 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/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/proto/src/metrics_constants/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto index f106228fc6f0..7447331b113d 100644 --- a/proto/src/metrics_constants/metrics_constants.proto +++ b/proto/src/metrics_constants/metrics_constants.proto @@ -7120,6 +7120,24 @@ message MetricsEvent { // Open: Settings > Special App Access > Do not disturb control for app ZEN_ACCESS_DETAIL = 1692; + // OPEN: Settings > Face > Remove face + // 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 65973121b74e..c1c125da1f69 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java @@ -569,6 +569,42 @@ public final class AutofillManagerService } } + // Called by Shell command + boolean isDefaultAugmentedServiceEnabled(@UserIdInt int userId) { + enforceCallingPermissionForManagement(); + + synchronized (mLock) { + final AutofillManagerServiceImpl service = getServiceForUserLocked(userId); + if (service != null) { + return service.mAugmentedAutofillResolver.isDefaultServiceEnabled(userId); + } + } + return false; + } + + // Called by Shell command + boolean setDefaultAugmentedServiceEnabled(@UserIdInt int userId, boolean enabled) { + Slog.i(mTag, "setDefaultAugmentedServiceEnabled() for userId " + userId + ": " + enabled); + enforceCallingPermissionForManagement(); + + synchronized (mLock) { + final AutofillManagerServiceImpl service = getServiceForUserLocked(userId); + if (service != null) { + final boolean changed = service.mAugmentedAutofillResolver + .setDefaultServiceEnabled(userId, enabled); + if (changed) { + service.updateRemoteAugmentedAutofillService(); + return true; + } else { + if (debug) { + Slog.d(TAG, "setDefaultAugmentedServiceEnabled(): already " + enabled); + } + } + } + } + return false; + } + private void setLoggingLevelsLocked(boolean debug, boolean verbose) { com.android.server.autofill.Helper.sDebug = debug; android.view.autofill.Helper.sDebug = debug; @@ -647,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) { @@ -967,14 +1011,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 96123468d245..720d319b12f8 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java @@ -18,6 +18,7 @@ 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_SESSION_FOR_AUGMENTED_AUTOFILL_ONLY; import static android.view.autofill.AutofillManager.NO_SESSION; import static com.android.server.autofill.Helper.sDebug; @@ -53,6 +54,7 @@ import android.service.autofill.FieldClassification; import android.service.autofill.FieldClassification.Match; import android.service.autofill.FillEventHistory; import android.service.autofill.FillEventHistory.Event; +import android.service.autofill.FillRequest; import android.service.autofill.FillResponse; import android.service.autofill.IAutoFillService; import android.service.autofill.UserData; @@ -156,6 +158,7 @@ final class AutofillManagerServiceImpl /** When was {@link PruneTask} last executed? */ private long mLastPrune = 0; + // TODO(b/128911469): move to AutofillManagerService /** * Object used to set the name of the augmented autofill service. */ @@ -221,7 +224,7 @@ final class AutofillManagerServiceImpl session.removeSelfLocked(); } } - sendStateToClients(false); + sendStateToClients(/* resetClient= */ false); } updateRemoteAugmentedAutofillService(); return enabledChanged; @@ -278,8 +281,15 @@ 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 FillRequest#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, @@ -289,33 +299,48 @@ final class AutofillManagerServiceImpl } final String shortComponentName = componentName.toShortString(); + boolean forAugmentedAutofillOnly = false; if (isAutofillDisabledLocked(componentName)) { - if (sDebug) { - Slog.d(TAG, "startSession(" + shortComponentName - + "): ignored because disabled by service"); - } + // Service disabled autofill; that means no session, unless the activity is whitelisted + // for augmented autofill + if (isWhitelistedForAugmentedAutofillLocked(componentName)) { + if (sDebug) { + Slog.d(TAG, "startSession(" + shortComponentName + "): disabled by service but " + + "whitelisted for augmented autofill"); + } + forAugmentedAutofillOnly = true; - 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); - } + } else { + if (sDebug) { + Slog.d(TAG, "startSession(" + shortComponentName + "): 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 " + 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; } @@ -324,12 +349,20 @@ final class AutofillManagerServiceImpl "id=" + newSession.id + " uid=" + uid + " a=" + shortComponentName + " s=" + mInfo.getServiceInfo().packageName + " 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; + } } /** @@ -435,7 +468,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; @@ -446,15 +479,17 @@ 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); 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); + componentName, compatMode, bindInstantServiceAllowed, forAugmentedAutofillOnly, + flags); mSessions.put(newSession.id, newSession); return newSession; @@ -634,7 +669,7 @@ final class AutofillManagerServiceImpl remoteFillServices.valueAt(i).destroy(); } - sendStateToClients(true); + sendStateToClients(/* resetclient=*/ true); if (mClients != null) { mClients.kill(); mClients = null; @@ -889,8 +924,6 @@ final class AutofillManagerServiceImpl } else { pw.println(); mInfo.dump(prefix2, pw); - pw.print(prefix); pw.print("Service Label: "); pw.println(getServiceLabelLocked()); - pw.print(prefix); pw.print("Target SDK: "); pw.println(getTargedSdkLocked()); } pw.print(prefix); pw.print("Default component: "); pw.println(getContext() .getString(R.string.config_defaultAutofillService)); diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java index c562fb1b7dde..bbe37a5df4f4 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java @@ -109,6 +109,13 @@ public final class AutofillManagerServiceShellCommand extends ShellCommand { + "implementation."); pw.println(" To reset, call with just the USER_ID argument."); pw.println(""); + pw.println(" set default-augmented-service-enabled USER_ID [true|false]"); + pw.println(" Enable / disable the default augmented autofill service for the user."); + pw.println(""); + pw.println(" get default-augmented-service-enabled USER_ID"); + pw.println(" Checks whether the default augmented autofill service is enabled for " + + "the user."); + pw.println(""); pw.println(" list sessions [--user USER_ID]"); pw.println(" Lists all pending sessions."); pw.println(""); @@ -136,6 +143,8 @@ public final class AutofillManagerServiceShellCommand extends ShellCommand { return getFullScreenMode(pw); case "bind-instant-service-allowed": return getBindInstantService(pw); + case "default-augmented-service-enabled": + return getDefaultAugmentedServiceEnabled(pw); default: pw.println("Invalid set: " + what); return -1; @@ -158,6 +167,8 @@ public final class AutofillManagerServiceShellCommand extends ShellCommand { return setBindInstantService(pw); case "temporary-augmented-service": return setTemporaryAugmentedService(pw); + case "default-augmented-service-enabled": + return setDefaultAugmentedServiceEnabled(pw); default: pw.println("Invalid set: " + what); return -1; @@ -314,6 +325,23 @@ public final class AutofillManagerServiceShellCommand extends ShellCommand { return 0; } + private int getDefaultAugmentedServiceEnabled(PrintWriter pw) { + final int userId = getNextIntArgRequired(); + final boolean enabled = mService.isDefaultAugmentedServiceEnabled(userId); + pw.println(enabled); + return 0; + } + + private int setDefaultAugmentedServiceEnabled(PrintWriter pw) { + final int userId = getNextIntArgRequired(); + final boolean enabled = Boolean.parseBoolean(getNextArgRequired()); + final boolean changed = mService.setDefaultAugmentedServiceEnabled(userId, enabled); + if (!changed) { + pw.println("already " + enabled); + } + return 0; + } + private int requestDestroy(PrintWriter pw) { if (!isNextArgSessions(pw)) { return -1; diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java index ea47033f7141..f08bab3f60cb 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 */ @@ -277,6 +281,13 @@ 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() { @@ -538,11 +549,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 +576,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 @@ -598,7 +610,10 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState @NonNull IBinder client, boolean hasCallback, @NonNull LocalLog uiLatencyHistory, @NonNull LocalLog wtfHistory, @NonNull 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; @@ -616,6 +631,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState mWtfHistory = wtfHistory; mComponentName = componentName; mCompatMode = compatMode; + mForAugmentedAutofillOnly = forAugmentedAutofillOnly; setClientLocked(client); mMetricsLogger.write(newLogMaker(MetricsEvent.AUTOFILL_SESSION_STARTED) @@ -727,14 +743,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 +750,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; } @@ -3005,6 +3030,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"); } 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/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerServiceShellCommand.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerServiceShellCommand.java index 86ad52d9a42b..fc9754a2b0f5 100644 --- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerServiceShellCommand.java +++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerServiceShellCommand.java @@ -114,7 +114,7 @@ public final class ContentCaptureManagerServiceShellCommand extends ShellCommand case "temporary-service": return setTemporaryService(pw); case "default-service-enabled": - return setDefaultServiceEnabled(); + return setDefaultServiceEnabled(pw); default: pw.println("Invalid set: " + what); return -1; @@ -159,10 +159,13 @@ public final class ContentCaptureManagerServiceShellCommand extends ShellCommand return 0; } - private int setDefaultServiceEnabled() { + private int setDefaultServiceEnabled(PrintWriter pw) { final int userId = getNextIntArgRequired(); - final boolean enabled = Boolean.parseBoolean(getNextArg()); - mService.setDefaultServiceEnabled(userId, enabled); + final boolean enabled = Boolean.parseBoolean(getNextArgRequired()); + final boolean changed = mService.setDefaultServiceEnabled(userId, enabled); + if (!changed) { + pw.println("already " + enabled); + } return 0; } diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java index c423f9c87d29..d7d97b39959f 100644 --- a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java +++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java @@ -27,12 +27,10 @@ import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_CONTE import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_DATA; import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_STRUCTURE; -import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.ActivityManagerInternal; -import android.app.AppGlobals; import android.app.assist.AssistContent; import android.app.assist.AssistStructure; import android.content.ComponentName; @@ -44,12 +42,12 @@ import android.content.pm.ServiceInfo; import android.os.Binder; import android.os.Bundle; import android.os.IBinder; -import android.os.RemoteException; import android.os.UserHandle; import android.provider.Settings; import android.service.contentcapture.ActivityEvent; import android.service.contentcapture.ActivityEvent.ActivityEventType; import android.service.contentcapture.ContentCaptureService; +import android.service.contentcapture.ContentCaptureServiceInfo; import android.service.contentcapture.IContentCaptureServiceCallback; import android.service.contentcapture.SnapshotData; import android.util.ArrayMap; @@ -107,6 +105,9 @@ final class ContentCapturePerUserService @GuardedBy("mLock") private boolean mZombie; + @GuardedBy("mLock") + private ContentCaptureServiceInfo mInfo; + // TODO(b/111276913): add mechanism to prune stale sessions, similar to Autofill's ContentCapturePerUserService(@NonNull ContentCaptureManagerService master, @@ -144,33 +145,9 @@ final class ContentCapturePerUserService @Override // from PerUserSystemService protected ServiceInfo newServiceInfoLocked(@NonNull ComponentName serviceComponent) throws NameNotFoundException { - - int flags = PackageManager.GET_META_DATA; - final boolean isTemp = isTemporaryServiceSetLocked(); - if (!isTemp) { - flags |= PackageManager.MATCH_SYSTEM_ONLY; - } - - ServiceInfo si; - try { - si = AppGlobals.getPackageManager().getServiceInfo(serviceComponent, flags, mUserId); - } catch (RemoteException e) { - Slog.w(TAG, "Could not get service for " + serviceComponent + ": " + e); - return null; - } - if (si == null) { - Slog.w(TAG, "Could not get serviceInfo for " + (isTemp ? " (temp)" : "(default system)") - + " " + serviceComponent.flattenToShortString()); - return null; - } - if (!Manifest.permission.BIND_CONTENT_CAPTURE_SERVICE.equals(si.permission)) { - Slog.w(TAG, "ContentCaptureService from '" + si.packageName - + "' does not require permission " - + Manifest.permission.BIND_CONTENT_CAPTURE_SERVICE); - throw new SecurityException("Service does not require permission " - + Manifest.permission.BIND_CONTENT_CAPTURE_SERVICE); - } - return si; + mInfo = new ContentCaptureServiceInfo(getContext(), serviceComponent, + isTemporaryServiceSetLocked(), mUserId); + return mInfo.getServiceInfo(); } @Override // from PerUserSystemService @@ -490,9 +467,16 @@ final class ContentCapturePerUserService protected void dumpLocked(String prefix, PrintWriter pw) { super.dumpLocked(prefix, pw); + final String prefix2 = prefix + " "; + pw.print(prefix); pw.print("Service Info: "); + if (mInfo == null) { + pw.println("N/A"); + } else { + pw.println(); + mInfo.dump(prefix2, pw); + } pw.print(prefix); pw.print("Zombie: "); pw.println(mZombie); - final String prefix2 = prefix + " "; if (mRemoteService != null) { pw.print(prefix); pw.println("remote service:"); mRemoteService.dump(prefix2, pw); 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..c06972932621 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -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/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java index 19b0bf795393..077920c04be6 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; @@ -208,6 +212,13 @@ class StorageManagerService extends IStorageManager.Stub private static final boolean ENABLE_LEGACY_GREYLIST = SystemProperties .getBoolean(StorageManager.PROP_LEGACY_GREYLIST, true); + /** + * If {@code 1}, enables the isolated storage feature. If {@code -1}, + * disables the isolated storage feature. If {@code 0}, uses the default + * value from the build system. + */ + private static final String ISOLATED_STORAGE_ENABLED = "isolated_storage_enabled"; + public static class Lifecycle extends SystemService { private StorageManagerService mStorageManagerService; @@ -294,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; /** @@ -797,7 +821,7 @@ class StorageManagerService extends IStorageManager.Stub } }); // For now, simply clone property when it changes - DeviceConfig.addOnPropertyChangedListener(DeviceConfig.Storage.NAMESPACE, + DeviceConfig.addOnPropertyChangedListener(DeviceConfig.NAMESPACE_STORAGE, mContext.getMainExecutor(), (namespace, name, value) -> { refreshIsolatedStorageSettings(); }); @@ -837,8 +861,7 @@ class StorageManagerService extends IStorageManager.Stub // Always copy value from newer DeviceConfig location Settings.Global.putString(mResolver, Settings.Global.ISOLATED_STORAGE_REMOTE, - DeviceConfig.getProperty(DeviceConfig.Storage.NAMESPACE, - DeviceConfig.Storage.ISOLATED_STORAGE_ENABLED)); + DeviceConfig.getProperty(DeviceConfig.NAMESPACE_STORAGE, ISOLATED_STORAGE_ENABLED)); final int local = Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.ISOLATED_STORAGE_LOCAL, 0); @@ -1668,16 +1691,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(); } } @@ -1685,23 +1710,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; @@ -1714,8 +1743,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); + } + } + } } } } @@ -1734,6 +1783,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); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 82254761817e..97cc756e3924 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -1273,11 +1273,13 @@ public class ActivityManagerService extends IActivityManager.Stub static final class ProcessChangeItem { static final int CHANGE_ACTIVITIES = 1<<0; + static final int CHANGE_FOREGROUND_SERVICES = 1<<1; int changes; int uid; int pid; int processState; boolean foregroundActivities; + int foregroundServiceTypes; } static final class UidObserverRegistration { @@ -2935,7 +2937,8 @@ public class ActivityManagerService extends IActivityManager.Stub } } if (mContentCaptureService != null && (event == Event.ACTIVITY_PAUSED - || event == Event.ACTIVITY_RESUMED || event == Event.ACTIVITY_STOPPED)) { + || event == Event.ACTIVITY_RESUMED || event == Event.ACTIVITY_STOPPED + || event == Event.ACTIVITY_DESTROYED)) { mContentCaptureService.notifyActivityEvent(userId, activity, event); } } @@ -3079,6 +3082,13 @@ public class ActivityManagerService extends IActivityManager.Stub observer.onForegroundActivitiesChanged(item.pid, item.uid, item.foregroundActivities); } + if ((item.changes & ProcessChangeItem.CHANGE_FOREGROUND_SERVICES) != 0) { + if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS, + "FOREGROUND SERVICES CHANGED pid=" + item.pid + " uid=" + + item.uid + ": " + item.foregroundServiceTypes); + observer.onForegroundServicesChanged(item.pid, item.uid, + item.foregroundServiceTypes); + } } } catch (RemoteException e) { } @@ -3093,6 +3103,47 @@ public class ActivityManagerService extends IActivityManager.Stub } } + @GuardedBy("this") + ProcessChangeItem enqueueProcessChangeItemLocked(int uid, int pid) { + int i = mPendingProcessChanges.size()-1; + ActivityManagerService.ProcessChangeItem item = null; + while (i >= 0) { + item = mPendingProcessChanges.get(i); + if (item.pid == pid) { + if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS, + "Re-using existing item: " + item); + break; + } + i--; + } + + if (i < 0) { + // No existing item in pending changes; need a new one. + final int NA = mAvailProcessChanges.size(); + if (NA > 0) { + item = mAvailProcessChanges.remove(NA-1); + if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS, + "Retrieving available item: " + item); + } else { + item = new ActivityManagerService.ProcessChangeItem(); + if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS, + "Allocating new item: " + item); + } + item.changes = 0; + item.pid = pid; + item.uid = uid; + if (mPendingProcessChanges.size() == 0) { + if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS, + "*** Enqueueing dispatch processes changed!"); + mUiHandler.obtainMessage(DISPATCH_PROCESSES_CHANGED_UI_MSG) + .sendToTarget(); + } + mPendingProcessChanges.add(item); + } + + return item; + } + private void dispatchProcessDied(int pid, int uid) { int i = mProcessObservers.beginBroadcast(); while (i > 0) { @@ -16275,11 +16326,12 @@ public class ActivityManagerService extends IActivityManager.Stub @GuardedBy("this") final void updateProcessForegroundLocked(ProcessRecord proc, boolean isForeground, int fgServiceTypes, boolean oomAdj) { + proc.setHasForegroundServices(isForeground, fgServiceTypes); + final boolean hasFgServiceLocationType = (fgServiceTypes & ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION) != 0; if (isForeground != proc.hasForegroundServices() || proc.hasLocationForegroundServices() != hasFgServiceLocationType) { - proc.setHasForegroundServices(isForeground, fgServiceTypes); ArrayList<ProcessRecord> curProcs = mForegroundPackages.get(proc.info.packageName, proc.info.uid); if (isForeground) { @@ -16308,6 +16360,13 @@ public class ActivityManagerService extends IActivityManager.Stub updateOomAdjLocked(); } } + + if (proc.getForegroundServiceTypes() != fgServiceTypes) { + proc.setReportedForegroundServiceTypes(fgServiceTypes); + ProcessChangeItem item = enqueueProcessChangeItemLocked(proc.info.uid, proc.pid); + item.changes = ProcessChangeItem.CHANGE_FOREGROUND_SERVICES; + item.foregroundServiceTypes = fgServiceTypes; + } } // TODO(b/111541062): This method is only used for updating OOM adjustments. We need to update @@ -18101,6 +18160,34 @@ public class ActivityManagerService extends IActivityManager.Stub public void prepareForPossibleShutdown() { ActivityManagerService.this.prepareForPossibleShutdown(); } + + @Override + public boolean hasRunningForegroundService(int uid, int foregroundServicetype) { + synchronized (ActivityManagerService.this) { + for (int i = 0; i < mProcessList.mLruProcesses.size(); i++) { + final ProcessRecord pr = mProcessList.mLruProcesses.get(i); + if (pr.uid != uid) { + continue; + } + + if ((pr.getForegroundServiceTypes() & foregroundServicetype) != 0) { + return true; + } + } + } + + return false; + } + + @Override + public void registerProcessObserver(IProcessObserver processObserver) { + ActivityManagerService.this.registerProcessObserver(processObserver); + } + + @Override + public void unregisterProcessObserver(IProcessObserver processObserver) { + ActivityManagerService.this.unregisterProcessObserver(processObserver); + } } long inputDispatchingTimedOut(int pid, final boolean aboveSystem, String reason) { diff --git a/services/core/java/com/android/server/am/AppCompactor.java b/services/core/java/com/android/server/am/AppCompactor.java index 438538ffde88..9216343e05d8 100644 --- a/services/core/java/com/android/server/am/AppCompactor.java +++ b/services/core/java/com/android/server/am/AppCompactor.java @@ -230,11 +230,8 @@ public final class AppCompactor { */ @GuardedBy("mPhenotypeFlagLock") private void updateUseCompaction() { - String useCompactionFlag = - DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, - KEY_USE_COMPACTION); - mUseCompaction = TextUtils.isEmpty(useCompactionFlag) - ? DEFAULT_USE_COMPACTION : Boolean.parseBoolean(useCompactionFlag); + mUseCompaction = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, + KEY_USE_COMPACTION, DEFAULT_USE_COMPACTION); if (mUseCompaction && !mCompactionThread.isAlive()) { mCompactionThread.start(); mCompactionHandler = new MemCompactionHandler(); @@ -243,28 +240,11 @@ public final class AppCompactor { @GuardedBy("mPhenotypeFlagLock") private void updateCompactionActions() { - String compactAction1Flag = - DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, - KEY_COMPACT_ACTION_1); - String compactAction2Flag = - DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, - KEY_COMPACT_ACTION_2); - - int compactAction1 = DEFAULT_COMPACT_ACTION_1; - try { - compactAction1 = TextUtils.isEmpty(compactAction1Flag) - ? DEFAULT_COMPACT_ACTION_1 : Integer.parseInt(compactAction1Flag); - } catch (NumberFormatException e) { - // Do nothing, leave default. - } + int compactAction1 = DeviceConfig.getInt(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, + KEY_COMPACT_ACTION_1, DEFAULT_COMPACT_ACTION_1); - int compactAction2 = DEFAULT_COMPACT_ACTION_2; - try { - compactAction2 = TextUtils.isEmpty(compactAction2Flag) - ? DEFAULT_COMPACT_ACTION_2 : Integer.parseInt(compactAction2Flag); - } catch (NumberFormatException e) { - // Do nothing, leave default. - } + int compactAction2 = DeviceConfig.getInt(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, + KEY_COMPACT_ACTION_2, DEFAULT_COMPACT_ACTION_2); mCompactActionSome = compactActionIntToString(compactAction1); mCompactActionFull = compactActionIntToString(compactAction2); @@ -312,14 +292,8 @@ public final class AppCompactor { @GuardedBy("mPhenotypeFlagLock") private void updateStatsdSampleRate() { - String sampleRateFlag = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, - KEY_COMPACT_STATSD_SAMPLE_RATE); - try { - mStatsdSampleRate = TextUtils.isEmpty(sampleRateFlag) - ? DEFAULT_STATSD_SAMPLE_RATE : Float.parseFloat(sampleRateFlag); - } catch (NumberFormatException e) { - mStatsdSampleRate = DEFAULT_STATSD_SAMPLE_RATE; - } + mStatsdSampleRate = DeviceConfig.getFloat(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, + KEY_COMPACT_STATSD_SAMPLE_RATE, DEFAULT_STATSD_SAMPLE_RATE); mStatsdSampleRate = Math.min(1.0f, Math.max(0.0f, mStatsdSampleRate)); } 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/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java index 9056f76c4086..aa03de1115b2 100644 --- a/services/core/java/com/android/server/am/OomAdjuster.java +++ b/services/core/java/com/android/server/am/OomAdjuster.java @@ -38,7 +38,6 @@ import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PSS; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_UID_OBSERVERS; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_USAGE_STATS; import static com.android.server.am.ActivityManagerService.DISPATCH_OOM_ADJ_OBSERVER_MSG; -import static com.android.server.am.ActivityManagerService.DISPATCH_PROCESSES_CHANGED_UI_MSG; import static com.android.server.am.ActivityManagerService.IDLE_UIDS_MSG; import static com.android.server.am.ActivityManagerService.TAG_BACKUP; import static com.android.server.am.ActivityManagerService.TAG_LRU; @@ -1921,41 +1920,9 @@ public final class OomAdjuster { if (changes != 0) { if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS, "Changes in " + app + ": " + changes); - int i = mService.mPendingProcessChanges.size()-1; - ActivityManagerService.ProcessChangeItem item = null; - while (i >= 0) { - item = mService.mPendingProcessChanges.get(i); - if (item.pid == app.pid) { - if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS, - "Re-using existing item: " + item); - break; - } - i--; - } - if (i < 0) { - // No existing item in pending changes; need a new one. - final int NA = mService.mAvailProcessChanges.size(); - if (NA > 0) { - item = mService.mAvailProcessChanges.remove(NA-1); - if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS, - "Retrieving available item: " + item); - } else { - item = new ActivityManagerService.ProcessChangeItem(); - if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS, - "Allocating new item: " + item); - } - item.changes = 0; - item.pid = app.pid; - item.uid = app.info.uid; - if (mService.mPendingProcessChanges.size() == 0) { - if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS, - "*** Enqueueing dispatch processes changed!"); - mService.mUiHandler.obtainMessage(DISPATCH_PROCESSES_CHANGED_UI_MSG) - .sendToTarget(); - } - mService.mPendingProcessChanges.add(item); - } - item.changes |= changes; + ActivityManagerService.ProcessChangeItem item = + mService.enqueueProcessChangeItemLocked(app.pid, app.info.uid); + item.changes = changes; item.foregroundActivities = app.repForegroundActivities; if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS, "Item " + Integer.toHexString(System.identityHashCode(item)) diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java index 51b1ae197821..17b244c75819 100644 --- a/services/core/java/com/android/server/am/ProcessRecord.java +++ b/services/core/java/com/android/server/am/ProcessRecord.java @@ -174,6 +174,7 @@ class ProcessRecord implements WindowProcessListener { boolean hasStartedServices; // Are there any started services running in this process? private boolean mHasForegroundServices; // Running any services that are foreground? private int mFgServiceTypes; // Type of foreground service, if there is a foreground service. + private int mRepFgServiceTypes; // Last reported foreground service types. private boolean mHasForegroundActivities; // Running any activities that are foreground? boolean repForegroundActivities; // Last reported foreground activities. boolean systemNoUi; // This is a system process, but not currently showing UI. @@ -1079,6 +1080,18 @@ class ProcessRecord implements WindowProcessListener { && (mFgServiceTypes & ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION) != 0; } + int getForegroundServiceTypes() { + return mHasForegroundServices ? mFgServiceTypes : 0; + } + + int getReportedForegroundServiceTypes() { + return mRepFgServiceTypes; + } + + void setReportedForegroundServiceTypes(int foregroundServiceTypes) { + mRepFgServiceTypes = foregroundServiceTypes; + } + void setHasForegroundActivities(boolean hasForegroundActivities) { mHasForegroundActivities = hasForegroundActivities; mWindowProcessController.setHasForegroundActivities(hasForegroundActivities); 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 4e0380d37820..31ba0f24cec6 100644 --- a/services/core/java/com/android/server/attention/AttentionManagerService.java +++ b/services/core/java/com/android/server/attention/AttentionManagerService.java @@ -19,6 +19,7 @@ package com.android.server.attention; import static android.provider.DeviceConfig.NAMESPACE_ATTENTION_MANAGER_SERVICE; import android.Manifest; +import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.ActivityManager; @@ -113,6 +114,11 @@ public class AttentionManagerService extends SystemService { cancelAndUnbindLocked(peekUserStateLocked(userId)); } + /** Returns {@code true} if attention service is configured on this device. */ + public static boolean isServiceConfigured(Context context) { + return !TextUtils.isEmpty(getServiceConfig(context)); + } + /** Resolves and sets up the attention service if it had not been done yet. */ private boolean isServiceAvailable() { if (mComponentName == null) { @@ -285,6 +291,10 @@ public class AttentionManagerService extends SystemService { return mUserStates.get(userId); } + private static String getServiceConfig(Context context) { + return context.getString(R.string.config_defaultAttentionService); + } + /** * Provides attention service component name at runtime, making sure it's provided by the * system. @@ -293,9 +303,7 @@ public class AttentionManagerService extends SystemService { final String flag = DeviceConfig.getProperty(NAMESPACE_ATTENTION_MANAGER_SERVICE, COMPONENT_NAME); - final String componentNameString = flag != null ? flag : context.getString( - R.string.config_defaultAttentionService); - + final String componentNameString = flag != null ? flag : getServiceConfig(context); if (TextUtils.isEmpty(componentNameString)) { return null; } @@ -553,8 +561,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); @@ -571,6 +579,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/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java index f313e1d48c53..516844d85484 100644 --- a/services/core/java/com/android/server/biometrics/BiometricService.java +++ b/services/core/java/com/android/server/biometrics/BiometricService.java @@ -628,6 +628,9 @@ public class BiometricService extends SystemService { null /* description */); // Then give it the bundle to do magic behavior.. intent.putExtra(KeyguardManager.EXTRA_BIOMETRIC_PROMPT_BUNDLE, bundle); + // Create a new task with this activity located at the root. + intent.setFlags( + Intent.FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_NEW_DOCUMENT); getContext().startActivityAsUser(intent, UserHandle.CURRENT); }); return; 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/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/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/display/color/ColorDisplayService.java b/services/core/java/com/android/server/display/color/ColorDisplayService.java index 45567e5a34cb..ed420b73e79b 100644 --- a/services/core/java/com/android/server/display/color/ColorDisplayService.java +++ b/services/core/java/com/android/server/display/color/ColorDisplayService.java @@ -1417,7 +1417,7 @@ public final class ColorDisplayService extends SystemService { mCurrentColorTemperature = cct; // Adapt the display's nominal white point to match the requested CCT value - mCurrentColorTemperatureXYZ = ColorSpace.cctToIlluminantdXyz(cct); + mCurrentColorTemperatureXYZ = ColorSpace.cctToXyz(cct); mChromaticAdaptationMatrix = ColorSpace.chromaticAdaptation(ColorSpace.Adaptation.BRADFORD, diff --git a/services/core/java/com/android/server/infra/AbstractMasterSystemService.java b/services/core/java/com/android/server/infra/AbstractMasterSystemService.java index 3c27bf240570..430203de8268 100644 --- a/services/core/java/com/android/server/infra/AbstractMasterSystemService.java +++ b/services/core/java/com/android/server/infra/AbstractMasterSystemService.java @@ -332,21 +332,31 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem * with the test results. * * @throws SecurityException if caller is not allowed to manage this service's settings. + * + * @return whether the enabled state changed. */ - public final void setDefaultServiceEnabled(@UserIdInt int userId, boolean enabled) { + public final boolean setDefaultServiceEnabled(@UserIdInt int userId, boolean enabled) { Slog.i(mTag, "setDefaultServiceEnabled() for userId " + userId + ": " + enabled); enforceCallingPermissionForManagement(); synchronized (mLock) { + final boolean changed = mServiceNameResolver.setDefaultServiceEnabled(userId, enabled); + if (!changed) { + if (verbose) { + Slog.v(mTag, "setDefaultServiceEnabled(" + userId + "): already " + enabled); + } + return false; + } + final S oldService = peekServiceForUserLocked(userId); if (oldService != null) { oldService.removeSelfFromCacheLocked(); } - mServiceNameResolver.setDefaultServiceEnabled(userId, enabled); // Must update the service on cache so its initialization code is triggered updateCachedServiceLocked(userId); } + return true; } /** diff --git a/services/core/java/com/android/server/infra/AbstractPerUserSystemService.java b/services/core/java/com/android/server/infra/AbstractPerUserSystemService.java index cd9ebcda009c..ac07e9d6b0b7 100644 --- a/services/core/java/com/android/server/infra/AbstractPerUserSystemService.java +++ b/services/core/java/com/android/server/infra/AbstractPerUserSystemService.java @@ -327,6 +327,10 @@ public abstract class AbstractPerUserSystemService<S extends AbstractPerUserSyst @GuardedBy("mLock") protected void dumpLocked(@NonNull String prefix, @NonNull PrintWriter pw) { pw.print(prefix); pw.print("User: "); pw.println(mUserId); + if (mServiceInfo != null) { + pw.print(prefix); pw.print("Service Label: "); pw.println(getServiceLabelLocked()); + pw.print(prefix); pw.print("Target SDK: "); pw.println(getTargedSdkLocked()); + } if (mMaster.mServiceNameResolver != null) { pw.print(prefix); pw.print("Name resolver: "); mMaster.mServiceNameResolver.dumpShort(pw, mUserId); pw.println(); diff --git a/services/core/java/com/android/server/infra/FrameworkResourcesServiceNameResolver.java b/services/core/java/com/android/server/infra/FrameworkResourcesServiceNameResolver.java index 1b237949a543..d20481331e56 100644 --- a/services/core/java/com/android/server/infra/FrameworkResourcesServiceNameResolver.java +++ b/services/core/java/com/android/server/infra/FrameworkResourcesServiceNameResolver.java @@ -174,23 +174,35 @@ public final class FrameworkResourcesServiceNameResolver implements ServiceNameR } @Override - public void setDefaultServiceEnabled(int userId, boolean enabled) { + public boolean setDefaultServiceEnabled(int userId, boolean enabled) { synchronized (mLock) { + final boolean currentlyEnabled = isDefaultServiceEnabledLocked(userId); + if (currentlyEnabled == enabled) { + Slog.i(TAG, "setDefaultServiceEnabled(" + userId + "): already " + enabled); + return false; + } if (enabled) { + Slog.i(TAG, "disabling default service for user " + userId); mDefaultServicesDisabled.removeAt(userId); } else { + Slog.i(TAG, "enabling default service for user " + userId); mDefaultServicesDisabled.put(userId, true); } } + return true; } @Override public boolean isDefaultServiceEnabled(int userId) { synchronized (mLock) { - return !mDefaultServicesDisabled.get(userId); + return isDefaultServiceEnabledLocked(userId); } } + private boolean isDefaultServiceEnabledLocked(int userId) { + return !mDefaultServicesDisabled.get(userId); + } + @Override public String toString() { return "FrameworkResourcesServiceNamer[temps=" + mTemporaryServiceNames + "]"; diff --git a/services/core/java/com/android/server/infra/ServiceNameResolver.java b/services/core/java/com/android/server/infra/ServiceNameResolver.java index 5b60413eefad..8c348ebbfcd4 100644 --- a/services/core/java/com/android/server/infra/ServiceNameResolver.java +++ b/services/core/java/com/android/server/infra/ServiceNameResolver.java @@ -115,11 +115,13 @@ public interface ServiceNameResolver { * * @param userId user handle * @param enabled whether the default service should be used when the temporary service is not - * set + * set. If the service enabled state is already that value, the command is ignored and this + * method return {@code false}. * + * @return whether the enabled state changed. * @throws UnsupportedOperationException if not implemented. */ - default void setDefaultServiceEnabled(@UserIdInt int userId, boolean enabled) { + default boolean setDefaultServiceEnabled(@UserIdInt int userId, boolean enabled) { throw new UnsupportedOperationException("changing default service not supported"); } 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/media/projection/MediaProjectionManagerService.java b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java index 270fbc68e143..3872523492a7 100644 --- a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java +++ b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java @@ -17,9 +17,14 @@ package com.android.server.media.projection; import android.Manifest; +import android.app.ActivityManagerInternal; import android.app.AppOpsManager; +import android.app.IProcessObserver; import android.content.Context; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; +import android.content.pm.ServiceInfo; import android.hardware.display.DisplayManager; import android.media.MediaRouter; import android.media.projection.IMediaProjection; @@ -29,6 +34,8 @@ import android.media.projection.IMediaProjectionWatcherCallback; import android.media.projection.MediaProjectionInfo; import android.media.projection.MediaProjectionManager; import android.os.Binder; +import android.os.Build; +import android.os.Build.VERSION_CODES; import android.os.Handler; import android.os.IBinder; import android.os.Looper; @@ -38,6 +45,7 @@ import android.util.ArrayMap; import android.util.Slog; import com.android.internal.util.DumpUtils; +import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.Watchdog; @@ -63,6 +71,8 @@ public final class MediaProjectionManagerService extends SystemService private final Context mContext; private final AppOpsManager mAppOps; + private final ActivityManagerInternal mActivityManagerInternal; + private final PackageManager mPackageManager; private final MediaRouter mMediaRouter; private final MediaRouterCallback mMediaRouterCallback; @@ -77,6 +87,8 @@ public final class MediaProjectionManagerService extends SystemService mDeathEaters = new ArrayMap<IBinder, IBinder.DeathRecipient>(); mCallbackDelegate = new CallbackDelegate(); mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); + mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class); + mPackageManager = mContext.getPackageManager(); mMediaRouter = (MediaRouter) mContext.getSystemService(Context.MEDIA_ROUTER_SERVICE); mMediaRouterCallback = new MediaRouterCallback(); Watchdog.getInstance().addMonitor(this); @@ -88,6 +100,21 @@ public final class MediaProjectionManagerService extends SystemService false /*allowIsolated*/); mMediaRouter.addCallback(MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY, mMediaRouterCallback, MediaRouter.CALLBACK_FLAG_PASSIVE_DISCOVERY); + mActivityManagerInternal.registerProcessObserver(new IProcessObserver.Stub() { + @Override + public void onForegroundActivitiesChanged(int pid, int uid, boolean fg) { + } + + @Override + public void onForegroundServicesChanged(int pid, int uid, int serviceTypes) { + MediaProjectionManagerService.this.handleForegroundServicesChanged(pid, uid, + serviceTypes); + } + + @Override + public void onProcessDied(int pid, int uid) { + } + }); } @Override @@ -105,6 +132,29 @@ public final class MediaProjectionManagerService extends SystemService synchronized (mLock) { /* check for deadlock */ } } + /** + * Called when the set of active foreground service types for a given {@code uid / pid} changes. + * We will stop the active projection grant if its owner targets {@code Q} or higher and has no + * started foreground services of type {@code FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION}. + */ + private void handleForegroundServicesChanged(int pid, int uid, int serviceTypes) { + synchronized (mLock) { + if (mProjectionGrant == null || mProjectionGrant.uid != uid) { + return; + } + + if (mProjectionGrant.targetSdkVersion < VERSION_CODES.Q) { + return; + } + + if ((serviceTypes & ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION) != 0) { + return; + } + + mProjectionGrant.stop(); + } + } + private void startProjectionLocked(final MediaProjection projection) { if (mProjectionGrant != null) { mProjectionGrant.stop(); @@ -229,10 +279,19 @@ public final class MediaProjectionManagerService extends SystemService if (packageName == null || packageName.isEmpty()) { throw new IllegalArgumentException("package name must not be empty"); } + long callingToken = Binder.clearCallingIdentity(); + MediaProjection projection; try { - projection = new MediaProjection(type, uid, packageName); + ApplicationInfo ai; + try { + ai = mPackageManager.getApplicationInfo(packageName, 0); + } catch (NameNotFoundException e) { + throw new IllegalArgumentException("No package matching :" + packageName); + } + + projection = new MediaProjection(type, uid, packageName, ai.targetSdkVersion); if (isPermanentGrant) { mAppOps.setMode(AppOpsManager.OP_PROJECT_MEDIA, projection.uid, projection.packageName, AppOpsManager.MODE_ALLOWED); @@ -334,17 +393,19 @@ public final class MediaProjectionManagerService extends SystemService public final int uid; public final String packageName; public final UserHandle userHandle; + public final int targetSdkVersion; private IMediaProjectionCallback mCallback; private IBinder mToken; private IBinder.DeathRecipient mDeathEater; private int mType; - public MediaProjection(int type, int uid, String packageName) { + MediaProjection(int type, int uid, String packageName, int targetSdkVersion) { mType = type; this.uid = uid; this.packageName = packageName; userHandle = new UserHandle(UserHandle.getUserId(uid)); + this.targetSdkVersion = targetSdkVersion; } @Override // Binder call @@ -400,6 +461,14 @@ public final class MediaProjectionManagerService extends SystemService + " attempted to start already started MediaProjection"); return; } + + if (targetSdkVersion >= Build.VERSION_CODES.Q + && !mActivityManagerInternal.hasRunningForegroundService( + uid, ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION)) { + throw new SecurityException("Media projections require a foreground service" + + " of type ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION"); + } + mCallback = callback; registerCallback(mCallback); try { 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/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java index d9ab13295166..de9312041c41 100644 --- a/services/core/java/com/android/server/notification/NotificationRecord.java +++ b/services/core/java/com/android/server/notification/NotificationRecord.java @@ -438,6 +438,8 @@ public final class NotificationRecord { if (getAudioAttributes() != null) { getAudioAttributes().writeToProto(proto, NotificationRecordProto.AUDIO_ATTRIBUTES); } + proto.write(NotificationRecordProto.PACKAGE, sbn.getPackageName()); + proto.write(NotificationRecordProto.DELEGATE_PACKAGE, sbn.getOpPkg()); proto.end(token); } @@ -458,6 +460,7 @@ public final class NotificationRecord { pw.println(prefix + this); prefix = prefix + " "; pw.println(prefix + "uid=" + sbn.getUid() + " userId=" + sbn.getUserId()); + pw.println(prefix + "opPkg=" + sbn.getOpPkg()); pw.println(prefix + "icon=" + iconStr); pw.println(prefix + "flags=0x" + Integer.toHexString(notification.flags)); pw.println(prefix + "pri=" + notification.priority); diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java index 181b7a2af8b0..ad17549d7448 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerService.java +++ b/services/core/java/com/android/server/pm/PackageInstallerService.java @@ -123,6 +123,8 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements /** Automatically destroy sessions older than this */ private static final long MAX_AGE_MILLIS = 3 * DateUtils.DAY_IN_MILLIS; + /** Automatically destroy staged sessions that have not changed state in this time */ + private static final long MAX_TIME_SINCE_UPDATE_MILLIS = 7 * DateUtils.DAY_IN_MILLIS; /** Upper bound on number of active sessions for a UID */ private static final long MAX_ACTIVE_SESSIONS = 1024; /** Upper bound on number of historical sessions for a UID */ @@ -357,11 +359,19 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements } final long age = System.currentTimeMillis() - session.createdMillis; - + final long timeSinceUpdate = + System.currentTimeMillis() - session.updatedMillis; final boolean valid; - if (age >= MAX_AGE_MILLIS) { - Slog.w(TAG, "Abandoning old session first created at " - + session.createdMillis); + if (session.isStaged()) { + if (timeSinceUpdate >= MAX_TIME_SINCE_UPDATE_MILLIS + && session.isStagedAndInTerminalState()) { + valid = false; + } else { + valid = true; + } + } else if (age >= MAX_AGE_MILLIS) { + Slog.w(TAG, "Abandoning old session created at " + + session.createdMillis); valid = false; } else { valid = true; @@ -1196,6 +1206,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements } public void onStagedSessionChanged(PackageInstallerSession session) { + session.markUpdated(); writeSessionsAsync(); if (mOkToSendBroadcasts) { mPm.sendSessionUpdatedBroadcast(session.generateInfo(false), diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index 6451b5653fe3..66b530f19ed8 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -144,6 +144,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { private static final String ATTR_INSTALLER_PACKAGE_NAME = "installerPackageName"; private static final String ATTR_INSTALLER_UID = "installerUid"; private static final String ATTR_CREATED_MILLIS = "createdMillis"; + private static final String ATTR_UPDATED_MILLIS = "updatedMillis"; private static final String ATTR_SESSION_STAGE_DIR = "sessionStageDir"; private static final String ATTR_SESSION_STAGE_CID = "sessionStageCid"; private static final String ATTR_PREPARED = "prepared"; @@ -199,6 +200,10 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { private final Object mLock = new Object(); + /** Timestamp of the last time this session changed state */ + @GuardedBy("mLock") + long updatedMillis; + /** Uid of the creator of this session. */ private final int mOriginalInstallerUid; @@ -422,6 +427,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { mInstallerUid = installerUid; this.params = params; this.createdMillis = createdMillis; + this.updatedMillis = createdMillis; this.stageDir = stageDir; this.stageCid = stageCid; if (childSessionIds != null) { @@ -521,6 +527,13 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } } + /** Returns true if a staged session has reached a final state and can be forgotten about */ + public boolean isStagedAndInTerminalState() { + synchronized (mLock) { + return params.isStaged && (mStagedSessionApplied || mStagedSessionFailed); + } + } + @GuardedBy("mLock") private void assertPreparedAndNotSealedLocked(String cookie) { assertPreparedAndNotCommittedOrDestroyedLocked(cookie); @@ -1034,6 +1047,13 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } } + /** Update the timestamp of when the staged session last changed state */ + public void markUpdated() { + synchronized (mLock) { + this.updatedMillis = System.currentTimeMillis(); + } + } + @Override public void transfer(String packageName) { Preconditions.checkNotNull(packageName); @@ -2114,7 +2134,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { private void destroyInternal() { synchronized (mLock) { mSealed = true; - if (!params.isStaged) { + if (!params.isStaged || isStagedAndInTerminalState()) { mDestroyed = true; } // Force shut down all bridges @@ -2224,6 +2244,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { mInstallerPackageName); writeIntAttribute(out, ATTR_INSTALLER_UID, mInstallerUid); writeLongAttribute(out, ATTR_CREATED_MILLIS, createdMillis); + writeLongAttribute(out, ATTR_UPDATED_MILLIS, updatedMillis); if (stageDir != null) { writeStringAttribute(out, ATTR_SESSION_STAGE_DIR, stageDir.getAbsolutePath()); @@ -2326,6 +2347,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { final int installerUid = readIntAttribute(in, ATTR_INSTALLER_UID, pm.getPackageUid( installerPackageName, PackageManager.MATCH_UNINSTALLED_PACKAGES, userId)); final long createdMillis = readLongAttribute(in, ATTR_CREATED_MILLIS); + long updatedMillis = readLongAttribute(in, ATTR_UPDATED_MILLIS); final String stageDirRaw = readStringAttribute(in, ATTR_SESSION_STAGE_DIR); final File stageDir = (stageDirRaw != null) ? new File(stageDirRaw) : null; final String stageCid = readStringAttribute(in, ATTR_SESSION_STAGE_CID); diff --git a/services/core/java/com/android/server/pm/PackageKeySetData.java b/services/core/java/com/android/server/pm/PackageKeySetData.java index a9126c0caa74..031b5ce3d5b9 100644 --- a/services/core/java/com/android/server/pm/PackageKeySetData.java +++ b/services/core/java/com/android/server/pm/PackageKeySetData.java @@ -107,10 +107,7 @@ public class PackageKeySetData { } protected void removeAllDefinedKeySets() { - final int aliasSize = mKeySetAliases.size(); - for (int i = 0; i < aliasSize; i++) { - mKeySetAliases.removeAt(i); - } + mKeySetAliases.erase(); } protected boolean isUsingDefinedKeySets() { diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index a679601bb306..ec2ff28b4a88 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -20173,21 +20173,20 @@ public class PackageManagerService extends IPackageManager.Stub } @Override - public String getContentCaptureServicePackageName() { - String contentCaptureServiceName = - mContext.getString(R.string.config_defaultContentCaptureService); + public String getSystemCaptionsServicePackageName() { + String flattenedSystemCaptionsServiceComponentName = + mContext.getString(R.string.config_defaultSystemCaptionsService); - if (TextUtils.isEmpty(contentCaptureServiceName)) { + if (TextUtils.isEmpty(flattenedSystemCaptionsServiceComponentName)) { return null; } - int separatorIndex = contentCaptureServiceName.indexOf("/"); - - if (separatorIndex < 0) { + ComponentName systemCaptionsServiceComponentName = + ComponentName.unflattenFromString(flattenedSystemCaptionsServiceComponentName); + if (systemCaptionsServiceComponentName == null) { return null; } - - return contentCaptureServiceName.substring(0, separatorIndex); + return systemCaptionsServiceComponentName.getPackageName(); } public String getIncidentReportApproverPackageName() { diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java index eced165bf257..9782648efb6b 100644 --- a/services/core/java/com/android/server/pm/ShortcutPackage.java +++ b/services/core/java/com/android/server/pm/ShortcutPackage.java @@ -99,6 +99,7 @@ class ShortcutPackage extends ShortcutPackageItem { private static final String ATTR_ICON_RES_ID = "icon-res"; private static final String ATTR_ICON_RES_NAME = "icon-resname"; private static final String ATTR_BITMAP_PATH = "bitmap-path"; + private static final String ATTR_LOCUS_ID = "locus-id"; private static final String ATTR_PERSON_NAME = "name"; private static final String ATTR_PERSON_URI = "uri"; @@ -1473,6 +1474,10 @@ class ShortcutPackage extends ShortcutPackageItem { ShortcutService.writeAttr(out, ATTR_DISABLED_REASON, si.getDisabledReason()); ShortcutService.writeAttr(out, ATTR_TIMESTAMP, si.getLastChangedTimestamp()); + final LocusId locusId = si.getLocusId(); + if (locusId != null) { + ShortcutService.writeAttr(out, ATTR_LOCUS_ID, si.getLocusId().getId()); + } if (forBackup) { // Don't write icon information. Also drop the dynamic flag. @@ -1612,6 +1617,7 @@ class ShortcutPackage extends ShortcutPackageItem { int iconResId; String iconResName; String bitmapPath; + final String locusIdString; int backupVersionCode; ArraySet<String> categories = null; ArrayList<Person> persons = new ArrayList<>(); @@ -1638,6 +1644,7 @@ class ShortcutPackage extends ShortcutPackageItem { iconResId = (int) ShortcutService.parseLongAttribute(parser, ATTR_ICON_RES_ID); iconResName = ShortcutService.parseStringAttribute(parser, ATTR_ICON_RES_NAME); bitmapPath = ShortcutService.parseStringAttribute(parser, ATTR_BITMAP_PATH); + locusIdString = ShortcutService.parseStringAttribute(parser, ATTR_LOCUS_ID); final int outerDepth = parser.getDepth(); int type; @@ -1703,7 +1710,7 @@ class ShortcutPackage extends ShortcutPackageItem { flags |= ShortcutInfo.FLAG_SHADOW; } - LocusId locusId = null; // LocusId is not set on XML. + final LocusId locusId = locusIdString == null ? null : new LocusId(locusIdString); return new ShortcutInfo( userId, id, packageName, activityComponent, /* icon= */ null, diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java index e9077a9df9cf..0a17e1305f03 100644 --- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java +++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java @@ -748,11 +748,11 @@ public final class DefaultPermissionGrantPolicy { grantSystemFixedPermissionsToSystemPackage("com.android.sharedstoragebackup", userId, STORAGE_PERMISSIONS); - // Content Capture Service - String contentCaptureServicePackageName = - mContext.getPackageManager().getContentCaptureServicePackageName(); - if (!TextUtils.isEmpty(contentCaptureServicePackageName)) { - grantPermissionsToSystemPackage(contentCaptureServicePackageName, userId, + // System Captions Service + String systemCaptionsServicePackageName = + mContext.getPackageManager().getSystemCaptionsServicePackageName(); + if (!TextUtils.isEmpty(systemCaptionsServicePackageName)) { + grantPermissionsToSystemPackage(systemCaptionsServicePackageName, userId, MICROPHONE_PERMISSIONS); } 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..1f898409af34 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; @@ -3362,9 +3364,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/power/AttentionDetector.java b/services/core/java/com/android/server/power/AttentionDetector.java index 406cbc10a8aa..701e5af01290 100644 --- a/services/core/java/com/android/server/power/AttentionDetector.java +++ b/services/core/java/com/android/server/power/AttentionDetector.java @@ -269,7 +269,7 @@ public class AttentionDetector { */ @VisibleForTesting boolean isAttentionServiceSupported() { - return mAttentionManager.isAttentionServiceSupported(); + return mAttentionManager != null && mAttentionManager.isAttentionServiceSupported(); } public void dump(PrintWriter pw) { 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/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java index c3582ea8fc7b..d6327494a24d 100644 --- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java +++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java @@ -16,6 +16,7 @@ package com.android.server.rollback; +import android.Manifest; import android.annotation.NonNull; import android.app.AppOpsManager; import android.content.BroadcastReceiver; @@ -24,6 +25,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.IntentSender; import android.content.pm.ApplicationInfo; +import android.content.pm.ModuleInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageInstaller; import android.content.pm.PackageManager; @@ -42,6 +44,7 @@ import android.os.HandlerThread; import android.os.ParcelFileDescriptor; import android.os.Process; import android.os.SystemClock; +import android.os.UserHandle; import android.provider.DeviceConfig; import android.util.IntArray; import android.util.Log; @@ -220,9 +223,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { @Override public ParceledListSlice getAvailableRollbacks() { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.MANAGE_ROLLBACKS, - "getAvailableRollbacks"); + enforceManageRollbacks("getAvailableRollbacks"); synchronized (mLock) { ensureRollbackDataLoadedLocked(); @@ -239,9 +240,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { @Override public ParceledListSlice<RollbackInfo> getRecentlyExecutedRollbacks() { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.MANAGE_ROLLBACKS, - "getRecentlyExecutedRollbacks"); + enforceManageRollbacks("getRecentlyCommittedRollbacks"); synchronized (mLock) { ensureRollbackDataLoadedLocked(); @@ -259,9 +258,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { @Override public void commitRollback(int rollbackId, ParceledListSlice causePackages, String callerPackageName, IntentSender statusReceiver) { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.MANAGE_ROLLBACKS, - "executeRollback"); + enforceManageRollbacks("executeRollback"); final int callingUid = Binder.getCallingUid(); AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class); @@ -459,11 +456,8 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { Intent broadcast = new Intent(Intent.ACTION_ROLLBACK_COMMITTED); - // TODO: This call emits the warning "Calling a method in the - // system process without a qualified user". Fix that. - // TODO: Limit this to receivers holding the - // MANAGE_ROLLBACKS permission? - mContext.sendBroadcast(broadcast); + mContext.sendBroadcastAsUser(broadcast, UserHandle.SYSTEM, + Manifest.permission.MANAGE_ROLLBACKS); }); } ); @@ -484,7 +478,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { @Override public void reloadPersistedData() { mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.MANAGE_ROLLBACKS, + Manifest.permission.TEST_MANAGE_ROLLBACKS, "reloadPersistedData"); synchronized (mLock) { @@ -499,7 +493,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { @Override public void expireRollbackForPackage(String packageName) { mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.MANAGE_ROLLBACKS, + Manifest.permission.TEST_MANAGE_ROLLBACKS, "expireRollbackForPackage"); synchronized (mLock) { ensureRollbackDataLoadedLocked(); @@ -894,12 +888,19 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { Log.i(TAG, "Enabling rollback for install of " + packageName + ", session:" + session.sessionId); + String installerPackageName = session.getInstallerPackageName(); + if (!enableRollbackAllowed(installerPackageName, packageName)) { + Log.e(TAG, "Installer " + installerPackageName + + " is not allowed to enable rollback on " + packageName); + return false; + } + VersionedPackage newVersion = new VersionedPackage(packageName, newPackage.versionCode); final boolean isApex = ((installFlags & PackageManager.INSTALL_APEX) != 0); // Get information about the currently installed package. PackageManager pm = mContext.getPackageManager(); - PackageInfo pkgInfo = null; + final PackageInfo pkgInfo; try { pkgInfo = pm.getPackageInfo(packageName, isApex ? PackageManager.MATCH_APEX : 0); } catch (PackageManager.NameNotFoundException e) { @@ -1086,6 +1087,44 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { } /** + * Returns true if the installer is allowed to enable rollback for the + * given named package, false otherwise. + */ + private boolean enableRollbackAllowed(String installerPackageName, String packageName) { + if (installerPackageName == null) { + return false; + } + + PackageManager pm = mContext.getPackageManager(); + boolean manageRollbacksGranted = pm.checkPermission( + Manifest.permission.MANAGE_ROLLBACKS, + installerPackageName) == PackageManager.PERMISSION_GRANTED; + + boolean testManageRollbacksGranted = pm.checkPermission( + Manifest.permission.TEST_MANAGE_ROLLBACKS, + installerPackageName) == PackageManager.PERMISSION_GRANTED; + + // For now only allow rollbacks for modules or for testing. + return (isModule(packageName) && manageRollbacksGranted) + || testManageRollbacksGranted; + } + + /** + * Returns true if the package name is the name of a module. + */ + private boolean isModule(String packageName) { + PackageManager pm = mContext.getPackageManager(); + final ModuleInfo moduleInfo; + try { + moduleInfo = pm.getModuleInfo(packageName, 0); + } catch (PackageManager.NameNotFoundException e) { + return false; + } + + return moduleInfo != null; + } + + /** * Gets the version of the package currently installed. * Returns null if the package is not currently installed. */ @@ -1311,4 +1350,15 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { } } } + + private void enforceManageRollbacks(@NonNull String message) { + if ((PackageManager.PERMISSION_GRANTED != mContext.checkCallingOrSelfPermission( + Manifest.permission.MANAGE_ROLLBACKS)) + && (PackageManager.PERMISSION_GRANTED != mContext.checkCallingOrSelfPermission( + Manifest.permission.TEST_MANAGE_ROLLBACKS))) { + throw new SecurityException(message + " requires " + + Manifest.permission.MANAGE_ROLLBACKS + " or " + + Manifest.permission.TEST_MANAGE_ROLLBACKS); + } + } } diff --git a/services/core/java/com/android/server/wm/ActivityDisplay.java b/services/core/java/com/android/server/wm/ActivityDisplay.java index a33b454d51dc..9d6efb4f76cb 100644 --- a/services/core/java/com/android/server/wm/ActivityDisplay.java +++ b/services/core/java/com/android/server/wm/ActivityDisplay.java @@ -1173,7 +1173,17 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> } private void releaseSelfIfNeeded() { - if (mStacks.isEmpty() && mRemoved) { + if (!mRemoved || mDisplayContent == null) { + return; + } + + final ActivityStack stack = mStacks.size() == 1 ? mStacks.get(0) : null; + if (stack != null && stack.isActivityTypeHome() && stack.getAllTasks().isEmpty()) { + // Release this display if an empty home stack is the only thing left. + // Since it is the last stack, this display will be released along with the stack + // removal. + stack.remove(); + } else if (mStacks.isEmpty()) { mDisplayContent.removeIfPossible(); mDisplayContent = null; mRootActivityContainer.removeChild(this); diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java index ad989704b823..4c9b80be5d7c 100644 --- a/services/core/java/com/android/server/wm/ActivityStack.java +++ b/services/core/java/com/android/server/wm/ActivityStack.java @@ -3053,7 +3053,17 @@ class ActivityStack extends ConfigurationContainer { ActivityOptions.abort(options); if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityInNextFocusableStack: " + reason + ", go home"); - return mRootActivityContainer.resumeHomeActivity(prev, reason, mDisplayId); + if (isActivityTypeHome()) { + // resumeTopActivityUncheckedLocked has been prevented to run recursively. Post a + // runnable to resume home since we are currently in the process of resuming top + // activity in home stack. + // See {@link #mInResumeTopActivity}. + mService.mH.post( + () -> mRootActivityContainer.resumeHomeActivity(prev, reason, mDisplayId)); + return true; + } else { + return mRootActivityContainer.resumeHomeActivity(prev, reason, mDisplayId); + } } /** Returns the position the input task should be placed in this stack. */ 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/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index b00cafdccf11..bec72f5686df 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -130,6 +130,7 @@ import static com.android.server.wm.WindowManagerService.logSurface; import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP; import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING; import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW; +import static com.android.server.wm.utils.RegionUtils.rectListToRegion; import android.animation.AnimationHandler; import android.annotation.CallSuper; @@ -153,6 +154,7 @@ import android.os.Debug; import android.os.Handler; import android.os.IBinder; import android.os.Process; +import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.SystemClock; import android.os.Trace; @@ -165,6 +167,7 @@ import android.view.Display; import android.view.DisplayCutout; import android.view.DisplayInfo; import android.view.Gravity; +import android.view.ISystemGestureExclusionListener; import android.view.InputChannel; import android.view.InputDevice; import android.view.InputWindowHandle; @@ -312,6 +315,10 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo private DisplayRotation mDisplayRotation; DisplayFrames mDisplayFrames; + private final RemoteCallbackList<ISystemGestureExclusionListener> + mSystemGestureExclusionListeners = new RemoteCallbackList<>(); + private final Region mSystemGestureExclusion = new Region(); + /** * For default display it contains real metrics, empty for others. * @see WindowManagerService#createWatermarkInTransaction() @@ -2818,6 +2825,14 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo mWallpaperController.dump(pw, " "); pw.println(); + pw.print("mSystemGestureExclusion="); + if (mSystemGestureExclusionListeners.getRegisteredCallbackCount() > 0) { + pw.println(mSystemGestureExclusion); + } else { + pw.println("<no lstnrs>"); + } + + pw.println(); pw.println(prefix + "Application tokens in top down Z order:"); for (int stackNdx = mTaskStackContainers.getChildCount() - 1; stackNdx >= 0; --stackNdx) { final TaskStack stack = mTaskStackContainers.getChildAt(stackNdx); @@ -4951,6 +4966,100 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo } /** + * Updates the display's system gesture exclusion. + * + * @return true, if the exclusion changed. + */ + boolean updateSystemGestureExclusion() { + if (mSystemGestureExclusionListeners.getRegisteredCallbackCount() == 0) { + // No one's interested anyways. + return false; + } + + final Region systemGestureExclusion = calculateSystemGestureExclusion(); + try { + if (mSystemGestureExclusion.equals(systemGestureExclusion)) { + return false; + } + mSystemGestureExclusion.set(systemGestureExclusion); + for (int i = mSystemGestureExclusionListeners.beginBroadcast() - 1; i >= 0; --i) { + try { + mSystemGestureExclusionListeners.getBroadcastItem(i) + .onSystemGestureExclusionChanged(mDisplayId, systemGestureExclusion); + } catch (RemoteException e) { + Slog.e(TAG, "Failed to notify SystemGestureExclusionListener", e); + } + } + mSystemGestureExclusionListeners.finishBroadcast(); + return true; + } finally { + systemGestureExclusion.recycle(); + } + } + + @VisibleForTesting + Region calculateSystemGestureExclusion() { + final Region global = Region.obtain(); + final Region touchableRegion = Region.obtain(); + final Region local = Region.obtain(); + + // Traverse all windows bottom up to assemble the gesture exclusion rects. + // For each window, we only take the rects that fall within its touchable region. + forAllWindows(w -> { + if (w.cantReceiveTouchInput() || !w.isVisible() + || (w.getAttrs().flags & FLAG_NOT_TOUCHABLE) != 0) { + return; + } + final boolean modal = + (w.mAttrs.flags & (FLAG_NOT_TOUCH_MODAL | FLAG_NOT_FOCUSABLE)) == 0; + + // Only keep the exclusion zones from the windows behind where the current window + // isn't touchable. + w.getTouchableRegion(touchableRegion); + global.op(touchableRegion, Op.DIFFERENCE); + + rectListToRegion(w.getSystemGestureExclusion(), local); + + // Transform to display coordinates + local.scale(w.mGlobalScale); + final Rect frame = w.getWindowFrames().mFrame; + local.translate(frame.left, frame.top); + + // A window can only exclude system gestures where it is actually touchable + local.op(touchableRegion, Op.INTERSECT); + + global.op(local, Op.UNION); + }, false /* topToBottom */); + local.recycle(); + touchableRegion.recycle(); + return global; + } + + void registerSystemGestureExclusionListener(ISystemGestureExclusionListener listener) { + mSystemGestureExclusionListeners.register(listener); + final boolean changed; + if (mSystemGestureExclusionListeners.getRegisteredCallbackCount() == 1) { + changed = updateSystemGestureExclusion(); + } else { + changed = false; + } + + if (!changed) { + // If updateSystemGestureExclusion changed the exclusion, it will already have + // notified the listener. Otherwise, we'll do it here. + try { + listener.onSystemGestureExclusionChanged(mDisplayId, mSystemGestureExclusion); + } catch (RemoteException e) { + Slog.e(TAG, "Failed to notify SystemGestureExclusionListener during register", e); + } + } + } + + void unregisterSystemGestureExclusionListener(ISystemGestureExclusionListener listener) { + mSystemGestureExclusionListeners.unregister(listener); + } + + /** * Create a portal window handle for input. This window transports any touch to the display * indicated by {@link InputWindowHandle#portalToDisplayId} if the touch hits this window. * 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/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index 8f4e8422581b..ed5f6658197b 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -682,6 +682,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> // Finally update all input windows now that the window changes have stabilized. forAllDisplays(dc -> { dc.getInputMonitor().updateInputWindowsLw(true /*force*/); + dc.updateSystemGestureExclusion(); }); mWmService.setHoldScreenLocked(mHoldScreen); diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java index dc8c7b79feef..9b634f959fca 100644 --- a/services/core/java/com/android/server/wm/Session.java +++ b/services/core/java/com/android/server/wm/Session.java @@ -57,6 +57,7 @@ import com.android.server.wm.WindowManagerService.H; import java.io.PrintWriter; import java.util.HashSet; +import java.util.List; import java.util.Set; import java.util.function.BiConsumer; @@ -314,6 +315,16 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient { } } + @Override + public void reportSystemGestureExclusionChanged(IWindow window, List<Rect> exclusionRects) { + long ident = Binder.clearCallingIdentity(); + try { + mService.reportSystemGestureExclusionChanged(this, window, exclusionRects); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + private void actionOnWallpaper(IBinder window, BiConsumer<WallpaperController, WindowState> action) { final WindowState windowState = mService.windowForClientLocked(this, window, true); 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/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 4a9d798fda3c..7751560203e7 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -202,6 +202,7 @@ import android.view.IOnKeyguardExitResult; import android.view.IPinnedStackListener; import android.view.IRecentsAnimationRunner; import android.view.IRotationWatcher; +import android.view.ISystemGestureExclusionListener; import android.view.IWallpaperVisibilityListener; import android.view.IWindow; import android.view.IWindowId; @@ -274,6 +275,7 @@ import java.text.DateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; +import java.util.List; /** {@hide} */ public class WindowManagerService extends IWindowManager.Stub @@ -3817,6 +3819,42 @@ public class WindowManagerService extends IWindowManager.Stub } @Override + public void registerSystemGestureExclusionListener(ISystemGestureExclusionListener listener, + int displayId) { + synchronized (mGlobalLock) { + final DisplayContent displayContent = mRoot.getDisplayContent(displayId); + if (displayContent == null) { + throw new IllegalArgumentException("Trying to register visibility event " + + "for invalid display: " + displayId); + } + displayContent.registerSystemGestureExclusionListener(listener); + } + } + + @Override + public void unregisterSystemGestureExclusionListener(ISystemGestureExclusionListener listener, + int displayId) { + synchronized (mGlobalLock) { + final DisplayContent displayContent = mRoot.getDisplayContent(displayId); + if (displayContent == null) { + throw new IllegalArgumentException("Trying to register visibility event " + + "for invalid display: " + displayId); + } + displayContent.unregisterSystemGestureExclusionListener(listener); + } + } + + void reportSystemGestureExclusionChanged(Session session, IWindow window, + List<Rect> exclusionRects) { + synchronized (mGlobalLock) { + final WindowState win = windowForClientLocked(session, window, true); + if (win.setSystemGestureExclusion(exclusionRects)) { + win.getDisplayContent().updateSystemGestureExclusion(); + } + } + } + + @Override public void registerDisplayFoldListener(IDisplayFoldListener listener) { mPolicy.registerDisplayFoldListener(listener); } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index ee445d836214..600178fa3276 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -205,6 +205,7 @@ import java.io.PrintWriter; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Comparator; +import java.util.List; import java.util.function.Predicate; /** A window in the window manager. */ @@ -363,6 +364,13 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP */ private final Rect mInsetFrame = new Rect(); + /** + * List of rects where system gestures should be ignored. + * + * Coordinates are relative to the window's position. + */ + private final List<Rect> mExclusionRects = new ArrayList<>(); + // If a window showing a wallpaper: the requested offset for the // wallpaper; if a wallpaper window: the currently applied offset. float mWallpaperX = -1; @@ -612,6 +620,24 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } } + List<Rect> getSystemGestureExclusion() { + return mExclusionRects; + } + + /** + * Sets the system gesture exclusion rects. + * + * @return {@code true} if anything changed + */ + boolean setSystemGestureExclusion(List<Rect> exclusionRects) { + if (mExclusionRects.equals(exclusionRects)) { + return false; + } + mExclusionRects.clear(); + mExclusionRects.addAll(exclusionRects); + return true; + } + interface PowerManagerWrapper { void wakeUp(long time, @WakeReason int reason, String details); diff --git a/services/core/java/com/android/server/wm/utils/RegionUtils.java b/services/core/java/com/android/server/wm/utils/RegionUtils.java new file mode 100644 index 000000000000..1458440f7b81 --- /dev/null +++ b/services/core/java/com/android/server/wm/utils/RegionUtils.java @@ -0,0 +1,45 @@ +/* + * 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.utils; + +import android.graphics.Rect; +import android.graphics.Region; + +import java.util.List; + +/** + * Utility methods to handle Regions. + */ +public class RegionUtils { + + private RegionUtils() {} + + + /** + * Converts a list of rects into a {@code Region}. + * + * @param rects the list of rects to convert + * @param outRegion the Region to set to the list of rects + */ + public static void rectListToRegion(List<Rect> rects, Region outRegion) { + outRegion.setEmpty(); + final int n = rects.size(); + for (int i = 0; i < n; i++) { + outRegion.union(rects.get(i)); + } + } +} 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 a4955f07801a..a6e9fdde7735 100644 --- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp +++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp @@ -119,7 +119,6 @@ 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::IGnssDebug; using android::hardware::gnss::V1_0::IGnssGeofenceCallback; using android::hardware::gnss::V1_0::IGnssGeofencing; using android::hardware::gnss::V1_0::IGnssNavigationMessage; @@ -143,9 +142,12 @@ using GnssLocation_V2_0 = android::hardware::gnss::V2_0::GnssLocation; using IGnss_V1_0 = android::hardware::gnss::V1_0::IGnss; using IGnss_V1_1 = android::hardware::gnss::V1_1::IGnss; using IGnss_V2_0 = android::hardware::gnss::V2_0::IGnss; +using IGnssCallback_V1_0 = android::hardware::gnss::V1_0::IGnssCallback; using IGnssConfiguration_V1_0 = android::hardware::gnss::V1_0::IGnssConfiguration; using IGnssConfiguration_V1_1 = android::hardware::gnss::V1_1::IGnssConfiguration; using IGnssConfiguration_V2_0 = android::hardware::gnss::V2_0::IGnssConfiguration; +using IGnssDebug_V1_0 = android::hardware::gnss::V1_0::IGnssDebug; +using IGnssDebug_V2_0 = android::hardware::gnss::V2_0::IGnssDebug; using IGnssMeasurement_V1_0 = android::hardware::gnss::V1_0::IGnssMeasurement; using IGnssMeasurement_V1_1 = android::hardware::gnss::V1_1::IGnssMeasurement; using IGnssMeasurement_V2_0 = android::hardware::gnss::V2_0::IGnssMeasurement; @@ -191,7 +193,8 @@ sp<IGnssGeofencing> gnssGeofencingIface = nullptr; sp<IAGnss_V1_0> agnssIface = nullptr; sp<IAGnss_V2_0> agnssIface_V2_0 = nullptr; sp<IGnssBatching> gnssBatchingIface = nullptr; -sp<IGnssDebug> gnssDebugIface = nullptr; +sp<IGnssDebug_V1_0> gnssDebugIface = nullptr; +sp<IGnssDebug_V2_0> gnssDebugIface_V2_0 = nullptr; sp<IGnssConfiguration_V1_0> gnssConfigurationIface = nullptr; sp<IGnssConfiguration_V1_1> gnssConfigurationIface_V1_1 = nullptr; sp<IGnssConfiguration_V2_0> gnssConfigurationIface_V2_0 = nullptr; @@ -548,7 +551,9 @@ static GnssLocation_V2_0 createGnssLocation_V2_0( struct GnssCallback : public IGnssCallback { Return<void> gnssLocationCb(const GnssLocation_V1_0& location) override; Return<void> gnssStatusCb(const IGnssCallback::GnssStatusValue status) override; - Return<void> gnssSvStatusCb(const IGnssCallback::GnssSvStatus& svStatus) override; + Return<void> gnssSvStatusCb(const IGnssCallback_V1_0::GnssSvStatus& svStatus) override { + return gnssSvStatusCbImpl(svStatus); + } Return<void> gnssNmeaCb(int64_t timestamp, const android::hardware::hidl_string& nmea) override; Return<void> gnssSetCapabilitesCb(uint32_t capabilities) override; Return<void> gnssAcquireWakelockCb() override; @@ -566,16 +571,47 @@ struct GnssCallback : public IGnssCallback { override; Return<void> gnssSetCapabilitiesCb_2_0(uint32_t capabilities) override; Return<void> gnssLocationCb_2_0(const GnssLocation_V2_0& location) override; - - // Templated implementation for gnnsLocationCb and gnnsLocationCb_2_0. - template <class T> - Return<void> gnssLocationCbImpl(const T& location); + Return<void> gnssSvStatusCb_2_0(const hidl_vec<IGnssCallback::GnssSvInfo>& svInfoList) override { + return gnssSvStatusCbImpl(svInfoList); + } Return<void> gnssSetCapabilitesCbImpl(uint32_t capabilities, bool hasSubHalCapabilityFlags); // TODO: Reconsider allocation cost vs threadsafety on these statics static const char* sNmeaString; static size_t sNmeaStringLength; +private: + template<class T> + Return<void> gnssLocationCbImpl(const T& location); + + template<class T> + Return<void> gnssSvStatusCbImpl(const T& svStatus); + + uint32_t getGnssSvInfoListSize(const IGnssCallback_V1_0::GnssSvStatus& svStatus) { + return svStatus.numSvs; + } + + uint32_t getGnssSvInfoListSize(const hidl_vec<IGnssCallback::GnssSvInfo>& svInfoList) { + return svInfoList.size(); + } + + const IGnssCallback_V1_0::GnssSvInfo& getGnssSvInfoOfIndex( + const IGnssCallback_V1_0::GnssSvStatus& svStatus, size_t i) { + return svStatus.gnssSvList.data()[i]; + } + + const IGnssCallback_V1_0::GnssSvInfo& getGnssSvInfoOfIndex( + const hidl_vec<IGnssCallback::GnssSvInfo>& svInfoList, size_t i) { + return svInfoList[i].v1_0; + } + + uint32_t getConstellationType(const IGnssCallback_V1_0::GnssSvStatus& svStatus, size_t i) { + return static_cast<uint32_t>(svStatus.gnssSvList.data()[i].constellation); + } + + uint32_t getConstellationType(const hidl_vec<IGnssCallback::GnssSvInfo>& svInfoList, size_t i) { + return static_cast<uint32_t>(svInfoList[i].constellation); + } }; Return<void> GnssCallback::gnssNameCb(const android::hardware::hidl_string& name) { @@ -623,10 +659,11 @@ Return<void> GnssCallback::gnssStatusCb(const IGnssCallback::GnssStatusValue sta return Void(); } -Return<void> GnssCallback::gnssSvStatusCb(const IGnssCallback::GnssSvStatus& svStatus) { +template<class T> +Return<void> GnssCallback::gnssSvStatusCbImpl(const T& svStatus) { JNIEnv* env = getJniEnv(); - uint32_t listSize = svStatus.numSvs; + uint32_t listSize = getGnssSvInfoListSize(svStatus); if (listSize > static_cast<uint32_t>( android::hardware::gnss::V1_0::GnssMax::SVS_COUNT)) { ALOGD("Too many satellites %u. Clamps to %u.", listSize, @@ -655,9 +692,9 @@ Return<void> GnssCallback::gnssSvStatusCb(const IGnssCallback::GnssSvStatus& svS CONSTELLATION_TYPE_SHIFT_WIDTH = 4 }; - const IGnssCallback::GnssSvInfo& info = svStatus.gnssSvList.data()[i]; + const IGnssCallback_V1_0::GnssSvInfo& info = getGnssSvInfoOfIndex(svStatus, i); svidWithFlags[i] = (info.svid << SVID_SHIFT_WIDTH) | - (static_cast<uint32_t>(info.constellation) << CONSTELLATION_TYPE_SHIFT_WIDTH) | + (getConstellationType(svStatus, i) << CONSTELLATION_TYPE_SHIFT_WIDTH) | static_cast<uint32_t>(info.svFlag); cn0s[i] = info.cN0Dbhz; elev[i] = info.elevationDegrees; @@ -1079,6 +1116,9 @@ void GnssMeasurementCallback::translateSingleGnssMeasurement // Overwrite with v2_0.state since v2_0->v1_1->v1_0.state is deprecated. SET(State, static_cast<int32_t>(measurement_V2_0->state)); + + // Overwrite with v2_0.constellation since v2_0->v1_1->v1_0.constellation is deprecated. + SET(ConstellationType, static_cast<int32_t>(measurement_V2_0->constellation)); } jobject GnssMeasurementCallback::translateGnssClock( @@ -1656,11 +1696,21 @@ static void android_location_GnssLocationProvider_init_once(JNIEnv* env, jclass } } - auto gnssDebug = gnssHal->getExtensionGnssDebug(); - if (!gnssDebug.isOk()) { - ALOGD("Unable to get a handle to GnssDebug"); + if (gnssHal_V2_0 != nullptr) { + auto gnssDebug = gnssHal_V2_0->getExtensionGnssDebug_2_0(); + if (!gnssDebug.isOk()) { + ALOGD("Unable to get a handle to GnssDebug_V2_0"); + } else { + gnssDebugIface_V2_0 = gnssDebug; + gnssDebugIface = gnssDebugIface_V2_0; + } } else { - gnssDebugIface = gnssDebug; + auto gnssDebug = gnssHal->getExtensionGnssDebug(); + if (!gnssDebug.isOk()) { + ALOGD("Unable to get a handle to GnssDebug"); + } else { + gnssDebugIface = gnssDebug; + } } auto gnssNi = gnssHal->getExtensionGnssNi(); @@ -2189,6 +2239,76 @@ static void android_location_GnssLocationProvider_send_ni_response(JNIEnv* /* en gnssNiIface->respond(notifId, static_cast<IGnssNiCallback::GnssUserResponseType>(response)); } +const IGnssDebug_V1_0::SatelliteData& getSatelliteData(const hidl_vec<IGnssDebug_V1_0::SatelliteData>& satelliteDataArray, size_t i) { + return satelliteDataArray[i]; +} + +const IGnssDebug_V1_0::SatelliteData& getSatelliteData(const hidl_vec<IGnssDebug_V2_0::SatelliteData>& satelliteDataArray, size_t i) { + return satelliteDataArray[i].v1_0; +} + +template<class T> +uint32_t getConstellationType(const hidl_vec<T>& satelliteDataArray, size_t i) { + return static_cast<uint32_t>(satelliteDataArray[i].constellation); +} + +template<class T> +static jstring parseDebugData(JNIEnv* env, std::stringstream& internalState, const T& data) { + internalState << "Gnss Location Data:: "; + if (!data.position.valid) { + internalState << "not valid"; + } else { + internalState << "LatitudeDegrees: " << data.position.latitudeDegrees + << ", LongitudeDegrees: " << data.position.longitudeDegrees + << ", altitudeMeters: " << data.position.altitudeMeters + << ", speedMetersPerSecond: " << data.position.speedMetersPerSec + << ", bearingDegrees: " << data.position.bearingDegrees + << ", horizontalAccuracyMeters: " + << data.position.horizontalAccuracyMeters + << ", verticalAccuracyMeters: " << data.position.verticalAccuracyMeters + << ", speedAccuracyMetersPerSecond: " + << data.position.speedAccuracyMetersPerSecond + << ", bearingAccuracyDegrees: " << data.position.bearingAccuracyDegrees + << ", ageSeconds: " << data.position.ageSeconds; + } + internalState << std::endl; + + internalState << "Gnss Time Data:: timeEstimate: " << data.time.timeEstimate + << ", timeUncertaintyNs: " << data.time.timeUncertaintyNs + << ", frequencyUncertaintyNsPerSec: " + << data.time.frequencyUncertaintyNsPerSec << std::endl; + + if (data.satelliteDataArray.size() != 0) { + internalState << "Satellite Data for " << data.satelliteDataArray.size() + << " satellites:: " << std::endl; + } + + internalState << "constell: 1=GPS, 2=SBAS, 3=GLO, 4=QZSS, 5=BDS, 6=GAL, 7=IRNSS; " + << "ephType: 0=Eph, 1=Alm, 2=Unk; " + << "ephSource: 0=Demod, 1=Supl, 2=Server, 3=Unk; " + << "ephHealth: 0=Good, 1=Bad, 2=Unk" << std::endl; + for (size_t i = 0; i < data.satelliteDataArray.size(); i++) { + IGnssDebug_V1_0::SatelliteData satelliteData = + getSatelliteData(data.satelliteDataArray, i); + internalState << "constell: " + << getConstellationType(data.satelliteDataArray, i) + << ", svid: " << std::setw(3) << satelliteData.svid + << ", serverPredAvail: " + << satelliteData.serverPredictionIsAvailable + << ", serverPredAgeSec: " << std::setw(7) + << satelliteData.serverPredictionAgeSeconds + << ", ephType: " + << static_cast<uint32_t>(satelliteData.ephemerisType) + << ", ephSource: " + << static_cast<uint32_t>(satelliteData.ephemerisSource) + << ", ephHealth: " + << static_cast<uint32_t>(satelliteData.ephemerisHealth) + << ", ephAgeSec: " << std::setw(7) + << satelliteData.ephemerisAgeSeconds << std::endl; + } + return (jstring) env->NewStringUTF(internalState.str().c_str()); +} + static jstring android_location_GnssLocationProvider_get_internal_state(JNIEnv* env, jobject /* obj */) { jstring result = nullptr; @@ -2200,65 +2320,19 @@ static jstring android_location_GnssLocationProvider_get_internal_state(JNIEnv* if (gnssDebugIface == nullptr) { internalState << "Gnss Debug Interface not available" << std::endl; + } else if (gnssDebugIface_V2_0 != nullptr) { + IGnssDebug_V2_0::DebugData data; + gnssDebugIface_V2_0->getDebugData_2_0([&data](const IGnssDebug_V2_0::DebugData& debugData) { + data = debugData; + }); + result = parseDebugData(env, internalState, data); } else { - IGnssDebug::DebugData data; - gnssDebugIface->getDebugData([&data](const IGnssDebug::DebugData& debugData) { + IGnssDebug_V1_0::DebugData data; + gnssDebugIface->getDebugData([&data](const IGnssDebug_V1_0::DebugData& debugData) { data = debugData; }); - - internalState << "Gnss Location Data:: "; - if (!data.position.valid) { - internalState << "not valid"; - } else { - internalState << "LatitudeDegrees: " << data.position.latitudeDegrees - << ", LongitudeDegrees: " << data.position.longitudeDegrees - << ", altitudeMeters: " << data.position.altitudeMeters - << ", speedMetersPerSecond: " << data.position.speedMetersPerSec - << ", bearingDegrees: " << data.position.bearingDegrees - << ", horizontalAccuracyMeters: " - << data.position.horizontalAccuracyMeters - << ", verticalAccuracyMeters: " << data.position.verticalAccuracyMeters - << ", speedAccuracyMetersPerSecond: " - << data.position.speedAccuracyMetersPerSecond - << ", bearingAccuracyDegrees: " << data.position.bearingAccuracyDegrees - << ", ageSeconds: " << data.position.ageSeconds; - } - internalState << std::endl; - - internalState << "Gnss Time Data:: timeEstimate: " << data.time.timeEstimate - << ", timeUncertaintyNs: " << data.time.timeUncertaintyNs - << ", frequencyUncertaintyNsPerSec: " - << data.time.frequencyUncertaintyNsPerSec << std::endl; - - if (data.satelliteDataArray.size() != 0) { - internalState << "Satellite Data for " << data.satelliteDataArray.size() - << " satellites:: " << std::endl; - } - - internalState << "constell: 1=GPS, 2=SBAS, 3=GLO, 4=QZSS, 5=BDS, 6=GAL; " - << "ephType: 0=Eph, 1=Alm, 2=Unk; " - << "ephSource: 0=Demod, 1=Supl, 2=Server, 3=Unk; " - << "ephHealth: 0=Good, 1=Bad, 2=Unk" << std::endl; - for (size_t i = 0; i < data.satelliteDataArray.size(); i++) { - internalState << "constell: " - << static_cast<uint32_t>(data.satelliteDataArray[i].constellation) - << ", svid: " << std::setw(3) << data.satelliteDataArray[i].svid - << ", serverPredAvail: " - << data.satelliteDataArray[i].serverPredictionIsAvailable - << ", serverPredAgeSec: " << std::setw(7) - << data.satelliteDataArray[i].serverPredictionAgeSeconds - << ", ephType: " - << static_cast<uint32_t>(data.satelliteDataArray[i].ephemerisType) - << ", ephSource: " - << static_cast<uint32_t>(data.satelliteDataArray[i].ephemerisSource) - << ", ephHealth: " - << static_cast<uint32_t>(data.satelliteDataArray[i].ephemerisHealth) - << ", ephAgeSec: " << std::setw(7) - << data.satelliteDataArray[i].ephemerisAgeSeconds << std::endl; - } + result = parseDebugData(env, internalState, data); } - - result = env->NewStringUTF(internalState.str().c_str()); return result; } diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 39af565d156f..419f52cff578 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -1230,6 +1230,7 @@ public final class SystemServer { } startContentCaptureService(context); + startAttentionService(context); // App prediction manager service traceBeginAndSlog("StartAppPredictionService"); @@ -1284,10 +1285,6 @@ public final class SystemServer { traceEnd(); } - traceBeginAndSlog("StartAttentionManagerService"); - mSystemServiceManager.startService(AttentionManagerService.class); - traceEnd(); - traceBeginAndSlog("StartNetworkScoreService"); mSystemServiceManager.startService(NetworkScoreService.Lifecycle.class); traceEnd(); @@ -2260,6 +2257,17 @@ public final class SystemServer { traceEnd(); } + private void startAttentionService(@NonNull Context context) { + if (!AttentionManagerService.isServiceConfigured(context)) { + Slog.d(TAG, "AttentionService is not configured on this device"); + return; + } + + traceBeginAndSlog("StartAttentionManagerService"); + mSystemServiceManager.startService(AttentionManagerService.class); + traceEnd(); + } + static final void startSystemUi(Context context, WindowManagerService windowManager) { Intent intent = new Intent(); intent.setComponent(new ComponentName("com.android.systemui", 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/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/backup/TrampolineTest.java b/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java index 3e5ce46e8e3a..dd79aad52fd2 100644 --- a/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java +++ b/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java @@ -82,7 +82,7 @@ public class TrampolineTest { private static final String CURRENT_PASSWORD = "current_password"; private static final String NEW_PASSWORD = "new_password"; private static final String ENCRYPTION_PASSWORD = "encryption_password"; - private static final String DATA_MANAGEMENT_LABEL = "data_management_label"; + private static final CharSequence DATA_MANAGEMENT_LABEL = "data_management_label"; private static final String DESTINATION_STRING = "destination_string"; private static final String[] PACKAGE_NAMES = new String[]{"some.package.name._1", "some.package.name._2"}; @@ -1104,8 +1104,8 @@ public class TrampolineTest { } @Test - public void getDataManagementLabel_calledBeforeInitialize_ignored() throws Exception { - assertNull(mTrampoline.getDataManagementLabel(TRANSPORT_NAME)); + public void getDataManagementLabelForUser_calledBeforeInitialize_ignored() throws Exception { + assertNull(mTrampoline.getDataManagementLabelForUser(mUserId, TRANSPORT_NAME)); verifyNoMoreInteractions(mBackupManagerServiceMock); } @@ -1122,17 +1122,6 @@ public class TrampolineTest { } @Test - public void getDataManagementLabel_forwarded() throws Exception { - TrampolineTestable.sCallingUserId = mUserId; - when(mBackupManagerServiceMock.getDataManagementLabel(mUserId, TRANSPORT_NAME)).thenReturn( - DATA_MANAGEMENT_LABEL); - mTrampoline.initializeService(); - - assertEquals(DATA_MANAGEMENT_LABEL, mTrampoline.getDataManagementLabel(TRANSPORT_NAME)); - verify(mBackupManagerServiceMock).getDataManagementLabel(mUserId, TRANSPORT_NAME); - } - - @Test public void beginRestoreSession_calledBeforeInitialize_ignored() throws Exception { mTrampoline.beginRestoreSessionForUser(mUserId, PACKAGE_NAME, TRANSPORT_NAME); verifyNoMoreInteractions(mBackupManagerServiceMock); diff --git a/services/tests/servicestests/src/com/android/server/backup/testutils/IPackageManagerStub.java b/services/tests/servicestests/src/com/android/server/backup/testutils/IPackageManagerStub.java index 26b122411c6b..caf6c9cac509 100644 --- a/services/tests/servicestests/src/com/android/server/backup/testutils/IPackageManagerStub.java +++ b/services/tests/servicestests/src/com/android/server/backup/testutils/IPackageManagerStub.java @@ -1138,7 +1138,7 @@ public class IPackageManagerStub implements IPackageManager { } @Override - public String getContentCaptureServicePackageName() throws RemoteException { + public String getSystemCaptionsServicePackageName() throws RemoteException { return null; } diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java index cd095a5fa6ff..fa1bcaccd786 100644 --- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java +++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java @@ -35,6 +35,7 @@ import android.app.ActivityManager; import android.app.Person; import android.content.ComponentName; import android.content.Intent; +import android.content.LocusId; import android.content.pm.ShortcutInfo; import android.content.res.Resources; import android.graphics.BitmapFactory; @@ -895,6 +896,7 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest { .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val")) .setRank(123) .setExtras(pb) + .setLocusId(new LocusId("1.2.3.4.5")) .build(); sorig.setTimestamp(mInjectedCurrentTimeMillis); @@ -906,6 +908,7 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest { .setPersons(list(makePerson("person1", "personKey1", "personUri1"), makePerson("person2", "personKey2", "personUri2")).toArray(new Person[2])) .setRank(456) + .setLocusId(new LocusId("6.7.8.9")) .build(); sorig2.setTimestamp(mInjectedCurrentTimeMillis); @@ -946,6 +949,7 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest { assertEquals("personUri", si.getPersons()[0].getUri()); assertEquals(0, si.getRank()); assertEquals(1, si.getExtras().getInt("k")); + assertEquals("1.2.3.4.5", si.getLocusId().getId()); assertEquals(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_HAS_ICON_FILE | ShortcutInfo.FLAG_STRINGS_RESOLVED, si.getFlags()); @@ -959,6 +963,7 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest { assertEquals(1, si.getRank()); assertEquals(2, si.getPersons().length); assertEquals("personUri2", si.getPersons()[1].getUri()); + assertEquals("6.7.8.9", si.getLocusId().getId()); dumpUserFile(USER_10); } diff --git a/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java b/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java index a2f1f01b689f..a1a58b49329f 100644 --- a/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java +++ b/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java @@ -105,6 +105,13 @@ public class AttentionDetectorTest extends AndroidTestCase { } @Test + public void testOnUserActivity_doesntCrashIfNoAttentionService() { + mAttentionManagerInternal = null; + registerAttention(); + // Does not crash. + } + + @Test public void onUserActivity_ignoresWhiteListedActivityTypes() { for (int i = 0; i < NUM_USER_ACTIVITY_TYPES; i++) { int result = mAttentionDetector.onUserActivity(SystemClock.uptimeMillis(), i); 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/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java index 98333b244e3b..e60e54c9e44f 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -25,6 +25,8 @@ import static android.view.Display.DEFAULT_DISPLAY; import static android.view.DisplayCutout.BOUNDS_POSITION_LEFT; import static android.view.DisplayCutout.BOUNDS_POSITION_TOP; import static android.view.DisplayCutout.fromBoundingRect; +import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR; +import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG; import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; @@ -58,12 +60,15 @@ import android.annotation.SuppressLint; import android.app.WindowConfiguration; import android.content.res.Configuration; import android.graphics.Rect; +import android.graphics.Region; import android.metrics.LogMaker; import android.os.SystemClock; import android.platform.test.annotations.Presubmit; import android.util.DisplayMetrics; +import android.util.MutableBoolean; import android.view.DisplayCutout; import android.view.Gravity; +import android.view.ISystemGestureExclusionListener; import android.view.MotionEvent; import android.view.Surface; import android.view.ViewRootImpl; @@ -683,6 +688,60 @@ public class DisplayContentTests extends WindowTestsBase { } @Test + public void testUpdateSystemGestureExclusion() throws Exception { + final DisplayContent dc = createNewDisplay(); + final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win"); + win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR; + win.setSystemGestureExclusion(Collections.singletonList(new Rect(10, 20, 30, 40))); + + dc.setLayoutNeeded(); + dc.performLayout(true /* initial */, false /* updateImeWindows */); + + win.setHasSurface(true); + dc.updateSystemGestureExclusion(); + + final MutableBoolean invoked = new MutableBoolean(false); + final ISystemGestureExclusionListener.Stub verifier = + new ISystemGestureExclusionListener.Stub() { + @Override + public void onSystemGestureExclusionChanged(int displayId, Region actual) { + Region expected = Region.obtain(); + expected.set(10, 20, 30, 40); + assertEquals(expected, actual); + invoked.value = true; + } + }; + try { + dc.registerSystemGestureExclusionListener(verifier); + } finally { + dc.unregisterSystemGestureExclusionListener(verifier); + } + assertTrue("SystemGestureExclusionListener was not invoked", invoked.value); + } + + @Test + public void testCalculateSystemGestureExclusion() throws Exception { + final DisplayContent dc = createNewDisplay(); + final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win"); + win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR; + win.setSystemGestureExclusion(Collections.singletonList(new Rect(10, 20, 30, 40))); + + final WindowState win2 = createWindow(null, TYPE_APPLICATION, dc, "win2"); + win2.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR; + win2.setSystemGestureExclusion(Collections.singletonList(new Rect(20, 30, 40, 50))); + + dc.setLayoutNeeded(); + dc.performLayout(true /* initial */, false /* updateImeWindows */); + + win.setHasSurface(true); + win2.setHasSurface(true); + + final Region expected = Region.obtain(); + expected.set(20, 30, 40, 50); + assertEquals(expected, dc.calculateSystemGestureExclusion()); + } + + @Test public void testOrientationChangeLogging() { MetricsLogger mockLogger = mock(MetricsLogger.class); Configuration oldConfig = new Configuration(); 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/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/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java index c4c598344a09..2edef838ff28 100644 --- a/telephony/java/android/telephony/SubscriptionManager.java +++ b/telephony/java/android/telephony/SubscriptionManager.java @@ -2595,7 +2595,9 @@ public class SubscriptionManager { * {@link SubscriptionManager#DEFAULT_SUBSCRIPTION_ID}, it means * it's unset and {@link SubscriptionManager#getDefaultDataSubscriptionId()} * is used to determine which modem is preferred. - * @param needValidation whether validation is needed before switch happens. + * @param needValidation whether Telephony will wait until the network is validated by + * connectivity service before switching data to it. More details see + * {@link NetworkCapabilities#NET_CAPABILITY_VALIDATED}. * @param executor The executor of where the callback will execute. * @param callback Callback will be triggered once it succeeds or failed. * See {@link TelephonyManager.SetOpportunisticSubscriptionResult} diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index a897e3542cf6..1eb6cc35848a 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -10373,7 +10373,7 @@ public class TelephonyManager { @IntDef(prefix = {"SET_OPPORTUNISTIC_SUB"}, value = { SET_OPPORTUNISTIC_SUB_SUCCESS, SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED, - SET_OPPORTUNISTIC_SUB_INVALID_PARAMETER}) + SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION}) public @interface SetOpportunisticSubscriptionResult {} /** @@ -10387,9 +10387,9 @@ public class TelephonyManager { public static final int SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED = 1; /** - * The parameter passed in is invalid. + * The subscription is not valid. It must be an active opportunistic subscription. */ - public static final int SET_OPPORTUNISTIC_SUB_INVALID_PARAMETER = 2; + public static final int SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION = 2; /** @hide */ @Retention(RetentionPolicy.SOURCE) @@ -10609,45 +10609,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/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/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/RollbackBroadcastReceiver.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackBroadcastReceiver.java index 8a925b9bad38..ebe54187ddb6 100644 --- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackBroadcastReceiver.java +++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackBroadcastReceiver.java @@ -63,6 +63,13 @@ class RollbackBroadcastReceiver extends BroadcastReceiver { } /** + * Waits forever for the next rollback broadcast. + */ + Intent take() throws InterruptedException { + return mRollbackBroadcasts.take(); + } + + /** * Unregisters this broadcast receiver. */ void unregister() { 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 48bc9e87eebb..834743d7ffed 100644 --- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java +++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java @@ -27,7 +27,6 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.fail; import android.Manifest; -import android.app.ActivityManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -40,14 +39,11 @@ 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; import java.util.Collections; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.SynchronousQueue; import java.util.concurrent.TimeUnit; /** @@ -87,6 +83,7 @@ public class RollbackTest { RollbackTestUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES, + Manifest.permission.TEST_MANAGE_ROLLBACKS, Manifest.permission.MANAGE_ROLLBACKS); // Register a broadcast receiver for notification when the @@ -175,7 +172,7 @@ public class RollbackTest { RollbackTestUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES, - Manifest.permission.MANAGE_ROLLBACKS); + Manifest.permission.TEST_MANAGE_ROLLBACKS); RollbackManager rm = RollbackTestUtils.getRollbackManager(); @@ -233,7 +230,7 @@ public class RollbackTest { RollbackTestUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES, - Manifest.permission.MANAGE_ROLLBACKS); + Manifest.permission.TEST_MANAGE_ROLLBACKS); RollbackManager rm = RollbackTestUtils.getRollbackManager(); @@ -290,7 +287,7 @@ public class RollbackTest { RollbackTestUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES, - Manifest.permission.MANAGE_ROLLBACKS); + Manifest.permission.TEST_MANAGE_ROLLBACKS); RollbackManager rm = RollbackTestUtils.getRollbackManager(); @@ -343,7 +340,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.WRITE_DEVICE_CONFIG); DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK_BOOT, @@ -403,7 +400,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.WRITE_DEVICE_CONFIG, Manifest.permission.SET_TIME); @@ -475,7 +472,7 @@ public class RollbackTest { RollbackTestUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES, - Manifest.permission.MANAGE_ROLLBACKS); + Manifest.permission.TEST_MANAGE_ROLLBACKS); RollbackManager rm = RollbackTestUtils.getRollbackManager(); RollbackTestUtils.uninstall(TEST_APP_A); @@ -512,7 +509,7 @@ public class RollbackTest { RollbackTestUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES, - Manifest.permission.MANAGE_ROLLBACKS); + Manifest.permission.TEST_MANAGE_ROLLBACKS); RollbackTestUtils.uninstall(TEST_APP_A); RollbackTestUtils.install("RollbackTestAppAv1.apk", false); @@ -533,14 +530,13 @@ 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 { RollbackTestUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES, - Manifest.permission.MANAGE_ROLLBACKS); + Manifest.permission.TEST_MANAGE_ROLLBACKS); RollbackTestUtils.uninstall(TEST_APP_A); RollbackTestUtils.installSplit(false, @@ -598,7 +594,7 @@ public class RollbackTest { RollbackTestUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES, - Manifest.permission.MANAGE_ROLLBACKS); + Manifest.permission.TEST_MANAGE_ROLLBACKS); RollbackManager rm = RollbackTestUtils.getRollbackManager(); // Prep installation of the test apps. @@ -693,6 +689,75 @@ public class RollbackTest { } /** + * Test that you cannot enable rollback for a package without the + * MANAGE_ROLLBACKS permission. + */ + @Test + public void testEnableRollbackPermission() throws Exception { + try { + RollbackTestUtils.adoptShellPermissionIdentity( + Manifest.permission.INSTALL_PACKAGES, + Manifest.permission.DELETE_PACKAGES); + + RollbackTestUtils.uninstall(TEST_APP_A); + RollbackTestUtils.install("RollbackTestAppAv1.apk", /* enableRollback */ false); + assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + + RollbackTestUtils.install("RollbackTestAppAv2.apk", /* enableRollback */ true); + + // We expect v2 of the app was installed, but rollback has not + // been enabled. + assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + + // TODO: See if there is a way to remove this race condition + // between when the app is installed and when the rollback + // would be made available. + Thread.sleep(1000); + + RollbackTestUtils.adoptShellPermissionIdentity( + Manifest.permission.TEST_MANAGE_ROLLBACKS); + RollbackManager rm = RollbackTestUtils.getRollbackManager(); + assertNull(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TEST_APP_A)); + } finally { + RollbackTestUtils.dropShellPermissionIdentity(); + } + } + + /** + * Test that you cannot enable rollback for a non-module package when + * holding the MANAGE_ROLLBACKS permission. + */ + @Test + public void testNonModuleEnableRollback() throws Exception { + try { + RollbackTestUtils.adoptShellPermissionIdentity( + Manifest.permission.INSTALL_PACKAGES, + Manifest.permission.DELETE_PACKAGES, + Manifest.permission.MANAGE_ROLLBACKS); + + RollbackTestUtils.uninstall(TEST_APP_A); + RollbackTestUtils.install("RollbackTestAppAv1.apk", /* enableRollback */ false); + assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + + RollbackTestUtils.install("RollbackTestAppAv2.apk", /* enableRollback */ true); + + // We expect v2 of the app was installed, but rollback has not + // been enabled because the test app is not a module. + assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + + // TODO: See if there is a way to remove this race condition + // between when the app is installed and when the rollback + // would be made available. + Thread.sleep(1000); + + RollbackManager rm = RollbackTestUtils.getRollbackManager(); + assertNull(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TEST_APP_A)); + } finally { + RollbackTestUtils.dropShellPermissionIdentity(); + } + } + + /** * Test rollback of multi-package installs is implemented. */ @Test @@ -701,7 +766,7 @@ public class RollbackTest { RollbackTestUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES, - Manifest.permission.MANAGE_ROLLBACKS); + Manifest.permission.TEST_MANAGE_ROLLBACKS); RollbackManager rm = RollbackTestUtils.getRollbackManager(); // Prep installation of the test apps. @@ -761,6 +826,7 @@ public class RollbackTest { 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); RollbackManager rm = RollbackTestUtils.getRollbackManager(); @@ -790,34 +856,14 @@ public class RollbackTest { rm.getAvailableRollbacks(), TEST_APP_B); assertRollbackInfoEquals(TEST_APP_B, 2, 1, rollbackB); - BlockingQueue<Integer> crashQueue = new SynchronousQueue<>(); - - IntentFilter crashCountFilter = new IntentFilter(); - crashCountFilter.addAction("com.android.tests.rollback.CRASH"); - crashCountFilter.addCategory(Intent.CATEGORY_DEFAULT); - - crashCountReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - try { - // Sleep long enough for packagewatchdog to be notified of crash - Thread.sleep(1000); - // Kill app and close AppErrorDialog - ActivityManager am = context.getSystemService(ActivityManager.class); - am.killBackgroundProcesses(TEST_APP_A); - // Allow another package launch - crashQueue.put(intent.getIntExtra("count", 0)); - } catch (InterruptedException e) { - fail("Failed to communicate with test app"); - } - } - }; - context.registerReceiver(crashCountReceiver, crashCountFilter); - - // Start apps PackageWatchdog#TRIGGER_FAILURE_COUNT times so TEST_APP_A crashes - do { - RollbackTestUtils.launchPackage(TEST_APP_A); - } while(crashQueue.take() < 5); + // Register rollback committed receiver + RollbackBroadcastReceiver rollbackReceiver = new RollbackBroadcastReceiver(); + + // Crash TEST_APP_A PackageWatchdog#TRIGGER_FAILURE_COUNT times to trigger rollback + crashCountReceiver = RollbackTestUtils.sendCrashBroadcast(context, TEST_APP_A, 5); + + // Verify we received a broadcast for the rollback. + rollbackReceiver.take(); // TEST_APP_A is automatically rolled back by the RollbackPackageHealthObserver assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java index 9aed0748266a..81629aaaec76 100644 --- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java +++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java @@ -21,6 +21,7 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.fail; +import android.app.ActivityManager; import android.app.AlarmManager; import android.content.BroadcastReceiver; import android.content.ComponentName; @@ -47,6 +48,7 @@ import java.util.Arrays; import java.util.List; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.SynchronousQueue; /** * Utilities to facilitate testing rollbacks. @@ -187,7 +189,7 @@ class RollbackTestUtils { } /** Launches {@code packageName} with {@link Intent#ACTION_MAIN}. */ - static void launchPackage(String packageName) + private static void launchPackage(String packageName) throws InterruptedException, IOException { Context context = InstrumentationRegistry.getContext(); Intent intent = new Intent(Intent.ACTION_MAIN); @@ -488,4 +490,39 @@ class RollbackTestUtils { } return null; } + + /** + * Send broadcast to crash {@code packageName} {@code count} times. If {@code count} is at least + * {@link PackageWatchdog#TRIGGER_FAILURE_COUNT}, watchdog crash detection will be triggered. + */ + static BroadcastReceiver sendCrashBroadcast(Context context, String packageName, int count) + throws InterruptedException, IOException { + BlockingQueue<Integer> crashQueue = new SynchronousQueue<>(); + IntentFilter crashCountFilter = new IntentFilter(); + crashCountFilter.addAction("com.android.tests.rollback.CRASH"); + crashCountFilter.addCategory(Intent.CATEGORY_DEFAULT); + + BroadcastReceiver crashCountReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + try { + // Sleep long enough for packagewatchdog to be notified of crash + Thread.sleep(1000); + // Kill app and close AppErrorDialog + ActivityManager am = context.getSystemService(ActivityManager.class); + am.killBackgroundProcesses(packageName); + // Allow another package launch + crashQueue.put(intent.getIntExtra("count", 0)); + } catch (InterruptedException e) { + fail("Failed to communicate with test app"); + } + } + }; + context.registerReceiver(crashCountReceiver, crashCountFilter); + + do { + launchPackage(packageName); + } while(crashQueue.take() < count); + return crashCountReceiver; + } } diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java index 047451b643da..7e711c290e5a 100644 --- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java +++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java @@ -63,7 +63,7 @@ public class StagedRollbackTest { RollbackTestUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES, - Manifest.permission.MANAGE_ROLLBACKS); + Manifest.permission.TEST_MANAGE_ROLLBACKS); } /** 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/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/aapt2/link/TableMerger.cpp b/tools/aapt2/link/TableMerger.cpp index e9375176f26b..a24e0d2f93d0 100644 --- a/tools/aapt2/link/TableMerger.cpp +++ b/tools/aapt2/link/TableMerger.cpp @@ -58,7 +58,7 @@ bool TableMerger::MergeImpl(const Source& src, ResourceTable* table, bool overla // valid. This is because un-mangled references are mangled, then looked up at resolution // time. Also, when linking, we convert references with no package name to use the compilation // package name. - error |= !DoMerge(src, table, package.get(), false /*mangle*/, overlay, allow_new); + error |= !DoMerge(src, package.get(), false /*mangle*/, overlay, allow_new); } } return !error; @@ -78,7 +78,7 @@ bool TableMerger::MergeAndMangle(const Source& src, const StringPiece& package_n bool mangle = package_name != context_->GetCompilationPackage(); merged_packages_.insert(package->name); - error |= !DoMerge(src, table, package.get(), mangle, false /*overlay*/, true /*allow_new*/); + error |= !DoMerge(src, package.get(), mangle, false /*overlay*/, true /*allow_new*/); } return !error; } @@ -213,9 +213,8 @@ static ResourceTable::CollisionResult MergeConfigValue(IAaptContext* context, return collision_result; } -bool TableMerger::DoMerge(const Source& src, ResourceTable* src_table, - ResourceTablePackage* src_package, bool mangle_package, bool overlay, - bool allow_new_resources) { +bool TableMerger::DoMerge(const Source& src, ResourceTablePackage* src_package, bool mangle_package, + bool overlay, bool allow_new_resources) { bool error = false; for (auto& src_type : src_package->types) { @@ -337,8 +336,7 @@ bool TableMerger::MergeFile(const ResourceFile& file_desc, bool overlay, io::IFi ->FindOrCreateValue(file_desc.config, {}) ->value = std::move(file_ref); - return DoMerge(file->GetSource(), &table, pkg, false /*mangle*/, overlay /*overlay*/, - true /*allow_new*/); + return DoMerge(file->GetSource(), pkg, false /*mangle*/, overlay /*overlay*/, true /*allow_new*/); } } // namespace aapt diff --git a/tools/aapt2/link/TableMerger.h b/tools/aapt2/link/TableMerger.h index 24c5e1329244..51305cfcdd25 100644 --- a/tools/aapt2/link/TableMerger.h +++ b/tools/aapt2/link/TableMerger.h @@ -85,8 +85,8 @@ class TableMerger { bool MergeImpl(const Source& src, ResourceTable* src_table, bool overlay, bool allow_new); - bool DoMerge(const Source& src, ResourceTable* src_table, ResourceTablePackage* src_package, - bool mangle_package, bool overlay, bool allow_new_resources); + bool DoMerge(const Source& src, ResourceTablePackage* src_package, bool mangle_package, + bool overlay, bool allow_new_resources); std::unique_ptr<FileReference> CloneAndMangleFile(const std::string& package, const FileReference& value); 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(); } /* |