diff options
230 files changed, 4177 insertions, 1852 deletions
diff --git a/Android.bp b/Android.bp index fd307e7796a1..523e35637f84 100644 --- a/Android.bp +++ b/Android.bp @@ -1552,6 +1552,7 @@ droidstubs { ":openjdk_java_files", ":non_openjdk_java_files", ":opt-telephony-common-srcs", + "core/java/**/*.java", ], arg_files: [ "core/res/AndroidManifest.xml", diff --git a/api/current.txt b/api/current.txt index e740b85a3e46..766b6b3609c4 100755 --- a/api/current.txt +++ b/api/current.txt @@ -54,6 +54,7 @@ package android { field public static final String BROADCAST_SMS = "android.permission.BROADCAST_SMS"; field public static final String BROADCAST_STICKY = "android.permission.BROADCAST_STICKY"; field public static final String BROADCAST_WAP_PUSH = "android.permission.BROADCAST_WAP_PUSH"; + field public static final String CALL_COMPANION_APP = "android.permission.CALL_COMPANION_APP"; field public static final String CALL_PHONE = "android.permission.CALL_PHONE"; field public static final String CALL_PRIVILEGED = "android.permission.CALL_PRIVILEGED"; field public static final String CAMERA = "android.permission.CAMERA"; @@ -27116,7 +27117,7 @@ package android.net { public class ConnectivityManager { method public void addDefaultNetworkActiveListener(android.net.ConnectivityManager.OnNetworkActiveListener); method public boolean bindProcessToNetwork(@Nullable android.net.Network); - method public android.net.SocketKeepalive createSocketKeepalive(@NonNull android.net.Network, @NonNull android.net.IpSecManager.UdpEncapsulationSocket, @NonNull java.net.InetAddress, @NonNull java.net.InetAddress, @NonNull java.util.concurrent.Executor, @NonNull android.net.SocketKeepalive.Callback); + method @NonNull public android.net.SocketKeepalive createSocketKeepalive(@NonNull android.net.Network, @NonNull android.net.IpSecManager.UdpEncapsulationSocket, @NonNull java.net.InetAddress, @NonNull java.net.InetAddress, @NonNull java.util.concurrent.Executor, @NonNull android.net.SocketKeepalive.Callback); method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) @Nullable public android.net.Network getActiveNetwork(); method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkInfo getActiveNetworkInfo(); method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkInfo[] getAllNetworkInfo(); @@ -27194,7 +27195,7 @@ package android.net { public static class ConnectivityManager.NetworkCallback { ctor public ConnectivityManager.NetworkCallback(); method public void onAvailable(android.net.Network); - method public void onBlockedStatusChanged(android.net.Network, boolean); + method public void onBlockedStatusChanged(@NonNull android.net.Network, boolean); method public void onCapabilitiesChanged(android.net.Network, android.net.NetworkCapabilities); method public void onLinkPropertiesChanged(android.net.Network, android.net.LinkProperties); method public void onLosing(android.net.Network, int); @@ -27230,6 +27231,7 @@ package android.net { method @NonNull public static android.net.DnsResolver getInstance(); method public <T> void query(@Nullable android.net.Network, @NonNull byte[], int, @NonNull java.util.concurrent.Executor, @Nullable android.os.CancellationSignal, @NonNull android.net.DnsResolver.AnswerCallback<T>); method public <T> void query(@Nullable android.net.Network, @NonNull String, int, int, int, @NonNull java.util.concurrent.Executor, @Nullable android.os.CancellationSignal, @NonNull android.net.DnsResolver.AnswerCallback<T>); + method public void query(@Nullable android.net.Network, @NonNull String, int, @NonNull java.util.concurrent.Executor, @Nullable android.os.CancellationSignal, @NonNull android.net.DnsResolver.InetAddressAnswerCallback); field public static final int CLASS_IN = 1; // 0x1 field public static final int FLAG_EMPTY = 0; // 0x0 field public static final int FLAG_NO_CACHE_LOOKUP = 4; // 0x4 @@ -27650,7 +27652,7 @@ package android.net { method public final void start(@IntRange(from=0xa, to=0xe10) int); method public final void stop(); field public static final int ERROR_HARDWARE_ERROR = -31; // 0xffffffe1 - field public static final int ERROR_HARDWARE_UNSUPPORTED = -30; // 0xffffffe2 + field public static final int ERROR_INSUFFICIENT_RESOURCES = -32; // 0xffffffe0 field public static final int ERROR_INVALID_INTERVAL = -24; // 0xffffffe8 field public static final int ERROR_INVALID_IP_ADDRESS = -21; // 0xffffffeb field public static final int ERROR_INVALID_LENGTH = -23; // 0xffffffe9 @@ -27658,6 +27660,7 @@ package android.net { field public static final int ERROR_INVALID_PORT = -22; // 0xffffffea field public static final int ERROR_INVALID_SOCKET = -25; // 0xffffffe7 field public static final int ERROR_SOCKET_NOT_IDLE = -26; // 0xffffffe6 + field public static final int ERROR_UNSUPPORTED = -30; // 0xffffffe2 } public static class SocketKeepalive.Callback { @@ -41957,6 +41960,7 @@ package android.telecom { field public static final String EXTRA_INCOMING_CALL_EXTRAS = "android.telecom.extra.INCOMING_CALL_EXTRAS"; field public static final String EXTRA_INCOMING_VIDEO_STATE = "android.telecom.extra.INCOMING_VIDEO_STATE"; field public static final String EXTRA_IS_DEFAULT_CALL_SCREENING_APP = "android.telecom.extra.IS_DEFAULT_CALL_SCREENING_APP"; + field public static final String EXTRA_IS_ENABLED = "android.telecom.extra.IS_ENABLED"; field public static final String EXTRA_NOTIFICATION_COUNT = "android.telecom.extra.NOTIFICATION_COUNT"; field public static final String EXTRA_NOTIFICATION_PHONE_NUMBER = "android.telecom.extra.NOTIFICATION_PHONE_NUMBER"; field public static final String EXTRA_OUTGOING_CALL_EXTRAS = "android.telecom.extra.OUTGOING_CALL_EXTRAS"; @@ -41968,6 +41972,7 @@ package android.telecom { field public static final String GATEWAY_PROVIDER_PACKAGE = "android.telecom.extra.GATEWAY_PROVIDER_PACKAGE"; field public static final String METADATA_INCLUDE_EXTERNAL_CALLS = "android.telecom.INCLUDE_EXTERNAL_CALLS"; field public static final String METADATA_INCLUDE_SELF_MANAGED_CALLS = "android.telecom.INCLUDE_SELF_MANAGED_CALLS"; + field public static final String METADATA_IN_CALL_SERVICE_CAR_MODE_UI = "android.telecom.IN_CALL_SERVICE_CAR_MODE_UI"; field public static final String METADATA_IN_CALL_SERVICE_RINGING = "android.telecom.IN_CALL_SERVICE_RINGING"; field public static final String METADATA_IN_CALL_SERVICE_UI = "android.telecom.IN_CALL_SERVICE_UI"; field public static final int PRESENTATION_ALLOWED = 1; // 0x1 @@ -42960,7 +42965,7 @@ package android.telephony { method public String getCountryIso(); method public int getDataRoaming(); method public CharSequence getDisplayName(); - method public String getGroupUuid(); + method @Nullable public String getGroupUuid(); method public String getIccId(); method public int getIconTint(); method @Deprecated public int getMcc(); @@ -43001,7 +43006,7 @@ package android.telephony { method public boolean isNetworkRoaming(int); method public static boolean isUsableSubscriptionId(int); method public static boolean isValidSubscriptionId(int); - method public void removeOnOpportunisticSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnOpportunisticSubscriptionsChangedListener); + method public void removeOnOpportunisticSubscriptionsChangedListener(@NonNull android.telephony.SubscriptionManager.OnOpportunisticSubscriptionsChangedListener); method public void removeOnSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnSubscriptionsChangedListener); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean removeSubscriptionsFromGroup(@NonNull int[]); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setMetered(boolean, int); @@ -43010,7 +43015,7 @@ package android.telephony { method public void setSubscriptionOverrideCongested(int, boolean, long); method public void setSubscriptionOverrideUnmetered(int, boolean, long); method public void setSubscriptionPlans(int, @NonNull java.util.List<android.telephony.SubscriptionPlan>); - method @RequiresPermission("android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS") public void switchToSubscription(int, android.app.PendingIntent); + method @RequiresPermission("android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS") public void switchToSubscription(int, @NonNull android.app.PendingIntent); field public static final String ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED = "android.telephony.action.DEFAULT_SMS_SUBSCRIPTION_CHANGED"; field public static final String ACTION_DEFAULT_SUBSCRIPTION_CHANGED = "android.telephony.action.DEFAULT_SUBSCRIPTION_CHANGED"; field public static final String ACTION_MANAGE_SUBSCRIPTION_PLANS = "android.telephony.action.MANAGE_SUBSCRIPTION_PLANS"; @@ -43429,26 +43434,26 @@ package android.telephony.data { public static class ApnSetting.Builder { ctor public ApnSetting.Builder(); method public android.telephony.data.ApnSetting build(); - method @NonNull public android.telephony.data.ApnSetting.Builder setApnName(String); + method @NonNull public android.telephony.data.ApnSetting.Builder setApnName(@Nullable String); method @NonNull public android.telephony.data.ApnSetting.Builder setApnTypeBitmask(int); method @NonNull public android.telephony.data.ApnSetting.Builder setAuthType(int); method @NonNull public android.telephony.data.ApnSetting.Builder setCarrierEnabled(boolean); method @NonNull public android.telephony.data.ApnSetting.Builder setCarrierId(int); - method @NonNull public android.telephony.data.ApnSetting.Builder setEntryName(String); + method @NonNull public android.telephony.data.ApnSetting.Builder setEntryName(@Nullable String); method @Deprecated public android.telephony.data.ApnSetting.Builder setMmsProxyAddress(java.net.InetAddress); - method @NonNull public android.telephony.data.ApnSetting.Builder setMmsProxyAddress(String); + method @NonNull public android.telephony.data.ApnSetting.Builder setMmsProxyAddress(@Nullable String); method @NonNull public android.telephony.data.ApnSetting.Builder setMmsProxyPort(int); - method @NonNull public android.telephony.data.ApnSetting.Builder setMmsc(android.net.Uri); + method @NonNull public android.telephony.data.ApnSetting.Builder setMmsc(@Nullable android.net.Uri); method @NonNull public android.telephony.data.ApnSetting.Builder setMvnoType(int); method @NonNull public android.telephony.data.ApnSetting.Builder setNetworkTypeBitmask(int); - method @NonNull public android.telephony.data.ApnSetting.Builder setOperatorNumeric(String); - method @NonNull public android.telephony.data.ApnSetting.Builder setPassword(String); + method @NonNull public android.telephony.data.ApnSetting.Builder setOperatorNumeric(@Nullable String); + method @NonNull public android.telephony.data.ApnSetting.Builder setPassword(@Nullable String); method @NonNull public android.telephony.data.ApnSetting.Builder setProtocol(int); method @Deprecated public android.telephony.data.ApnSetting.Builder setProxyAddress(java.net.InetAddress); - method @NonNull public android.telephony.data.ApnSetting.Builder setProxyAddress(String); + method @NonNull public android.telephony.data.ApnSetting.Builder setProxyAddress(@Nullable String); method @NonNull public android.telephony.data.ApnSetting.Builder setProxyPort(int); method @NonNull public android.telephony.data.ApnSetting.Builder setRoamingProtocol(int); - method @NonNull public android.telephony.data.ApnSetting.Builder setUser(String); + method @NonNull public android.telephony.data.ApnSetting.Builder setUser(@Nullable String); } } diff --git a/api/system-current.txt b/api/system-current.txt index a6328a54ca1d..1717382272f3 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -836,7 +836,7 @@ package android.content { method public abstract void sendBroadcast(android.content.Intent, @Nullable String, @Nullable android.os.Bundle); method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public abstract void sendBroadcastAsUser(@RequiresPermission android.content.Intent, android.os.UserHandle, @Nullable String, @Nullable android.os.Bundle); method public abstract void sendOrderedBroadcast(@NonNull android.content.Intent, @Nullable String, @Nullable android.os.Bundle, @Nullable android.content.BroadcastReceiver, @Nullable android.os.Handler, int, @Nullable String, @Nullable android.os.Bundle); - method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public void startActivityAsUser(@RequiresPermission android.content.Intent, android.os.UserHandle); + method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public void startActivityAsUser(@RequiresPermission @NonNull android.content.Intent, @NonNull android.os.UserHandle); field public static final String BACKUP_SERVICE = "backup"; field public static final String CONTEXTHUB_SERVICE = "contexthub"; field public static final String DYNAMIC_ANDROID_SERVICE = "dynamic_android"; @@ -3086,7 +3086,6 @@ package android.metrics { package android.net { public class CaptivePortal implements android.os.Parcelable { - 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 @@ -3095,14 +3094,14 @@ package android.net { } public class ConnectivityManager { - method @RequiresPermission(android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD) public android.net.SocketKeepalive createNattKeepalive(@NonNull android.net.Network, @NonNull java.io.FileDescriptor, @NonNull java.net.InetAddress, @NonNull java.net.InetAddress, @NonNull java.util.concurrent.Executor, @NonNull android.net.SocketKeepalive.Callback); - method @RequiresPermission(android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD) public android.net.SocketKeepalive createSocketKeepalive(@NonNull android.net.Network, @NonNull java.net.Socket, @NonNull java.util.concurrent.Executor, @NonNull android.net.SocketKeepalive.Callback); - method public boolean getAvoidBadWifi(); + method @NonNull @RequiresPermission(android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD) public android.net.SocketKeepalive createNattKeepalive(@NonNull android.net.Network, @NonNull android.os.ParcelFileDescriptor, @NonNull java.net.InetAddress, @NonNull java.net.InetAddress, @NonNull java.util.concurrent.Executor, @NonNull android.net.SocketKeepalive.Callback); + method @NonNull @RequiresPermission(android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD) public android.net.SocketKeepalive createSocketKeepalive(@NonNull android.net.Network, @NonNull java.net.Socket, @NonNull java.util.concurrent.Executor, @NonNull android.net.SocketKeepalive.Callback); method @RequiresPermission(android.Manifest.permission.LOCAL_MAC_ADDRESS) public String getCaptivePortalServerUrl(); method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void getLatestTetheringEntitlementResult(int, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityManager.OnTetheringEntitlementResultListener); method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public boolean isTetheringSupported(); method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void registerTetheringEventCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityManager.OnTetheringEventCallback); method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void setAirplaneMode(boolean); + method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, "android.permission.NETWORK_STACK"}) public boolean shouldAvoidBadWifi(); method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void startCaptivePortalApp(@NonNull android.net.Network, @NonNull android.os.Bundle); method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback); method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback, android.os.Handler); @@ -3276,7 +3275,7 @@ package android.net { 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 @NonNull public java.util.List<android.net.RouteInfo> getRoutes(@Nullable String); method public void setDomains(@Nullable String); method public void setGateway(@Nullable java.net.InetAddress); method public void setIpAddress(@Nullable android.net.LinkAddress); @@ -3496,7 +3495,7 @@ package android.net.metrics { } public final class ValidationProbeEvent implements android.net.metrics.IpConnectivityLog.Event { - method public static String getProbeName(int); + method @NonNull public static String getProbeName(int); field public static final int DNS_FAILURE = 0; // 0x0 field public static final int DNS_SUCCESS = 1; // 0x1 field public static final int PROBE_DNS = 0; // 0x0 @@ -5917,11 +5916,11 @@ package android.telephony { field public static final int VSNCP_TIMEOUT = 2236; // 0x8bc } - public final class DataSpecificRegistrationStates implements android.os.Parcelable { + public final class DataSpecificRegistrationInfo implements android.os.Parcelable { method public int describeContents(); method @NonNull public android.telephony.LteVopsSupportInfo getLteVopsSupportInfo(); method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator<android.telephony.DataSpecificRegistrationStates> CREATOR; + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.DataSpecificRegistrationInfo> CREATOR; } public final class DisconnectCause { @@ -6030,7 +6029,7 @@ package android.telephony { method public int getAccessNetworkTechnology(); method @NonNull public java.util.List<java.lang.Integer> getAvailableServices(); method @Nullable public android.telephony.CellIdentity getCellIdentity(); - method @Nullable public android.telephony.DataSpecificRegistrationStates getDataSpecificStates(); + method @Nullable public android.telephony.DataSpecificRegistrationInfo getDataSpecificInfo(); method public int getDomain(); method public int getRegistrationState(); method public int getRejectCause(); diff --git a/api/test-current.txt b/api/test-current.txt index 3c0a75eb5bc6..ca7410931a50 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -602,7 +602,6 @@ package android.media.audiofx { package android.net { public class CaptivePortal implements android.os.Parcelable { - 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 @@ -696,7 +695,7 @@ package android.net { 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 @NonNull public java.util.List<android.net.RouteInfo> getRoutes(@Nullable String); method public void setDomains(@Nullable String); method public void setGateway(@Nullable java.net.InetAddress); method public void setIpAddress(@Nullable android.net.LinkAddress); @@ -915,7 +914,7 @@ package android.net.metrics { } public final class ValidationProbeEvent implements android.net.metrics.IpConnectivityLog.Event { - method public static String getProbeName(int); + method @NonNull public static String getProbeName(int); field public static final int DNS_FAILURE = 0; // 0x0 field public static final int DNS_SUCCESS = 1; // 0x1 field public static final int PROBE_DNS = 0; // 0x0 @@ -1485,10 +1484,34 @@ package android.telecom { package android.telephony { + public final class AccessNetworkConstants { + field public static final int TRANSPORT_TYPE_WLAN = 2; // 0x2 + field public static final int TRANSPORT_TYPE_WWAN = 1; // 0x1 + } + public class CarrierConfigManager { method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void overrideConfig(int, @Nullable android.os.PersistableBundle); } + public final class DataSpecificRegistrationInfo implements android.os.Parcelable { + method public int describeContents(); + method @NonNull public android.telephony.LteVopsSupportInfo getLteVopsSupportInfo(); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.DataSpecificRegistrationInfo> CREATOR; + } + + public final class LteVopsSupportInfo implements android.os.Parcelable { + ctor public LteVopsSupportInfo(int, int); + method public int describeContents(); + method public int getEmcBearerSupport(); + method public int getVopsSupport(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.telephony.LteVopsSupportInfo> CREATOR; + field public static final int LTE_STATUS_NOT_AVAILABLE = 1; // 0x1 + field public static final int LTE_STATUS_NOT_SUPPORTED = 3; // 0x3 + field public static final int LTE_STATUS_SUPPORTED = 2; // 0x2 + } + public class MbmsDownloadSession implements java.lang.AutoCloseable { field public static final String MBMS_DOWNLOAD_SERVICE_OVERRIDE_METADATA = "mbms-download-service-override"; } @@ -1501,12 +1524,59 @@ package android.telephony { field public static final String MBMS_STREAMING_SERVICE_OVERRIDE_METADATA = "mbms-streaming-service-override"; } + public final class NetworkRegistrationInfo implements android.os.Parcelable { + method public int describeContents(); + method public int getAccessNetworkTechnology(); + method @NonNull public java.util.List<java.lang.Integer> getAvailableServices(); + method @Nullable public android.telephony.CellIdentity getCellIdentity(); + method @Nullable public android.telephony.DataSpecificRegistrationInfo getDataSpecificInfo(); + method public int getDomain(); + method public int getRegistrationState(); + method public int getRejectCause(); + method public int getRoamingType(); + method public int getTransportType(); + method public boolean isEmergencyEnabled(); + method public boolean isRoaming(); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.NetworkRegistrationInfo> CREATOR; + field public static final int DOMAIN_CS = 1; // 0x1 + field public static final int DOMAIN_PS = 2; // 0x2 + field public static final int REGISTRATION_STATE_DENIED = 3; // 0x3 + field public static final int REGISTRATION_STATE_HOME = 1; // 0x1 + field public static final int REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING = 0; // 0x0 + field public static final int REGISTRATION_STATE_NOT_REGISTERED_SEARCHING = 2; // 0x2 + field public static final int REGISTRATION_STATE_ROAMING = 5; // 0x5 + field public static final int REGISTRATION_STATE_UNKNOWN = 4; // 0x4 + field public static final int SERVICE_TYPE_DATA = 2; // 0x2 + field public static final int SERVICE_TYPE_EMERGENCY = 5; // 0x5 + field public static final int SERVICE_TYPE_SMS = 3; // 0x3 + field public static final int SERVICE_TYPE_UNKNOWN = 0; // 0x0 + field public static final int SERVICE_TYPE_VIDEO = 4; // 0x4 + field public static final int SERVICE_TYPE_VOICE = 1; // 0x1 + } + + public static final class NetworkRegistrationInfo.Builder { + ctor public NetworkRegistrationInfo.Builder(); + method @NonNull public android.telephony.NetworkRegistrationInfo build(); + method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setAccessNetworkTechnology(int); + method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setAvailableServices(@NonNull java.util.List<java.lang.Integer>); + method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setCellIdentity(@Nullable android.telephony.CellIdentity); + method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setDomain(int); + method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setEmergencyOnly(boolean); + method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setRegistrationState(int); + method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setRejectCause(int); + method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setTransportType(int); + } + public class ServiceState implements android.os.Parcelable { + method public void addNetworkRegistrationInfo(android.telephony.NetworkRegistrationInfo); method public void setCdmaSystemAndNetworkId(int, int); method public void setCellBandwidths(int[]); method public void setChannelNumber(int); + method public void setDataRoamingType(int); method public void setRilDataRadioTechnology(int); method public void setRilVoiceRadioTechnology(int); + method public void setVoiceRoamingType(int); } public class TelephonyManager { diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto index 2a9f24863852..564e9186b868 100644 --- a/cmds/statsd/src/atoms.proto +++ b/cmds/statsd/src/atoms.proto @@ -32,6 +32,7 @@ import "frameworks/base/core/proto/android/net/networkcapabilities.proto"; import "frameworks/base/core/proto/android/os/enums.proto"; import "frameworks/base/core/proto/android/server/connectivity/data_stall_event.proto"; import "frameworks/base/core/proto/android/server/enums.proto"; +import "frameworks/base/core/proto/android/stats/connectivity/network_stack.proto"; import "frameworks/base/core/proto/android/stats/launcher/launcher.proto"; import "frameworks/base/core/proto/android/telecomm/enums.proto"; import "frameworks/base/core/proto/android/telephony/enums.proto"; @@ -164,6 +165,7 @@ message Atom { BluetoothSmpPairingEventReported bluetooth_smp_pairing_event_reported = 167; ProcessStartTime process_start_time = 169; BluetoothSocketConnectionStateChanged bluetooth_socket_connection_state_changed = 171; + NetworkStackReported network_stack_reported = 182; } // Pulled events will start at field 10000. @@ -3052,3 +3054,16 @@ message ProcessStartTime { optional string hosting_name = 9; } +/** + * Push network stack events. + * + * Log from: + * frameworks/base/packages/NetworkStack/ + */ +message NetworkStackReported { + // The id that indicates the event reported from NetworkStack. + optional int32 event_id = 1; + // The data for the reported events. + optional android.stats.connectivity.NetworkStackEventData network_stack_event = 2 [(log_mode) = MODE_BYTES]; +} + diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt index e3c7a2f9431a..7efadf20c3e4 100644 --- a/config/hiddenapi-greylist.txt +++ b/config/hiddenapi-greylist.txt @@ -794,11 +794,6 @@ Lcom/android/ims/internal/uce/presence/IPresenceService$Stub;-><init>()V Lcom/android/ims/internal/uce/uceservice/IUceListener$Stub;-><init>()V Lcom/android/ims/internal/uce/uceservice/IUceService$Stub;-><init>()V Lcom/android/internal/app/AlertActivity;-><init>()V -Lcom/android/internal/app/AlertActivity;->mAlert:Lcom/android/internal/app/AlertController; -Lcom/android/internal/app/AlertActivity;->mAlertParams:Lcom/android/internal/app/AlertController$AlertParams; -Lcom/android/internal/app/AlertActivity;->setupAlert()V -Lcom/android/internal/app/AssistUtils;-><init>(Landroid/content/Context;)V -Lcom/android/internal/app/AssistUtils;->getAssistComponentForUser(I)Landroid/content/ComponentName; Lcom/android/internal/app/ChooserActivity;-><init>()V Lcom/android/internal/app/IAppOpsCallback$Stub;-><init>()V Lcom/android/internal/app/IAppOpsService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V @@ -826,34 +821,9 @@ Lcom/android/internal/app/IAppOpsService$Stub;->TRANSACTION_stopWatchingMode:I Lcom/android/internal/app/IBatteryStats$Stub$Proxy;-><init>(Landroid/os/IBinder;)V Lcom/android/internal/app/IBatteryStats$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/app/IBatteryStats; Lcom/android/internal/app/IMediaContainerService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/app/IMediaContainerService; -Lcom/android/internal/app/IntentForwarderActivity;->TAG:Ljava/lang/String; Lcom/android/internal/app/IVoiceInteractionManagerService$Stub$Proxy;->showSessionFromSession(Landroid/os/IBinder;Landroid/os/Bundle;I)Z Lcom/android/internal/app/IVoiceInteractionManagerService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/app/IVoiceInteractionManagerService; -Lcom/android/internal/app/LocaleHelper$LocaleInfoComparator;-><init>(Ljava/util/Locale;Z)V -Lcom/android/internal/app/LocaleHelper$LocaleInfoComparator;->compare(Lcom/android/internal/app/LocaleStore$LocaleInfo;Lcom/android/internal/app/LocaleStore$LocaleInfo;)I -Lcom/android/internal/app/LocaleHelper;->getDisplayCountry(Ljava/util/Locale;Ljava/util/Locale;)Ljava/lang/String; -Lcom/android/internal/app/LocaleHelper;->getDisplayName(Ljava/util/Locale;Ljava/util/Locale;Z)Ljava/lang/String; -Lcom/android/internal/app/LocaleHelper;->normalizeForSearch(Ljava/lang/String;Ljava/util/Locale;)Ljava/lang/String; -Lcom/android/internal/app/LocalePicker$LocaleInfo;->getLocale()Ljava/util/Locale; -Lcom/android/internal/app/LocalePicker;->getLocales()Landroid/os/LocaleList; -Lcom/android/internal/app/LocalePicker;->updateLocale(Ljava/util/Locale;)V -Lcom/android/internal/app/LocalePicker;->updateLocales(Landroid/os/LocaleList;)V -Lcom/android/internal/app/LocaleStore$LocaleInfo;->getFullNameInUiLanguage()Ljava/lang/String; -Lcom/android/internal/app/LocaleStore$LocaleInfo;->getFullNameNative()Ljava/lang/String; -Lcom/android/internal/app/LocaleStore$LocaleInfo;->getId()Ljava/lang/String; -Lcom/android/internal/app/LocaleStore$LocaleInfo;->getLocale()Ljava/util/Locale; -Lcom/android/internal/app/LocaleStore$LocaleInfo;->getParent()Ljava/util/Locale; -Lcom/android/internal/app/LocaleStore;->fillCache(Landroid/content/Context;)V -Lcom/android/internal/app/LocaleStore;->getLevelLocales(Landroid/content/Context;Ljava/util/Set;Lcom/android/internal/app/LocaleStore$LocaleInfo;Z)Ljava/util/Set; -Lcom/android/internal/app/LocaleStore;->getLocaleInfo(Ljava/util/Locale;)Lcom/android/internal/app/LocaleStore$LocaleInfo; -Lcom/android/internal/app/NetInitiatedActivity;->handleNIVerify(Landroid/content/Intent;)V Lcom/android/internal/app/ResolverActivity;-><init>()V -Lcom/android/internal/app/ResolverActivity;->mAdapter:Lcom/android/internal/app/ResolverActivity$ResolveListAdapter; -Lcom/android/internal/app/ResolverActivity;->mPm:Landroid/content/pm/PackageManager; -Lcom/android/internal/app/ResolverActivity;->onCreate(Landroid/os/Bundle;Landroid/content/Intent;Ljava/lang/CharSequence;[Landroid/content/Intent;Ljava/util/List;Z)V -Lcom/android/internal/app/WindowDecorActionBar$TabImpl;->mCallback:Landroid/app/ActionBar$TabListener; -Lcom/android/internal/app/WindowDecorActionBar;->mTabScrollView:Lcom/android/internal/widget/ScrollingTabContainerView; -Lcom/android/internal/app/WindowDecorActionBar;->setShowHideAnimationEnabled(Z)V Lcom/android/internal/appwidget/IAppWidgetService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/appwidget/IAppWidgetService; Lcom/android/internal/appwidget/IAppWidgetService$Stub;->TRANSACTION_bindAppWidgetId:I Lcom/android/internal/backup/IBackupTransport$Stub;-><init>()V @@ -861,10 +831,6 @@ Lcom/android/internal/backup/LocalTransport;->mDataDir:Ljava/io/File; Lcom/android/internal/backup/LocalTransport;->mRestorePackage:I Lcom/android/internal/backup/LocalTransport;->mRestorePackages:[Landroid/content/pm/PackageInfo; Lcom/android/internal/content/PackageMonitor;-><init>()V -Lcom/android/internal/database/SortCursor;-><init>([Landroid/database/Cursor;Ljava/lang/String;)V -Lcom/android/internal/database/SortCursor;->mCursor:Landroid/database/Cursor; -Lcom/android/internal/database/SortCursor;->mCursors:[Landroid/database/Cursor; -Lcom/android/internal/http/HttpDateTime;->parse(Ljava/lang/String;)J Lcom/android/internal/location/GpsNetInitiatedHandler$GpsNiNotification;-><init>()V Lcom/android/internal/location/GpsNetInitiatedHandler$GpsNiNotification;->requestorId:Ljava/lang/String; Lcom/android/internal/location/GpsNetInitiatedHandler$GpsNiNotification;->requestorIdEncoding:I @@ -878,48 +844,11 @@ Lcom/android/internal/location/ILocationProvider$Stub;->asInterface(Landroid/os/ Lcom/android/internal/logging/MetricsLogger;-><init>()V Lcom/android/internal/net/LegacyVpnInfo;-><init>()V Lcom/android/internal/net/VpnConfig;-><init>()V -Lcom/android/internal/os/AndroidPrintStream;-><init>(ILjava/lang/String;)V Lcom/android/internal/os/BaseCommand;-><init>()V -Lcom/android/internal/os/BaseCommand;->mArgs:Landroid/os/ShellCommand; Lcom/android/internal/os/BatterySipper$DrainType;->values()[Lcom/android/internal/os/BatterySipper$DrainType; -Lcom/android/internal/os/BinderInternal;->getContextObject()Landroid/os/IBinder; -Lcom/android/internal/os/BinderInternal;->handleGc()V -Lcom/android/internal/os/ClassLoaderFactory;->createClassloaderNamespace(Ljava/lang/ClassLoader;ILjava/lang/String;Ljava/lang/String;ZLjava/lang/String;)Ljava/lang/String; Lcom/android/internal/os/IDropBoxManagerService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/os/IDropBoxManagerService; -Lcom/android/internal/os/ProcessCpuTracker$Stats;->name:Ljava/lang/String; -Lcom/android/internal/os/ProcessCpuTracker$Stats;->rel_stime:I -Lcom/android/internal/os/ProcessCpuTracker$Stats;->rel_uptime:J -Lcom/android/internal/os/ProcessCpuTracker$Stats;->rel_utime:I -Lcom/android/internal/os/ProcessCpuTracker;-><init>(Z)V -Lcom/android/internal/os/ProcessCpuTracker;->countWorkingStats()I -Lcom/android/internal/os/ProcessCpuTracker;->getWorkingStats(I)Lcom/android/internal/os/ProcessCpuTracker$Stats; -Lcom/android/internal/os/ProcessCpuTracker;->update()V -Lcom/android/internal/os/RuntimeInit;->commonInit()V -Lcom/android/internal/os/RuntimeInit;->getApplicationObject()Landroid/os/IBinder; -Lcom/android/internal/os/RuntimeInit;->initialized:Z -Lcom/android/internal/os/RuntimeInit;->main([Ljava/lang/String;)V -Lcom/android/internal/os/RuntimeInit;->mApplicationObject:Landroid/os/IBinder; -Lcom/android/internal/os/ZygoteConnection;->closeSocket()V -Lcom/android/internal/os/ZygoteConnection;->mSocket:Landroid/net/LocalSocket; -Lcom/android/internal/os/ZygoteConnection;->mSocketOutStream:Ljava/io/DataOutputStream; -Lcom/android/internal/os/ZygoteConnection;->peer:Landroid/net/Credentials; -Lcom/android/internal/os/ZygoteInit;->main([Ljava/lang/String;)V -Lcom/android/internal/os/ZygoteInit;->mResources:Landroid/content/res/Resources; -Lcom/android/internal/os/ZygoteSecurityException;-><init>(Ljava/lang/String;)V -Lcom/android/internal/policy/DecorView;->mLastBottomInset:I -Lcom/android/internal/policy/DecorView;->mLastLeftInset:I -Lcom/android/internal/policy/DecorView;->mLastRightInset:I -Lcom/android/internal/policy/DecorView;->mWindow:Lcom/android/internal/policy/PhoneWindow; Lcom/android/internal/policy/IKeyguardService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/policy/IKeyguardService; Lcom/android/internal/policy/IKeyguardStateCallback$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/policy/IKeyguardStateCallback; -Lcom/android/internal/policy/PhoneFallbackEventHandler;-><init>(Landroid/content/Context;)V -Lcom/android/internal/policy/PhoneFallbackEventHandler;->mContext:Landroid/content/Context; -Lcom/android/internal/policy/PhoneFallbackEventHandler;->mView:Landroid/view/View; -Lcom/android/internal/policy/PhoneFallbackEventHandler;->onKeyDown(ILandroid/view/KeyEvent;)Z -Lcom/android/internal/policy/PhoneFallbackEventHandler;->onKeyUp(ILandroid/view/KeyEvent;)Z -Lcom/android/internal/policy/PhoneFallbackEventHandler;->startCallActivity()V -Lcom/android/internal/policy/PhoneWindow;-><init>(Landroid/content/Context;)V -Lcom/android/internal/policy/PhoneWindow;->mTitle:Ljava/lang/CharSequence; Lcom/android/internal/preference/YesNoPreference;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;)V Lcom/android/internal/R$anim;->fade_in:I Lcom/android/internal/R$array;->config_autoBrightnessLcdBacklightValues:I @@ -1671,203 +1600,15 @@ Lcom/android/internal/telephony/uicc/IccUtils;->parseToBnW([BI)Landroid/graphics Lcom/android/internal/telephony/uicc/IccUtils;->parseToRGB([BIZ)Landroid/graphics/Bitmap; Lcom/android/internal/telephony/uicc/SIMRecords$GetSpnFsmState;->values()[Lcom/android/internal/telephony/uicc/SIMRecords$GetSpnFsmState; Lcom/android/internal/textservice/ITextServicesManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V -Lcom/android/internal/util/ArrayUtils;->appendElement(Ljava/lang/Class;[Ljava/lang/Object;Ljava/lang/Object;)[Ljava/lang/Object; -Lcom/android/internal/util/ArrayUtils;->appendInt([II)[I -Lcom/android/internal/util/ArrayUtils;->contains([II)Z -Lcom/android/internal/util/ArrayUtils;->contains([Ljava/lang/Object;Ljava/lang/Object;)Z -Lcom/android/internal/util/ArrayUtils;->emptyArray(Ljava/lang/Class;)[Ljava/lang/Object; -Lcom/android/internal/util/ArrayUtils;->indexOf([Ljava/lang/Object;Ljava/lang/Object;)I -Lcom/android/internal/util/ArrayUtils;->isEmpty([Ljava/lang/Object;)Z -Lcom/android/internal/util/ArrayUtils;->newUnpaddedArray(Ljava/lang/Class;I)[Ljava/lang/Object; -Lcom/android/internal/util/ArrayUtils;->newUnpaddedIntArray(I)[I -Lcom/android/internal/util/ArrayUtils;->removeElement(Ljava/lang/Class;[Ljava/lang/Object;Ljava/lang/Object;)[Ljava/lang/Object; -Lcom/android/internal/util/BitwiseInputStream;-><init>([B)V -Lcom/android/internal/util/BitwiseInputStream;->available()I -Lcom/android/internal/util/BitwiseInputStream;->read(I)I -Lcom/android/internal/util/BitwiseInputStream;->readByteArray(I)[B -Lcom/android/internal/util/BitwiseInputStream;->skip(I)V -Lcom/android/internal/util/BitwiseOutputStream;-><init>(I)V -Lcom/android/internal/util/BitwiseOutputStream;->toByteArray()[B -Lcom/android/internal/util/BitwiseOutputStream;->write(II)V -Lcom/android/internal/util/BitwiseOutputStream;->writeByteArray(I[B)V -Lcom/android/internal/util/CharSequences;->compareToIgnoreCase(Ljava/lang/CharSequence;Ljava/lang/CharSequence;)I -Lcom/android/internal/util/CharSequences;->equals(Ljava/lang/CharSequence;Ljava/lang/CharSequence;)Z -Lcom/android/internal/util/FastMath;->round(F)I -Lcom/android/internal/util/FastXmlSerializer;-><init>()V -Lcom/android/internal/util/GrowingArrayUtils;->append([III)[I -Lcom/android/internal/util/GrowingArrayUtils;->append([Ljava/lang/Object;ILjava/lang/Object;)[Ljava/lang/Object; -Lcom/android/internal/util/HexDump;->hexStringToByteArray(Ljava/lang/String;)[B -Lcom/android/internal/util/HexDump;->toHexString(I)Ljava/lang/String; -Lcom/android/internal/util/HexDump;->toHexString([B)Ljava/lang/String; -Lcom/android/internal/util/HexDump;->toHexString([BII)Ljava/lang/String; -Lcom/android/internal/util/HexDump;->toHexString([BZ)Ljava/lang/String; -Lcom/android/internal/util/IState;->getName()Ljava/lang/String; Lcom/android/internal/util/MemInfoReader;-><init>()V -Lcom/android/internal/util/MemInfoReader;->getCachedSize()J -Lcom/android/internal/util/MemInfoReader;->getFreeSize()J -Lcom/android/internal/util/MemInfoReader;->getRawInfo()[J -Lcom/android/internal/util/MemInfoReader;->getTotalSize()J -Lcom/android/internal/util/MemInfoReader;->readMemInfo()V -Lcom/android/internal/util/Preconditions;->checkArgument(Z)V -Lcom/android/internal/util/Preconditions;->checkArgument(ZLjava/lang/Object;)V -Lcom/android/internal/util/Preconditions;->checkArgumentInRange(IIILjava/lang/String;)I -Lcom/android/internal/util/Preconditions;->checkNotNull(Ljava/lang/Object;)Ljava/lang/Object; -Lcom/android/internal/util/Preconditions;->checkNotNull(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; -Lcom/android/internal/util/Preconditions;->checkState(Z)V -Lcom/android/internal/util/Preconditions;->checkState(ZLjava/lang/String;)V -Lcom/android/internal/util/State;-><init>()V -Lcom/android/internal/util/State;->enter()V -Lcom/android/internal/util/State;->exit()V -Lcom/android/internal/util/State;->getName()Ljava/lang/String; -Lcom/android/internal/util/State;->processMessage(Landroid/os/Message;)Z -Lcom/android/internal/util/StateMachine;-><init>(Ljava/lang/String;)V -Lcom/android/internal/util/StateMachine;-><init>(Ljava/lang/String;Landroid/os/Handler;)V -Lcom/android/internal/util/StateMachine;-><init>(Ljava/lang/String;Landroid/os/Looper;)V -Lcom/android/internal/util/StateMachine;->dump(Ljava/io/FileDescriptor;Ljava/io/PrintWriter;[Ljava/lang/String;)V -Lcom/android/internal/util/StateMachine;->obtainMessage(III)Landroid/os/Message; -Lcom/android/internal/util/StateMachine;->obtainMessage(IIILjava/lang/Object;)Landroid/os/Message; -Lcom/android/internal/util/StateMachine;->sendMessage(I)V -Lcom/android/internal/util/StateMachine;->sendMessage(II)V -Lcom/android/internal/util/StateMachine;->sendMessage(IIILjava/lang/Object;)V -Lcom/android/internal/util/StateMachine;->sendMessage(ILjava/lang/Object;)V -Lcom/android/internal/util/StateMachine;->sendMessage(Landroid/os/Message;)V -Lcom/android/internal/view/ActionBarPolicy;-><init>(Landroid/content/Context;)V -Lcom/android/internal/view/ActionBarPolicy;->get(Landroid/content/Context;)Lcom/android/internal/view/ActionBarPolicy; -Lcom/android/internal/view/ActionBarPolicy;->getEmbeddedMenuWidthLimit()I -Lcom/android/internal/view/ActionBarPolicy;->getMaxActionButtons()I -Lcom/android/internal/view/ActionBarPolicy;->getStackedTabMaxWidth()I -Lcom/android/internal/view/ActionBarPolicy;->getTabContainerHeight()I -Lcom/android/internal/view/ActionBarPolicy;->hasEmbeddedTabs()Z -Lcom/android/internal/view/ActionBarPolicy;->mContext:Landroid/content/Context; -Lcom/android/internal/view/ActionBarPolicy;->showsOverflowMenuButton()Z Lcom/android/internal/view/IInputMethodManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V Lcom/android/internal/view/IInputMethodManager$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/view/IInputMethodManager; Lcom/android/internal/view/IInputMethodSession$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/view/IInputMethodSession; -Lcom/android/internal/view/InputConnectionWrapper$InputContextCallback;->dispose()V -Lcom/android/internal/view/InputConnectionWrapper$InputContextCallback;->getInstance()Lcom/android/internal/view/InputConnectionWrapper$InputContextCallback; -Lcom/android/internal/view/menu/ActionMenu;-><init>(Landroid/content/Context;)V -Lcom/android/internal/view/menu/ActionMenuItem;-><init>(Landroid/content/Context;IIIILjava/lang/CharSequence;)V -Lcom/android/internal/view/menu/ContextMenuBuilder;-><init>(Landroid/content/Context;)V -Lcom/android/internal/view/menu/IconMenuItemView;->getTextAppropriateLayoutParams()Lcom/android/internal/view/menu/IconMenuView$LayoutParams; -Lcom/android/internal/view/menu/IconMenuItemView;->setIconMenuView(Lcom/android/internal/view/menu/IconMenuView;)V -Lcom/android/internal/view/menu/IconMenuItemView;->setItemInvoker(Lcom/android/internal/view/menu/MenuBuilder$ItemInvoker;)V -Lcom/android/internal/view/menu/IconMenuView$SavedState;-><init>(Landroid/os/Parcel;)V -Lcom/android/internal/view/menu/IconMenuView;->createMoreItemView()Lcom/android/internal/view/menu/IconMenuItemView; -Lcom/android/internal/view/menu/IconMenuView;->getNumActualItemsShown()I -Lcom/android/internal/view/menu/IconMenuView;->mItemBackground:Landroid/graphics/drawable/Drawable; -Lcom/android/internal/view/menu/IconMenuView;->mMaxItems:I -Lcom/android/internal/view/menu/IconMenuView;->mMenu:Lcom/android/internal/view/menu/MenuBuilder; -Lcom/android/internal/view/menu/MenuDialogHelper;-><init>(Lcom/android/internal/view/menu/MenuBuilder;)V -Lcom/android/internal/view/menu/MenuDialogHelper;->dismiss()V -Lcom/android/internal/view/menu/MenuDialogHelper;->show(Landroid/os/IBinder;)V -Lcom/android/internal/view/WindowManagerPolicyThread;->getLooper()Landroid/os/Looper; -Lcom/android/internal/widget/AbsActionBarView;->dismissPopupMenus()V -Lcom/android/internal/widget/ActionBarContextView;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;)V -Lcom/android/internal/widget/ActionBarOverlayLayout;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;)V -Lcom/android/internal/widget/ActionBarOverlayLayout;->setWindowCallback(Landroid/view/Window$Callback;)V -Lcom/android/internal/widget/EditableInputConnection;-><init>(Landroid/widget/TextView;)V Lcom/android/internal/widget/ILockSettings$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/widget/ILockSettings; Lcom/android/internal/widget/IRemoteViewsFactory$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/widget/IRemoteViewsFactory; -Lcom/android/internal/widget/LinearLayoutWithDefaultTouchRecepient;-><init>(Landroid/content/Context;)V -Lcom/android/internal/widget/LinearLayoutWithDefaultTouchRecepient;->setDefaultTouchRecepient(Landroid/view/View;)V -Lcom/android/internal/widget/LockPatternChecker;->checkPassword(Lcom/android/internal/widget/LockPatternUtils;Ljava/lang/String;ILcom/android/internal/widget/LockPatternChecker$OnCheckCallback;)Landroid/os/AsyncTask; -Lcom/android/internal/widget/LockPatternUtils$RequestThrottledException;-><init>(I)V -Lcom/android/internal/widget/LockPatternUtils$RequestThrottledException;->getTimeoutMs()I -Lcom/android/internal/widget/LockPatternUtils;-><init>(Landroid/content/Context;)V -Lcom/android/internal/widget/LockPatternUtils;->checkPassword(Ljava/lang/String;I)Z -Lcom/android/internal/widget/LockPatternUtils;->getActivePasswordQuality(I)I -Lcom/android/internal/widget/LockPatternUtils;->getDevicePolicyManager()Landroid/app/admin/DevicePolicyManager; -Lcom/android/internal/widget/LockPatternUtils;->getKeyguardStoredPasswordQuality(I)I -Lcom/android/internal/widget/LockPatternUtils;->getLockSettings()Lcom/android/internal/widget/ILockSettings; -Lcom/android/internal/widget/LockPatternUtils;->getOwnerInfo(I)Ljava/lang/String; -Lcom/android/internal/widget/LockPatternUtils;->getPowerButtonInstantlyLocks(I)Z -Lcom/android/internal/widget/LockPatternUtils;->getString(Ljava/lang/String;I)Ljava/lang/String; -Lcom/android/internal/widget/LockPatternUtils;->isDeviceEncryptionEnabled()Z -Lcom/android/internal/widget/LockPatternUtils;->isLockPasswordEnabled(I)Z -Lcom/android/internal/widget/LockPatternUtils;->isLockPatternEnabled(I)Z -Lcom/android/internal/widget/LockPatternUtils;->isLockScreenDisabled(I)Z -Lcom/android/internal/widget/LockPatternUtils;->isSecure(I)Z -Lcom/android/internal/widget/LockPatternUtils;->isTactileFeedbackEnabled()Z -Lcom/android/internal/widget/LockPatternUtils;->isVisiblePatternEnabled(I)Z -Lcom/android/internal/widget/LockPatternUtils;->mContentResolver:Landroid/content/ContentResolver; -Lcom/android/internal/widget/LockPatternUtils;->mContext:Landroid/content/Context; -Lcom/android/internal/widget/LockPatternUtils;->patternToHash(Ljava/util/List;)[B -Lcom/android/internal/widget/LockPatternUtils;->patternToString(Ljava/util/List;)Ljava/lang/String; -Lcom/android/internal/widget/LockPatternUtils;->reportFailedPasswordAttempt(I)V -Lcom/android/internal/widget/LockPatternUtils;->reportSuccessfulPasswordAttempt(I)V -Lcom/android/internal/widget/LockPatternUtils;->saveLockPassword(Ljava/lang/String;Ljava/lang/String;II)V -Lcom/android/internal/widget/LockPatternUtils;->setLockoutAttemptDeadline(II)J -Lcom/android/internal/widget/LockPatternUtils;->setLong(Ljava/lang/String;JI)V -Lcom/android/internal/widget/LockPatternUtils;->setOwnerInfo(Ljava/lang/String;I)V -Lcom/android/internal/widget/LockPatternUtils;->setOwnerInfoEnabled(ZI)V -Lcom/android/internal/widget/LockPatternUtils;->setString(Ljava/lang/String;Ljava/lang/String;I)V -Lcom/android/internal/widget/LockPatternView$Cell;->column:I -Lcom/android/internal/widget/LockPatternView$Cell;->row:I -Lcom/android/internal/widget/LockPatternView$DisplayMode;->Animate:Lcom/android/internal/widget/LockPatternView$DisplayMode; -Lcom/android/internal/widget/LockPatternView$DisplayMode;->Correct:Lcom/android/internal/widget/LockPatternView$DisplayMode; -Lcom/android/internal/widget/LockPatternView$DisplayMode;->Wrong:Lcom/android/internal/widget/LockPatternView$DisplayMode; -Lcom/android/internal/widget/LockPatternView$SavedState;-><init>(Landroid/os/Parcel;)V -Lcom/android/internal/widget/LockPatternView$SavedState;-><init>(Landroid/os/Parcelable;Ljava/lang/String;IZZZ)V -Lcom/android/internal/widget/LockPatternView;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;)V -Lcom/android/internal/widget/LockPatternView;->clearPattern()V -Lcom/android/internal/widget/LockPatternView;->disableInput()V -Lcom/android/internal/widget/LockPatternView;->enableInput()V -Lcom/android/internal/widget/LockPatternView;->getCellStates()[[Lcom/android/internal/widget/LockPatternView$CellState; -Lcom/android/internal/widget/LockPatternView;->mInStealthMode:Z -Lcom/android/internal/widget/LockPatternView;->mPaint:Landroid/graphics/Paint; -Lcom/android/internal/widget/LockPatternView;->mPathPaint:Landroid/graphics/Paint; -Lcom/android/internal/widget/LockPatternView;->mPattern:Ljava/util/ArrayList; -Lcom/android/internal/widget/LockPatternView;->mPatternDisplayMode:Lcom/android/internal/widget/LockPatternView$DisplayMode; -Lcom/android/internal/widget/LockPatternView;->mPatternInProgress:Z -Lcom/android/internal/widget/LockPatternView;->mSquareHeight:F -Lcom/android/internal/widget/LockPatternView;->mSquareWidth:F -Lcom/android/internal/widget/LockPatternView;->notifyPatternDetected()V -Lcom/android/internal/widget/LockPatternView;->setDisplayMode(Lcom/android/internal/widget/LockPatternView$DisplayMode;)V -Lcom/android/internal/widget/LockPatternView;->setInStealthMode(Z)V -Lcom/android/internal/widget/LockPatternView;->setOnPatternListener(Lcom/android/internal/widget/LockPatternView$OnPatternListener;)V -Lcom/android/internal/widget/LockPatternView;->setTactileFeedbackEnabled(Z)V Lcom/android/internal/widget/PointerLocationView$PointerState;-><init>()V -Lcom/android/internal/widget/PointerLocationView$PointerState;->mCurDown:Z -Lcom/android/internal/widget/PointerLocationView;->mCurDown:Z -Lcom/android/internal/widget/PointerLocationView;->mCurNumPointers:I -Lcom/android/internal/widget/PointerLocationView;->mMaxNumPointers:I -Lcom/android/internal/widget/PointerLocationView;->mPointers:Ljava/util/ArrayList; -Lcom/android/internal/widget/PointerLocationView;->mPrintCoords:Z -Lcom/android/internal/widget/PreferenceImageView;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;)V -Lcom/android/internal/widget/RecyclerView$RecycledViewPool$ScrapData;->mScrapHeap:Ljava/util/ArrayList; -Lcom/android/internal/widget/ScrollBarUtils;->getThumbLength(IIII)I -Lcom/android/internal/widget/SlidingTab$Slider;->tab:Landroid/widget/ImageView; -Lcom/android/internal/widget/SlidingTab$Slider;->text:Landroid/widget/TextView; -Lcom/android/internal/widget/SlidingTab;->mAnimationDoneListener:Landroid/view/animation/Animation$AnimationListener; -Lcom/android/internal/widget/SlidingTab;->mLeftSlider:Lcom/android/internal/widget/SlidingTab$Slider; -Lcom/android/internal/widget/SlidingTab;->mRightSlider:Lcom/android/internal/widget/SlidingTab$Slider; -Lcom/android/internal/widget/SlidingTab;->onAnimationDone()V -Lcom/android/internal/widget/SlidingTab;->resetView()V -Lcom/android/internal/widget/SlidingTab;->setHoldAfterTrigger(ZZ)V -Lcom/android/internal/widget/SlidingTab;->setLeftHintText(I)V -Lcom/android/internal/widget/SlidingTab;->setLeftTabResources(IIII)V -Lcom/android/internal/widget/SlidingTab;->setOnTriggerListener(Lcom/android/internal/widget/SlidingTab$OnTriggerListener;)V -Lcom/android/internal/widget/SlidingTab;->setRightHintText(I)V -Lcom/android/internal/widget/SlidingTab;->setRightTabResources(IIII)V -Lcom/android/internal/widget/TextViewInputDisabler;-><init>(Landroid/widget/TextView;)V -Lcom/android/internal/widget/TextViewInputDisabler;->setInputEnabled(Z)V -Lcom/android/internal/widget/ViewPager$OnPageChangeListener;->onPageScrolled(IFI)V -Lcom/android/internal/widget/ViewPager$OnPageChangeListener;->onPageScrollStateChanged(I)V -Lcom/android/internal/widget/ViewPager$OnPageChangeListener;->onPageSelected(I)V -Lcom/android/internal/widget/ViewPager;->getCurrentItem()I Lcom/android/server/net/BaseNetworkObserver;-><init>()V -Lcom/android/server/net/NetlinkTracker;-><init>(Ljava/lang/String;Lcom/android/server/net/NetlinkTracker$Callback;)V -Lcom/android/server/net/NetlinkTracker;->clearLinkProperties()V -Lcom/android/server/net/NetlinkTracker;->getLinkProperties()Landroid/net/LinkProperties; Lcom/android/server/ResettableTimeout$T;-><init>(Lcom/android/server/ResettableTimeout;)V -Lcom/android/server/ResettableTimeout;->mLock:Landroid/os/ConditionVariable; -Lcom/android/server/ResettableTimeout;->mOffAt:J -Lcom/google/android/collect/Lists;->newArrayList([Ljava/lang/Object;)Ljava/util/ArrayList; -Lcom/google/android/collect/Sets;->newArraySet()Landroid/util/ArraySet; -Lcom/google/android/collect/Sets;->newArraySet([Ljava/lang/Object;)Landroid/util/ArraySet; -Lcom/google/android/collect/Sets;->newHashSet()Ljava/util/HashSet; -Lcom/google/android/collect/Sets;->newHashSet([Ljava/lang/Object;)Ljava/util/HashSet; -Lcom/google/android/collect/Sets;->newSortedSet()Ljava/util/SortedSet; Lcom/google/android/gles_jni/EGLImpl;-><init>()V Lcom/google/android/gles_jni/GLImpl;-><init>()V Lcom/google/android/mms/ContentType;->getAudioTypes()Ljava/util/ArrayList; @@ -2150,17 +1891,7 @@ Lcom/google/android/mms/util/SqliteWrapper;->insert(Landroid/content/Context;Lan Lcom/google/android/mms/util/SqliteWrapper;->query(Landroid/content/Context;Landroid/content/ContentResolver;Landroid/net/Uri;[Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)Landroid/database/Cursor; Lcom/google/android/mms/util/SqliteWrapper;->requery(Landroid/content/Context;Landroid/database/Cursor;)Z Lcom/google/android/mms/util/SqliteWrapper;->update(Landroid/content/Context;Landroid/content/ContentResolver;Landroid/net/Uri;Landroid/content/ContentValues;Ljava/lang/String;[Ljava/lang/String;)I -Lcom/google/android/util/AbstractMessageParser$Token$Type;->ACRONYM:Lcom/google/android/util/AbstractMessageParser$Token$Type; -Lcom/google/android/util/AbstractMessageParser$Token$Type;->FLICKR:Lcom/google/android/util/AbstractMessageParser$Token$Type; -Lcom/google/android/util/AbstractMessageParser$Token$Type;->FORMAT:Lcom/google/android/util/AbstractMessageParser$Token$Type; -Lcom/google/android/util/AbstractMessageParser$Token$Type;->GOOGLE_VIDEO:Lcom/google/android/util/AbstractMessageParser$Token$Type; -Lcom/google/android/util/AbstractMessageParser$Token$Type;->HTML:Lcom/google/android/util/AbstractMessageParser$Token$Type; -Lcom/google/android/util/AbstractMessageParser$Token$Type;->LINK:Lcom/google/android/util/AbstractMessageParser$Token$Type; -Lcom/google/android/util/AbstractMessageParser$Token$Type;->MUSIC:Lcom/google/android/util/AbstractMessageParser$Token$Type; -Lcom/google/android/util/AbstractMessageParser$Token$Type;->PHOTO:Lcom/google/android/util/AbstractMessageParser$Token$Type; -Lcom/google/android/util/AbstractMessageParser$Token$Type;->SMILEY:Lcom/google/android/util/AbstractMessageParser$Token$Type; Lcom/google/android/util/AbstractMessageParser$Token$Type;->values()[Lcom/google/android/util/AbstractMessageParser$Token$Type; -Lcom/google/android/util/AbstractMessageParser$Token$Type;->YOUTUBE_VIDEO:Lcom/google/android/util/AbstractMessageParser$Token$Type; Lgov/nist/core/Debug;->printStackTrace(Ljava/lang/Exception;)V Lgov/nist/core/GenericObject;-><init>()V Lgov/nist/core/GenericObject;->dbgPrint()V diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 8625a04963a7..9223f71b4428 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -1711,7 +1711,8 @@ public abstract class Context { */ @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) @SystemApi - public void startActivityAsUser(@RequiresPermission Intent intent, UserHandle user) { + public void startActivityAsUser(@RequiresPermission @NonNull Intent intent, + @NonNull UserHandle user) { throw new RuntimeException("Not implemented. Must override in a subclass."); } diff --git a/core/java/android/net/CaptivePortal.java b/core/java/android/net/CaptivePortal.java index ebd8a7e3528a..db1951520a26 100644 --- a/core/java/android/net/CaptivePortal.java +++ b/core/java/android/net/CaptivePortal.java @@ -64,8 +64,6 @@ public class CaptivePortal implements Parcelable { private final IBinder mBinder; /** @hide */ - @SystemApi - @TestApi public CaptivePortal(@NonNull IBinder binder) { mBinder = binder; } diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 16322353add2..4a64128f146b 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -44,6 +44,7 @@ import android.os.INetworkManagementService; import android.os.Looper; import android.os.Message; import android.os.Messenger; +import android.os.ParcelFileDescriptor; import android.os.Process; import android.os.RemoteException; import android.os.ResultReceiver; @@ -64,6 +65,8 @@ import com.android.internal.util.Protocol; import libcore.net.event.NetworkEventDispatcher; import java.io.FileDescriptor; +import java.io.IOException; +import java.io.UncheckedIOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.net.InetAddress; @@ -1345,12 +1348,15 @@ public class ConnectivityManager { } /** - * Gets the URL that should be used for resolving whether a captive portal is present. + * Gets a URL that can be used for resolving whether a captive portal is present. * 1. This URL should respond with a 204 response to a GET request to indicate no captive * portal is present. * 2. This URL must be HTTP as redirect responses are used to find captive portal * sign-in pages. Captive portals cannot respond to HTTPS requests with redirects. * + * The system network validation may be using different strategies to detect captive portals, + * so this method does not necessarily return a URL used by the system. It only returns a URL + * that may be relevant for other components trying to detect captive portals. * @hide */ @SystemApi @@ -1920,14 +1926,24 @@ public class ConnectivityManager { * @return A {@link SocketKeepalive} object that can be used to control the keepalive on the * given socket. **/ - public SocketKeepalive createSocketKeepalive(@NonNull Network network, + public @NonNull SocketKeepalive createSocketKeepalive(@NonNull Network network, @NonNull UdpEncapsulationSocket socket, @NonNull InetAddress source, @NonNull InetAddress destination, @NonNull @CallbackExecutor Executor executor, @NonNull Callback callback) { - return new NattSocketKeepalive(mService, network, socket.getFileDescriptor(), - socket.getResourceId(), source, destination, executor, callback); + ParcelFileDescriptor dup; + try { + // Dup is needed here as the pfd inside the socket is owned by the IpSecService, + // which cannot be obtained by the app process. + dup = ParcelFileDescriptor.dup(socket.getFileDescriptor()); + } catch (IOException ignored) { + // Construct an invalid fd, so that if the user later calls start(), it will fail with + // ERROR_INVALID_SOCKET. + dup = new ParcelFileDescriptor(new FileDescriptor()); + } + return new NattSocketKeepalive(mService, network, dup, socket.getResourceId(), source, + destination, executor, callback); } /** @@ -1935,9 +1951,9 @@ public class ConnectivityManager { * by system apps which don't use IpSecService to create {@link UdpEncapsulationSocket}. * * @param network The {@link Network} the socket is on. - * @param fd The {@link FileDescriptor} that needs to be kept alive. The provided - * {@link FileDescriptor} must be bound to a port and the keepalives will be sent from - * that port. + * @param pfd The {@link ParcelFileDescriptor} that needs to be kept alive. The provided + * {@link ParcelFileDescriptor} must be bound to a port and the keepalives will be sent + * from that port. * @param source The source address of the {@link UdpEncapsulationSocket}. * @param destination The destination address of the {@link UdpEncapsulationSocket}. The * keepalive packets will always be sent to port 4500 of the given {@code destination}. @@ -1953,14 +1969,23 @@ public class ConnectivityManager { */ @SystemApi @RequiresPermission(android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD) - public SocketKeepalive createNattKeepalive(@NonNull Network network, - @NonNull FileDescriptor fd, + public @NonNull SocketKeepalive createNattKeepalive(@NonNull Network network, + @NonNull ParcelFileDescriptor pfd, @NonNull InetAddress source, @NonNull InetAddress destination, @NonNull @CallbackExecutor Executor executor, @NonNull Callback callback) { - return new NattSocketKeepalive(mService, network, fd, INVALID_RESOURCE_ID /* Unused */, - source, destination, executor, callback); + ParcelFileDescriptor dup; + try { + // TODO: Consider remove unnecessary dup. + dup = pfd.dup(); + } catch (IOException ignored) { + // Construct an invalid fd, so that if the user later calls start(), it will fail with + // ERROR_INVALID_SOCKET. + dup = new ParcelFileDescriptor(new FileDescriptor()); + } + return new NattSocketKeepalive(mService, network, dup, + INVALID_RESOURCE_ID /* Unused */, source, destination, executor, callback); } /** @@ -1984,11 +2009,19 @@ public class ConnectivityManager { */ @SystemApi @RequiresPermission(android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD) - public SocketKeepalive createSocketKeepalive(@NonNull Network network, + public @NonNull SocketKeepalive createSocketKeepalive(@NonNull Network network, @NonNull Socket socket, @NonNull Executor executor, @NonNull Callback callback) { - return new TcpSocketKeepalive(mService, network, socket, executor, callback); + ParcelFileDescriptor dup; + try { + dup = ParcelFileDescriptor.fromSocket(socket); + } catch (UncheckedIOException ignored) { + // Construct an invalid fd, so that if the user later calls start(), it will fail with + // ERROR_INVALID_SOCKET. + dup = new ParcelFileDescriptor(new FileDescriptor()); + } + return new TcpSocketKeepalive(mService, network, dup, executor, callback); } /** @@ -3320,7 +3353,7 @@ public class ConnectivityManager { * @param network The {@link Network} whose blocked status has changed. * @param blocked The blocked status of this {@link Network}. */ - public void onBlockedStatusChanged(Network network, boolean blocked) {} + public void onBlockedStatusChanged(@NonNull Network network, boolean blocked) {} private NetworkRequest networkRequest; } @@ -4101,9 +4134,12 @@ public class ConnectivityManager { * @hide */ @SystemApi - public boolean getAvoidBadWifi() { + @RequiresPermission(anyOf = { + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, + android.Manifest.permission.NETWORK_STACK}) + public boolean shouldAvoidBadWifi() { try { - return mService.getAvoidBadWifi(); + return mService.shouldAvoidBadWifi(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/net/DnsResolver.java b/core/java/android/net/DnsResolver.java index 59802514c7a3..687b721834cb 100644 --- a/core/java/android/net/DnsResolver.java +++ b/core/java/android/net/DnsResolver.java @@ -22,6 +22,10 @@ import static android.net.NetworkUtils.resNetworkResult; import static android.net.NetworkUtils.resNetworkSend; import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_ERROR; import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT; +import static android.system.OsConstants.AF_INET; +import static android.system.OsConstants.AF_INET6; +import static android.system.OsConstants.IPPROTO_UDP; +import static android.system.OsConstants.SOCK_DGRAM; import android.annotation.CallbackExecutor; import android.annotation.IntDef; @@ -30,12 +34,18 @@ import android.annotation.Nullable; import android.os.CancellationSignal; import android.os.Looper; import android.system.ErrnoException; +import android.system.Os; import android.util.Log; +import libcore.io.IoUtils; + import java.io.FileDescriptor; +import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.SocketAddress; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; @@ -52,6 +62,7 @@ public final class DnsResolver { private static final String TAG = "DnsResolver"; private static final int FD_EVENTS = EVENT_INPUT | EVENT_ERROR; private static final int MAXPACKET = 8 * 1024; + private static final int SLEEP_TIME = 2; @IntDef(prefix = { "CLASS_" }, value = { CLASS_IN @@ -188,9 +199,9 @@ public final class DnsResolver { * Send a raw DNS query. * The answer will be provided asynchronously through the provided {@link AnswerCallback}. * - * @param network {@link Network} specifying which network for querying. + * @param network {@link Network} specifying which network to query on. * {@code null} for query on default network. - * @param query blob message + * @param query blob message to query * @param flags flags as a combination of the FLAGS_* constants * @param executor The {@link Executor} that the callback should be executed on. * @param cancellationSignal used by the caller to signal if the query should be @@ -205,26 +216,29 @@ public final class DnsResolver { if (cancellationSignal != null && cancellationSignal.isCanceled()) { return; } + final Object lock = new Object(); final FileDescriptor queryfd; try { queryfd = resNetworkSend((network != null ? network.netId : NETID_UNSET), query, query.length, flags); } catch (ErrnoException e) { - callback.onQueryException(e); + executor.execute(() -> { + callback.onQueryException(e); + }); return; } - maybeAddCancellationSignal(cancellationSignal, queryfd); - registerFDListener(executor, queryfd, callback); + registerFDListener(executor, queryfd, callback, cancellationSignal, lock); + maybeAddCancellationSignal(cancellationSignal, queryfd, lock); } /** * Send a DNS query with the specified name, class and query type. * The answer will be provided asynchronously through the provided {@link AnswerCallback}. * - * @param network {@link Network} specifying which network for querying. + * @param network {@link Network} specifying which network to query on. * {@code null} for query on default network. - * @param domain domain name for querying + * @param domain domain name to query * @param nsClass dns class as one of the CLASS_* constants * @param nsType dns resource record (RR) type as one of the TYPE_* constants * @param flags flags as a combination of the FLAGS_* constants @@ -242,40 +256,180 @@ public final class DnsResolver { if (cancellationSignal != null && cancellationSignal.isCanceled()) { return; } + final Object lock = new Object(); final FileDescriptor queryfd; try { queryfd = resNetworkQuery((network != null ? network.netId : NETID_UNSET), domain, nsClass, nsType, flags); } catch (ErrnoException e) { - callback.onQueryException(e); + executor.execute(() -> { + callback.onQueryException(e); + }); return; } - maybeAddCancellationSignal(cancellationSignal, queryfd); - registerFDListener(executor, queryfd, callback); + registerFDListener(executor, queryfd, callback, cancellationSignal, lock); + maybeAddCancellationSignal(cancellationSignal, queryfd, lock); + } + + private class InetAddressAnswerAccumulator extends InetAddressAnswerCallback { + private final List<InetAddress> mAllAnswers; + private ParseException mParseException; + private ErrnoException mErrnoException; + private final InetAddressAnswerCallback mUserCallback; + private final int mTargetAnswerCount; + private int mReceivedAnswerCount = 0; + + InetAddressAnswerAccumulator(int size, @NonNull InetAddressAnswerCallback callback) { + mTargetAnswerCount = size; + mAllAnswers = new ArrayList<>(); + mUserCallback = callback; + } + + private boolean maybeReportException() { + if (mErrnoException != null) { + mUserCallback.onQueryException(mErrnoException); + return true; + } + if (mParseException != null) { + mUserCallback.onParseException(mParseException); + return true; + } + return false; + } + + private void maybeReportAnswer() { + if (++mReceivedAnswerCount != mTargetAnswerCount) return; + if (mAllAnswers.isEmpty() && maybeReportException()) return; + // TODO: Do RFC6724 sort. + mUserCallback.onAnswer(mAllAnswers); + } + + @Override + public void onAnswer(@NonNull List<InetAddress> answer) { + mAllAnswers.addAll(answer); + maybeReportAnswer(); + } + + @Override + public void onParseException(@NonNull ParseException e) { + mParseException = e; + maybeReportAnswer(); + } + + @Override + public void onQueryException(@NonNull ErrnoException e) { + mErrnoException = e; + maybeReportAnswer(); + } + } + + /** + * Send a DNS query with the specified name, get back a set of InetAddresses asynchronously. + * The answer will be provided asynchronously through the provided + * {@link InetAddressAnswerCallback}. + * + * @param network {@link Network} specifying which network to query on. + * {@code null} for query on default network. + * @param domain domain name to query + * @param flags flags as a combination of the FLAGS_* constants + * @param executor The {@link Executor} that the callback should be executed on. + * @param cancellationSignal used by the caller to signal if the query should be + * cancelled. May be {@code null}. + * @param callback an {@link InetAddressAnswerCallback} which will be called to notify the + * caller of the result of dns query. + */ + public void query(@Nullable Network network, @NonNull String domain, @QueryFlag int flags, + @NonNull @CallbackExecutor Executor executor, + @Nullable CancellationSignal cancellationSignal, + @NonNull InetAddressAnswerCallback callback) { + if (cancellationSignal != null && cancellationSignal.isCanceled()) { + return; + } + final Object lock = new Object(); + final boolean queryIpv6 = haveIpv6(network); + final boolean queryIpv4 = haveIpv4(network); + + final FileDescriptor v4fd; + final FileDescriptor v6fd; + + int queryCount = 0; + + if (queryIpv6) { + try { + v6fd = resNetworkQuery((network != null + ? network.netId : NETID_UNSET), domain, CLASS_IN, TYPE_AAAA, flags); + } catch (ErrnoException e) { + executor.execute(() -> { + callback.onQueryException(e); + }); + return; + } + queryCount++; + } else v6fd = null; + + // TODO: Use device flag to controll the sleep time. + // Avoiding gateways drop packets if queries are sent too close together + try { + Thread.sleep(SLEEP_TIME); + } catch (InterruptedException ex) { } + + if (queryIpv4) { + try { + v4fd = resNetworkQuery((network != null + ? network.netId : NETID_UNSET), domain, CLASS_IN, TYPE_A, flags); + } catch (ErrnoException e) { + if (queryIpv6) resNetworkCancel(v6fd); // Closes fd, marks it invalid. + executor.execute(() -> { + callback.onQueryException(e); + }); + return; + } + queryCount++; + } else v4fd = null; + + final InetAddressAnswerAccumulator accumulator = + new InetAddressAnswerAccumulator(queryCount, callback); + + if (queryIpv6) registerFDListener(executor, v6fd, accumulator, cancellationSignal, lock); + if (queryIpv4) registerFDListener(executor, v4fd, accumulator, cancellationSignal, lock); + + if (cancellationSignal == null) return; + cancellationSignal.setOnCancelListener(() -> { + synchronized (lock) { + if (queryIpv4) cancelQuery(v4fd); + if (queryIpv6) cancelQuery(v6fd); + } + }); } private <T> void registerFDListener(@NonNull Executor executor, - @NonNull FileDescriptor queryfd, @NonNull AnswerCallback<T> answerCallback) { + @NonNull FileDescriptor queryfd, @NonNull AnswerCallback<T> answerCallback, + @Nullable CancellationSignal cancellationSignal, @NonNull Object lock) { Looper.getMainLooper().getQueue().addOnFileDescriptorEventListener( queryfd, FD_EVENTS, (fd, events) -> { executor.execute(() -> { - byte[] answerbuf = null; - try { - answerbuf = resNetworkResult(fd); - } catch (ErrnoException e) { - Log.e(TAG, "resNetworkResult:" + e.toString()); - answerCallback.onQueryException(e); - return; - } - - try { - answerCallback.onAnswer( - answerCallback.parser.parse(answerbuf)); - } catch (ParseException e) { - answerCallback.onParseException(e); + synchronized (lock) { + if (cancellationSignal != null && cancellationSignal.isCanceled()) { + return; + } + byte[] answerbuf = null; + try { + answerbuf = resNetworkResult(fd); // Closes fd, marks it invalid. + } catch (ErrnoException e) { + Log.e(TAG, "resNetworkResult:" + e.toString()); + answerCallback.onQueryException(e); + return; + } + + try { + answerCallback.onAnswer( + answerCallback.parser.parse(answerbuf)); + } catch (ParseException e) { + answerCallback.onParseException(e); + } } }); // Unregister this fd listener @@ -283,15 +437,52 @@ public final class DnsResolver { }); } + private void cancelQuery(@NonNull FileDescriptor queryfd) { + if (!queryfd.valid()) return; + Looper.getMainLooper().getQueue().removeOnFileDescriptorEventListener(queryfd); + resNetworkCancel(queryfd); // Closes fd, marks it invalid. + } + private void maybeAddCancellationSignal(@Nullable CancellationSignal cancellationSignal, - @NonNull FileDescriptor queryfd) { + @NonNull FileDescriptor queryfd, @NonNull Object lock) { if (cancellationSignal == null) return; - cancellationSignal.setOnCancelListener( - () -> { - Looper.getMainLooper().getQueue() - .removeOnFileDescriptorEventListener(queryfd); - resNetworkCancel(queryfd); - }); + cancellationSignal.setOnCancelListener(() -> { + synchronized (lock) { + cancelQuery(queryfd); + } + }); + } + + // These two functions match the behaviour of have_ipv4 and have_ipv6 in the native resolver. + private boolean haveIpv4(@Nullable Network network) { + final SocketAddress addrIpv4 = + new InetSocketAddress(InetAddresses.parseNumericAddress("8.8.8.8"), 0); + return checkConnectivity(network, AF_INET, addrIpv4); + } + + private boolean haveIpv6(@Nullable Network network) { + final SocketAddress addrIpv6 = + new InetSocketAddress(InetAddresses.parseNumericAddress("2000::"), 0); + return checkConnectivity(network, AF_INET6, addrIpv6); + } + + private boolean checkConnectivity(@Nullable Network network, + int domain, @NonNull SocketAddress addr) { + final FileDescriptor socket; + try { + socket = Os.socket(domain, SOCK_DGRAM, IPPROTO_UDP); + } catch (ErrnoException e) { + return false; + } + try { + if (network != null) network.bindSocket(socket); + Os.connect(socket, addr); + } catch (IOException | ErrnoException e) { + return false; + } finally { + IoUtils.closeQuietly(socket); + } + return true; } private static class DnsAddressAnswer extends DnsPacket { diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl index 24e6a855ffe8..61648dc7f1d8 100644 --- a/core/java/android/net/IConnectivityManager.aidl +++ b/core/java/android/net/IConnectivityManager.aidl @@ -182,7 +182,7 @@ interface IConnectivityManager void startCaptivePortalApp(in Network network); void startCaptivePortalAppInternal(in Network network, in Bundle appExtras); - boolean getAvoidBadWifi(); + boolean shouldAvoidBadWifi(); int getMultipathPreference(in Network Network); NetworkRequest getDefaultRequest(); diff --git a/core/java/android/net/NattSocketKeepalive.java b/core/java/android/net/NattSocketKeepalive.java index 84da294f8940..b0ce0c71fbeb 100644 --- a/core/java/android/net/NattSocketKeepalive.java +++ b/core/java/android/net/NattSocketKeepalive.java @@ -17,10 +17,10 @@ package android.net; import android.annotation.NonNull; +import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.util.Log; -import java.io.FileDescriptor; import java.net.InetAddress; import java.util.concurrent.Executor; @@ -31,21 +31,19 @@ public final class NattSocketKeepalive extends SocketKeepalive { @NonNull private final InetAddress mSource; @NonNull private final InetAddress mDestination; - @NonNull private final FileDescriptor mFd; private final int mResourceId; NattSocketKeepalive(@NonNull IConnectivityManager service, @NonNull Network network, - @NonNull FileDescriptor fd, + @NonNull ParcelFileDescriptor pfd, int resourceId, @NonNull InetAddress source, @NonNull InetAddress destination, @NonNull Executor executor, @NonNull Callback callback) { - super(service, network, executor, callback); + super(service, network, pfd, executor, callback); mSource = source; mDestination = destination; - mFd = fd; mResourceId = resourceId; } @@ -53,8 +51,8 @@ public final class NattSocketKeepalive extends SocketKeepalive { void startImpl(int intervalSec) { mExecutor.execute(() -> { try { - mService.startNattKeepaliveWithFd(mNetwork, mFd, mResourceId, intervalSec, - mCallback, + mService.startNattKeepaliveWithFd(mNetwork, mPfd.getFileDescriptor(), mResourceId, + intervalSec, mCallback, mSource.getHostAddress(), mDestination.getHostAddress()); } catch (RemoteException e) { Log.e(TAG, "Error starting socket keepalive: ", e); @@ -75,6 +73,5 @@ public final class NattSocketKeepalive extends SocketKeepalive { throw e.rethrowFromSystemServer(); } }); - } } diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java index b55f6ba06438..1edea556c574 100644 --- a/core/java/android/net/NetworkAgent.java +++ b/core/java/android/net/NetworkAgent.java @@ -488,14 +488,14 @@ public abstract class NetworkAgent extends Handler { * Requests that the network hardware send the specified packet at the specified interval. */ protected void startSocketKeepalive(Message msg) { - onSocketKeepaliveEvent(msg.arg1, SocketKeepalive.ERROR_HARDWARE_UNSUPPORTED); + onSocketKeepaliveEvent(msg.arg1, SocketKeepalive.ERROR_UNSUPPORTED); } /** * Requests that the network hardware stops sending keepalive packets. */ protected void stopSocketKeepalive(Message msg) { - onSocketKeepaliveEvent(msg.arg1, SocketKeepalive.ERROR_HARDWARE_UNSUPPORTED); + onSocketKeepaliveEvent(msg.arg1, SocketKeepalive.ERROR_UNSUPPORTED); } /** @@ -511,7 +511,7 @@ public abstract class NetworkAgent extends Handler { * override this method. */ protected void addKeepalivePacketFilter(Message msg) { - onSocketKeepaliveEvent(msg.arg1, SocketKeepalive.ERROR_HARDWARE_UNSUPPORTED); + onSocketKeepaliveEvent(msg.arg1, SocketKeepalive.ERROR_UNSUPPORTED); } /** @@ -520,7 +520,7 @@ public abstract class NetworkAgent extends Handler { * must override this method. */ protected void removeKeepalivePacketFilter(Message msg) { - onSocketKeepaliveEvent(msg.arg1, SocketKeepalive.ERROR_HARDWARE_UNSUPPORTED); + onSocketKeepaliveEvent(msg.arg1, SocketKeepalive.ERROR_UNSUPPORTED); } /** diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 9cf582bef1d4..27e041496173 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -18,6 +18,7 @@ package android.net; import static android.os.Process.CLAT_UID; +import android.annotation.NonNull; import android.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; @@ -33,6 +34,7 @@ import libcore.util.EmptyArray; import java.io.CharArrayWriter; import java.io.PrintWriter; import java.util.Arrays; +import java.util.function.Predicate; import java.util.HashSet; import java.util.Map; import java.util.Objects; @@ -993,23 +995,33 @@ public class NetworkStats implements Parcelable { if (limitUid == UID_ALL && limitTag == TAG_ALL && limitIfaces == INTERFACES_ALL) { return; } + filter(e -> (limitUid == UID_ALL || limitUid == e.uid) + && (limitTag == TAG_ALL || limitTag == e.tag) + && (limitIfaces == INTERFACES_ALL + || ArrayUtils.contains(limitIfaces, e.iface))); + } + + /** + * Only keep entries with {@link #set} value less than {@link #SET_DEBUG_START}. + * + * <p>This mutates the original structure in place. + */ + public void filterDebugEntries() { + filter(e -> e.set < SET_DEBUG_START); + } + private void filter(Predicate<Entry> predicate) { Entry entry = new Entry(); int nextOutputEntry = 0; for (int i = 0; i < size; i++) { entry = getValues(i, entry); - final boolean matches = - (limitUid == UID_ALL || limitUid == entry.uid) - && (limitTag == TAG_ALL || limitTag == entry.tag) - && (limitIfaces == INTERFACES_ALL - || ArrayUtils.contains(limitIfaces, entry.iface)); - - if (matches) { - setValues(nextOutputEntry, entry); + if (predicate.test(entry)) { + if (nextOutputEntry != i) { + setValues(nextOutputEntry, entry); + } nextOutputEntry++; } } - size = nextOutputEntry; } @@ -1175,133 +1187,217 @@ public class NetworkStats implements Parcelable { /** * VPN accounting. Move some VPN's underlying traffic to other UIDs that use tun0 iface. * - * This method should only be called on delta NetworkStats. Do not call this method on a - * snapshot {@link NetworkStats} object because the tunUid and/or the underlyingIface may - * change over time. - * - * This method performs adjustments for one active VPN package and one VPN iface at a time. + * <p>This method should only be called on delta NetworkStats. Do not call this method on a + * snapshot {@link NetworkStats} object because the tunUid and/or the underlyingIface may change + * over time. * - * It is possible for the VPN software to use multiple underlying networks. This method - * only migrates traffic for the primary underlying network. + * <p>This method performs adjustments for one active VPN package and one VPN iface at a time. * * @param tunUid uid of the VPN application * @param tunIface iface of the vpn tunnel - * @param underlyingIface the primary underlying network iface used by the VPN application - * @return true if it successfully adjusts the accounting for VPN, false otherwise + * @param underlyingIfaces underlying network ifaces used by the VPN application */ - public boolean migrateTun(int tunUid, String tunIface, String underlyingIface) { - Entry tunIfaceTotal = new Entry(); - Entry underlyingIfaceTotal = new Entry(); + public void migrateTun(int tunUid, @NonNull String tunIface, + @NonNull String[] underlyingIfaces) { + // Combined usage by all apps using VPN. + final Entry tunIfaceTotal = new Entry(); + // Usage by VPN, grouped by its {@code underlyingIfaces}. + final Entry[] perInterfaceTotal = new Entry[underlyingIfaces.length]; + // Usage by VPN, summed across all its {@code underlyingIfaces}. + final Entry underlyingIfacesTotal = new Entry(); + + for (int i = 0; i < perInterfaceTotal.length; i++) { + perInterfaceTotal[i] = new Entry(); + } - tunAdjustmentInit(tunUid, tunIface, underlyingIface, tunIfaceTotal, underlyingIfaceTotal); + tunAdjustmentInit(tunUid, tunIface, underlyingIfaces, tunIfaceTotal, perInterfaceTotal, + underlyingIfacesTotal); - // If tunIface < underlyingIface, it leaves the overhead traffic in the VPN app. - // If tunIface > underlyingIface, the VPN app doesn't get credit for data compression. + // If tunIface < underlyingIfacesTotal, it leaves the overhead traffic in the VPN app. + // If tunIface > underlyingIfacesTotal, the VPN app doesn't get credit for data compression. // Negative stats should be avoided. - Entry pool = tunGetPool(tunIfaceTotal, underlyingIfaceTotal); - if (pool.isEmpty()) { - return true; - } - Entry moved = - addTrafficToApplications(tunUid, tunIface, underlyingIface, tunIfaceTotal, pool); - deductTrafficFromVpnApp(tunUid, underlyingIface, moved); - - if (!moved.isEmpty()) { - Slog.wtf(TAG, "Failed to deduct underlying network traffic from VPN package. Moved=" - + moved); - return false; - } - return true; + final Entry[] moved = + addTrafficToApplications(tunUid, tunIface, underlyingIfaces, tunIfaceTotal, + perInterfaceTotal, underlyingIfacesTotal); + deductTrafficFromVpnApp(tunUid, underlyingIfaces, moved); } /** * Initializes the data used by the migrateTun() method. * - * This is the first pass iteration which does the following work: - * (1) Adds up all the traffic through the tunUid's underlyingIface - * (both foreground and background). - * (2) Adds up all the traffic through tun0 excluding traffic from the vpn app itself. + * <p>This is the first pass iteration which does the following work: + * + * <ul> + * <li>Adds up all the traffic through the tunUid's underlyingIfaces (both foreground and + * background). + * <li>Adds up all the traffic through tun0 excluding traffic from the vpn app itself. + * </ul> + * + * @param tunUid uid of the VPN application + * @param tunIface iface of the vpn tunnel + * @param underlyingIfaces underlying network ifaces used by the VPN application + * @param tunIfaceTotal output parameter; combined data usage by all apps using VPN + * @param perInterfaceTotal output parameter; data usage by VPN app, grouped by its {@code + * underlyingIfaces} + * @param underlyingIfacesTotal output parameter; data usage by VPN, summed across all of its + * {@code underlyingIfaces} */ - private void tunAdjustmentInit(int tunUid, String tunIface, String underlyingIface, - Entry tunIfaceTotal, Entry underlyingIfaceTotal) { - Entry recycle = new Entry(); + private void tunAdjustmentInit(int tunUid, @NonNull String tunIface, + @NonNull String[] underlyingIfaces, @NonNull Entry tunIfaceTotal, + @NonNull Entry[] perInterfaceTotal, @NonNull Entry underlyingIfacesTotal) { + final Entry recycle = new Entry(); for (int i = 0; i < size; i++) { getValues(i, recycle); if (recycle.uid == UID_ALL) { throw new IllegalStateException( "Cannot adjust VPN accounting on an iface aggregated NetworkStats."); - } if (recycle.set == SET_DBG_VPN_IN || recycle.set == SET_DBG_VPN_OUT) { + } + if (recycle.set == SET_DBG_VPN_IN || recycle.set == SET_DBG_VPN_OUT) { throw new IllegalStateException( "Cannot adjust VPN accounting on a NetworkStats containing SET_DBG_VPN_*"); } - - if (recycle.uid == tunUid && recycle.tag == TAG_NONE - && Objects.equals(underlyingIface, recycle.iface)) { - underlyingIfaceTotal.add(recycle); + if (recycle.tag != TAG_NONE) { + // TODO(b/123666283): Take all tags for tunUid into account. + continue; } - if (recycle.uid != tunUid && recycle.tag == TAG_NONE - && Objects.equals(tunIface, recycle.iface)) { + if (recycle.uid == tunUid) { + // Add up traffic through tunUid's underlying interfaces. + for (int j = 0; j < underlyingIfaces.length; j++) { + if (Objects.equals(underlyingIfaces[j], recycle.iface)) { + perInterfaceTotal[j].add(recycle); + underlyingIfacesTotal.add(recycle); + break; + } + } + } else if (tunIface.equals(recycle.iface)) { // Add up all tunIface traffic excluding traffic from the vpn app itself. tunIfaceTotal.add(recycle); } } } - private static Entry tunGetPool(Entry tunIfaceTotal, Entry underlyingIfaceTotal) { - Entry pool = new Entry(); - pool.rxBytes = Math.min(tunIfaceTotal.rxBytes, underlyingIfaceTotal.rxBytes); - pool.rxPackets = Math.min(tunIfaceTotal.rxPackets, underlyingIfaceTotal.rxPackets); - pool.txBytes = Math.min(tunIfaceTotal.txBytes, underlyingIfaceTotal.txBytes); - pool.txPackets = Math.min(tunIfaceTotal.txPackets, underlyingIfaceTotal.txPackets); - pool.operations = Math.min(tunIfaceTotal.operations, underlyingIfaceTotal.operations); - return pool; - } + /** + * Distributes traffic across apps that are using given {@code tunIface}, and returns the total + * traffic that should be moved off of {@code tunUid} grouped by {@code underlyingIfaces}. + * + * @param tunUid uid of the VPN application + * @param tunIface iface of the vpn tunnel + * @param underlyingIfaces underlying network ifaces used by the VPN application + * @param tunIfaceTotal combined data usage across all apps using {@code tunIface} + * @param perInterfaceTotal data usage by VPN app, grouped by its {@code underlyingIfaces} + * @param underlyingIfacesTotal data usage by VPN, summed across all of its {@code + * underlyingIfaces} + */ + private Entry[] addTrafficToApplications(int tunUid, @NonNull String tunIface, + @NonNull String[] underlyingIfaces, @NonNull Entry tunIfaceTotal, + @NonNull Entry[] perInterfaceTotal, @NonNull Entry underlyingIfacesTotal) { + // Traffic that should be moved off of each underlying interface for tunUid (see + // deductTrafficFromVpnApp below). + final Entry[] moved = new Entry[underlyingIfaces.length]; + for (int i = 0; i < underlyingIfaces.length; i++) { + moved[i] = new Entry(); + } - private Entry addTrafficToApplications(int tunUid, String tunIface, String underlyingIface, - Entry tunIfaceTotal, Entry pool) { - Entry moved = new Entry(); - Entry tmpEntry = new Entry(); - tmpEntry.iface = underlyingIface; + final Entry tmpEntry = new Entry(); for (int i = 0; i < size; i++) { - // the vpn app is excluded from the redistribution but all moved traffic will be - // deducted from the vpn app (see deductTrafficFromVpnApp below). - if (Objects.equals(iface[i], tunIface) && uid[i] != tunUid) { - if (tunIfaceTotal.rxBytes > 0) { - tmpEntry.rxBytes = pool.rxBytes * rxBytes[i] / tunIfaceTotal.rxBytes; - } else { - tmpEntry.rxBytes = 0; + if (!Objects.equals(iface[i], tunIface)) { + // Consider only entries that go onto the VPN interface. + continue; + } + if (uid[i] == tunUid) { + // Exclude VPN app from the redistribution, as it can choose to create packet + // streams by writing to itself. + continue; + } + tmpEntry.uid = uid[i]; + tmpEntry.tag = tag[i]; + tmpEntry.metered = metered[i]; + tmpEntry.roaming = roaming[i]; + tmpEntry.defaultNetwork = defaultNetwork[i]; + + // In a first pass, compute each UID's total share of data across all underlyingIfaces. + // This is computed on the basis of the share of each UID's usage over tunIface. + // TODO: Consider refactoring first pass into a separate helper method. + long totalRxBytes = 0; + if (tunIfaceTotal.rxBytes > 0) { + // Note - The multiplication below should not overflow since NetworkStatsService + // processes this every time device has transmitted/received amount equivalent to + // global threshold alert (~ 2MB) across all interfaces. + final long rxBytesAcrossUnderlyingIfaces = + underlyingIfacesTotal.rxBytes * rxBytes[i] / tunIfaceTotal.rxBytes; + // app must not be blamed for more than it consumed on tunIface + totalRxBytes = Math.min(rxBytes[i], rxBytesAcrossUnderlyingIfaces); + } + long totalRxPackets = 0; + if (tunIfaceTotal.rxPackets > 0) { + final long rxPacketsAcrossUnderlyingIfaces = + underlyingIfacesTotal.rxPackets * rxPackets[i] / tunIfaceTotal.rxPackets; + totalRxPackets = Math.min(rxPackets[i], rxPacketsAcrossUnderlyingIfaces); + } + long totalTxBytes = 0; + if (tunIfaceTotal.txBytes > 0) { + final long txBytesAcrossUnderlyingIfaces = + underlyingIfacesTotal.txBytes * txBytes[i] / tunIfaceTotal.txBytes; + totalTxBytes = Math.min(txBytes[i], txBytesAcrossUnderlyingIfaces); + } + long totalTxPackets = 0; + if (tunIfaceTotal.txPackets > 0) { + final long txPacketsAcrossUnderlyingIfaces = + underlyingIfacesTotal.txPackets * txPackets[i] / tunIfaceTotal.txPackets; + totalTxPackets = Math.min(txPackets[i], txPacketsAcrossUnderlyingIfaces); + } + long totalOperations = 0; + if (tunIfaceTotal.operations > 0) { + final long operationsAcrossUnderlyingIfaces = + underlyingIfacesTotal.operations * operations[i] / tunIfaceTotal.operations; + totalOperations = Math.min(operations[i], operationsAcrossUnderlyingIfaces); + } + // In a second pass, distribute these values across interfaces in the proportion that + // each interface represents of the total traffic of the underlying interfaces. + for (int j = 0; j < underlyingIfaces.length; j++) { + tmpEntry.iface = underlyingIfaces[j]; + tmpEntry.rxBytes = 0; + // Reset 'set' to correct value since it gets updated when adding debug info below. + tmpEntry.set = set[i]; + if (underlyingIfacesTotal.rxBytes > 0) { + tmpEntry.rxBytes = + totalRxBytes + * perInterfaceTotal[j].rxBytes + / underlyingIfacesTotal.rxBytes; } - if (tunIfaceTotal.rxPackets > 0) { - tmpEntry.rxPackets = pool.rxPackets * rxPackets[i] / tunIfaceTotal.rxPackets; - } else { - tmpEntry.rxPackets = 0; + tmpEntry.rxPackets = 0; + if (underlyingIfacesTotal.rxPackets > 0) { + tmpEntry.rxPackets = + totalRxPackets + * perInterfaceTotal[j].rxPackets + / underlyingIfacesTotal.rxPackets; } - if (tunIfaceTotal.txBytes > 0) { - tmpEntry.txBytes = pool.txBytes * txBytes[i] / tunIfaceTotal.txBytes; - } else { - tmpEntry.txBytes = 0; + tmpEntry.txBytes = 0; + if (underlyingIfacesTotal.txBytes > 0) { + tmpEntry.txBytes = + totalTxBytes + * perInterfaceTotal[j].txBytes + / underlyingIfacesTotal.txBytes; } - if (tunIfaceTotal.txPackets > 0) { - tmpEntry.txPackets = pool.txPackets * txPackets[i] / tunIfaceTotal.txPackets; - } else { - tmpEntry.txPackets = 0; + tmpEntry.txPackets = 0; + if (underlyingIfacesTotal.txPackets > 0) { + tmpEntry.txPackets = + totalTxPackets + * perInterfaceTotal[j].txPackets + / underlyingIfacesTotal.txPackets; } - if (tunIfaceTotal.operations > 0) { + tmpEntry.operations = 0; + if (underlyingIfacesTotal.operations > 0) { tmpEntry.operations = - pool.operations * operations[i] / tunIfaceTotal.operations; - } else { - tmpEntry.operations = 0; + totalOperations + * perInterfaceTotal[j].operations + / underlyingIfacesTotal.operations; } - tmpEntry.uid = uid[i]; - tmpEntry.tag = tag[i]; - tmpEntry.set = set[i]; - tmpEntry.metered = metered[i]; - tmpEntry.roaming = roaming[i]; - tmpEntry.defaultNetwork = defaultNetwork[i]; + combineValues(tmpEntry); if (tag[i] == TAG_NONE) { - moved.add(tmpEntry); + moved[j].add(tmpEntry); // Add debug info tmpEntry.set = SET_DBG_VPN_IN; combineValues(tmpEntry); @@ -1311,38 +1407,45 @@ public class NetworkStats implements Parcelable { return moved; } - private void deductTrafficFromVpnApp(int tunUid, String underlyingIface, Entry moved) { - // Add debug info - moved.uid = tunUid; - moved.set = SET_DBG_VPN_OUT; - moved.tag = TAG_NONE; - moved.iface = underlyingIface; - moved.metered = METERED_ALL; - moved.roaming = ROAMING_ALL; - moved.defaultNetwork = DEFAULT_NETWORK_ALL; - combineValues(moved); - - // Caveat: if the vpn software uses tag, the total tagged traffic may be greater than - // the TAG_NONE traffic. - // - // Relies on the fact that the underlying traffic only has state ROAMING_NO and METERED_NO, - // which should be the case as it comes directly from the /proc file. We only blend in the - // roaming data after applying these adjustments, by checking the NetworkIdentity of the - // underlying iface. - int idxVpnBackground = findIndex(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO); - if (idxVpnBackground != -1) { - tunSubtract(idxVpnBackground, this, moved); - } + private void deductTrafficFromVpnApp( + int tunUid, + @NonNull String[] underlyingIfaces, + @NonNull Entry[] moved) { + for (int i = 0; i < underlyingIfaces.length; i++) { + // Add debug info + moved[i].uid = tunUid; + moved[i].set = SET_DBG_VPN_OUT; + moved[i].tag = TAG_NONE; + moved[i].iface = underlyingIfaces[i]; + moved[i].metered = METERED_ALL; + moved[i].roaming = ROAMING_ALL; + moved[i].defaultNetwork = DEFAULT_NETWORK_ALL; + combineValues(moved[i]); + + // Caveat: if the vpn software uses tag, the total tagged traffic may be greater than + // the TAG_NONE traffic. + // + // Relies on the fact that the underlying traffic only has state ROAMING_NO and + // METERED_NO, which should be the case as it comes directly from the /proc file. + // We only blend in the roaming data after applying these adjustments, by checking the + // NetworkIdentity of the underlying iface. + final int idxVpnBackground = findIndex(underlyingIfaces[i], tunUid, SET_DEFAULT, + TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO); + if (idxVpnBackground != -1) { + // Note - tunSubtract also updates moved[i]; whatever traffic that's left is removed + // from foreground usage. + tunSubtract(idxVpnBackground, this, moved[i]); + } - int idxVpnForeground = findIndex(underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO); - if (idxVpnForeground != -1) { - tunSubtract(idxVpnForeground, this, moved); + final int idxVpnForeground = findIndex(underlyingIfaces[i], tunUid, SET_FOREGROUND, + TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO); + if (idxVpnForeground != -1) { + tunSubtract(idxVpnForeground, this, moved[i]); + } } } - private static void tunSubtract(int i, NetworkStats left, Entry right) { + private static void tunSubtract(int i, @NonNull NetworkStats left, @NonNull Entry right) { long rxBytes = Math.min(left.rxBytes[i], right.rxBytes); left.rxBytes[i] -= rxBytes; right.rxBytes -= rxBytes; diff --git a/core/java/android/net/SocketKeepalive.java b/core/java/android/net/SocketKeepalive.java index 0e768dfc8eb9..9d91620bdf96 100644 --- a/core/java/android/net/SocketKeepalive.java +++ b/core/java/android/net/SocketKeepalive.java @@ -21,8 +21,10 @@ import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.Binder; +import android.os.ParcelFileDescriptor; import android.os.RemoteException; +import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.concurrent.Executor; @@ -73,10 +75,15 @@ public abstract class SocketKeepalive implements AutoCloseable { /** The target socket is not idle. */ public static final int ERROR_SOCKET_NOT_IDLE = -26; - /** The hardware does not support this request. */ - public static final int ERROR_HARDWARE_UNSUPPORTED = -30; + /** The device does not support this request. */ + public static final int ERROR_UNSUPPORTED = -30; + /** @hide TODO: delete when telephony code has been updated. */ + public static final int ERROR_HARDWARE_UNSUPPORTED = ERROR_UNSUPPORTED; /** The hardware returned an error. */ public static final int ERROR_HARDWARE_ERROR = -31; + /** The limitation of resource is reached. */ + public static final int ERROR_INSUFFICIENT_RESOURCES = -32; + /** @hide */ @Retention(RetentionPolicy.SOURCE) @@ -147,15 +154,18 @@ public abstract class SocketKeepalive implements AutoCloseable { @NonNull final IConnectivityManager mService; @NonNull final Network mNetwork; + @NonNull final ParcelFileDescriptor mPfd; @NonNull final Executor mExecutor; @NonNull final ISocketKeepaliveCallback mCallback; // TODO: remove slot since mCallback could be used to identify which keepalive to stop. @Nullable Integer mSlot; SocketKeepalive(@NonNull IConnectivityManager service, @NonNull Network network, + @NonNull ParcelFileDescriptor pfd, @NonNull Executor executor, @NonNull Callback callback) { mService = service; mNetwork = network; + mPfd = pfd; mExecutor = executor; mCallback = new ISocketKeepaliveCallback.Stub() { @Override @@ -233,6 +243,11 @@ public abstract class SocketKeepalive implements AutoCloseable { @Override public final void close() { stop(); + try { + mPfd.close(); + } catch (IOException e) { + // Nothing much can be done. + } } /** diff --git a/services/net/java/android/net/StaticIpConfigurationParcelable.aidl b/core/java/android/net/StaticIpConfiguration.aidl index 6fffb423edb5..8aac701fe7e1 100644 --- a/services/net/java/android/net/StaticIpConfigurationParcelable.aidl +++ b/core/java/android/net/StaticIpConfiguration.aidl @@ -17,11 +17,4 @@ package android.net; -import android.net.LinkAddress; - -parcelable StaticIpConfigurationParcelable { - LinkAddress ipAddress; - String gateway; - String[] dnsServers; - String domains; -} +@JavaOnlyStableParcelable parcelable StaticIpConfiguration;
\ No newline at end of file diff --git a/core/java/android/net/StaticIpConfiguration.java b/core/java/android/net/StaticIpConfiguration.java index 0728d83cbdb1..14dbca0183f0 100644 --- a/core/java/android/net/StaticIpConfiguration.java +++ b/core/java/android/net/StaticIpConfiguration.java @@ -134,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 @NonNull List<RouteInfo> getRoutes(String iface) { + public @NonNull List<RouteInfo> getRoutes(@Nullable String iface) { List<RouteInfo> routes = new ArrayList<RouteInfo>(3); if (ipAddress != null) { RouteInfo connectedRoute = new RouteInfo(ipAddress, null, iface); diff --git a/core/java/android/net/TcpSocketKeepalive.java b/core/java/android/net/TcpSocketKeepalive.java index 26cc8ff181b2..436397ea7754 100644 --- a/core/java/android/net/TcpSocketKeepalive.java +++ b/core/java/android/net/TcpSocketKeepalive.java @@ -17,25 +17,22 @@ package android.net; import android.annotation.NonNull; +import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.util.Log; import java.io.FileDescriptor; -import java.net.Socket; import java.util.concurrent.Executor; /** @hide */ final class TcpSocketKeepalive extends SocketKeepalive { - private final Socket mSocket; - TcpSocketKeepalive(@NonNull IConnectivityManager service, @NonNull Network network, - @NonNull Socket socket, + @NonNull ParcelFileDescriptor pfd, @NonNull Executor executor, @NonNull Callback callback) { - super(service, network, executor, callback); - mSocket = socket; + super(service, network, pfd, executor, callback); } /** @@ -57,7 +54,7 @@ final class TcpSocketKeepalive extends SocketKeepalive { void startImpl(int intervalSec) { mExecutor.execute(() -> { try { - final FileDescriptor fd = mSocket.getFileDescriptor$(); + final FileDescriptor fd = mPfd.getFileDescriptor(); mService.startTcpKeepalive(mNetwork, fd, intervalSec, mCallback); } catch (RemoteException e) { Log.e(TAG, "Error starting packet keepalive: ", e); diff --git a/core/java/android/net/apf/ApfCapabilities.aidl b/core/java/android/net/apf/ApfCapabilities.aidl new file mode 100644 index 000000000000..7c4d4c2da4bc --- /dev/null +++ b/core/java/android/net/apf/ApfCapabilities.aidl @@ -0,0 +1,20 @@ +/* +** +** 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.net.apf; + +@JavaOnlyStableParcelable parcelable ApfCapabilities;
\ No newline at end of file diff --git a/core/java/android/net/metrics/DhcpErrorEvent.java b/core/java/android/net/metrics/DhcpErrorEvent.java index 8beaa40ec2fc..84823464a093 100644 --- a/core/java/android/net/metrics/DhcpErrorEvent.java +++ b/core/java/android/net/metrics/DhcpErrorEvent.java @@ -37,27 +37,6 @@ 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 = (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 = (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 = (L4_ERROR << 24) | (1 << 16); - public static final int L4_WRONG_PORT = (L4_ERROR << 24) | (2 << 16); - - 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 = (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 // byte 1: error subtype @@ -66,6 +45,33 @@ public final class DhcpErrorEvent implements IpConnectivityLog.Event { /** @hide */ public final int errorCode; + private static final int L2_ERROR_TYPE = L2_ERROR << 8; + private static final int L3_ERROR_TYPE = L3_ERROR << 8; + private static final int L4_ERROR_TYPE = L4_ERROR << 8; + private static final int DHCP_ERROR_TYPE = DHCP_ERROR << 8; + private static final int MISC_ERROR_TYPE = MISC_ERROR << 8; + + public static final int L2_TOO_SHORT = (L2_ERROR_TYPE | 0x1) << 16; + public static final int L2_WRONG_ETH_TYPE = (L2_ERROR_TYPE | 0x2) << 16; + + public static final int L3_TOO_SHORT = (L3_ERROR_TYPE | 0x1) << 16; + public static final int L3_NOT_IPV4 = (L3_ERROR_TYPE | 0x2) << 16; + public static final int L3_INVALID_IP = (L3_ERROR_TYPE | 0x3) << 16; + + public static final int L4_NOT_UDP = (L4_ERROR_TYPE | 0x1) << 16; + public static final int L4_WRONG_PORT = (L4_ERROR_TYPE | 0x2) << 16; + + public static final int BOOTP_TOO_SHORT = (DHCP_ERROR_TYPE | 0x1) << 16; + public static final int DHCP_BAD_MAGIC_COOKIE = (DHCP_ERROR_TYPE | 0x2) << 16; + public static final int DHCP_INVALID_OPTION_LENGTH = (DHCP_ERROR_TYPE | 0x3) << 16; + public static final int DHCP_NO_MSG_TYPE = (DHCP_ERROR_TYPE | 0x4) << 16; + public static final int DHCP_UNKNOWN_MSG_TYPE = (DHCP_ERROR_TYPE | 0x5) << 16; + public static final int DHCP_NO_COOKIE = (DHCP_ERROR_TYPE | 0x6) << 16; + + public static final int BUFFER_UNDERFLOW = (MISC_ERROR_TYPE | 0x1) << 16; + public static final int RECEIVE_ERROR = (MISC_ERROR_TYPE | 0x2) << 16; + public static final int PARSING_ERROR = (MISC_ERROR_TYPE | 0x3) << 16; + public DhcpErrorEvent(int errorCode) { this.errorCode = errorCode; } diff --git a/core/java/android/net/metrics/ValidationProbeEvent.java b/core/java/android/net/metrics/ValidationProbeEvent.java index 9eb87ef43cbb..ebca7e6d5607 100644 --- a/core/java/android/net/metrics/ValidationProbeEvent.java +++ b/core/java/android/net/metrics/ValidationProbeEvent.java @@ -153,11 +153,14 @@ public final class ValidationProbeEvent implements IpConnectivityLog.Event { return (probeType & 0xff) | (firstValidation ? FIRST_VALIDATION : REVALIDATION); } - public static String getProbeName(int probeType) { + /** + * Get the name of a probe specified by its probe type. + */ + public static @NonNull String getProbeName(int probeType) { return Decoder.constants.get(probeType & 0xff, "PROBE_???"); } - private static String getValidationStage(int probeType) { + private static @NonNull String getValidationStage(int probeType) { return Decoder.constants.get(probeType & 0xff00, "UNKNOWN"); } diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java index a7d2ee98b45c..b90a60e5bca0 100644 --- a/core/java/android/nfc/NfcAdapter.java +++ b/core/java/android/nfc/NfcAdapter.java @@ -373,7 +373,8 @@ public final class NfcAdapter { * A callback to be invoked when the system successfully delivers your {@link NdefMessage} * to another device. * @see #setOnNdefPushCompleteCallback - * @deprecated this feature is deprecated. + * @deprecated this feature is deprecated. File sharing can work using other technology like + * Bluetooth. */ @java.lang.Deprecated public interface OnNdefPushCompleteCallback { @@ -398,7 +399,8 @@ public final class NfcAdapter { * content currently visible to the user. Alternatively, you can call {@link * #setNdefPushMessage setNdefPushMessage()} if the {@link NdefMessage} always contains the * same data. - * @deprecated this feature is deprecated. + * @deprecated this feature is deprecated. File sharing can work using other technology like + * Bluetooth. */ @java.lang.Deprecated public interface CreateNdefMessageCallback { @@ -427,7 +429,8 @@ public final class NfcAdapter { /** - * @deprecated this feature is deprecated. + * @deprecated this feature is deprecated. File sharing can work using other technology like + * Bluetooth. */ @java.lang.Deprecated public interface CreateBeamUrisCallback { @@ -981,7 +984,8 @@ public final class NfcAdapter { * @param uris an array of Uri(s) to push over Android Beam * @param activity activity for which the Uri(s) will be pushed * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. - * @deprecated this feature is deprecated. + * @deprecated this feature is deprecated. File sharing can work using other technology like + * Bluetooth. */ @java.lang.Deprecated public void setBeamPushUris(Uri[] uris, Activity activity) { @@ -1068,7 +1072,8 @@ public final class NfcAdapter { * @param callback callback, or null to disable * @param activity activity for which the Uri(s) will be pushed * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. - * @deprecated this feature is deprecated. + * @deprecated this feature is deprecated. File sharing can work using other technology like + * Bluetooth. */ @java.lang.Deprecated public void setBeamPushUrisCallback(CreateBeamUrisCallback callback, Activity activity) { @@ -1157,7 +1162,8 @@ public final class NfcAdapter { * to only register one at a time, and to do so in that activity's * {@link Activity#onCreate} * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. - * @deprecated this feature is deprecated. + * @deprecated this feature is deprecated. File sharing can work using other technology like + * Bluetooth. */ @java.lang.Deprecated public void setNdefPushMessage(NdefMessage message, Activity activity, @@ -1275,7 +1281,8 @@ public final class NfcAdapter { * to only register one at a time, and to do so in that activity's * {@link Activity#onCreate} * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. - * @deprecated this feature is deprecated. + * @deprecated this feature is deprecated. File sharing can work using other technology like + * Bluetooth. */ @java.lang.Deprecated public void setNdefPushMessageCallback(CreateNdefMessageCallback callback, Activity activity, @@ -1361,7 +1368,8 @@ public final class NfcAdapter { * to only register one at a time, and to do so in that activity's * {@link Activity#onCreate} * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. - * @deprecated this feature is deprecated. + * @deprecated this feature is deprecated. File sharing can work using other technology like + * Bluetooth. */ @java.lang.Deprecated public void setOnNdefPushCompleteCallback(OnNdefPushCompleteCallback callback, @@ -1577,7 +1585,8 @@ public final class NfcAdapter { * @param activity the current foreground Activity that has registered data to share * @return whether the Beam animation was successfully invoked * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. - * @deprecated this feature is deprecated. + * @deprecated this feature is deprecated. File sharing can work using other technology like + * Bluetooth. */ @java.lang.Deprecated public boolean invokeBeam(Activity activity) { @@ -1821,7 +1830,8 @@ public final class NfcAdapter { * @see android.provider.Settings#ACTION_NFCSHARING_SETTINGS * @return true if NDEF Push feature is enabled * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. - * @deprecated this feature is deprecated. + * @deprecated this feature is deprecated. File sharing can work using other technology like + * Bluetooth. */ @java.lang.Deprecated diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl index 6536fc991b30..03e8c154e3fc 100644 --- a/core/java/android/os/INetworkManagementService.aidl +++ b/core/java/android/os/INetworkManagementService.aidl @@ -330,12 +330,6 @@ interface INetworkManagementService */ void removeIdleTimer(String iface); - /** - * Configure name servers, search paths, and resolver parameters for the given network. - */ - void setDnsConfigurationForNetwork(int netId, in String[] servers, in String[] domains, - in int[] params, String tlsHostname, in String[] tlsServers); - void setFirewallEnabled(boolean enabled); boolean isFirewallEnabled(); void setFirewallInterfaceRule(String iface, boolean allow); @@ -381,11 +375,6 @@ interface INetworkManagementService void createVirtualNetwork(int netId, boolean secure); /** - * Remove a network. - */ - void removeNetwork(int netId); - - /** * Add an interface to a network. */ void addInterfaceToNetwork(String iface, int netId); diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 8a199275b123..080c0d23f426 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -9420,7 +9420,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } /** - * Return true iff there is a selection inside this text view. + * Return true iff there is a selection of nonzero length inside this text view. */ public boolean hasSelection() { final int selectionStart = getSelectionStart(); diff --git a/core/java/com/android/internal/app/AlertActivity.java b/core/java/com/android/internal/app/AlertActivity.java index 999a908251dd..0b08099b51ed 100644 --- a/core/java/com/android/internal/app/AlertActivity.java +++ b/core/java/com/android/internal/app/AlertActivity.java @@ -16,6 +16,7 @@ package com.android.internal.app; +import android.annotation.UnsupportedAppUsage; import android.app.Activity; import android.app.Dialog; import android.content.DialogInterface; @@ -38,11 +39,13 @@ public abstract class AlertActivity extends Activity implements DialogInterface * * @see #mAlertParams */ + @UnsupportedAppUsage protected AlertController mAlert; /** * The parameters for the alert. */ + @UnsupportedAppUsage protected AlertController.AlertParams mAlertParams; @Override @@ -90,6 +93,7 @@ public abstract class AlertActivity extends Activity implements DialogInterface * @see #mAlert * @see #mAlertParams */ + @UnsupportedAppUsage protected void setupAlert() { mAlert.installContent(mAlertParams); } diff --git a/core/java/com/android/internal/app/AssistUtils.java b/core/java/com/android/internal/app/AssistUtils.java index fed0a89a4d75..9ae614982fb5 100644 --- a/core/java/com/android/internal/app/AssistUtils.java +++ b/core/java/com/android/internal/app/AssistUtils.java @@ -18,6 +18,7 @@ package com.android.internal.app; import com.android.internal.R; +import android.annotation.UnsupportedAppUsage; import android.app.SearchManager; import android.content.ComponentName; import android.content.Context; @@ -53,6 +54,7 @@ public class AssistUtils { private final Context mContext; private final IVoiceInteractionManagerService mVoiceInteractionManagerService; + @UnsupportedAppUsage public AssistUtils(Context context) { mContext = context; mVoiceInteractionManagerService = IVoiceInteractionManagerService.Stub.asInterface( @@ -155,6 +157,7 @@ public class AssistUtils { } } + @UnsupportedAppUsage public ComponentName getAssistComponentForUser(int userId) { final String setting = Settings.Secure.getStringForUser(mContext.getContentResolver(), Settings.Secure.ASSISTANT, userId); diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java index c31f17af67af..6343908738fc 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -20,6 +20,7 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; import android.annotation.NonNull; +import android.annotation.UnsupportedAppUsage; import android.app.Activity; import android.app.ActivityManager; import android.app.usage.UsageStatsManager; diff --git a/core/java/com/android/internal/app/IntentForwarderActivity.java b/core/java/com/android/internal/app/IntentForwarderActivity.java index 4728124c17c5..ed771406db5c 100644 --- a/core/java/com/android/internal/app/IntentForwarderActivity.java +++ b/core/java/com/android/internal/app/IntentForwarderActivity.java @@ -20,6 +20,7 @@ import static android.content.pm.PackageManager.MATCH_DEFAULT_ONLY; import android.annotation.Nullable; import android.annotation.StringRes; +import android.annotation.UnsupportedAppUsage; import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityThread; @@ -50,6 +51,7 @@ import java.util.Set; * be passed in and out of a managed profile. */ public class IntentForwarderActivity extends Activity { + @UnsupportedAppUsage public static String TAG = "IntentForwarderActivity"; public static String FORWARD_INTENT_TO_PARENT diff --git a/core/java/com/android/internal/app/LocaleHelper.java b/core/java/com/android/internal/app/LocaleHelper.java index 0a230a90a735..aef4dbf41d35 100644 --- a/core/java/com/android/internal/app/LocaleHelper.java +++ b/core/java/com/android/internal/app/LocaleHelper.java @@ -17,6 +17,7 @@ package com.android.internal.app; import android.annotation.IntRange; +import android.annotation.UnsupportedAppUsage; import android.icu.text.ListFormatter; import android.icu.util.ULocale; import android.os.LocaleList; @@ -84,6 +85,7 @@ public class LocaleHelper { * @param locale the locale that might be used for certain operations (i.e. case conversion) * @return the string normalized for search */ + @UnsupportedAppUsage public static String normalizeForSearch(String str, Locale locale) { // TODO: tbd if it needs to be smarter (real normalization, remove accents, etc.) // If needed we might use case folding and ICU/CLDR's collation-based loose searching. @@ -109,6 +111,7 @@ public class LocaleHelper { * @param sentenceCase true if the result should be sentence-cased * @return the localized name of the locale. */ + @UnsupportedAppUsage public static String getDisplayName(Locale locale, Locale displayLocale, boolean sentenceCase) { final ULocale displayULocale = ULocale.forLocale(displayLocale); String result = shouldUseDialectName(locale) @@ -135,6 +138,7 @@ public class LocaleHelper { * @param displayLocale the locale in which to display the name. * @return the localized country name. */ + @UnsupportedAppUsage public static String getDisplayCountry(Locale locale, Locale displayLocale) { final String languageTag = locale.toLanguageTag(); final ULocale uDisplayLocale = ULocale.forLocale(displayLocale); @@ -226,6 +230,7 @@ public class LocaleHelper { * * @param sortLocale the locale to be used for sorting. */ + @UnsupportedAppUsage public LocaleInfoComparator(Locale sortLocale, boolean countryMode) { mCollator = Collator.getInstance(sortLocale); mCountryMode = countryMode; @@ -253,6 +258,7 @@ public class LocaleHelper { * @return a negative integer, zero, or a positive integer as the first * argument is less than, equal to, or greater than the second. */ + @UnsupportedAppUsage @Override public int compare(LocaleStore.LocaleInfo lhs, LocaleStore.LocaleInfo rhs) { // We don't care about the various suggestion types, just "suggested" (!= 0) diff --git a/core/java/com/android/internal/app/LocalePicker.java b/core/java/com/android/internal/app/LocalePicker.java index c8c2fcf60d1f..75174246cd99 100644 --- a/core/java/com/android/internal/app/LocalePicker.java +++ b/core/java/com/android/internal/app/LocalePicker.java @@ -18,6 +18,7 @@ package com.android.internal.app; import com.android.internal.R; +import android.annotation.UnsupportedAppUsage; import android.app.ActivityManager; import android.app.IActivityManager; import android.app.ListFragment; @@ -70,6 +71,7 @@ public class LocalePicker extends ListFragment { return label; } + @UnsupportedAppUsage public Locale getLocale() { return locale; } @@ -251,6 +253,7 @@ public class LocalePicker extends ListFragment { * * @see #updateLocales(LocaleList) */ + @UnsupportedAppUsage public static void updateLocale(Locale locale) { updateLocales(new LocaleList(locale)); } @@ -260,6 +263,7 @@ public class LocalePicker extends ListFragment { * Note that the system looks halted for a while during the Locale migration, * so the caller need to take care of it. */ + @UnsupportedAppUsage public static void updateLocales(LocaleList locales) { try { final IActivityManager am = ActivityManager.getService(); @@ -281,6 +285,7 @@ public class LocalePicker extends ListFragment { * * @return The locale list. */ + @UnsupportedAppUsage public static LocaleList getLocales() { try { return ActivityManager.getService() diff --git a/core/java/com/android/internal/app/LocaleStore.java b/core/java/com/android/internal/app/LocaleStore.java index d24701372453..df2df4e92200 100644 --- a/core/java/com/android/internal/app/LocaleStore.java +++ b/core/java/com/android/internal/app/LocaleStore.java @@ -16,6 +16,7 @@ package com.android.internal.app; +import android.annotation.UnsupportedAppUsage; import android.content.Context; import android.os.LocaleList; import android.provider.Settings; @@ -80,14 +81,17 @@ public class LocaleStore { return mId; } + @UnsupportedAppUsage public Locale getLocale() { return mLocale; } + @UnsupportedAppUsage public Locale getParent() { return mParent; } + @UnsupportedAppUsage public String getId() { return mId; } @@ -114,6 +118,7 @@ public class LocaleStore { return (mSuggestionFlags & suggestionMask) == suggestionMask; } + @UnsupportedAppUsage public String getFullNameNative() { if (mFullNameNative == null) { mFullNameNative = @@ -139,6 +144,7 @@ public class LocaleStore { * For instance German will show as "Deutsch" in the list, but we will also search for * "allemand" if the system UI is in French. */ + @UnsupportedAppUsage public String getFullNameInUiLanguage() { // We don't cache the UI name because the default locale keeps changing return LocaleHelper.getDisplayName(mLocale, true /* sentence case */); @@ -253,6 +259,7 @@ public class LocaleStore { } } + @UnsupportedAppUsage public static void fillCache(Context context) { if (sFullyInitialized) { return; @@ -339,6 +346,7 @@ public class LocaleStore { * Example: if the parent is "ar", then the region list will contain all Arabic locales. * (this is not language based, but language-script, so that it works for zh-Hant and so on. */ + @UnsupportedAppUsage public static Set<LocaleInfo> getLevelLocales(Context context, Set<String> ignorables, LocaleInfo parent, boolean translatedOnly) { fillCache(context); @@ -364,6 +372,7 @@ public class LocaleStore { return result; } + @UnsupportedAppUsage public static LocaleInfo getLocaleInfo(Locale locale) { String id = locale.toLanguageTag(); LocaleInfo result; diff --git a/core/java/com/android/internal/app/NetInitiatedActivity.java b/core/java/com/android/internal/app/NetInitiatedActivity.java index d3bae16d03a7..9a802a9c0fa9 100644 --- a/core/java/com/android/internal/app/NetInitiatedActivity.java +++ b/core/java/com/android/internal/app/NetInitiatedActivity.java @@ -16,6 +16,7 @@ package com.android.internal.app; +import android.annotation.UnsupportedAppUsage; import android.app.AlertDialog; import android.content.BroadcastReceiver; import android.content.Context; @@ -141,6 +142,7 @@ public class NetInitiatedActivity extends AlertActivity implements DialogInterfa locationManager.sendNiResponse(notificationId, response); } + @UnsupportedAppUsage private void handleNIVerify(Intent intent) { int notifId = intent.getIntExtra(GpsNetInitiatedHandler.NI_INTENT_KEY_NOTIF_ID, -1); notificationId = notifId; diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java index ceb06f511108..5ab76694df65 100644 --- a/core/java/com/android/internal/app/ResolverActivity.java +++ b/core/java/com/android/internal/app/ResolverActivity.java @@ -19,6 +19,7 @@ package com.android.internal.app; import android.annotation.Nullable; import android.annotation.StringRes; import android.annotation.UiThread; +import android.annotation.UnsupportedAppUsage; import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityThread; @@ -90,6 +91,7 @@ import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; @UiThread public class ResolverActivity extends Activity { + @UnsupportedAppUsage protected ResolveListAdapter mAdapter; private boolean mSafeForwardingMode; private AbsListView mAdapterView; @@ -110,6 +112,7 @@ public class ResolverActivity extends Activity { // Whether or not this activity supports choosing a default handler for the intent. private boolean mSupportsAlwaysUseOption; protected ResolverDrawerLayout mResolverDrawerLayout; + @UnsupportedAppUsage protected PackageManager mPm; protected int mLaunchedFromUid; @@ -242,6 +245,7 @@ public class ResolverActivity extends Activity { * Compatibility version for other bundled services that use this overload without * a default title resource */ + @UnsupportedAppUsage protected void onCreate(Bundle savedInstanceState, Intent intent, CharSequence title, Intent[] initialIntents, List<ResolveInfo> rList, boolean supportsAlwaysUseOption) { diff --git a/core/java/com/android/internal/app/WindowDecorActionBar.java b/core/java/com/android/internal/app/WindowDecorActionBar.java index 119f30df8946..e71ee66c677c 100644 --- a/core/java/com/android/internal/app/WindowDecorActionBar.java +++ b/core/java/com/android/internal/app/WindowDecorActionBar.java @@ -84,6 +84,7 @@ public class WindowDecorActionBar extends ActionBar implements private ActionBarContextView mContextView; private ActionBarContainer mSplitView; private View mContentView; + @UnsupportedAppUsage private ScrollingTabContainerView mTabScrollView; private ArrayList<TabImpl> mTabs = new ArrayList<TabImpl>(); @@ -331,6 +332,7 @@ public class WindowDecorActionBar extends ActionBar implements * * @param enabled true to animate, false to not animate. */ + @UnsupportedAppUsage public void setShowHideAnimationEnabled(boolean enabled) { mShowHideAnimationEnabled = enabled; if (!enabled && mCurrentShowAnim != null) { @@ -1147,6 +1149,7 @@ public class WindowDecorActionBar extends ActionBar implements * @hide */ public class TabImpl extends ActionBar.Tab { + @UnsupportedAppUsage private ActionBar.TabListener mCallback; private Object mTag; private Drawable mIcon; diff --git a/core/java/com/android/internal/database/SortCursor.java b/core/java/com/android/internal/database/SortCursor.java index 00255128972c..7fe809ee319b 100644 --- a/core/java/com/android/internal/database/SortCursor.java +++ b/core/java/com/android/internal/database/SortCursor.java @@ -16,6 +16,7 @@ package com.android.internal.database; +import android.annotation.UnsupportedAppUsage; import android.database.AbstractCursor; import android.database.Cursor; import android.database.DataSetObserver; @@ -28,7 +29,9 @@ import android.util.Log; public class SortCursor extends AbstractCursor { private static final String TAG = "SortCursor"; + @UnsupportedAppUsage private Cursor mCursor; // updated in onMove + @UnsupportedAppUsage private Cursor[] mCursors; private int [] mSortColumns; private final int ROWCACHESIZE = 64; @@ -52,6 +55,7 @@ public class SortCursor extends AbstractCursor } }; + @UnsupportedAppUsage public SortCursor(Cursor[] cursors, String sortcolumn) { mCursors = cursors; diff --git a/core/java/com/android/internal/http/HttpDateTime.java b/core/java/com/android/internal/http/HttpDateTime.java index 8ebd4aaf1ac0..f7706e310952 100644 --- a/core/java/com/android/internal/http/HttpDateTime.java +++ b/core/java/com/android/internal/http/HttpDateTime.java @@ -16,6 +16,7 @@ package com.android.internal.http; +import android.annotation.UnsupportedAppUsage; import android.text.format.Time; import java.util.Calendar; @@ -82,6 +83,7 @@ public final class HttpDateTime { int second; } + @UnsupportedAppUsage public static long parse(String timeString) throws IllegalArgumentException { diff --git a/core/java/com/android/internal/net/NetworkStatsFactory.java b/core/java/com/android/internal/net/NetworkStatsFactory.java index f8483461c2d2..1f3b4c4121d1 100644 --- a/core/java/com/android/internal/net/NetworkStatsFactory.java +++ b/core/java/com/android/internal/net/NetworkStatsFactory.java @@ -256,6 +256,11 @@ public class NetworkStatsFactory { return stats; } + /** + * @deprecated Use NetworkStatsService#getDetailedUidStats which also accounts for + * VPN traffic + */ + @Deprecated public NetworkStats readNetworkStatsDetail() throws IOException { return readNetworkStatsDetail(UID_ALL, null, TAG_ALL, null); } diff --git a/core/java/com/android/internal/net/VpnInfo.java b/core/java/com/android/internal/net/VpnInfo.java index b1a412871bd2..e74af5eb50de 100644 --- a/core/java/com/android/internal/net/VpnInfo.java +++ b/core/java/com/android/internal/net/VpnInfo.java @@ -19,6 +19,8 @@ package com.android.internal.net; import android.os.Parcel; import android.os.Parcelable; +import java.util.Arrays; + /** * A lightweight container used to carry information of the ongoing VPN. * Internal use only.. @@ -28,14 +30,14 @@ import android.os.Parcelable; public class VpnInfo implements Parcelable { public int ownerUid; public String vpnIface; - public String primaryUnderlyingIface; + public String[] underlyingIfaces; @Override public String toString() { return "VpnInfo{" + "ownerUid=" + ownerUid + ", vpnIface='" + vpnIface + '\'' - + ", primaryUnderlyingIface='" + primaryUnderlyingIface + '\'' + + ", underlyingIfaces='" + Arrays.toString(underlyingIfaces) + '\'' + '}'; } @@ -48,7 +50,7 @@ public class VpnInfo implements Parcelable { public void writeToParcel(Parcel dest, int flags) { dest.writeInt(ownerUid); dest.writeString(vpnIface); - dest.writeString(primaryUnderlyingIface); + dest.writeStringArray(underlyingIfaces); } public static final Parcelable.Creator<VpnInfo> CREATOR = new Parcelable.Creator<VpnInfo>() { @@ -57,7 +59,7 @@ public class VpnInfo implements Parcelable { VpnInfo info = new VpnInfo(); info.ownerUid = source.readInt(); info.vpnIface = source.readString(); - info.primaryUnderlyingIface = source.readString(); + info.underlyingIfaces = source.readStringArray(); return info; } diff --git a/core/java/com/android/internal/os/AndroidPrintStream.java b/core/java/com/android/internal/os/AndroidPrintStream.java index 7f4807a5b863..fe2341144d28 100644 --- a/core/java/com/android/internal/os/AndroidPrintStream.java +++ b/core/java/com/android/internal/os/AndroidPrintStream.java @@ -16,6 +16,7 @@ package com.android.internal.os; +import android.annotation.UnsupportedAppUsage; import android.util.Log; /** @@ -34,6 +35,7 @@ class AndroidPrintStream extends LoggingPrintStream { * @param priority from {@link android.util.Log} * @param tag to log */ + @UnsupportedAppUsage public AndroidPrintStream(int priority, String tag) { if (tag == null) { throw new NullPointerException("tag"); diff --git a/core/java/com/android/internal/os/BaseCommand.java b/core/java/com/android/internal/os/BaseCommand.java index 05ec9e90513e..278f40660ee9 100644 --- a/core/java/com/android/internal/os/BaseCommand.java +++ b/core/java/com/android/internal/os/BaseCommand.java @@ -17,12 +17,14 @@ package com.android.internal.os; +import android.annotation.UnsupportedAppUsage; import android.os.ShellCommand; import java.io.PrintStream; public abstract class BaseCommand { + @UnsupportedAppUsage final protected ShellCommand mArgs = new ShellCommand() { @Override public int onCommand(String cmd) { return 0; diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 4ad454514532..274c44446a8c 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -30,6 +30,7 @@ import android.content.IntentFilter; import android.database.ContentObserver; import android.hardware.usb.UsbManager; import android.net.ConnectivityManager; +import android.net.INetworkStatsService; import android.net.NetworkStats; import android.net.Uri; import android.net.wifi.WifiActivityEnergyInfo; @@ -87,7 +88,6 @@ import android.view.Display; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.location.gnssmetrics.GnssMetrics; -import com.android.internal.net.NetworkStatsFactory; import com.android.internal.util.ArrayUtils; import com.android.internal.util.FastPrintWriter; import com.android.internal.util.FastXmlSerializer; @@ -11092,7 +11092,6 @@ public class BatteryStatsImpl extends BatteryStats { } } - private final NetworkStatsFactory mNetworkStatsFactory = new NetworkStatsFactory(); private final Pools.Pool<NetworkStats> mNetworkStatsPool = new Pools.SynchronizedPool<>(6); private final Object mWifiNetworkLock = new Object(); @@ -11114,11 +11113,16 @@ public class BatteryStatsImpl extends BatteryStats { private NetworkStats readNetworkStatsLocked(String[] ifaces) { try { if (!ArrayUtils.isEmpty(ifaces)) { - return mNetworkStatsFactory.readNetworkStatsDetail(NetworkStats.UID_ALL, ifaces, - NetworkStats.TAG_NONE, mNetworkStatsPool.acquire()); + INetworkStatsService statsService = INetworkStatsService.Stub.asInterface( + ServiceManager.getService(Context.NETWORK_STATS_SERVICE)); + if (statsService != null) { + return statsService.getDetailedUidStats(ifaces); + } else { + Slog.e(TAG, "Failed to get networkStatsService "); + } } - } catch (IOException e) { - Slog.e(TAG, "failed to read network stats for ifaces: " + Arrays.toString(ifaces)); + } catch (RemoteException e) { + Slog.e(TAG, "failed to read network stats for ifaces: " + Arrays.toString(ifaces) + e); } return null; } diff --git a/core/java/com/android/internal/os/BinderInternal.java b/core/java/com/android/internal/os/BinderInternal.java index 5bddd2f98983..6efcbda9a00d 100644 --- a/core/java/com/android/internal/os/BinderInternal.java +++ b/core/java/com/android/internal/os/BinderInternal.java @@ -17,6 +17,7 @@ package com.android.internal.os; import android.annotation.NonNull; +import android.annotation.UnsupportedAppUsage; import android.os.Handler; import android.os.IBinder; import android.os.SystemClock; @@ -94,6 +95,7 @@ public class BinderInternal { * an implementation of IServiceManager, which you can use to find * other services. */ + @UnsupportedAppUsage public static final native IBinder getContextObject(); /** @@ -105,6 +107,7 @@ public class BinderInternal { public static final native void setMaxThreads(int numThreads); + @UnsupportedAppUsage static native final void handleGc(); public static void forceGc(String reason) { diff --git a/core/java/com/android/internal/os/ClassLoaderFactory.java b/core/java/com/android/internal/os/ClassLoaderFactory.java index 99a1a19686e4..d32349834dd8 100644 --- a/core/java/com/android/internal/os/ClassLoaderFactory.java +++ b/core/java/com/android/internal/os/ClassLoaderFactory.java @@ -16,6 +16,7 @@ package com.android.internal.os; +import android.annotation.UnsupportedAppUsage; import android.os.Trace; import dalvik.system.DelegateLastClassLoader; @@ -132,6 +133,7 @@ public class ClassLoaderFactory { return classLoader; } + @UnsupportedAppUsage private static native String createClassloaderNamespace(ClassLoader classLoader, int targetSdkVersion, String librarySearchPath, diff --git a/core/java/com/android/internal/os/ProcessCpuTracker.java b/core/java/com/android/internal/os/ProcessCpuTracker.java index 1ee4269d974b..e097ddbdab40 100644 --- a/core/java/com/android/internal/os/ProcessCpuTracker.java +++ b/core/java/com/android/internal/os/ProcessCpuTracker.java @@ -18,6 +18,7 @@ package com.android.internal.os; import static android.os.Process.*; +import android.annotation.UnsupportedAppUsage; import android.os.FileUtils; import android.os.Process; import android.os.StrictMode; @@ -197,6 +198,7 @@ public class ProcessCpuTracker { public boolean interesting; public String baseName; + @UnsupportedAppUsage public String name; public int nameWidth; @@ -212,6 +214,7 @@ public class ProcessCpuTracker { /** * Time in milliseconds. */ + @UnsupportedAppUsage public long rel_uptime; /** @@ -227,11 +230,13 @@ public class ProcessCpuTracker { /** * Time in milliseconds. */ + @UnsupportedAppUsage public int rel_utime; /** * Time in milliseconds. */ + @UnsupportedAppUsage public int rel_stime; public long base_minfaults; @@ -292,6 +297,7 @@ public class ProcessCpuTracker { }; + @UnsupportedAppUsage public ProcessCpuTracker(boolean includeThreads) { mIncludeThreads = includeThreads; long jiffyHz = Os.sysconf(OsConstants._SC_CLK_TCK); @@ -311,6 +317,7 @@ public class ProcessCpuTracker { update(); } + @UnsupportedAppUsage public void update() { if (DEBUG) Slog.v(TAG, "Update: " + this); @@ -713,11 +720,13 @@ public class ProcessCpuTracker { return statses; } + @UnsupportedAppUsage final public int countWorkingStats() { buildWorkingProcs(); return mWorkingProcs.size(); } + @UnsupportedAppUsage final public Stats getWorkingStats(int index) { return mWorkingProcs.get(index); } diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java index e37e650f6e50..eac150dbd320 100644 --- a/core/java/com/android/internal/os/RuntimeInit.java +++ b/core/java/com/android/internal/os/RuntimeInit.java @@ -16,6 +16,7 @@ package com.android.internal.os; +import android.annotation.UnsupportedAppUsage; import android.app.ActivityManager; import android.app.ActivityThread; import android.app.ApplicationErrorReport; @@ -48,8 +49,10 @@ public class RuntimeInit { final static boolean DEBUG = false; /** true if commonInit() has been called */ + @UnsupportedAppUsage private static boolean initialized; + @UnsupportedAppUsage private static IBinder mApplicationObject; private static volatile boolean mCrashing = false; @@ -186,6 +189,7 @@ public class RuntimeInit { } } + @UnsupportedAppUsage protected static final void commonInit() { if (DEBUG) Slog.d(TAG, "Entered RuntimeInit!"); @@ -315,6 +319,7 @@ public class RuntimeInit { return new MethodAndArgsCaller(m, argv); } + @UnsupportedAppUsage public static final void main(String[] argv) { enableDdms(); if (argv.length == 2 && argv[1].equals("application")) { @@ -402,6 +407,7 @@ public class RuntimeInit { mApplicationObject = app; } + @UnsupportedAppUsage public static final IBinder getApplicationObject() { return mApplicationObject; } diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java index 14958ca539de..034c37cdf4c3 100644 --- a/core/java/com/android/internal/os/ZygoteConnection.java +++ b/core/java/com/android/internal/os/ZygoteConnection.java @@ -26,6 +26,7 @@ import static android.system.OsConstants.STDOUT_FILENO; import static com.android.internal.os.ZygoteConnectionConstants.CONNECTION_TIMEOUT_MILLIS; import static com.android.internal.os.ZygoteConnectionConstants.WRAPPED_PID_TIMEOUT_MILLIS; +import android.annotation.UnsupportedAppUsage; import android.metrics.LogMaker; import android.net.Credentials; import android.net.LocalSocket; @@ -65,9 +66,12 @@ class ZygoteConnection { * that it closes when the child process terminates. In other cases, * it is closed in the peer. */ + @UnsupportedAppUsage private final LocalSocket mSocket; + @UnsupportedAppUsage private final DataOutputStream mSocketOutStream; private final BufferedReader mSocketReader; + @UnsupportedAppUsage private final Credentials peer; private final String abiList; private boolean isEof; @@ -396,6 +400,7 @@ class ZygoteConnection { /** * Closes socket associated with this connection. */ + @UnsupportedAppUsage void closeSocket() { try { mSocket.close(); diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java index c6303518d9ae..ce1ee3dc957a 100644 --- a/core/java/com/android/internal/os/ZygoteInit.java +++ b/core/java/com/android/internal/os/ZygoteInit.java @@ -19,6 +19,7 @@ package com.android.internal.os; import static android.system.OsConstants.S_IRWXG; import static android.system.OsConstants.S_IRWXO; +import android.annotation.UnsupportedAppUsage; import android.content.res.Resources; import android.content.res.TypedArray; import android.os.Build; @@ -105,6 +106,7 @@ public class ZygoteInit { /** * Used to pre-load resources. */ + @UnsupportedAppUsage private static Resources mResources; /** @@ -787,6 +789,7 @@ public class ZygoteInit { return result; } + @UnsupportedAppUsage public static void main(String argv[]) { ZygoteServer zygoteServer = new ZygoteServer(); diff --git a/core/java/com/android/internal/os/ZygoteSecurityException.java b/core/java/com/android/internal/os/ZygoteSecurityException.java index 13b47597c1eb..7e50cb885324 100644 --- a/core/java/com/android/internal/os/ZygoteSecurityException.java +++ b/core/java/com/android/internal/os/ZygoteSecurityException.java @@ -16,10 +16,13 @@ package com.android.internal.os; +import android.annotation.UnsupportedAppUsage; + /** * Exception thrown when a security policy is violated. */ class ZygoteSecurityException extends RuntimeException { + @UnsupportedAppUsage ZygoteSecurityException(String message) { super(message); } diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java index 6ad1d72eaec4..b38a7c1c47b2 100644 --- a/core/java/com/android/internal/policy/DecorView.java +++ b/core/java/com/android/internal/policy/DecorView.java @@ -41,6 +41,7 @@ import java.util.List; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; +import android.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.res.Configuration; import android.content.res.Resources; @@ -207,8 +208,11 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind private final BackgroundFallback mBackgroundFallback = new BackgroundFallback(); private int mLastTopInset = 0; + @UnsupportedAppUsage private int mLastBottomInset = 0; + @UnsupportedAppUsage private int mLastRightInset = 0; + @UnsupportedAppUsage private int mLastLeftInset = 0; private boolean mLastHasTopStableInset = false; private boolean mLastHasBottomStableInset = false; @@ -219,6 +223,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind private int mRootScrollY = 0; + @UnsupportedAppUsage private PhoneWindow mWindow; ViewGroup mContentRoot; diff --git a/core/java/com/android/internal/policy/PhoneFallbackEventHandler.java b/core/java/com/android/internal/policy/PhoneFallbackEventHandler.java index d8ee4dd34269..791c2d7aa4b2 100644 --- a/core/java/com/android/internal/policy/PhoneFallbackEventHandler.java +++ b/core/java/com/android/internal/policy/PhoneFallbackEventHandler.java @@ -16,6 +16,7 @@ package com.android.internal.policy; +import android.annotation.UnsupportedAppUsage; import android.app.KeyguardManager; import android.app.SearchManager; import android.content.ActivityNotFoundException; @@ -41,7 +42,9 @@ public class PhoneFallbackEventHandler implements FallbackEventHandler { private static String TAG = "PhoneFallbackEventHandler"; private static final boolean DEBUG = false; + @UnsupportedAppUsage Context mContext; + @UnsupportedAppUsage View mView; AudioManager mAudioManager; @@ -50,6 +53,7 @@ public class PhoneFallbackEventHandler implements FallbackEventHandler { TelephonyManager mTelephonyManager; MediaSessionManager mMediaSessionManager; + @UnsupportedAppUsage public PhoneFallbackEventHandler(Context context) { mContext = context; } @@ -74,6 +78,7 @@ public class PhoneFallbackEventHandler implements FallbackEventHandler { } } + @UnsupportedAppUsage boolean onKeyDown(int keyCode, KeyEvent event) { /* **************************************************************************** * HOW TO DECIDE WHERE YOUR KEY HANDLING GOES. @@ -207,6 +212,7 @@ public class PhoneFallbackEventHandler implements FallbackEventHandler { && (getKeyguardManager().inKeyguardRestrictedInputMode() || dispatcher == null); } + @UnsupportedAppUsage boolean onKeyUp(int keyCode, KeyEvent event) { if (DEBUG) { Log.d(TAG, "up " + keyCode); @@ -270,6 +276,7 @@ public class PhoneFallbackEventHandler implements FallbackEventHandler { return false; } + @UnsupportedAppUsage void startCallActivity() { sendCloseSystemWindows(); Intent intent = new Intent(Intent.ACTION_CALL_BUTTON); diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java index daea9a8eff41..0fa43a6f069d 100644 --- a/core/java/com/android/internal/policy/PhoneWindow.java +++ b/core/java/com/android/internal/policy/PhoneWindow.java @@ -63,6 +63,7 @@ import com.android.internal.view.menu.MenuView; import com.android.internal.widget.DecorContentParent; import com.android.internal.widget.SwipeDismissLayout; +import android.annotation.UnsupportedAppUsage; import android.app.ActivityManager; import android.app.KeyguardManager; import android.content.Context; @@ -237,6 +238,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { private boolean mForcedStatusBarColor = false; private boolean mForcedNavigationBarColor = false; + @UnsupportedAppUsage private CharSequence mTitle = null; private int mTitleColor = 0; @@ -300,6 +302,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { static final RotationWatcher sRotationWatcher = new RotationWatcher(); + @UnsupportedAppUsage public PhoneWindow(Context context) { super(context); mLayoutInflater = LayoutInflater.from(context); diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java index 4b662670f5e7..eb556855ad41 100644 --- a/core/java/com/android/internal/util/ArrayUtils.java +++ b/core/java/com/android/internal/util/ArrayUtils.java @@ -18,6 +18,7 @@ package com.android.internal.util; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.UnsupportedAppUsage; import android.util.ArraySet; import dalvik.system.VMRuntime; @@ -51,6 +52,7 @@ public class ArrayUtils { return (char[])VMRuntime.getRuntime().newUnpaddedArray(char.class, minLen); } + @UnsupportedAppUsage public static int[] newUnpaddedIntArray(int minLen) { return (int[])VMRuntime.getRuntime().newUnpaddedArray(int.class, minLen); } @@ -71,6 +73,7 @@ public class ArrayUtils { return (Object[])VMRuntime.getRuntime().newUnpaddedArray(Object.class, minLen); } + @UnsupportedAppUsage @SuppressWarnings("unchecked") public static <T> T[] newUnpaddedArray(Class<T> clazz, int minLen) { return (T[])VMRuntime.getRuntime().newUnpaddedArray(clazz, minLen); @@ -108,6 +111,7 @@ public class ArrayUtils { * it will return the same empty array every time to avoid reallocation, * although this is not guaranteed. */ + @UnsupportedAppUsage @SuppressWarnings("unchecked") public static <T> T[] emptyArray(Class<T> kind) { if (kind == Object.class) { @@ -144,6 +148,7 @@ public class ArrayUtils { /** * Checks if given array is null or has zero elements. */ + @UnsupportedAppUsage public static <T> boolean isEmpty(@Nullable T[] array) { return array == null || array.length == 0; } @@ -196,6 +201,7 @@ public class ArrayUtils { * @param value the value to check for * @return true if the value is present in the array */ + @UnsupportedAppUsage public static <T> boolean contains(@Nullable T[] array, T value) { return indexOf(array, value) != -1; } @@ -204,6 +210,7 @@ public class ArrayUtils { * Return first index of {@code value} in {@code array}, or {@code -1} if * not found. */ + @UnsupportedAppUsage public static <T> int indexOf(@Nullable T[] array, T value) { if (array == null) return -1; for (int i = 0; i < array.length; i++) { @@ -238,6 +245,7 @@ public class ArrayUtils { return false; } + @UnsupportedAppUsage public static boolean contains(@Nullable int[] array, int value) { if (array == null) return false; for (int element : array) { @@ -329,6 +337,7 @@ public class ArrayUtils { * Adds value to given array if not already present, providing set-like * behavior. */ + @UnsupportedAppUsage @SuppressWarnings("unchecked") public static @NonNull <T> T[] appendElement(Class<T> kind, @Nullable T[] array, T element) { return appendElement(kind, array, element, false); @@ -358,6 +367,7 @@ public class ArrayUtils { /** * Removes value from given array if present, providing set-like behavior. */ + @UnsupportedAppUsage @SuppressWarnings("unchecked") public static @Nullable <T> T[] removeElement(Class<T> kind, @Nullable T[] array, T element) { if (array != null) { @@ -404,6 +414,7 @@ public class ArrayUtils { * Adds value to given array if not already present, providing set-like * behavior. */ + @UnsupportedAppUsage public static @NonNull int[] appendInt(@Nullable int[] cur, int val) { return appendInt(cur, val, false); } diff --git a/core/java/com/android/internal/util/BitwiseInputStream.java b/core/java/com/android/internal/util/BitwiseInputStream.java index 86f74f302518..6ff67e9b9718 100644 --- a/core/java/com/android/internal/util/BitwiseInputStream.java +++ b/core/java/com/android/internal/util/BitwiseInputStream.java @@ -16,6 +16,8 @@ package com.android.internal.util; +import android.annotation.UnsupportedAppUsage; + /** * An object that provides bitwise incremental read access to a byte array. * @@ -49,6 +51,7 @@ public class BitwiseInputStream { * * @param buf a byte array containing data */ + @UnsupportedAppUsage public BitwiseInputStream(byte buf[]) { mBuf = buf; mEnd = buf.length << 3; @@ -58,6 +61,7 @@ public class BitwiseInputStream { /** * Return the number of bit still available for reading. */ + @UnsupportedAppUsage public int available() { return mEnd - mPos; } @@ -71,6 +75,7 @@ public class BitwiseInputStream { * @param bits the amount of data to read (gte 0, lte 8) * @return byte of read data (possibly partially filled, from lsb) */ + @UnsupportedAppUsage public int read(int bits) throws AccessException { int index = mPos >>> 3; int offset = 16 - (mPos & 0x07) - bits; // &7==%8 @@ -92,6 +97,7 @@ public class BitwiseInputStream { * @param bits the amount of data to read * @return newly allocated byte array of read data */ + @UnsupportedAppUsage public byte[] readByteArray(int bits) throws AccessException { int bytes = (bits >>> 3) + ((bits & 0x07) > 0 ? 1 : 0); // &7==%8 byte[] arr = new byte[bytes]; @@ -107,6 +113,7 @@ public class BitwiseInputStream { * * @param bits the amount by which to increment the position */ + @UnsupportedAppUsage public void skip(int bits) throws AccessException { if ((mPos + bits) > mEnd) { throw new AccessException("illegal skip " + diff --git a/core/java/com/android/internal/util/BitwiseOutputStream.java b/core/java/com/android/internal/util/BitwiseOutputStream.java index ddecbed1d97c..cdd6f173484c 100644 --- a/core/java/com/android/internal/util/BitwiseOutputStream.java +++ b/core/java/com/android/internal/util/BitwiseOutputStream.java @@ -16,6 +16,8 @@ package com.android.internal.util; +import android.annotation.UnsupportedAppUsage; + /** * An object that provides bitwise incremental write access to a byte array. * @@ -49,6 +51,7 @@ public class BitwiseOutputStream { * * @param startingLength initial internal byte array length in bytes */ + @UnsupportedAppUsage public BitwiseOutputStream(int startingLength) { mBuf = new byte[startingLength]; mEnd = startingLength << 3; @@ -60,6 +63,7 @@ public class BitwiseOutputStream { * * @return newly allocated byte array */ + @UnsupportedAppUsage public byte[] toByteArray() { int len = (mPos >>> 3) + ((mPos & 0x07) > 0 ? 1 : 0); // &7==%8 byte[] newBuf = new byte[len]; @@ -89,6 +93,7 @@ public class BitwiseOutputStream { * @param bits the amount of data to write (gte 0, lte 8) * @param data to write, will be masked to expose only bits param from lsb */ + @UnsupportedAppUsage public void write(int bits, int data) throws AccessException { if ((bits < 0) || (bits > 8)) { throw new AccessException("illegal write (" + bits + " bits)"); @@ -109,6 +114,7 @@ public class BitwiseOutputStream { * @param bits the amount of data to write * @param arr the byte array containing data to be written */ + @UnsupportedAppUsage public void writeByteArray(int bits, byte[] arr) throws AccessException { for (int i = 0; i < arr.length; i++) { int increment = Math.min(8, bits - (i << 3)); diff --git a/core/java/com/android/internal/util/CharSequences.java b/core/java/com/android/internal/util/CharSequences.java index fdaa4bce25db..6b6c43ce8195 100644 --- a/core/java/com/android/internal/util/CharSequences.java +++ b/core/java/com/android/internal/util/CharSequences.java @@ -16,6 +16,8 @@ package com.android.internal.util; +import android.annotation.UnsupportedAppUsage; + /** * {@link CharSequence} utility methods. */ @@ -93,6 +95,7 @@ public class CharSequences { /** * Compares two character sequences for equality. */ + @UnsupportedAppUsage public static boolean equals(CharSequence a, CharSequence b) { if (a.length() != b.length()) { return false; @@ -114,6 +117,7 @@ public class CharSequences { * @param another The other CharSequence. * @return See {@link Comparable#compareTo}. */ + @UnsupportedAppUsage public static int compareToIgnoreCase(CharSequence me, CharSequence another) { // Code adapted from String#compareTo int myLen = me.length(), anotherLen = another.length(); diff --git a/core/java/com/android/internal/util/FastMath.java b/core/java/com/android/internal/util/FastMath.java index 88a17e6ba259..35efe708795e 100644 --- a/core/java/com/android/internal/util/FastMath.java +++ b/core/java/com/android/internal/util/FastMath.java @@ -16,6 +16,8 @@ package com.android.internal.util; +import android.annotation.UnsupportedAppUsage; + /** * Fast and loose math routines. */ @@ -26,6 +28,7 @@ public class FastMath { * thought it may return slightly different results. It does not try to * handle (in any meaningful way) NaN or infinities. */ + @UnsupportedAppUsage public static int round(float value) { long lx = (long) (value * (65536 * 256f)); return (int) ((lx + 0x800000) >> 24); diff --git a/core/java/com/android/internal/util/FastXmlSerializer.java b/core/java/com/android/internal/util/FastXmlSerializer.java index b85b84fb3dc8..9f76aeb663c5 100644 --- a/core/java/com/android/internal/util/FastXmlSerializer.java +++ b/core/java/com/android/internal/util/FastXmlSerializer.java @@ -18,6 +18,7 @@ package com.android.internal.util; import org.xmlpull.v1.XmlSerializer; +import android.annotation.UnsupportedAppUsage; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; @@ -69,6 +70,7 @@ public class FastXmlSerializer implements XmlSerializer { private int mNesting = 0; private boolean mLineStart = true; + @UnsupportedAppUsage public FastXmlSerializer() { this(DEFAULT_BUFFER_LEN); } diff --git a/core/java/com/android/internal/util/GrowingArrayUtils.java b/core/java/com/android/internal/util/GrowingArrayUtils.java index 968d9204b106..9f563667e019 100644 --- a/core/java/com/android/internal/util/GrowingArrayUtils.java +++ b/core/java/com/android/internal/util/GrowingArrayUtils.java @@ -16,6 +16,8 @@ package com.android.internal.util; +import android.annotation.UnsupportedAppUsage; + /** * A helper class that aims to provide comparable growth performance to ArrayList, but on primitive * arrays. Common array operations are implemented for efficient use in dynamic containers. @@ -37,6 +39,7 @@ public final class GrowingArrayUtils { * @return the array to which the element was appended. This may be different than the given * array. */ + @UnsupportedAppUsage public static <T> T[] append(T[] array, int currentSize, T element) { assert currentSize <= array.length; @@ -54,6 +57,7 @@ public final class GrowingArrayUtils { /** * Primitive int version of {@link #append(Object[], int, Object)}. */ + @UnsupportedAppUsage public static int[] append(int[] array, int currentSize, int element) { assert currentSize <= array.length; diff --git a/core/java/com/android/internal/util/HexDump.java b/core/java/com/android/internal/util/HexDump.java index af004009e1ee..6ffc92853b08 100644 --- a/core/java/com/android/internal/util/HexDump.java +++ b/core/java/com/android/internal/util/HexDump.java @@ -17,6 +17,7 @@ package com.android.internal.util; import android.annotation.Nullable; +import android.annotation.UnsupportedAppUsage; public class HexDump { @@ -100,16 +101,19 @@ public class HexDump return toHexString(toByteArray(b)); } + @UnsupportedAppUsage public static String toHexString(byte[] array) { return toHexString(array, 0, array.length, true); } + @UnsupportedAppUsage public static String toHexString(byte[] array, boolean upperCase) { return toHexString(array, 0, array.length, upperCase); } + @UnsupportedAppUsage public static String toHexString(byte[] array, int offset, int length) { return toHexString(array, offset, length, true); @@ -131,6 +135,7 @@ public class HexDump return new String(buf); } + @UnsupportedAppUsage public static String toHexString(int i) { return toHexString(toByteArray(i)); @@ -164,6 +169,7 @@ public class HexDump throw new RuntimeException ("Invalid hex char '" + c + "'"); } + @UnsupportedAppUsage public static byte[] hexStringToByteArray(String hexString) { int length = hexString.length(); diff --git a/core/java/com/android/internal/util/IState.java b/core/java/com/android/internal/util/IState.java index 056f8e9b0424..eb66e2ce94d7 100644 --- a/core/java/com/android/internal/util/IState.java +++ b/core/java/com/android/internal/util/IState.java @@ -16,6 +16,7 @@ package com.android.internal.util; +import android.annotation.UnsupportedAppUsage; import android.os.Message; /** @@ -67,5 +68,6 @@ public interface IState { * * @return name of state. */ + @UnsupportedAppUsage String getName(); } diff --git a/core/java/com/android/internal/util/MemInfoReader.java b/core/java/com/android/internal/util/MemInfoReader.java index 8d7166679b78..630916ebeecb 100644 --- a/core/java/com/android/internal/util/MemInfoReader.java +++ b/core/java/com/android/internal/util/MemInfoReader.java @@ -16,12 +16,14 @@ package com.android.internal.util; +import android.annotation.UnsupportedAppUsage; import android.os.Debug; import android.os.StrictMode; public final class MemInfoReader { final long[] mInfos = new long[Debug.MEMINFO_COUNT]; + @UnsupportedAppUsage public void readMemInfo() { // Permit disk reads here, as /proc/meminfo isn't really "on // disk" and should be fast. TODO: make BlockGuard ignore @@ -37,6 +39,7 @@ public final class MemInfoReader { /** * Total amount of RAM available to the kernel. */ + @UnsupportedAppUsage public long getTotalSize() { return mInfos[Debug.MEMINFO_TOTAL] * 1024; } @@ -44,6 +47,7 @@ public final class MemInfoReader { /** * Amount of RAM that is not being used for anything. */ + @UnsupportedAppUsage public long getFreeSize() { return mInfos[Debug.MEMINFO_FREE] * 1024; } @@ -52,6 +56,7 @@ public final class MemInfoReader { * Amount of RAM that the kernel is being used for caches, not counting caches * that are mapped in to processes. */ + @UnsupportedAppUsage public long getCachedSize() { return getCachedSizeKb() * 1024; } @@ -107,6 +112,7 @@ public final class MemInfoReader { return mInfos[Debug.MEMINFO_ZRAM_TOTAL]; } + @UnsupportedAppUsage public long[] getRawInfo() { return mInfos; } diff --git a/core/java/com/android/internal/util/Preconditions.java b/core/java/com/android/internal/util/Preconditions.java index 91c76afdf5b2..3a5720f6e918 100644 --- a/core/java/com/android/internal/util/Preconditions.java +++ b/core/java/com/android/internal/util/Preconditions.java @@ -18,6 +18,7 @@ package com.android.internal.util; import android.annotation.IntRange; import android.annotation.NonNull; +import android.annotation.UnsupportedAppUsage; import android.text.TextUtils; import java.util.Collection; @@ -28,6 +29,7 @@ import java.util.Collection; */ public class Preconditions { + @UnsupportedAppUsage public static void checkArgument(boolean expression) { if (!expression) { throw new IllegalArgumentException(); @@ -42,6 +44,7 @@ public class Preconditions { * be converted to a string using {@link String#valueOf(Object)} * @throws IllegalArgumentException if {@code expression} is false */ + @UnsupportedAppUsage public static void checkArgument(boolean expression, final Object errorMessage) { if (!expression) { throw new IllegalArgumentException(String.valueOf(errorMessage)); @@ -106,6 +109,7 @@ public class Preconditions { * @return the non-null reference that was validated * @throws NullPointerException if {@code reference} is null */ + @UnsupportedAppUsage public static @NonNull <T> T checkNotNull(final T reference) { if (reference == null) { throw new NullPointerException(); @@ -123,6 +127,7 @@ public class Preconditions { * @return the non-null reference that was validated * @throws NullPointerException if {@code reference} is null */ + @UnsupportedAppUsage public static @NonNull <T> T checkNotNull(final T reference, final Object errorMessage) { if (reference == null) { throw new NullPointerException(String.valueOf(errorMessage)); @@ -158,6 +163,7 @@ public class Preconditions { * @param message exception message * @throws IllegalStateException if {@code expression} is false */ + @UnsupportedAppUsage public static void checkState(final boolean expression, String message) { if (!expression) { throw new IllegalStateException(message); @@ -171,6 +177,7 @@ public class Preconditions { * @param expression a boolean expression * @throws IllegalStateException if {@code expression} is false */ + @UnsupportedAppUsage public static void checkState(final boolean expression) { checkState(expression, null); } @@ -338,6 +345,7 @@ public class Preconditions { * * @throws IllegalArgumentException if {@code value} was not within the range */ + @UnsupportedAppUsage public static int checkArgumentInRange(int value, int lower, int upper, String valueName) { if (value < lower) { diff --git a/core/java/com/android/internal/util/State.java b/core/java/com/android/internal/util/State.java index 3eadff58bc09..3c61e035e886 100644 --- a/core/java/com/android/internal/util/State.java +++ b/core/java/com/android/internal/util/State.java @@ -16,6 +16,7 @@ package com.android.internal.util; +import android.annotation.UnsupportedAppUsage; import android.os.Message; /** @@ -28,12 +29,14 @@ public class State implements IState { /** * Constructor */ + @UnsupportedAppUsage protected State() { } /* (non-Javadoc) * @see com.android.internal.util.IState#enter() */ + @UnsupportedAppUsage @Override public void enter() { } @@ -41,6 +44,7 @@ public class State implements IState { /* (non-Javadoc) * @see com.android.internal.util.IState#exit() */ + @UnsupportedAppUsage @Override public void exit() { } @@ -48,6 +52,7 @@ public class State implements IState { /* (non-Javadoc) * @see com.android.internal.util.IState#processMessage(android.os.Message) */ + @UnsupportedAppUsage @Override public boolean processMessage(Message msg) { return false; @@ -65,6 +70,7 @@ public class State implements IState { * * @see com.android.internal.util.IState#processMessage(android.os.Message) */ + @UnsupportedAppUsage @Override public String getName() { String name = getClass().getName(); diff --git a/core/java/com/android/internal/util/StateMachine.java b/core/java/com/android/internal/util/StateMachine.java index 7398e9526a42..dacdae6fd6c6 100644 --- a/core/java/com/android/internal/util/StateMachine.java +++ b/core/java/com/android/internal/util/StateMachine.java @@ -1301,6 +1301,7 @@ public class StateMachine { * * @param name of the state machine */ + @UnsupportedAppUsage protected StateMachine(String name) { mSmThread = new HandlerThread(name); mSmThread.start(); @@ -1314,6 +1315,7 @@ public class StateMachine { * * @param name of the state machine */ + @UnsupportedAppUsage protected StateMachine(String name, Looper looper) { initStateMachine(name, looper); } @@ -1323,6 +1325,7 @@ public class StateMachine { * * @param name of the state machine */ + @UnsupportedAppUsage protected StateMachine(String name, Handler handler) { initStateMachine(name, handler.getLooper()); } @@ -1678,6 +1681,7 @@ public class StateMachine { * @param arg2 is assigned to Message.arg2 * @return A Message object from the global pool */ + @UnsupportedAppUsage public final Message obtainMessage(int what, int arg1, int arg2) { return Message.obtain(mSmHandler, what, arg1, arg2); } @@ -1697,6 +1701,7 @@ public class StateMachine { * @param obj is assigned to Message.obj * @return A Message object from the global pool */ + @UnsupportedAppUsage public final Message obtainMessage(int what, int arg1, int arg2, Object obj) { return Message.obtain(mSmHandler, what, arg1, arg2, obj); } @@ -1706,6 +1711,7 @@ public class StateMachine { * * Message is ignored if state machine has quit. */ + @UnsupportedAppUsage public void sendMessage(int what) { // mSmHandler can be null if the state machine has quit. SmHandler smh = mSmHandler; @@ -1719,6 +1725,7 @@ public class StateMachine { * * Message is ignored if state machine has quit. */ + @UnsupportedAppUsage public void sendMessage(int what, Object obj) { // mSmHandler can be null if the state machine has quit. SmHandler smh = mSmHandler; @@ -1732,6 +1739,7 @@ public class StateMachine { * * Message is ignored if state machine has quit. */ + @UnsupportedAppUsage public void sendMessage(int what, int arg1) { // mSmHandler can be null if the state machine has quit. SmHandler smh = mSmHandler; @@ -1758,6 +1766,7 @@ public class StateMachine { * * Message is ignored if state machine has quit. */ + @UnsupportedAppUsage public void sendMessage(int what, int arg1, int arg2, Object obj) { // mSmHandler can be null if the state machine has quit. SmHandler smh = mSmHandler; @@ -1771,6 +1780,7 @@ public class StateMachine { * * Message is ignored if state machine has quit. */ + @UnsupportedAppUsage public void sendMessage(Message msg) { // mSmHandler can be null if the state machine has quit. SmHandler smh = mSmHandler; @@ -2074,6 +2084,7 @@ public class StateMachine { * @param pw * @param args */ + @UnsupportedAppUsage public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println(getName() + ":"); pw.println(" total records=" + getLogRecCount()); diff --git a/core/java/com/android/internal/view/ActionBarPolicy.java b/core/java/com/android/internal/view/ActionBarPolicy.java index 755faf333a1e..d18c35e703da 100644 --- a/core/java/com/android/internal/view/ActionBarPolicy.java +++ b/core/java/com/android/internal/view/ActionBarPolicy.java @@ -18,6 +18,7 @@ package com.android.internal.view; import com.android.internal.R; +import android.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.res.Configuration; import android.content.res.Resources; @@ -29,12 +30,15 @@ import android.os.Build; * about how the action bar should lay out and behave on the current device. */ public class ActionBarPolicy { + @UnsupportedAppUsage private Context mContext; + @UnsupportedAppUsage public static ActionBarPolicy get(Context context) { return new ActionBarPolicy(context); } + @UnsupportedAppUsage private ActionBarPolicy(Context context) { mContext = context; } @@ -44,6 +48,7 @@ public class ActionBarPolicy { * bar/action mode. This will be used to determine how many showAsAction="ifRoom" items can fit. * "always" items can override this. */ + @UnsupportedAppUsage public int getMaxActionButtons() { final Configuration config = mContext.getResources().getConfiguration(); final int width = config.screenWidthDp; @@ -62,14 +67,17 @@ public class ActionBarPolicy { return 2; } } + @UnsupportedAppUsage public boolean showsOverflowMenuButton() { return true; } + @UnsupportedAppUsage public int getEmbeddedMenuWidthLimit() { return mContext.getResources().getDisplayMetrics().widthPixels / 2; } + @UnsupportedAppUsage public boolean hasEmbeddedTabs() { final int targetSdk = mContext.getApplicationInfo().targetSdkVersion; if (targetSdk >= Build.VERSION_CODES.JELLY_BEAN) { @@ -85,6 +93,7 @@ public class ActionBarPolicy { width >= 480 || (width >= 640 && height >= 480); } + @UnsupportedAppUsage public int getTabContainerHeight() { TypedArray a = mContext.obtainStyledAttributes(null, R.styleable.ActionBar, com.android.internal.R.attr.actionBarStyle, 0); @@ -106,6 +115,7 @@ public class ActionBarPolicy { Build.VERSION_CODES.ICE_CREAM_SANDWICH; } + @UnsupportedAppUsage public int getStackedTabMaxWidth() { return mContext.getResources().getDimensionPixelSize( R.dimen.action_bar_stacked_tab_max_width); diff --git a/core/java/com/android/internal/view/InputConnectionWrapper.java b/core/java/com/android/internal/view/InputConnectionWrapper.java index 5b65bbe1e90e..666c9e093218 100644 --- a/core/java/com/android/internal/view/InputConnectionWrapper.java +++ b/core/java/com/android/internal/view/InputConnectionWrapper.java @@ -19,6 +19,7 @@ package com.android.internal.view; import android.annotation.AnyThread; import android.annotation.BinderThread; import android.annotation.NonNull; +import android.annotation.UnsupportedAppUsage; import android.inputmethodservice.AbstractInputMethodService; import android.os.Bundle; import android.os.Handler; @@ -78,6 +79,7 @@ public class InputConnectionWrapper implements InputConnection { * sequence number is set to a new integer. We use a sequence number so that replies that * occur after a timeout has expired are not interpreted as replies to a later request. */ + @UnsupportedAppUsage @AnyThread private static InputContextCallback getInstance() { synchronized (InputContextCallback.class) { @@ -102,6 +104,7 @@ public class InputConnectionWrapper implements InputConnection { /** * Makes the given InputContextCallback available for use in the future. */ + @UnsupportedAppUsage @AnyThread private void dispose() { synchronized (InputContextCallback.class) { diff --git a/core/java/com/android/internal/view/WindowManagerPolicyThread.java b/core/java/com/android/internal/view/WindowManagerPolicyThread.java index c8c38bb01886..b009a2d8ca30 100644 --- a/core/java/com/android/internal/view/WindowManagerPolicyThread.java +++ b/core/java/com/android/internal/view/WindowManagerPolicyThread.java @@ -16,6 +16,7 @@ package com.android.internal.view; +import android.annotation.UnsupportedAppUsage; import android.os.Looper; /** @@ -35,6 +36,7 @@ public class WindowManagerPolicyThread { return mThread; } + @UnsupportedAppUsage public static Looper getLooper() { return mLooper; } diff --git a/core/java/com/android/internal/view/menu/ActionMenu.java b/core/java/com/android/internal/view/menu/ActionMenu.java index c657b872e71e..977c1f6fda7b 100644 --- a/core/java/com/android/internal/view/menu/ActionMenu.java +++ b/core/java/com/android/internal/view/menu/ActionMenu.java @@ -19,6 +19,7 @@ package com.android.internal.view.menu; import java.util.ArrayList; import java.util.List; +import android.annotation.UnsupportedAppUsage; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -39,6 +40,7 @@ public class ActionMenu implements Menu { private ArrayList<ActionMenuItem> mItems; + @UnsupportedAppUsage public ActionMenu(Context context) { mContext = context; mItems = new ArrayList<ActionMenuItem>(); diff --git a/core/java/com/android/internal/view/menu/ActionMenuItem.java b/core/java/com/android/internal/view/menu/ActionMenuItem.java index b807a42e922e..ed253d58fb82 100644 --- a/core/java/com/android/internal/view/menu/ActionMenuItem.java +++ b/core/java/com/android/internal/view/menu/ActionMenuItem.java @@ -17,6 +17,7 @@ package com.android.internal.view.menu; import android.annotation.Nullable; +import android.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.Intent; import android.content.res.ColorStateList; @@ -69,6 +70,7 @@ public class ActionMenuItem implements MenuItem { private static final int HIDDEN = 0x00000008; private static final int ENABLED = 0x00000010; + @UnsupportedAppUsage public ActionMenuItem(Context context, int group, int id, int categoryOrder, int ordering, CharSequence title) { mContext = context; diff --git a/core/java/com/android/internal/view/menu/ContextMenuBuilder.java b/core/java/com/android/internal/view/menu/ContextMenuBuilder.java index 82f061cb86ca..3d3aceb4a85f 100644 --- a/core/java/com/android/internal/view/menu/ContextMenuBuilder.java +++ b/core/java/com/android/internal/view/menu/ContextMenuBuilder.java @@ -16,6 +16,7 @@ package com.android.internal.view.menu; +import android.annotation.UnsupportedAppUsage; import android.content.Context; import android.graphics.drawable.Drawable; import android.os.IBinder; @@ -39,6 +40,7 @@ import android.view.View; */ public class ContextMenuBuilder extends MenuBuilder implements ContextMenu { + @UnsupportedAppUsage public ContextMenuBuilder(Context context) { super(context); } diff --git a/core/java/com/android/internal/view/menu/IconMenuItemView.java b/core/java/com/android/internal/view/menu/IconMenuItemView.java index 6c8f330fbcc8..3d888d347d65 100644 --- a/core/java/com/android/internal/view/menu/IconMenuItemView.java +++ b/core/java/com/android/internal/view/menu/IconMenuItemView.java @@ -18,6 +18,7 @@ package com.android.internal.view.menu; import com.android.internal.view.menu.MenuBuilder.ItemInvoker; +import android.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Rect; @@ -213,6 +214,7 @@ public final class IconMenuItemView extends TextView implements MenuView.ItemVie } } + @UnsupportedAppUsage public void setItemInvoker(ItemInvoker itemInvoker) { mItemInvoker = itemInvoker; } @@ -232,6 +234,7 @@ public final class IconMenuItemView extends TextView implements MenuView.ItemVie } } + @UnsupportedAppUsage void setIconMenuView(IconMenuView iconMenuView) { mIconMenuView = iconMenuView; } @@ -267,6 +270,7 @@ public final class IconMenuItemView extends TextView implements MenuView.ItemVie * @return layout params appropriate for this view. If layout params already exist, it will * augment them to be appropriate to the current text size. */ + @UnsupportedAppUsage IconMenuView.LayoutParams getTextAppropriateLayoutParams() { IconMenuView.LayoutParams lp = (IconMenuView.LayoutParams) getLayoutParams(); if (lp == null) { diff --git a/core/java/com/android/internal/view/menu/IconMenuView.java b/core/java/com/android/internal/view/menu/IconMenuView.java index dab43ebfe5d5..6f264341f7b4 100644 --- a/core/java/com/android/internal/view/menu/IconMenuView.java +++ b/core/java/com/android/internal/view/menu/IconMenuView.java @@ -18,6 +18,7 @@ package com.android.internal.view.menu; import com.android.internal.view.menu.MenuBuilder.ItemInvoker; +import android.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.res.Resources; import android.content.res.TypedArray; @@ -51,6 +52,7 @@ import java.util.ArrayList; public final class IconMenuView extends ViewGroup implements ItemInvoker, MenuView, Runnable { private static final int ITEM_CAPTION_CYCLE_DELAY = 1000; + @UnsupportedAppUsage private MenuBuilder mMenu; /** Height of each row */ @@ -58,6 +60,7 @@ public final class IconMenuView extends ViewGroup implements ItemInvoker, MenuVi /** Maximum number of rows to be shown */ private int mMaxRows; /** Maximum number of items to show in the icon menu. */ + @UnsupportedAppUsage private int mMaxItems; /** Maximum number of items per row */ private int mMaxItemsPerRow; @@ -82,6 +85,7 @@ public final class IconMenuView extends ViewGroup implements ItemInvoker, MenuVi private Drawable mMoreIcon; /** Background of each item (should contain the selected and focused states) */ + @UnsupportedAppUsage private Drawable mItemBackground; /** Default animations for this menu */ @@ -288,6 +292,7 @@ public final class IconMenuView extends ViewGroup implements ItemInvoker, MenuVi * have a MenuItemData backing it. * @return The IconMenuItemView for the 'More' button */ + @UnsupportedAppUsage IconMenuItemView createMoreItemView() { Context context = getContext(); LayoutInflater inflater = LayoutInflater.from(context); @@ -494,6 +499,7 @@ public final class IconMenuView extends ViewGroup implements ItemInvoker, MenuVi * {@link MenuView.ItemView} implementation--eg: excludes More * item). */ + @UnsupportedAppUsage int getNumActualItemsShown() { return mNumActualItemsShown; } @@ -717,6 +723,7 @@ public final class IconMenuView extends ViewGroup implements ItemInvoker, MenuVi /** * Constructor called from {@link #CREATOR} */ + @UnsupportedAppUsage private SavedState(Parcel in) { super(in); focusedPosition = in.readInt(); diff --git a/core/java/com/android/internal/view/menu/MenuDialogHelper.java b/core/java/com/android/internal/view/menu/MenuDialogHelper.java index ecab29fdbbd4..88d0a03bd55f 100644 --- a/core/java/com/android/internal/view/menu/MenuDialogHelper.java +++ b/core/java/com/android/internal/view/menu/MenuDialogHelper.java @@ -16,6 +16,7 @@ package com.android.internal.view.menu; +import android.annotation.UnsupportedAppUsage; import android.app.AlertDialog; import android.app.Dialog; import android.content.DialogInterface; @@ -36,6 +37,7 @@ public class MenuDialogHelper implements MenuHelper, DialogInterface.OnKeyListen ListMenuPresenter mPresenter; private MenuPresenter.Callback mPresenterCallback; + @UnsupportedAppUsage public MenuDialogHelper(MenuBuilder menu) { mMenu = menu; } @@ -45,6 +47,7 @@ public class MenuDialogHelper implements MenuHelper, DialogInterface.OnKeyListen * * @param windowToken Optional token to assign to the window. */ + @UnsupportedAppUsage public void show(IBinder windowToken) { // Many references to mMenu, create local reference final MenuBuilder menu = mMenu; @@ -132,6 +135,7 @@ public class MenuDialogHelper implements MenuHelper, DialogInterface.OnKeyListen * * @see Dialog#dismiss() */ + @UnsupportedAppUsage @Override public void dismiss() { if (mDialog != null) { diff --git a/core/java/com/android/internal/widget/AbsActionBarView.java b/core/java/com/android/internal/widget/AbsActionBarView.java index 582c4f1dd669..9ccee7fc32ff 100644 --- a/core/java/com/android/internal/widget/AbsActionBarView.java +++ b/core/java/com/android/internal/widget/AbsActionBarView.java @@ -27,6 +27,7 @@ import android.animation.Animator; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.TimeInterpolator; +import android.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.res.Configuration; import android.content.res.TypedArray; @@ -294,6 +295,7 @@ public abstract class AbsActionBarView extends ViewGroup { return isOverflowReserved() && getVisibility() == VISIBLE; } + @UnsupportedAppUsage public void dismissPopupMenus() { if (mActionMenuPresenter != null) { mActionMenuPresenter.dismissPopupMenus(); diff --git a/core/java/com/android/internal/widget/ActionBarContextView.java b/core/java/com/android/internal/widget/ActionBarContextView.java index 693b194caa8b..78ed53fa918c 100644 --- a/core/java/com/android/internal/widget/ActionBarContextView.java +++ b/core/java/com/android/internal/widget/ActionBarContextView.java @@ -21,6 +21,7 @@ import android.widget.ActionMenuPresenter; import android.widget.ActionMenuView; import com.android.internal.view.menu.MenuBuilder; +import android.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.res.TypedArray; import android.graphics.drawable.Drawable; @@ -58,6 +59,7 @@ public class ActionBarContextView extends AbsActionBarView { this(context, null); } + @UnsupportedAppUsage public ActionBarContextView(Context context, AttributeSet attrs) { this(context, attrs, com.android.internal.R.attr.actionModeStyle); } diff --git a/core/java/com/android/internal/widget/ActionBarOverlayLayout.java b/core/java/com/android/internal/widget/ActionBarOverlayLayout.java index 4a1c95532ba0..efa8f2c3888a 100644 --- a/core/java/com/android/internal/widget/ActionBarOverlayLayout.java +++ b/core/java/com/android/internal/widget/ActionBarOverlayLayout.java @@ -18,6 +18,7 @@ package com.android.internal.widget; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; +import android.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.pm.ActivityInfo; import android.content.res.Configuration; @@ -168,6 +169,7 @@ public class ActionBarOverlayLayout extends ViewGroup implements DecorContentPar init(context); } + @UnsupportedAppUsage public ActionBarOverlayLayout(Context context, AttributeSet attrs) { super(context, attrs); init(context); @@ -672,6 +674,7 @@ public class ActionBarOverlayLayout extends ViewGroup implements DecorContentPar return finalY > mActionBarTop.getHeight(); } + @UnsupportedAppUsage @Override public void setWindowCallback(Window.Callback cb) { pullChildren(); diff --git a/core/java/com/android/internal/widget/EditableInputConnection.java b/core/java/com/android/internal/widget/EditableInputConnection.java index 7f7528dd3de0..4bf34c83a872 100644 --- a/core/java/com/android/internal/widget/EditableInputConnection.java +++ b/core/java/com/android/internal/widget/EditableInputConnection.java @@ -16,6 +16,7 @@ package com.android.internal.widget; +import android.annotation.UnsupportedAppUsage; import android.os.Bundle; import android.text.Editable; import android.text.Spanned; @@ -41,6 +42,7 @@ public class EditableInputConnection extends BaseInputConnection { // A negative value means that this connection has been finished by the InputMethodManager. private int mBatchEditNesting; + @UnsupportedAppUsage public EditableInputConnection(TextView textview) { super(textview, true); mTextView = textview; diff --git a/core/java/com/android/internal/widget/LinearLayoutWithDefaultTouchRecepient.java b/core/java/com/android/internal/widget/LinearLayoutWithDefaultTouchRecepient.java index b2001cbe15ef..cc7911da0b96 100644 --- a/core/java/com/android/internal/widget/LinearLayoutWithDefaultTouchRecepient.java +++ b/core/java/com/android/internal/widget/LinearLayoutWithDefaultTouchRecepient.java @@ -16,6 +16,7 @@ package com.android.internal.widget; +import android.annotation.UnsupportedAppUsage; import android.content.Context; import android.graphics.Rect; import android.util.AttributeSet; @@ -36,6 +37,7 @@ public class LinearLayoutWithDefaultTouchRecepient extends LinearLayout { private final Rect mTempRect = new Rect(); private View mDefaultTouchRecepient; + @UnsupportedAppUsage public LinearLayoutWithDefaultTouchRecepient(Context context) { super(context); } @@ -44,6 +46,7 @@ public class LinearLayoutWithDefaultTouchRecepient extends LinearLayout { super(context, attrs); } + @UnsupportedAppUsage public void setDefaultTouchRecepient(View defaultTouchRecepient) { mDefaultTouchRecepient = defaultTouchRecepient; } diff --git a/core/java/com/android/internal/widget/LockPatternChecker.java b/core/java/com/android/internal/widget/LockPatternChecker.java index 586ece0a274a..2a485f129ab8 100644 --- a/core/java/com/android/internal/widget/LockPatternChecker.java +++ b/core/java/com/android/internal/widget/LockPatternChecker.java @@ -1,5 +1,6 @@ package com.android.internal.widget; +import android.annotation.UnsupportedAppUsage; import android.os.AsyncTask; import com.android.internal.widget.LockPatternUtils.RequestThrottledException; @@ -223,6 +224,7 @@ public final class LockPatternChecker { * @param userId The user to check against the pattern. * @param callback The callback to be invoked with the check result. */ + @UnsupportedAppUsage public static AsyncTask<?, ?, ?> checkPassword(final LockPatternUtils utils, final String password, final int userId, diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index 8eae8afe2407..a3bfd021ca87 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -27,6 +27,7 @@ import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED import android.annotation.IntDef; import android.annotation.Nullable; +import android.annotation.UnsupportedAppUsage; import android.app.admin.DevicePolicyManager; import android.app.admin.PasswordMetrics; import android.app.trust.IStrongAuthTracker; @@ -169,7 +170,9 @@ public class LockPatternUtils { public static final String SYNTHETIC_PASSWORD_ENABLED_KEY = "enable-sp"; private static final String HISTORY_DELIMITER = ","; + @UnsupportedAppUsage private final Context mContext; + @UnsupportedAppUsage private final ContentResolver mContentResolver; private DevicePolicyManager mDevicePolicyManager; private ILockSettings mLockSettingsService; @@ -212,6 +215,7 @@ public class LockPatternUtils { public static final class RequestThrottledException extends Exception { private int mTimeoutMs; + @UnsupportedAppUsage public RequestThrottledException(int timeoutMs) { mTimeoutMs = timeoutMs; } @@ -220,12 +224,14 @@ public class LockPatternUtils { * @return The amount of time in ms before another request may * be executed */ + @UnsupportedAppUsage public int getTimeoutMs() { return mTimeoutMs; } } + @UnsupportedAppUsage public DevicePolicyManager getDevicePolicyManager() { if (mDevicePolicyManager == null) { mDevicePolicyManager = @@ -254,6 +260,7 @@ public class LockPatternUtils { return trust; } + @UnsupportedAppUsage public LockPatternUtils(Context context) { mContext = context; mContentResolver = context.getContentResolver(); @@ -262,6 +269,7 @@ public class LockPatternUtils { mHandler = looper != null ? new Handler(looper) : null; } + @UnsupportedAppUsage @VisibleForTesting public ILockSettings getLockSettings() { if (mLockSettingsService == null) { @@ -312,6 +320,7 @@ public class LockPatternUtils { return getDevicePolicyManager().getPasswordMinimumNonLetter(null, userId); } + @UnsupportedAppUsage public void reportFailedPasswordAttempt(int userId) { if (userId == USER_FRP && frpCredentialEnabled(mContext)) { return; @@ -320,6 +329,7 @@ public class LockPatternUtils { getTrustManager().reportUnlockAttempt(false /* authenticated */, userId); } + @UnsupportedAppUsage public void reportSuccessfulPasswordAttempt(int userId) { if (userId == USER_FRP && frpCredentialEnabled(mContext)) { return; @@ -479,6 +489,7 @@ public class LockPatternUtils { * @param password The password to check. * @return Whether the password matches the stored one. */ + @UnsupportedAppUsage public boolean checkPassword(String password, int userId) throws RequestThrottledException { return checkPassword(password, userId, null /* progressCallback */); } @@ -602,6 +613,7 @@ public class LockPatternUtils { * Used by device policy manager to validate the current password * information it has. */ + @UnsupportedAppUsage public int getActivePasswordQuality(int userId) { int quality = getKeyguardStoredPasswordQuality(userId); @@ -672,6 +684,7 @@ public class LockPatternUtils { * * @return true if lock screen is disabled */ + @UnsupportedAppUsage public boolean isLockScreenDisabled(int userId) { if (isSecure(userId)) { return false; @@ -754,16 +767,19 @@ public class LockPatternUtils { } } + @UnsupportedAppUsage public void setOwnerInfo(String info, int userId) { setString(LOCK_SCREEN_OWNER_INFO, info, userId); updateCryptoUserInfo(userId); } + @UnsupportedAppUsage public void setOwnerInfoEnabled(boolean enabled, int userId) { setBoolean(LOCK_SCREEN_OWNER_INFO_ENABLED, enabled, userId); updateCryptoUserInfo(userId); } + @UnsupportedAppUsage public String getOwnerInfo(int userId) { return getString(LOCK_SCREEN_OWNER_INFO, userId); } @@ -829,6 +845,7 @@ public class LockPatternUtils { * @param requestedQuality {@see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)} * @param userHandle The userId of the user to change the password for */ + @UnsupportedAppUsage public void saveLockPassword(String password, String savedPassword, int requestedQuality, int userHandle) { if (password == null || password.length() < MIN_LOCK_PASSWORD_SIZE) { @@ -926,6 +943,7 @@ public class LockPatternUtils { * encrypted with the default password. * @return true if device encryption is enabled */ + @UnsupportedAppUsage public static boolean isDeviceEncryptionEnabled() { return StorageManager.isEncrypted(); } @@ -951,6 +969,7 @@ public class LockPatternUtils { * * @return stored password quality */ + @UnsupportedAppUsage public int getKeyguardStoredPasswordQuality(int userHandle) { return (int) getLong(PASSWORD_TYPE_KEY, PASSWORD_QUALITY_UNSPECIFIED, userHandle); } @@ -1072,6 +1091,7 @@ public class LockPatternUtils { * @param pattern The pattern. * @return The pattern in string form. */ + @UnsupportedAppUsage public static String patternToString(List<LockPatternView.Cell> pattern) { if (pattern == null) { return ""; @@ -1107,6 +1127,7 @@ public class LockPatternUtils { * @param pattern the gesture pattern. * @return the hash of the pattern in a byte array. */ + @UnsupportedAppUsage public static byte[] patternToHash(List<LockPatternView.Cell> pattern) { if (pattern == null) { return null; @@ -1193,11 +1214,13 @@ public class LockPatternUtils { * @param userId the user for which to report the value * @return Whether the lock screen is secured. */ + @UnsupportedAppUsage public boolean isSecure(int userId) { int mode = getKeyguardStoredPasswordQuality(userId); return isLockPatternEnabled(mode, userId) || isLockPasswordEnabled(mode, userId); } + @UnsupportedAppUsage public boolean isLockPasswordEnabled(int userId) { return isLockPasswordEnabled(getKeyguardStoredPasswordQuality(userId), userId); } @@ -1215,6 +1238,7 @@ public class LockPatternUtils { /** * @return Whether the lock pattern is enabled */ + @UnsupportedAppUsage public boolean isLockPatternEnabled(int userId) { return isLockPatternEnabled(getKeyguardStoredPasswordQuality(userId), userId); } @@ -1239,6 +1263,7 @@ public class LockPatternUtils { /** * @return Whether the visible pattern is enabled. */ + @UnsupportedAppUsage public boolean isVisiblePatternEnabled(int userId) { return getBoolean(Settings.Secure.LOCK_PATTERN_VISIBLE, false, userId); } @@ -1298,6 +1323,7 @@ public class LockPatternUtils { /** * @return Whether tactile feedback for the pattern is enabled. */ + @UnsupportedAppUsage public boolean isTactileFeedbackEnabled() { return Settings.System.getIntForUser(mContentResolver, Settings.System.HAPTIC_FEEDBACK_ENABLED, 1, UserHandle.USER_CURRENT) != 0; @@ -1308,6 +1334,7 @@ public class LockPatternUtils { * pattern until the deadline has passed. * @return the chosen deadline. */ + @UnsupportedAppUsage public long setLockoutAttemptDeadline(int userId, int timeoutMs) { final long deadline = SystemClock.elapsedRealtime() + timeoutMs; if (userId == USER_FRP) { @@ -1360,6 +1387,7 @@ public class LockPatternUtils { } } + @UnsupportedAppUsage private void setLong(String secureSettingKey, long value, int userHandle) { try { getLockSettings().setLong(secureSettingKey, value, userHandle); @@ -1369,6 +1397,7 @@ public class LockPatternUtils { } } + @UnsupportedAppUsage private String getString(String secureSettingKey, int userHandle) { try { return getLockSettings().getString(secureSettingKey, null, userHandle); @@ -1377,6 +1406,7 @@ public class LockPatternUtils { } } + @UnsupportedAppUsage private void setString(String secureSettingKey, String value, int userHandle) { try { getLockSettings().setString(secureSettingKey, value, userHandle); @@ -1390,6 +1420,7 @@ public class LockPatternUtils { setBoolean(LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS, enabled, userId); } + @UnsupportedAppUsage public boolean getPowerButtonInstantlyLocks(int userId) { return getBoolean(LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS, true, userId); } diff --git a/core/java/com/android/internal/widget/LockPatternView.java b/core/java/com/android/internal/widget/LockPatternView.java index e8fc5989354a..70efd0081fcc 100644 --- a/core/java/com/android/internal/widget/LockPatternView.java +++ b/core/java/com/android/internal/widget/LockPatternView.java @@ -19,6 +19,7 @@ package com.android.internal.widget; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; +import android.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.res.Resources; import android.content.res.TypedArray; @@ -79,7 +80,9 @@ public class LockPatternView extends View { private boolean mDrawingProfilingStarted = false; + @UnsupportedAppUsage private final Paint mPaint = new Paint(); + @UnsupportedAppUsage private final Paint mPathPaint = new Paint(); /** @@ -99,6 +102,7 @@ public class LockPatternView extends View { private static final String TAG = "LockPatternView"; private OnPatternListener mOnPatternListener; + @UnsupportedAppUsage private final ArrayList<Cell> mPattern = new ArrayList<Cell>(9); /** @@ -120,16 +124,21 @@ public class LockPatternView extends View { private long mAnimatingPeriodStart; private long[] mLineFadeStart = new long[9]; + @UnsupportedAppUsage private DisplayMode mPatternDisplayMode = DisplayMode.Correct; private boolean mInputEnabled = true; + @UnsupportedAppUsage private boolean mInStealthMode = false; private boolean mEnableHapticFeedback = true; + @UnsupportedAppUsage private boolean mPatternInProgress = false; private boolean mFadePattern = true; private float mHitFactor = 0.6f; + @UnsupportedAppUsage private float mSquareWidth; + @UnsupportedAppUsage private float mSquareHeight; private final Path mCurrentPath = new Path(); @@ -154,7 +163,9 @@ public class LockPatternView extends View { * Represents a cell in the 3 X 3 matrix of the unlock pattern view. */ public static final class Cell { + @UnsupportedAppUsage final int row; + @UnsupportedAppUsage final int column; // keep # objects limited to 9 @@ -232,16 +243,19 @@ public class LockPatternView extends View { /** * The pattern drawn is correct (i.e draw it in a friendly color) */ + @UnsupportedAppUsage Correct, /** * Animate the pattern (for demo, and help). */ + @UnsupportedAppUsage Animate, /** * The pattern is wrong (i.e draw a foreboding color) */ + @UnsupportedAppUsage Wrong } @@ -277,6 +291,7 @@ public class LockPatternView extends View { this(context, null); } + @UnsupportedAppUsage public LockPatternView(Context context, AttributeSet attrs) { super(context, attrs); @@ -348,6 +363,7 @@ public class LockPatternView extends View { a.recycle(); } + @UnsupportedAppUsage public CellState[][] getCellStates() { return mCellStates; } @@ -372,6 +388,7 @@ public class LockPatternView extends View { * * @param inStealthMode Whether in stealth mode. */ + @UnsupportedAppUsage public void setInStealthMode(boolean inStealthMode) { mInStealthMode = inStealthMode; } @@ -390,6 +407,7 @@ public class LockPatternView extends View { * * @param tactileFeedbackEnabled Whether tactile feedback is enabled */ + @UnsupportedAppUsage public void setTactileFeedbackEnabled(boolean tactileFeedbackEnabled) { mEnableHapticFeedback = tactileFeedbackEnabled; } @@ -398,6 +416,7 @@ public class LockPatternView extends View { * Set the call back for pattern detection. * @param onPatternListener The call back. */ + @UnsupportedAppUsage public void setOnPatternListener( OnPatternListener onPatternListener) { mOnPatternListener = onPatternListener; @@ -426,6 +445,7 @@ public class LockPatternView extends View { * in progress result to correct or wrong. * @param displayMode The display mode. */ + @UnsupportedAppUsage public void setDisplayMode(DisplayMode displayMode) { mPatternDisplayMode = displayMode; if (displayMode == DisplayMode.Animate) { @@ -565,6 +585,7 @@ public class LockPatternView extends View { } } + @UnsupportedAppUsage private void notifyPatternDetected() { sendAccessEvent(R.string.lockscreen_access_pattern_detected); if (mOnPatternListener != null) { @@ -582,6 +603,7 @@ public class LockPatternView extends View { /** * Clear the pattern. */ + @UnsupportedAppUsage public void clearPattern() { resetPattern(); } @@ -622,6 +644,7 @@ public class LockPatternView extends View { * Disable input (for instance when displaying a message that will * timeout so user doesn't get view into messy state). */ + @UnsupportedAppUsage public void disableInput() { mInputEnabled = false; } @@ -629,6 +652,7 @@ public class LockPatternView extends View { /** * Enable input. */ + @UnsupportedAppUsage public void enableInput() { mInputEnabled = true; } @@ -1307,6 +1331,7 @@ public class LockPatternView extends View { /** * Constructor called from {@link LockPatternView#onSaveInstanceState()} */ + @UnsupportedAppUsage private SavedState(Parcelable superState, String serializedPattern, int displayMode, boolean inputEnabled, boolean inStealthMode, boolean tactileFeedbackEnabled) { super(superState); @@ -1320,6 +1345,7 @@ public class LockPatternView extends View { /** * Constructor called from {@link #CREATOR} */ + @UnsupportedAppUsage private SavedState(Parcel in) { super(in); mSerializedPattern = in.readString(); diff --git a/core/java/com/android/internal/widget/PointerLocationView.java b/core/java/com/android/internal/widget/PointerLocationView.java index 5847033feb1e..65e10029f37e 100644 --- a/core/java/com/android/internal/widget/PointerLocationView.java +++ b/core/java/com/android/internal/widget/PointerLocationView.java @@ -16,6 +16,7 @@ package com.android.internal.widget; +import android.annotation.UnsupportedAppUsage; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; @@ -53,6 +54,7 @@ public class PointerLocationView extends View implements InputDeviceListener, private int mTraceCount; // True if the pointer is down. + @UnsupportedAppUsage private boolean mCurDown; // Most recent coordinates. @@ -120,10 +122,14 @@ public class PointerLocationView extends View implements InputDeviceListener, private final Paint mPathPaint; private final FontMetricsInt mTextMetrics = new FontMetricsInt(); private int mHeaderBottom; + @UnsupportedAppUsage private boolean mCurDown; + @UnsupportedAppUsage private int mCurNumPointers; + @UnsupportedAppUsage private int mMaxNumPointers; private int mActivePointerId; + @UnsupportedAppUsage private final ArrayList<PointerState> mPointers = new ArrayList<PointerState>(); private final PointerCoords mTempCoords = new PointerCoords(); @@ -132,6 +138,7 @@ public class PointerLocationView extends View implements InputDeviceListener, private final FasterStringBuilder mText = new FasterStringBuilder(); + @UnsupportedAppUsage private boolean mPrintCoords = true; public PointerLocationView(Context c) { diff --git a/core/java/com/android/internal/widget/PreferenceImageView.java b/core/java/com/android/internal/widget/PreferenceImageView.java index 8730cdab258b..02a0b8d436b9 100644 --- a/core/java/com/android/internal/widget/PreferenceImageView.java +++ b/core/java/com/android/internal/widget/PreferenceImageView.java @@ -16,6 +16,7 @@ package com.android.internal.widget; +import android.annotation.UnsupportedAppUsage; import android.content.Context; import android.util.AttributeSet; import android.widget.ImageView; @@ -29,6 +30,7 @@ public class PreferenceImageView extends ImageView { this(context, null); } + @UnsupportedAppUsage public PreferenceImageView(Context context, AttributeSet attrs) { this(context, attrs, 0); } diff --git a/core/java/com/android/internal/widget/RecyclerView.java b/core/java/com/android/internal/widget/RecyclerView.java index 408a4e9b02a4..b66a7b44f05d 100644 --- a/core/java/com/android/internal/widget/RecyclerView.java +++ b/core/java/com/android/internal/widget/RecyclerView.java @@ -20,6 +20,7 @@ import android.annotation.CallSuper; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.res.TypedArray; import android.database.Observable; @@ -4953,6 +4954,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * constructed by {@link GapWorker} prefetch from being bound to a lower priority prefetch. */ static class ScrapData { + @UnsupportedAppUsage ArrayList<ViewHolder> mScrapHeap = new ArrayList<>(); int mMaxScrap = DEFAULT_MAX_SCRAP; long mCreateRunningAverageNs = 0; diff --git a/core/java/com/android/internal/widget/ScrollBarUtils.java b/core/java/com/android/internal/widget/ScrollBarUtils.java index 0ae9f74167d5..982e3152fc7c 100644 --- a/core/java/com/android/internal/widget/ScrollBarUtils.java +++ b/core/java/com/android/internal/widget/ScrollBarUtils.java @@ -16,8 +16,11 @@ package com.android.internal.widget; +import android.annotation.UnsupportedAppUsage; + public class ScrollBarUtils { + @UnsupportedAppUsage public static int getThumbLength(int size, int thickness, int extent, int range) { // Avoid the tiny thumb. final int minLength = thickness * 2; diff --git a/core/java/com/android/internal/widget/SlidingTab.java b/core/java/com/android/internal/widget/SlidingTab.java index 79adada9cc98..4b5d62467af0 100644 --- a/core/java/com/android/internal/widget/SlidingTab.java +++ b/core/java/com/android/internal/widget/SlidingTab.java @@ -16,6 +16,7 @@ package com.android.internal.widget; +import android.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.res.Resources; import android.content.res.TypedArray; @@ -83,7 +84,9 @@ public class SlidingTab extends ViewGroup { */ private final int mOrientation; + @UnsupportedAppUsage private final Slider mLeftSlider; + @UnsupportedAppUsage private final Slider mRightSlider; private Slider mCurrentSlider; private boolean mTracking; @@ -95,6 +98,7 @@ public class SlidingTab extends ViewGroup { /** * Listener used to reset the view when the current animation completes. */ + @UnsupportedAppUsage private final AnimationListener mAnimationDoneListener = new AnimationListener() { public void onAnimationStart(Animation animation) { @@ -178,7 +182,9 @@ public class SlidingTab extends ViewGroup { private static final int STATE_PRESSED = 1; private static final int STATE_ACTIVE = 2; + @UnsupportedAppUsage private final ImageView tab; + @UnsupportedAppUsage private final TextView text; private final ImageView target; private int currentState = STATE_NORMAL; @@ -708,6 +714,7 @@ public class SlidingTab extends ViewGroup { slider.startAnimation(trans1, trans2); } + @UnsupportedAppUsage private void onAnimationDone() { resetView(); mAnimating = false; @@ -722,6 +729,7 @@ public class SlidingTab extends ViewGroup { return mOrientation == HORIZONTAL; } + @UnsupportedAppUsage private void resetView() { mLeftSlider.reset(false); mRightSlider.reset(false); @@ -763,6 +771,7 @@ public class SlidingTab extends ViewGroup { * @param barId the resource of the bar drawable (stateful) * @param tabId the resource of the */ + @UnsupportedAppUsage public void setLeftTabResources(int iconId, int targetId, int barId, int tabId) { mLeftSlider.setIcon(iconId); mLeftSlider.setTarget(targetId); @@ -776,6 +785,7 @@ public class SlidingTab extends ViewGroup { * * @param resId */ + @UnsupportedAppUsage public void setLeftHintText(int resId) { if (isHorizontal()) { mLeftSlider.setHintText(resId); @@ -793,6 +803,7 @@ public class SlidingTab extends ViewGroup { * @param barId the resource of the bar drawable (stateful) * @param tabId the resource of the */ + @UnsupportedAppUsage public void setRightTabResources(int iconId, int targetId, int barId, int tabId) { mRightSlider.setIcon(iconId); mRightSlider.setTarget(targetId); @@ -806,12 +817,14 @@ public class SlidingTab extends ViewGroup { * * @param resId */ + @UnsupportedAppUsage public void setRightHintText(int resId) { if (isHorizontal()) { mRightSlider.setHintText(resId); } } + @UnsupportedAppUsage public void setHoldAfterTrigger(boolean holdLeft, boolean holdRight) { mHoldLeftOnTransition = holdLeft; mHoldRightOnTransition = holdRight; @@ -838,6 +851,7 @@ public class SlidingTab extends ViewGroup { * * @param listener the OnDialTriggerListener to attach to this view */ + @UnsupportedAppUsage public void setOnTriggerListener(OnTriggerListener listener) { mOnTriggerListener = listener; } diff --git a/core/java/com/android/internal/widget/TextViewInputDisabler.java b/core/java/com/android/internal/widget/TextViewInputDisabler.java index fb0b3b95b6f2..8d8f0fe52d64 100644 --- a/core/java/com/android/internal/widget/TextViewInputDisabler.java +++ b/core/java/com/android/internal/widget/TextViewInputDisabler.java @@ -16,6 +16,7 @@ package com.android.internal.widget; +import android.annotation.UnsupportedAppUsage; import android.text.InputFilter; import android.text.Spanned; import android.widget.TextView; @@ -38,11 +39,13 @@ public class TextViewInputDisabler { } }; + @UnsupportedAppUsage public TextViewInputDisabler(TextView textView) { mTextView = textView; mDefaultFilters = mTextView.getFilters(); } + @UnsupportedAppUsage public void setInputEnabled(boolean enabled) { mTextView.setFilters(enabled ? mDefaultFilters : mNoInputFilters); } diff --git a/core/java/com/android/internal/widget/ViewPager.java b/core/java/com/android/internal/widget/ViewPager.java index 64bdc6e1eb37..574a09f8d3af 100644 --- a/core/java/com/android/internal/widget/ViewPager.java +++ b/core/java/com/android/internal/widget/ViewPager.java @@ -18,6 +18,7 @@ package com.android.internal.widget; import android.annotation.DrawableRes; import android.annotation.NonNull; +import android.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.res.Resources; import android.content.res.TypedArray; @@ -243,6 +244,7 @@ public class ViewPager extends ViewGroup { * @param positionOffset Value from [0, 1) indicating the offset from the page at position. * @param positionOffsetPixels Value in pixels indicating the offset from position. */ + @UnsupportedAppUsage public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels); /** @@ -251,6 +253,7 @@ public class ViewPager extends ViewGroup { * * @param position Position index of the new selected page. */ + @UnsupportedAppUsage public void onPageSelected(int position); /** @@ -263,6 +266,7 @@ public class ViewPager extends ViewGroup { * @see com.android.internal.widget.ViewPager#SCROLL_STATE_DRAGGING * @see com.android.internal.widget.ViewPager#SCROLL_STATE_SETTLING */ + @UnsupportedAppUsage public void onPageScrollStateChanged(int state); } @@ -483,6 +487,7 @@ public class ViewPager extends ViewGroup { setCurrentItemInternal(item, smoothScroll, false); } + @UnsupportedAppUsage public int getCurrentItem() { return mCurItem; } diff --git a/core/java/com/android/server/ResettableTimeout.java b/core/java/com/android/server/ResettableTimeout.java index ac5b160670b0..64083f72aff5 100644 --- a/core/java/com/android/server/ResettableTimeout.java +++ b/core/java/com/android/server/ResettableTimeout.java @@ -18,6 +18,7 @@ package com.android.server; import android.os.SystemClock; +import android.annotation.UnsupportedAppUsage; import android.os.ConditionVariable; /** @@ -120,9 +121,11 @@ abstract class ResettableTimeout } } + @UnsupportedAppUsage private ConditionVariable mLock = new ConditionVariable(); // turn it off at this time. + @UnsupportedAppUsage private volatile long mOffAt; private volatile boolean mOffCalled; diff --git a/core/java/com/android/server/net/BaseNetworkObserver.java b/core/java/com/android/server/net/BaseNetworkObserver.java index 3d9fb5c872f7..a0740eee5df6 100644 --- a/core/java/com/android/server/net/BaseNetworkObserver.java +++ b/core/java/com/android/server/net/BaseNetworkObserver.java @@ -16,6 +16,7 @@ package com.android.server.net; +import android.annotation.UnsupportedAppUsage; import android.net.INetworkManagementEventObserver; import android.net.LinkAddress; import android.net.RouteInfo; diff --git a/core/java/com/android/server/net/NetlinkTracker.java b/core/java/com/android/server/net/NetlinkTracker.java index 5b421d988e0a..647fb5b9d079 100644 --- a/core/java/com/android/server/net/NetlinkTracker.java +++ b/core/java/com/android/server/net/NetlinkTracker.java @@ -16,6 +16,7 @@ package com.android.server.net; +import android.annotation.UnsupportedAppUsage; import android.net.LinkAddress; import android.net.LinkProperties; import android.net.RouteInfo; @@ -79,6 +80,7 @@ public class NetlinkTracker extends BaseNetworkObserver { private static final boolean DBG = false; + @UnsupportedAppUsage public NetlinkTracker(String iface, Callback callback) { TAG = "NetlinkTracker/" + iface; mInterfaceName = iface; @@ -187,10 +189,12 @@ public class NetlinkTracker extends BaseNetworkObserver { /** * Returns a copy of this object's LinkProperties. */ + @UnsupportedAppUsage public synchronized LinkProperties getLinkProperties() { return new LinkProperties(mLinkProperties); } + @UnsupportedAppUsage public synchronized void clearLinkProperties() { // Clear the repository before clearing mLinkProperties. That way, if a clear() happens // while interfaceDnsServerInfo() is being called, we'll end up with no DNS servers in diff --git a/core/java/com/google/android/collect/Lists.java b/core/java/com/google/android/collect/Lists.java index 3ea873bbb0f9..8f6594aefb0a 100644 --- a/core/java/com/google/android/collect/Lists.java +++ b/core/java/com/google/android/collect/Lists.java @@ -57,6 +57,7 @@ public class Lists { * @param elements the elements that the list should contain, in order * @return a newly-created {@code ArrayList} containing those elements */ + @UnsupportedAppUsage public static <E> ArrayList<E> newArrayList(E... elements) { int capacity = (elements.length * 110) / 100 + 5; ArrayList<E> list = new ArrayList<E>(capacity); diff --git a/core/java/com/google/android/collect/Sets.java b/core/java/com/google/android/collect/Sets.java index dd3cab15d0b2..09b5e51ae2c6 100644 --- a/core/java/com/google/android/collect/Sets.java +++ b/core/java/com/google/android/collect/Sets.java @@ -16,6 +16,7 @@ package com.google.android.collect; +import android.annotation.UnsupportedAppUsage; import android.util.ArraySet; import java.util.Collections; @@ -42,6 +43,7 @@ public class Sets { * * @return a newly-created, initially-empty {@code HashSet} */ + @UnsupportedAppUsage public static <K> HashSet<K> newHashSet() { return new HashSet<K>(); } @@ -63,6 +65,7 @@ public class Sets { * @return a newly-created {@code HashSet} containing those elements (minus * duplicates) */ + @UnsupportedAppUsage public static <E> HashSet<E> newHashSet(E... elements) { int capacity = elements.length * 4 / 3 + 1; HashSet<E> set = new HashSet<E>(capacity); @@ -75,6 +78,7 @@ public class Sets { * * @return a newly-created, initially-empty {@code SortedSet}. */ + @UnsupportedAppUsage public static <E> SortedSet<E> newSortedSet() { return new TreeSet<E>(); } @@ -95,6 +99,7 @@ public class Sets { /** * Creates a {@code ArraySet} instance. */ + @UnsupportedAppUsage public static <E> ArraySet<E> newArraySet() { return new ArraySet<E>(); } @@ -102,6 +107,7 @@ public class Sets { /** * Creates a {@code ArraySet} instance containing the given elements. */ + @UnsupportedAppUsage public static <E> ArraySet<E> newArraySet(E... elements) { int capacity = elements.length * 4 / 3 + 1; ArraySet<E> set = new ArraySet<E>(capacity); diff --git a/core/java/com/google/android/util/AbstractMessageParser.java b/core/java/com/google/android/util/AbstractMessageParser.java index 1871682ee063..9d12f82aeb75 100644 --- a/core/java/com/google/android/util/AbstractMessageParser.java +++ b/core/java/com/google/android/util/AbstractMessageParser.java @@ -16,6 +16,7 @@ package com.google.android.util; +import android.annotation.UnsupportedAppUsage; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; @@ -654,15 +655,25 @@ public abstract class AbstractMessageParser { public static abstract class Token { public enum Type { + @UnsupportedAppUsage HTML ("html"), + @UnsupportedAppUsage FORMAT ("format"), // subtype of HTML + @UnsupportedAppUsage LINK ("l"), + @UnsupportedAppUsage SMILEY ("e"), + @UnsupportedAppUsage ACRONYM ("a"), + @UnsupportedAppUsage MUSIC ("m"), + @UnsupportedAppUsage GOOGLE_VIDEO ("v"), + @UnsupportedAppUsage YOUTUBE_VIDEO ("yt"), + @UnsupportedAppUsage PHOTO ("p"), + @UnsupportedAppUsage FLICKR ("f"); //stringreps for HTML and FORMAT don't really matter diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp index d7a981ed3e9d..82acf6fb432b 100644 --- a/core/jni/android_net_NetUtils.cpp +++ b/core/jni/android_net_NetUtils.cpp @@ -470,6 +470,7 @@ static jbyteArray android_net_utils_resNetworkResult(JNIEnv *env, jobject thiz, std::vector<uint8_t> buf(MAXPACKETSIZE, 0); int res = resNetworkResult(fd, &rcode, buf.data(), MAXPACKETSIZE); + jniSetFileDescriptorOfFD(env, javaFd, -1); if (res < 0) { throwErrnoException(env, "resNetworkResult", -res); return nullptr; @@ -490,6 +491,7 @@ static jbyteArray android_net_utils_resNetworkResult(JNIEnv *env, jobject thiz, static void android_net_utils_resNetworkCancel(JNIEnv *env, jobject thiz, jobject javaFd) { int fd = jniGetFDFromFileDescriptor(env, javaFd); resNetworkCancel(fd); + jniSetFileDescriptorOfFD(env, javaFd, -1); } static jobject android_net_utils_getTcpRepairWindow(JNIEnv *env, jobject thiz, jobject javaFd) { diff --git a/core/proto/android/stats/connectivity/Android.bp b/core/proto/android/stats/connectivity/Android.bp new file mode 100644 index 000000000000..5aa4ddbdf7f9 --- /dev/null +++ b/core/proto/android/stats/connectivity/Android.bp @@ -0,0 +1,25 @@ +// Copyright (C) 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +java_library_static { + name: "networkstackprotosnano", + proto: { + type: "nano", + }, + srcs: [ + "network_stack.proto", + ], + sdk_version: "system_current", + no_framework_libs: true, +}
\ No newline at end of file diff --git a/services/net/java/android/net/ApfCapabilitiesParcelable.aidl b/core/proto/android/stats/connectivity/network_stack.proto index f0645d2782d2..7d9aa1c6eb23 100644 --- a/services/net/java/android/net/ApfCapabilitiesParcelable.aidl +++ b/core/proto/android/stats/connectivity/network_stack.proto @@ -14,10 +14,13 @@ * limitations under the License. */ -package android.net; +syntax = "proto2"; + +package android.stats.connectivity; +option java_multiple_files = true; +option java_outer_classname = "NetworkStackProto"; + +message NetworkStackEventData { + +} -parcelable ApfCapabilitiesParcelable { - int apfVersionSupported; - int maximumApfProgramSize; - int apfPacketFormat; -}
\ No newline at end of file diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index e62df2a189a7..9aedb7618142 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -608,6 +608,9 @@ <protected-broadcast android:name="android.provider.action.DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL" /> + <!-- For tether entitlement recheck--> + <protected-broadcast + android:name="com.android.server.connectivity.tethering.PROVISIONING_RECHECK_ALARM" /> <!-- ====================================================================== --> <!-- RUNTIME PERMISSIONS --> <!-- ====================================================================== --> @@ -1009,6 +1012,18 @@ android:description="@string/permdesc_manageOwnCalls" android:protectionLevel="normal" /> + <!--Allows an app which implements the + {@link android.telecom.InCallService} API to be eligible to be enabled as a calling companion app. This + means that the Telecom framework will bind to the app's InCallService implementation when + there are calls active. The app can use the InCallService API to view information about + calls on the system and control these calls. + <p>Protection level: normal + --> + <permission android:name="android.permission.CALL_COMPANION_APP" + android:label="@string/permlab_callCompanionApp" + android:description="@string/permdesc_callCompanionApp" + android:protectionLevel="normal" /> + <!-- Allows a calling app to continue a call which was started in another app. An example is a video calling app that wants to continue a voice call on the user's mobile network.<p> When the handover of a call from one app to another takes place, there are two devices diff --git a/core/res/res/drawable/ic_bluetooth_share_icon.xml b/core/res/res/drawable/ic_bluetooth_share_icon.xml new file mode 100644 index 000000000000..2446402be93f --- /dev/null +++ b/core/res/res/drawable/ic_bluetooth_share_icon.xml @@ -0,0 +1,27 @@ +<!-- + 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. +--> +<!-- This drawable should only be used by the Bluetooth application for its share target icon. --> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24" + android:tint="@android:color/accent_device_default"> + + <path + android:fillColor="@android:color/white" + android:pathData="M17.71,7.71L12,2h-1v7.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L11,14.41V22h1l5.71-5.71L13.41,12L17.71,7.71z M13,5.83 l1.88,1.88L13,9.59V5.83z M14.88,16.29L13,18.17v-3.76L14.88,16.29z" /> +</vector>
\ No newline at end of file diff --git a/core/res/res/values-night/colors_device_defaults.xml b/core/res/res/values-night/colors_device_defaults.xml new file mode 100644 index 000000000000..08ad4926197b --- /dev/null +++ b/core/res/res/values-night/colors_device_defaults.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2019 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<resources> + <color name="accent_device_default">@color/accent_device_default_dark</color> +</resources>
\ No newline at end of file diff --git a/core/res/res/values/colors_device_defaults.xml b/core/res/res/values/colors_device_defaults.xml index 256c53133096..212e1cc55137 100644 --- a/core/res/res/values/colors_device_defaults.xml +++ b/core/res/res/values/colors_device_defaults.xml @@ -35,6 +35,7 @@ <color name="accent_device_default_light">@color/accent_material_light</color> <color name="accent_device_default_dark">@color/accent_material_dark</color> + <color name="accent_device_default">@color/accent_device_default_light</color> <color name="background_device_default_dark">@color/background_material_dark</color> <color name="background_device_default_light">@color/background_material_light</color> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 97ae8e5215fe..7698d271cfac 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -302,6 +302,15 @@ Settings.Global.NETWORK_AVOID_BAD_WIFI. This is the default value of that setting. --> <integer translatable="false" name="config_networkAvoidBadWifi">1</integer> + <!-- The URL returned by ConnectivityManager#getCaptivePortalServerUrl. The actual returned + value is controlled by Settings.Global.CAPTIVE_PORTAL_HTTP_URL. This is the default value + used if that setting is unset. + This is *NOT* a URL that will always be used by the system network validation to detect + captive portals: NetworkMonitor may use different strategies and will not necessarily use + this URL. NetworkMonitor behaviour should be configured with NetworkStack resource overlays + instead. --> + <string translatable="false" name="config_networkDefaultCaptivePortalServerUrl">http://connectivitycheck.gstatic.com/generate_204</string> + <!-- If the hardware supports specially marking packets that caused a wakeup of the main CPU, set this value to the mark used. --> <integer name="config_networkWakeupPacketMark">0</integer> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 75aa60f1242a..4f6775b99e10 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -1185,6 +1185,15 @@ <string name="permdesc_manageOwnCalls">Allows the app to route its calls through the system in order to improve the calling experience.</string> + <!-- Title of an application permission. When granted the app is allowed to be enabled as + a companion app. [CHAR LIMIT=NONE]--> + <string name="permlab_callCompanionApp">see and control calls through the system.</string> + <!-- Description of an application permission. When granted the app is allowed to be enabled as + a companion app. [CHAR LIMIT=NONE]--> + <string name="permdesc_callCompanionApp">Allows the app to see and control ongoing calls on the + device. This includes information such as call numbers for calls and the state of the + calls.</string> + <!-- Title of an application permission. When granted the user is giving access to a third party app to continue a call which originated in another app. For example, the user could be in a voice call over their carrier's mobile network, and a third party video diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index a95fa540e33a..05303c96ea80 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1945,6 +1945,7 @@ <java-symbol type="integer" name="config_networkNotifySwitchType" /> <java-symbol type="array" name="config_networkNotifySwitches" /> <java-symbol type="integer" name="config_networkAvoidBadWifi" /> + <java-symbol type="string" name="config_networkDefaultCaptivePortalServerUrl" /> <java-symbol type="integer" name="config_networkWakeupPacketMark" /> <java-symbol type="integer" name="config_networkWakeupPacketMask" /> <java-symbol type="bool" name="config_apfDrop802_3Frames" /> diff --git a/core/tests/benchmarks/src/android/net/NetworkStatsBenchmark.java b/core/tests/benchmarks/src/android/net/NetworkStatsBenchmark.java index 1b6560322a13..707d7b30e09b 100644 --- a/core/tests/benchmarks/src/android/net/NetworkStatsBenchmark.java +++ b/core/tests/benchmarks/src/android/net/NetworkStatsBenchmark.java @@ -19,13 +19,22 @@ package android.net; import com.google.caliper.BeforeExperiment; import com.google.caliper.Param; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + public class NetworkStatsBenchmark { - private static final String UNDERLYING_IFACE = "wlan0"; + private static final String[] UNDERLYING_IFACES = {"wlan0", "rmnet0"}; private static final String TUN_IFACE = "tun0"; private static final int TUN_UID = 999999999; @Param({"100", "1000"}) private int mSize; + /** + * Should not be more than the length of {@link #UNDERLYING_IFACES}. + */ + @Param({"1", "2"}) + private int mNumUnderlyingIfaces; private NetworkStats mNetworkStats; @BeforeExperiment @@ -33,8 +42,10 @@ public class NetworkStatsBenchmark { mNetworkStats = new NetworkStats(0, mSize + 2); int uid = 0; NetworkStats.Entry recycle = new NetworkStats.Entry(); + final List<String> allIfaces = getAllIfacesForBenchmark(); // also contains TUN_IFACE. + final int totalIfaces = allIfaces.size(); for (int i = 0; i < mSize; i++) { - recycle.iface = (i < mSize / 2) ? TUN_IFACE : UNDERLYING_IFACE; + recycle.iface = allIfaces.get(i % totalIfaces); recycle.uid = uid; recycle.set = i % 2; recycle.tag = NetworkStats.TAG_NONE; @@ -48,22 +59,39 @@ public class NetworkStatsBenchmark { uid++; } } - recycle.iface = UNDERLYING_IFACE; - recycle.uid = TUN_UID; - recycle.set = NetworkStats.SET_FOREGROUND; - recycle.tag = NetworkStats.TAG_NONE; - recycle.rxBytes = 90000 * mSize; - recycle.rxPackets = 40 * mSize; - recycle.txBytes = 180000 * mSize; - recycle.txPackets = 1200 * mSize; - recycle.operations = 0; - mNetworkStats.addValues(recycle); + + for (int i = 0; i < mNumUnderlyingIfaces; i++) { + recycle.iface = UNDERLYING_IFACES[i]; + recycle.uid = TUN_UID; + recycle.set = NetworkStats.SET_FOREGROUND; + recycle.tag = NetworkStats.TAG_NONE; + recycle.rxBytes = 90000 * mSize; + recycle.rxPackets = 40 * mSize; + recycle.txBytes = 180000 * mSize; + recycle.txPackets = 1200 * mSize; + recycle.operations = 0; + mNetworkStats.addValues(recycle); + } + } + + private String[] getVpnUnderlyingIfaces() { + return Arrays.copyOf(UNDERLYING_IFACES, mNumUnderlyingIfaces); + } + + /** + * Same as {@link #getVpnUnderlyingIfaces}, but also contains {@link #TUN_IFACE}. + */ + private List<String> getAllIfacesForBenchmark() { + List<String> ifaces = new ArrayList<>(); + ifaces.add(TUN_IFACE); + ifaces.addAll(Arrays.asList(getVpnUnderlyingIfaces())); + return ifaces; } public void timeMigrateTun(int reps) { for (int i = 0; i < reps; i++) { NetworkStats stats = mNetworkStats.clone(); - stats.migrateTun(TUN_UID, TUN_IFACE, UNDERLYING_IFACE); + stats.migrateTun(TUN_UID, TUN_IFACE, getVpnUnderlyingIfaces()); } } diff --git a/core/tests/coretests/src/android/app/servertransaction/ClientTransactionTests.java b/core/tests/coretests/src/android/app/servertransaction/ClientTransactionTests.java index b1f855246320..c59098795faf 100644 --- a/core/tests/coretests/src/android/app/servertransaction/ClientTransactionTests.java +++ b/core/tests/coretests/src/android/app/servertransaction/ClientTransactionTests.java @@ -29,6 +29,15 @@ import android.support.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; +/** + * Tests for {@link ClientTransaction}. + * + * <p>Build/Install/Run: + * atest FrameworksCoreTests:ClientTransactionTests + * + * <p>This test class is a part of Window Manager Service tests and specified in + * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}. + */ @RunWith(AndroidJUnit4.class) @SmallTest @Presubmit diff --git a/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java b/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java index fb0f5344f643..32e5f008c729 100644 --- a/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java +++ b/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java @@ -41,6 +41,15 @@ import android.support.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; +/** + * Tests for {@link ObjectPool}. + * + * <p>Build/Install/Run: + * atest FrameworksCoreTests:ObjectPoolTests + * + * <p>This test class is a part of Window Manager Service tests and specified in + * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}. + */ @RunWith(AndroidJUnit4.class) @SmallTest @Presubmit diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java index fe58116002f2..6620a2e86272 100644 --- a/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java +++ b/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java @@ -26,9 +26,8 @@ import static android.app.servertransaction.ActivityLifecycleItem.ON_STOP; import static android.app.servertransaction.ActivityLifecycleItem.PRE_ON_CREATE; import static android.app.servertransaction.ActivityLifecycleItem.UNDEFINED; -import static junit.framework.Assert.assertEquals; - import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.inOrder; @@ -58,7 +57,15 @@ import java.util.Collections; import java.util.List; import java.util.stream.Collectors; -/** Test {@link TransactionExecutor} logic. */ +/** + * Test {@link TransactionExecutor} logic. + * + * <p>Build/Install/Run: + * atest FrameworksCoreTests:TransactionExecutorTests + * + * <p>This test class is a part of Window Manager Service tests and specified in + * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}. + */ @RunWith(AndroidJUnit4.class) @SmallTest @Presubmit diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java index 104208eefef7..d922c16a9297 100644 --- a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java +++ b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java @@ -21,8 +21,8 @@ import static android.app.servertransaction.TestUtils.mergedConfig; import static android.app.servertransaction.TestUtils.referrerIntentList; import static android.app.servertransaction.TestUtils.resultInfoList; -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertTrue; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import android.app.IApplicationThread; import android.app.IInstrumentationWatcher; @@ -60,7 +60,15 @@ import org.junit.runner.RunWith; import java.util.List; import java.util.Map; -/** Test parcelling and unparcelling of transactions and transaction items. */ +/** + * Test parcelling and unparcelling of transactions and transaction items. + * + * <p>Build/Install/Run: + * atest FrameworksCoreTests:TransactionParcelTests + * + * <p>This test class is a part of Window Manager Service tests and specified in + * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}. + */ @RunWith(AndroidJUnit4.class) @SmallTest @Presubmit diff --git a/core/tests/coretests/src/android/view/DisplayCutoutTest.java b/core/tests/coretests/src/android/view/DisplayCutoutTest.java index fe45fe7d3aaf..a3df1a094ec0 100644 --- a/core/tests/coretests/src/android/view/DisplayCutoutTest.java +++ b/core/tests/coretests/src/android/view/DisplayCutoutTest.java @@ -40,6 +40,15 @@ import org.junit.runner.RunWith; import java.util.Arrays; +/** + * Tests for {@link DisplayCutout}. + * + * <p>Build/Install/Run: + * atest FrameworksCoreTests:DisplayCutoutTest + * + * <p>This test class is a part of Window Manager Service tests and specified in + * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}. + */ @RunWith(AndroidJUnit4.class) @SmallTest @Presubmit diff --git a/core/tests/coretests/src/com/android/server/wm/test/filters/CoreTestsFilter.java b/core/tests/coretests/src/com/android/server/wm/test/filters/CoreTestsFilter.java deleted file mode 100644 index 941cfdb20fed..000000000000 --- a/core/tests/coretests/src/com/android/server/wm/test/filters/CoreTestsFilter.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.wm.test.filters; - -import android.os.Bundle; - -import com.android.test.filters.SelectTest; - -/** - * JUnit test filter that select Window Manager Service related tests from FrameworksCoreTests. - * - * <p>Use this filter when running FrameworksCoreTests as - * <pre> - * adb shell am instrument -w \ - * -e filter com.android.server.wm.test.filters.CoreTestsFilter \ - * -e selectTest_verbose true \ - * com.android.frameworks.coretests/androidx.test.runner.AndroidJUnitRunner - * </pre> - */ -public final class CoreTestsFilter extends SelectTest { - - private static final String[] SELECTED_CORE_TESTS = { - "android.app.servertransaction.", // all tests under the package. - "android.view.DisplayCutoutTest", - }; - - public CoreTestsFilter(Bundle testArgs) { - super(addSelectTest(testArgs, SELECTED_CORE_TESTS)); - } -} diff --git a/core/xsd/Android.bp b/core/xsd/Android.bp index 81669eb290db..738f33076ac9 100644 --- a/core/xsd/Android.bp +++ b/core/xsd/Android.bp @@ -2,5 +2,5 @@ xsd_config { name: "permission", srcs: ["permission.xsd"], api_dir: "schema", - package_name: "com.android.xml.permission", + package_name: "com.android.xml.permission.configfile", } diff --git a/core/xsd/permission.xsd b/core/xsd/permission.xsd index d90863b2c716..2ef2d04d3b34 100644 --- a/core/xsd/permission.xsd +++ b/core/xsd/permission.xsd @@ -60,8 +60,6 @@ <xs:attribute name="uid" type="xs:int"/> </xs:complexType> <xs:complexType name="split-permission"> - <xs:attribute name="name" type="xs:string"/> - <xs:attribute name="targetSdk" type="xs:int"/> <xs:sequence> <xs:element name="library" maxOccurs="unbounded"> <xs:complexType> @@ -69,6 +67,8 @@ </xs:complexType> </xs:element> </xs:sequence> + <xs:attribute name="name" type="xs:string"/> + <xs:attribute name="targetSdk" type="xs:int"/> </xs:complexType> <xs:complexType name="library"> <xs:attribute name="name" type="xs:string"/> @@ -78,6 +78,7 @@ <xs:complexType name="feature"> <xs:attribute name="name" type="xs:string"/> <xs:attribute name="notLowRam" type="xs:string"/> + <xs:attribute name="version" type="xs:int"/> </xs:complexType> <xs:complexType name="unavailable-feature"> <xs:attribute name="name" type="xs:string"/> @@ -124,7 +125,6 @@ <xs:attribute name="package" type="xs:string"/> </xs:complexType> <xs:complexType name="privapp-permissions"> - <xs:attribute name="package" type="xs:string"/> <xs:sequence> <xs:element name="permission" maxOccurs="unbounded"> <xs:complexType> @@ -137,9 +137,9 @@ </xs:complexType> </xs:element> </xs:sequence> + <xs:attribute name="package" type="xs:string"/> </xs:complexType> <xs:complexType name="oem-permissions"> - <xs:attribute name="package" type="xs:string"/> <xs:sequence> <xs:element name="permission" maxOccurs="unbounded"> <xs:complexType> @@ -152,6 +152,7 @@ </xs:complexType> </xs:element> </xs:sequence> + <xs:attribute name="package" type="xs:string"/> </xs:complexType> <xs:complexType name="hidden-api-whitelisted-app"> <xs:attribute name="package" type="xs:string"/> diff --git a/core/xsd/schema/current.txt b/core/xsd/schema/current.txt index 82bb0feac089..c25bc146045b 100644 --- a/core/xsd/schema/current.txt +++ b/core/xsd/schema/current.txt @@ -1,5 +1,5 @@ // Signature format: 2.0 -package com.android.xml.permission { +package com.android.xml.permission.configfile { public class AllowAssociation { ctor public AllowAssociation(); @@ -97,8 +97,10 @@ package com.android.xml.permission { ctor public Feature(); method public String getName(); method public String getNotLowRam(); + method public int getVersion(); method public void setName(String); method public void setNotLowRam(String); + method public void setVersion(int); } public class Group { @@ -125,8 +127,8 @@ package com.android.xml.permission { public class OemPermissions { ctor public OemPermissions(); - method public java.util.List<com.android.xml.permission.OemPermissions.DenyPermission> getDenyPermission(); - method public java.util.List<com.android.xml.permission.OemPermissions.Permission> getPermission(); + method public java.util.List<com.android.xml.permission.configfile.OemPermissions.DenyPermission> getDenyPermission(); + method public java.util.List<com.android.xml.permission.configfile.OemPermissions.Permission> getPermission(); method public String get_package(); method public void set_package(String); } @@ -151,37 +153,37 @@ package com.android.xml.permission { public class Permissions { ctor public Permissions(); - method public java.util.List<com.android.xml.permission.AllowAssociation> getAllowAssociation(); - method public java.util.List<com.android.xml.permission.AllowIgnoreLocationSettings> getAllowIgnoreLocationSettings(); - method public java.util.List<com.android.xml.permission.AllowImplicitBroadcast> getAllowImplicitBroadcast(); - method public java.util.List<com.android.xml.permission.AllowInDataUsageSave> getAllowInDataUsageSave(); - method public java.util.List<com.android.xml.permission.AllowInPowerSave> getAllowInPowerSave(); - method public java.util.List<com.android.xml.permission.AllowInPowerSaveExceptIdle> getAllowInPowerSaveExceptIdle(); - method public java.util.List<com.android.xml.permission.AllowUnthrottledLocation> getAllowUnthrottledLocation(); - method public java.util.List<com.android.xml.permission.AppLink> getAppLink(); - method public java.util.List<com.android.xml.permission.AssignPermission> getAssignPermission(); - method public java.util.List<com.android.xml.permission.BackupTransportWhitelistedService> getBackupTransportWhitelistedService(); - method public java.util.List<com.android.xml.permission.BugreportWhitelisted> getBugreportWhitelisted(); - method public java.util.List<com.android.xml.permission.DefaultEnabledVrApp> getDefaultEnabledVrApp(); - method public java.util.List<com.android.xml.permission.DisabledUntilUsedPreinstalledCarrierApp> getDisabledUntilUsedPreinstalledCarrierApp(); - method public java.util.List<com.android.xml.permission.DisabledUntilUsedPreinstalledCarrierAssociatedApp> getDisabledUntilUsedPreinstalledCarrierAssociatedApp(); - method public java.util.List<com.android.xml.permission.Feature> getFeature(); - method public java.util.List<com.android.xml.permission.Group> getGroup(); - method public java.util.List<com.android.xml.permission.HiddenApiWhitelistedApp> getHiddenApiWhitelistedApp(); - method public java.util.List<com.android.xml.permission.Library> getLibrary(); - method public java.util.List<com.android.xml.permission.OemPermissions> getOemPermissions(); - method public java.util.List<com.android.xml.permission.Permission> getPermission(); - method public java.util.List<com.android.xml.permission.PrivappPermissions> getPrivappPermissions(); - method public java.util.List<com.android.xml.permission.SplitPermission> getSplitPermission(); - method public java.util.List<com.android.xml.permission.SystemUserBlacklistedApp> getSystemUserBlacklistedApp(); - method public java.util.List<com.android.xml.permission.SystemUserWhitelistedApp> getSystemUserWhitelistedApp(); - method public java.util.List<com.android.xml.permission.UnavailableFeature> getUnavailableFeature(); + method public java.util.List<com.android.xml.permission.configfile.AllowAssociation> getAllowAssociation(); + method public java.util.List<com.android.xml.permission.configfile.AllowIgnoreLocationSettings> getAllowIgnoreLocationSettings(); + method public java.util.List<com.android.xml.permission.configfile.AllowImplicitBroadcast> getAllowImplicitBroadcast(); + method public java.util.List<com.android.xml.permission.configfile.AllowInDataUsageSave> getAllowInDataUsageSave(); + method public java.util.List<com.android.xml.permission.configfile.AllowInPowerSave> getAllowInPowerSave(); + method public java.util.List<com.android.xml.permission.configfile.AllowInPowerSaveExceptIdle> getAllowInPowerSaveExceptIdle(); + method public java.util.List<com.android.xml.permission.configfile.AllowUnthrottledLocation> getAllowUnthrottledLocation(); + method public java.util.List<com.android.xml.permission.configfile.AppLink> getAppLink(); + method public java.util.List<com.android.xml.permission.configfile.AssignPermission> getAssignPermission(); + method public java.util.List<com.android.xml.permission.configfile.BackupTransportWhitelistedService> getBackupTransportWhitelistedService(); + method public java.util.List<com.android.xml.permission.configfile.BugreportWhitelisted> getBugreportWhitelisted(); + method public java.util.List<com.android.xml.permission.configfile.DefaultEnabledVrApp> getDefaultEnabledVrApp(); + method public java.util.List<com.android.xml.permission.configfile.DisabledUntilUsedPreinstalledCarrierApp> getDisabledUntilUsedPreinstalledCarrierApp(); + method public java.util.List<com.android.xml.permission.configfile.DisabledUntilUsedPreinstalledCarrierAssociatedApp> getDisabledUntilUsedPreinstalledCarrierAssociatedApp(); + method public java.util.List<com.android.xml.permission.configfile.Feature> getFeature(); + method public java.util.List<com.android.xml.permission.configfile.Group> getGroup(); + method public java.util.List<com.android.xml.permission.configfile.HiddenApiWhitelistedApp> getHiddenApiWhitelistedApp(); + method public java.util.List<com.android.xml.permission.configfile.Library> getLibrary(); + method public java.util.List<com.android.xml.permission.configfile.OemPermissions> getOemPermissions(); + method public java.util.List<com.android.xml.permission.configfile.Permission> getPermission(); + method public java.util.List<com.android.xml.permission.configfile.PrivappPermissions> getPrivappPermissions(); + method public java.util.List<com.android.xml.permission.configfile.SplitPermission> getSplitPermission(); + method public java.util.List<com.android.xml.permission.configfile.SystemUserBlacklistedApp> getSystemUserBlacklistedApp(); + method public java.util.List<com.android.xml.permission.configfile.SystemUserWhitelistedApp> getSystemUserWhitelistedApp(); + method public java.util.List<com.android.xml.permission.configfile.UnavailableFeature> getUnavailableFeature(); } public class PrivappPermissions { ctor public PrivappPermissions(); - method public java.util.List<com.android.xml.permission.PrivappPermissions.DenyPermission> getDenyPermission(); - method public java.util.List<com.android.xml.permission.PrivappPermissions.Permission> getPermission(); + method public java.util.List<com.android.xml.permission.configfile.PrivappPermissions.DenyPermission> getDenyPermission(); + method public java.util.List<com.android.xml.permission.configfile.PrivappPermissions.Permission> getPermission(); method public String get_package(); method public void set_package(String); } @@ -200,7 +202,7 @@ package com.android.xml.permission { public class SplitPermission { ctor public SplitPermission(); - method public java.util.List<com.android.xml.permission.SplitPermission.Library> getLibrary(); + method public java.util.List<com.android.xml.permission.configfile.SplitPermission.Library> getLibrary(); method public String getName(); method public int getTargetSdk(); method public void setName(String); @@ -233,7 +235,7 @@ package com.android.xml.permission { public class XmlParser { ctor public XmlParser(); - method public static com.android.xml.permission.Permissions read(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException; + method public static com.android.xml.permission.configfile.Permissions read(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException; method public static String readText(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; method public static void skip(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; } diff --git a/data/etc/Android.bp b/data/etc/Android.bp index bb4765835890..3968f84471c5 100644 --- a/data/etc/Android.bp +++ b/data/etc/Android.bp @@ -66,6 +66,14 @@ prebuilt_etc { } prebuilt_etc { + name: "privapp_whitelist_com.android.emergency", + product_specific: true, + sub_dir: "permissions", + src: "com.android.emergency.xml", + filename_from_src: true, +} + +prebuilt_etc { name: "privapp_whitelist_com.android.launcher3", product_specific: true, sub_dir: "permissions", diff --git a/data/etc/com.android.emergency.xml b/data/etc/com.android.emergency.xml new file mode 100644 index 000000000000..28f99dd1d018 --- /dev/null +++ b/data/etc/com.android.emergency.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2019 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> +<permissions> + <privapp-permissions package="com.android.emergency"> + <!-- Required to place emergency calls from emergency info screen. --> + <permission name="android.permission.CALL_PRIVILEGED"/> + <permission name="android.permission.MANAGE_USERS"/> + </privapp-permissions> +</permissions> diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml index 78bbcf137f2a..d44f5a934280 100644 --- a/data/etc/privapp-permissions-platform.xml +++ b/data/etc/privapp-permissions-platform.xml @@ -48,12 +48,6 @@ applications that come with the platform <permission name="android.permission.WRITE_MEDIA_STORAGE"/> </privapp-permissions> - <privapp-permissions package="com.android.emergency"> - <!-- Required to place emergency calls from emergency info screen. --> - <permission name="android.permission.CALL_PRIVILEGED"/> - <permission name="android.permission.MANAGE_USERS"/> - </privapp-permissions> - <privapp-permissions package="com.android.externalstorage"> <permission name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <permission name="android.permission.WRITE_MEDIA_STORAGE"/> @@ -268,6 +262,8 @@ applications that come with the platform <permission name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <permission name="android.permission.MOVE_PACKAGE"/> <permission name="android.permission.PACKAGE_USAGE_STATS" /> + <!-- Needed for test only --> + <permission name="android.permission.PACKET_KEEPALIVE_OFFLOAD" /> <permission name="android.permission.READ_FRAME_BUFFER"/> <permission name="android.permission.READ_LOWPAN_CREDENTIAL"/> <!-- Needed for test only --> diff --git a/media/java/android/media/projection/OWNERS b/media/java/android/media/projection/OWNERS new file mode 100644 index 000000000000..7e7335d68d3b --- /dev/null +++ b/media/java/android/media/projection/OWNERS @@ -0,0 +1 @@ +michaelwr@google.com diff --git a/packages/ExternalStorageProvider/Android.bp b/packages/ExternalStorageProvider/Android.bp new file mode 100644 index 000000000000..973fef3e666d --- /dev/null +++ b/packages/ExternalStorageProvider/Android.bp @@ -0,0 +1,19 @@ +android_app { + name: "ExternalStorageProvider", + + manifest: "AndroidManifest.xml", + + resource_dirs: [ + "res", + ], + + srcs: [ + "src/**/*.java", + ], + + platform_apis: true, + + certificate: "platform", + + privileged: true, +} diff --git a/packages/ExternalStorageProvider/Android.mk b/packages/ExternalStorageProvider/Android.mk deleted file mode 100644 index 9e99313cd03a..000000000000 --- a/packages/ExternalStorageProvider/Android.mk +++ /dev/null @@ -1,13 +0,0 @@ -LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_MODULE_TAGS := optional - -LOCAL_SRC_FILES := $(call all-subdir-java-files) - -LOCAL_PACKAGE_NAME := ExternalStorageProvider -LOCAL_PRIVATE_PLATFORM_APIS := true -LOCAL_CERTIFICATE := platform -LOCAL_PRIVILEGED_MODULE := true - -include $(BUILD_PACKAGE) diff --git a/packages/ExternalStorageProvider/tests/Android.bp b/packages/ExternalStorageProvider/tests/Android.bp new file mode 100644 index 000000000000..83427d4ebf00 --- /dev/null +++ b/packages/ExternalStorageProvider/tests/Android.bp @@ -0,0 +1,25 @@ +android_test { + name: "ExternalStorageProviderTests", + + manifest: "AndroidManifest.xml", + + srcs: [ + "src/**/*.java", + ], + + libs: [ + "android.test.base", + "android.test.mock", + "android.test.runner", + ], + + static_libs: [ + "android-support-test", + "mockito-target", + "truth-prebuilt", + ], + + certificate: "platform", + + instrumentation_for: "ExternalStorageProvider", +} diff --git a/packages/ExternalStorageProvider/tests/AndroidManifest.xml b/packages/ExternalStorageProvider/tests/AndroidManifest.xml new file mode 100644 index 000000000000..58b6e86dfc77 --- /dev/null +++ b/packages/ExternalStorageProvider/tests/AndroidManifest.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.externalstorage.tests"> + + <application android:label="ExternalStorageProvider Tests"> + <uses-library android:name="android.test.runner" /> + </application> + + <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner" + android:targetPackage="com.android.externalstorage" + android:label="ExternalStorageProvider Tests" /> +</manifest> + diff --git a/packages/ExternalStorageProvider/tests/AndroidTest.xml b/packages/ExternalStorageProvider/tests/AndroidTest.xml new file mode 100644 index 000000000000..e5fa73f59836 --- /dev/null +++ b/packages/ExternalStorageProvider/tests/AndroidTest.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2018 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<configuration description="Runs Tests for ExternalStorageProvider."> + <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup"> + <option name="test-file-name" value="ExternalStorageProviderTests.apk" /> + </target_preparer> + + <option name="test-suite-tag" value="apct" /> + <option name="test-suite-tag" value="framework-base-presubmit" /> + <option name="test-tag" value="ExternalStorageProviderTests" /> + <test class="com.android.tradefed.testtype.AndroidJUnitTest" > + <option name="package" value="com.android.externalstorage.tests" /> + <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" /> + <option name="hidden-api-checks" value="false"/> + </test> +</configuration> diff --git a/packages/ExternalStorageProvider/tests/src/com/android/externalstorage/ExternalStorageProviderTest.java b/packages/ExternalStorageProvider/tests/src/com/android/externalstorage/ExternalStorageProviderTest.java new file mode 100644 index 000000000000..a88b3e146ea1 --- /dev/null +++ b/packages/ExternalStorageProvider/tests/src/com/android/externalstorage/ExternalStorageProviderTest.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.externalstorage; + +import static com.android.externalstorage.ExternalStorageProvider.AUTHORITY; + +import static org.mockito.Mockito.atLeast; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; + +import android.content.pm.ProviderInfo; +import android.support.test.InstrumentationRegistry; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +public class ExternalStorageProviderTest { + @Test + public void onCreate_shouldUpdateVolumes() throws Exception { + ExternalStorageProvider externalStorageProvider = new ExternalStorageProvider(); + ExternalStorageProvider spyProvider = spy(externalStorageProvider); + ProviderInfo providerInfo = new ProviderInfo(); + providerInfo.authority = AUTHORITY; + providerInfo.grantUriPermissions = true; + providerInfo.exported = true; + + InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() { + @Override + public void run() { + spyProvider.attachInfoForTesting( + InstrumentationRegistry.getTargetContext(), providerInfo); + } + }); + + verify(spyProvider, atLeast(1)).updateVolumes(); + } +} diff --git a/packages/NetworkStack/Android.bp b/packages/NetworkStack/Android.bp index 8872147b65ed..0bd5c5f59133 100644 --- a/packages/NetworkStack/Android.bp +++ b/packages/NetworkStack/Android.bp @@ -14,11 +14,16 @@ // limitations under the License. // +java_defaults { + name: "NetworkStackCommon", + sdk_version: "system_current", + min_sdk_version: "28", +} + // Library including the network stack, used to compile both variants of the network stack android_library { name: "NetworkStackBase", - sdk_version: "system_current", - min_sdk_version: "28", + defaults: ["NetworkStackCommon"], srcs: [ "src/**/*.java", ":framework-networkstack-shared-srcs", @@ -29,38 +34,40 @@ android_library { "netd_aidl_interface-java", "networkstack-aidl-interfaces-java", "datastallprotosnano", + "networkstackprotosnano", ], manifest: "AndroidManifestBase.xml", } -// Non-updatable in-process network stack for devices not using the module -android_app { - name: "InProcessNetworkStack", - sdk_version: "system_current", - min_sdk_version: "28", - certificate: "platform", +java_defaults { + name: "NetworkStackAppCommon", + defaults: ["NetworkStackCommon"], privileged: true, static_libs: [ "NetworkStackBase", ], + // Resources already included in NetworkStackBase + resource_dirs: [], jarjar_rules: "jarjar-rules-shared.txt", + optimize: { + proguard_flags_files: ["proguard.flags"], + }, // The permission configuration *must* be included to ensure security of the device required: ["NetworkStackPermissionStub"], +} + +// Non-updatable network stack running in the system server process for devices not using the module +android_app { + name: "InProcessNetworkStack", + defaults: ["NetworkStackAppCommon"], + certificate: "platform", manifest: "AndroidManifest_InProcess.xml", } // Updatable network stack packaged as an application android_app { name: "NetworkStack", - sdk_version: "system_current", - min_sdk_version: "28", + defaults: ["NetworkStackAppCommon"], certificate: "networkstack", - privileged: true, - static_libs: [ - "NetworkStackBase" - ], - jarjar_rules: "jarjar-rules-shared.txt", - // The permission configuration *must* be included to ensure security of the device - required: ["NetworkStackPermissionStub"], manifest: "AndroidManifest.xml", } diff --git a/packages/NetworkStack/proguard.flags b/packages/NetworkStack/proguard.flags new file mode 100644 index 000000000000..c60f6c338d83 --- /dev/null +++ b/packages/NetworkStack/proguard.flags @@ -0,0 +1,9 @@ +-keepclassmembers class android.net.ip.IpClient { + static final int CMD_*; + static final int EVENT_*; +} + +-keepclassmembers class android.net.dhcp.DhcpClient { + static final int CMD_*; + static final int EVENT_*; +} diff --git a/packages/NetworkStack/res/values/config.xml b/packages/NetworkStack/res/values/config.xml new file mode 100644 index 000000000000..52425e57ba3a --- /dev/null +++ b/packages/NetworkStack/res/values/config.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Captive portal http url --> + <string name="config_captive_portal_http_url" translatable="false">http://connectivitycheck.gstatic.com/generate_204</string> +</resources>
\ No newline at end of file diff --git a/packages/NetworkStack/src/android/net/apf/ApfFilter.java b/packages/NetworkStack/src/android/net/apf/ApfFilter.java index 3dd90eeff767..d2f32591cbbe 100644 --- a/packages/NetworkStack/src/android/net/apf/ApfFilter.java +++ b/packages/NetworkStack/src/android/net/apf/ApfFilter.java @@ -74,6 +74,7 @@ import java.net.SocketException; import java.net.UnknownHostException; import java.nio.BufferUnderflowException; import java.nio.ByteBuffer; +import java.nio.ByteOrder; import java.util.ArrayList; import java.util.Arrays; @@ -282,6 +283,7 @@ public class ApfFilter { private static final byte[] ETH_BROADCAST_MAC_ADDRESS = {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff }; // TODO: Make these offsets relative to end of link-layer header; don't include ETH_HEADER_LEN. + private static final int IPV4_TOTAL_LENGTH_OFFSET = ETH_HEADER_LEN + 2; private static final int IPV4_FRAGMENT_OFFSET_OFFSET = ETH_HEADER_LEN + 6; // Endianness is not an issue for this constant because the APF interpreter always operates in // network byte order. @@ -881,10 +883,23 @@ public class ApfFilter { protected final TcpKeepaliveAckData mPacket; protected final byte[] mSrcDstAddr; + protected final byte[] mPortSeqAckFingerprint; TcpKeepaliveAck(final TcpKeepaliveAckData packet, final byte[] srcDstAddr) { mPacket = packet; mSrcDstAddr = srcDstAddr; + mPortSeqAckFingerprint = generatePortSeqAckFingerprint(mPacket.srcPort, + mPacket.dstPort, mPacket.seq, mPacket.ack); + } + + static byte[] generatePortSeqAckFingerprint(int srcPort, int dstPort, int seq, int ack) { + final ByteBuffer fp = ByteBuffer.allocate(12); + fp.order(ByteOrder.BIG_ENDIAN); + fp.putShort((short) srcPort); + fp.putShort((short) dstPort); + fp.putInt(seq); + fp.putInt(ack); + return fp.array(); } static byte[] concatArrays(final byte[]... arr) { @@ -919,10 +934,6 @@ public class ApfFilter { private class TcpKeepaliveAckV4 extends TcpKeepaliveAck { private static final int IPV4_SRC_ADDR_OFFSET = IP_HEADER_OFFSET + 12; - private static final int IPV4_TCP_SRC_PORT_OFFSET = 0; - private static final int IPV4_TCP_DST_PORT_OFFSET = 2; - private static final int IPV4_TCP_SEQ_OFFSET = 4; - private static final int IPV4_TCP_ACK_OFFSET = 8; TcpKeepaliveAckV4(final TcpKeepalivePacketDataParcelable sentKeepalivePacket) { this(new TcpKeepaliveAckData(sentKeepalivePacket)); @@ -934,12 +945,12 @@ public class ApfFilter { @Override void generateFilterLocked(ApfGenerator gen) throws IllegalInstructionException { final String nextFilterLabel = "keepalive_ack" + getUniqueNumberLocked(); - gen.addLoad8(Register.R0, IPV4_PROTOCOL_OFFSET); - gen.addJumpIfR0NotEquals(IPPROTO_TCP, nextFilterLabel); + gen.addLoadImmediate(Register.R0, ETH_HEADER_LEN + IPV4_SRC_ADDR_OFFSET); gen.addJumpIfBytesNotEqual(Register.R0, mSrcDstAddr, nextFilterLabel); - // Pass the packet if it's not zero-sized : + // Skip to the next filter if it's not zero-sized : + // TCP_HEADER_SIZE + IPV4_HEADER_SIZE - ipv4_total_length == 0 // Load the IP header size into R1 gen.addLoadFromMemory(Register.R1, gen.IPV4_HEADER_SIZE_MEMORY_SLOT); // Load the TCP header size into R0 (it's indexed by R1) @@ -947,27 +958,18 @@ public class ApfFilter { // Size offset is in the top nibble, but it must be multiplied by 4, and the two // top bits of the low nibble are guaranteed to be zeroes. Right-shift R0 by 2. gen.addRightShift(2); - // R0 += R1 -> R0 contains TCP + IP headers lenght - gen.addAddR1(); - // Add the Ethernet header length to R0. - gen.addLoadImmediate(Register.R1, ETH_HEADER_LEN); + // R0 += R1 -> R0 contains TCP + IP headers length gen.addAddR1(); - // Compare total length of headers to the size of the packet. - gen.addLoadFromMemory(Register.R1, gen.PACKET_SIZE_MEMORY_SLOT); + // Load IPv4 total length + gen.addLoad16(Register.R1, IPV4_TOTAL_LENGTH_OFFSET); gen.addNeg(Register.R0); gen.addAddR1(); gen.addJumpIfR0NotEquals(0, nextFilterLabel); - // Add IPv4 header length gen.addLoadFromMemory(Register.R1, gen.IPV4_HEADER_SIZE_MEMORY_SLOT); - gen.addLoad16Indexed(Register.R0, ETH_HEADER_LEN + IPV4_TCP_SRC_PORT_OFFSET); - gen.addJumpIfR0NotEquals(mPacket.srcPort, nextFilterLabel); - gen.addLoad16Indexed(Register.R0, ETH_HEADER_LEN + IPV4_TCP_DST_PORT_OFFSET); - gen.addJumpIfR0NotEquals(mPacket.dstPort, nextFilterLabel); - gen.addLoad32Indexed(Register.R0, ETH_HEADER_LEN + IPV4_TCP_SEQ_OFFSET); - gen.addJumpIfR0NotEquals(mPacket.seq, nextFilterLabel); - gen.addLoad32Indexed(Register.R0, ETH_HEADER_LEN + IPV4_TCP_ACK_OFFSET); - gen.addJumpIfR0NotEquals(mPacket.ack, nextFilterLabel); + gen.addLoadImmediate(Register.R0, ETH_HEADER_LEN); + gen.addAddR1(); + gen.addJumpIfBytesNotEqual(Register.R0, mPortSeqAckFingerprint, nextFilterLabel); maybeSetupCounter(gen, Counter.DROPPED_IPV4_KEEPALIVE_ACK); gen.addJump(mCountAndDropLabel); @@ -1169,9 +1171,10 @@ public class ApfFilter { gen.addJumpIfR0Equals(broadcastAddr, mCountAndDropLabel); } - // If any keepalive filters, - generateKeepaliveFilter(gen); + // If any keepalive filter matches, drop + generateV4KeepaliveFilters(gen); + // Otherwise, this is an IPv4 unicast, pass // If L2 broadcast packet, drop. // TODO: can we invert this condition to fall through to the common pass case below? maybeSetupCounter(gen, Counter.PASSED_IPV4_UNICAST); @@ -1180,7 +1183,7 @@ public class ApfFilter { maybeSetupCounter(gen, Counter.DROPPED_IPV4_L2_BROADCAST); gen.addJump(mCountAndDropLabel); } else { - generateKeepaliveFilter(gen); + generateV4KeepaliveFilters(gen); } // Otherwise, pass @@ -1188,12 +1191,25 @@ public class ApfFilter { gen.addJump(mCountAndPassLabel); } - private void generateKeepaliveFilter(ApfGenerator gen) throws IllegalInstructionException { + private void generateV4KeepaliveFilters(ApfGenerator gen) throws IllegalInstructionException { + final String skipV4KeepaliveFilter = "skip_v4_keepalive_filter"; + final boolean haveV4KeepaliveAcks = NetworkStackUtils.any(mKeepaliveAcks, + ack -> ack instanceof TcpKeepaliveAckV4); + + // If no keepalive acks + if (!haveV4KeepaliveAcks) return; + + // If not tcp, skip keepalive filters + gen.addLoad8(Register.R0, IPV4_PROTOCOL_OFFSET); + gen.addJumpIfR0NotEquals(IPPROTO_TCP, skipV4KeepaliveFilter); + // Drop IPv4 Keepalive acks for (int i = 0; i < mKeepaliveAcks.size(); ++i) { final TcpKeepaliveAck ack = mKeepaliveAcks.valueAt(i); if (ack instanceof TcpKeepaliveAckV4) ack.generateFilterLocked(gen); } + + gen.defineLabel(skipV4KeepaliveFilter); } /** @@ -1244,11 +1260,14 @@ public class ApfFilter { maybeSetupCounter(gen, Counter.DROPPED_IPV6_NON_ICMP_MULTICAST); gen.addLoad8(Register.R0, IPV6_DEST_ADDR_OFFSET); gen.addJumpIfR0Equals(0xff, mCountAndDropLabel); + // If any keepalive filter matches, drop + generateV6KeepaliveFilters(gen); // Not multicast. Pass. maybeSetupCounter(gen, Counter.PASSED_IPV6_UNICAST_NON_ICMP); gen.addJump(mCountAndPassLabel); gen.defineLabel(skipIPv6MulticastFilterLabel); } else { + generateV6KeepaliveFilters(gen); // If not ICMPv6, pass. maybeSetupCounter(gen, Counter.PASSED_IPV6_NON_ICMP); gen.addJumpIfR0NotEquals(IPPROTO_ICMPV6, mCountAndPassLabel); @@ -1272,12 +1291,27 @@ public class ApfFilter { maybeSetupCounter(gen, Counter.DROPPED_IPV6_MULTICAST_NA); gen.addJump(mCountAndDropLabel); gen.defineLabel(skipUnsolicitedMulticastNALabel); + } + + private void generateV6KeepaliveFilters(ApfGenerator gen) throws IllegalInstructionException { + final String skipV6KeepaliveFilter = "skip_v6_keepalive_filter"; + final boolean haveV6KeepaliveAcks = NetworkStackUtils.any(mKeepaliveAcks, + ack -> ack instanceof TcpKeepaliveAckV6); + + // If no keepalive acks + if (!haveV6KeepaliveAcks) return; + + // If not tcp, skip keepalive filters + gen.addLoad8(Register.R0, IPV6_NEXT_HEADER_OFFSET); + gen.addJumpIfR0NotEquals(IPPROTO_TCP, skipV6KeepaliveFilter); // Drop IPv6 Keepalive acks for (int i = 0; i < mKeepaliveAcks.size(); ++i) { final TcpKeepaliveAck ack = mKeepaliveAcks.valueAt(i); if (ack instanceof TcpKeepaliveAckV6) ack.generateFilterLocked(gen); } + + gen.defineLabel(skipV6KeepaliveFilter); } /** @@ -1294,6 +1328,8 @@ public class ApfFilter { * <li>Pass all non-IPv4 and non-IPv6 packets, * <li>Drop IPv6 ICMPv6 NAs to ff02::1. * <li>Drop IPv6 ICMPv6 RSs. + * <li>Filter IPv4 packets (see generateIPv4FilterLocked()) + * <li>Filter IPv6 packets (see generateIPv6FilterLocked()) * <li>Let execution continue off the end of the program for IPv6 ICMPv6 packets. This allows * insertion of RA filters here, or if there aren't any, just passes the packets. * </ul> @@ -1737,7 +1773,7 @@ public class ApfFilter { } pw.decreaseIndent(); - pw.println("Keepalive filter:"); + pw.println("Keepalive filters:"); pw.increaseIndent(); for (int i = 0; i < mKeepaliveAcks.size(); ++i) { final TcpKeepaliveAck keepaliveAck = mKeepaliveAcks.valueAt(i); diff --git a/packages/NetworkStack/src/android/net/apf/ApfGenerator.java b/packages/NetworkStack/src/android/net/apf/ApfGenerator.java index 809327a0b79d..44ce2db8547c 100644 --- a/packages/NetworkStack/src/android/net/apf/ApfGenerator.java +++ b/packages/NetworkStack/src/android/net/apf/ApfGenerator.java @@ -108,7 +108,7 @@ public class ApfGenerator { private String mLabel; // When mOpcode == Opcodes.JNEBS: private byte[] mCompareBytes; - // Offset in bytes from the begining of this program. Set by {@link ApfGenerator#generate}. + // Offset in bytes from the beginning of this program. Set by {@link ApfGenerator#generate}. int offset; Instruction(Opcodes opcode, Register register) { @@ -431,7 +431,7 @@ public class ApfGenerator { /** * Add an instruction to the end of the program to load the byte at offset {@code offset} - * bytes from the begining of the packet into {@code register}. + * bytes from the beginning of the packet into {@code register}. */ public ApfGenerator addLoad8(Register register, int offset) { Instruction instruction = new Instruction(Opcodes.LDB, register); @@ -442,7 +442,7 @@ public class ApfGenerator { /** * Add an instruction to the end of the program to load 16-bits at offset {@code offset} - * bytes from the begining of the packet into {@code register}. + * bytes from the beginning of the packet into {@code register}. */ public ApfGenerator addLoad16(Register register, int offset) { Instruction instruction = new Instruction(Opcodes.LDH, register); @@ -453,7 +453,7 @@ public class ApfGenerator { /** * Add an instruction to the end of the program to load 32-bits at offset {@code offset} - * bytes from the begining of the packet into {@code register}. + * bytes from the beginning of the packet into {@code register}. */ public ApfGenerator addLoad32(Register register, int offset) { Instruction instruction = new Instruction(Opcodes.LDW, register); @@ -464,7 +464,7 @@ public class ApfGenerator { /** * Add an instruction to the end of the program to load a byte from the packet into - * {@code register}. The offset of the loaded byte from the begining of the packet is + * {@code register}. The offset of the loaded byte from the beginning of the packet is * the sum of {@code offset} and the value in register R1. */ public ApfGenerator addLoad8Indexed(Register register, int offset) { diff --git a/packages/NetworkStack/src/android/net/dhcp/DhcpClient.java b/packages/NetworkStack/src/android/net/dhcp/DhcpClient.java index 0b7809e9f614..79d6a554e251 100644 --- a/packages/NetworkStack/src/android/net/dhcp/DhcpClient.java +++ b/packages/NetworkStack/src/android/net/dhcp/DhcpClient.java @@ -102,9 +102,9 @@ public class DhcpClient extends StateMachine { private static final String TAG = "DhcpClient"; private static final boolean DBG = true; - private static final boolean STATE_DBG = false; - private static final boolean MSG_DBG = false; - private static final boolean PACKET_DBG = false; + private static final boolean STATE_DBG = Log.isLoggable(TAG, Log.DEBUG); + private static final boolean MSG_DBG = Log.isLoggable(TAG, Log.DEBUG); + private static final boolean PACKET_DBG = Log.isLoggable(TAG, Log.DEBUG); // Metrics events: must be kept in sync with server-side aggregation code. /** Represents transitions from DhcpInitState to DhcpBoundState */ @@ -126,6 +126,7 @@ public class DhcpClient extends StateMachine { // DhcpClient uses IpClient's handler. private static final int PUBLIC_BASE = IpClient.DHCPCLIENT_CMD_BASE; + // Below constants are picked up by MessageUtils and exempt from ProGuard optimization. /* Commands from controller to start/stop DHCP */ public static final int CMD_START_DHCP = PUBLIC_BASE + 1; public static final int CMD_STOP_DHCP = PUBLIC_BASE + 2; diff --git a/packages/NetworkStack/src/android/net/ip/IpClient.java b/packages/NetworkStack/src/android/net/ip/IpClient.java index 61dc966076a8..7a06af41f951 100644 --- a/packages/NetworkStack/src/android/net/ip/IpClient.java +++ b/packages/NetworkStack/src/android/net/ip/IpClient.java @@ -282,6 +282,7 @@ public class IpClient extends StateMachine { public static final String DUMP_ARG_CONFIRM = "confirm"; + // Below constants are picked up by MessageUtils and exempt from ProGuard optimization. private static final int CMD_TERMINATE_AFTER_STOP = 1; private static final int CMD_STOP = 2; private static final int CMD_START = 3; @@ -897,7 +898,7 @@ public class IpClient extends StateMachine { // accompanying code in IpReachabilityMonitor) is unreachable. final boolean ignoreIPv6ProvisioningLoss = mConfiguration != null && mConfiguration.mUsingMultinetworkPolicyTracker - && mCm.getAvoidBadWifi(); + && mCm.shouldAvoidBadWifi(); // Additionally: // diff --git a/packages/NetworkStack/src/android/net/ip/IpReachabilityMonitor.java b/packages/NetworkStack/src/android/net/ip/IpReachabilityMonitor.java index e73cba626f15..c19a24eb7fb6 100644 --- a/packages/NetworkStack/src/android/net/ip/IpReachabilityMonitor.java +++ b/packages/NetworkStack/src/android/net/ip/IpReachabilityMonitor.java @@ -129,8 +129,8 @@ import java.util.Map; */ public class IpReachabilityMonitor { private static final String TAG = "IpReachabilityMonitor"; - private static final boolean DBG = false; - private static final boolean VDBG = false; + private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG); + private static final boolean VDBG = Log.isLoggable(TAG, Log.VERBOSE); public interface Callback { // This callback function must execute as quickly as possible as it is @@ -332,7 +332,7 @@ public class IpReachabilityMonitor { } private boolean avoidingBadLinks() { - return !mUsingMultinetworkPolicyTracker || mCm.getAvoidBadWifi(); + return !mUsingMultinetworkPolicyTracker || mCm.shouldAvoidBadWifi(); } public void probeAll() { diff --git a/packages/NetworkStack/src/android/net/util/NetworkStackUtils.java b/packages/NetworkStack/src/android/net/util/NetworkStackUtils.java index 481dbdadbac0..fedb8d110197 100644 --- a/packages/NetworkStack/src/android/net/util/NetworkStackUtils.java +++ b/packages/NetworkStack/src/android/net/util/NetworkStackUtils.java @@ -17,10 +17,13 @@ package android.net.util; import android.annotation.NonNull; +import android.util.SparseArray; import java.io.FileDescriptor; import java.io.IOException; import java.util.List; +import java.util.function.Predicate; + /** * Collection of utilities for the network stack. @@ -65,4 +68,17 @@ public class NetworkStackUtils { } return array; } + + /** + * @return True if there exists at least one element in the sparse array for which + * condition {@code predicate} + */ + public static <T> boolean any(SparseArray<T> array, Predicate<T> predicate) { + for (int i = 0; i < array.size(); ++i) { + if (predicate.test(array.valueAt(i))) { + return true; + } + } + return false; + } } diff --git a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java index 73b203c3df49..f3476ed1566f 100644 --- a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java +++ b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java @@ -83,6 +83,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.RingBufferIndices; import com.android.internal.util.State; import com.android.internal.util.StateMachine; +import com.android.networkstack.R; import java.io.IOException; import java.net.HttpURLConnection; @@ -1710,9 +1711,15 @@ public class NetworkMonitor extends StateMachine { /** * Get the captive portal server HTTP URL that is configured on the device. + * + * NetworkMonitor does not use {@link ConnectivityManager#getCaptivePortalServerUrl()} as + * it has its own updatable strategies to detect captive portals. The framework only advises + * on one URL that can be used, while NetworkMonitor may implement more complex logic. */ public String getCaptivePortalServerHttpUrl(Context context) { - return NetworkMonitorUtils.getCaptivePortalServerHttpUrl(context); + final String defaultUrl = + context.getResources().getString(R.string.config_captive_portal_http_url); + return NetworkMonitorUtils.getCaptivePortalServerHttpUrl(context, defaultUrl); } /** diff --git a/packages/NetworkStack/tests/src/android/net/apf/ApfTest.java b/packages/NetworkStack/tests/src/android/net/apf/ApfTest.java index 88a05d506aa4..a0e508f130a5 100644 --- a/packages/NetworkStack/tests/src/android/net/apf/ApfTest.java +++ b/packages/NetworkStack/tests/src/android/net/apf/ApfTest.java @@ -1006,7 +1006,7 @@ public class ApfTest { private static final int IPV4_HEADER_LEN = 20; private static final int IPV4_VERSION_IHL_OFFSET = ETH_HEADER_LEN + 0; - private static final int IPV4_TOTAL_LENGTH_OFFSET = ETH_HEADER_LEN + 2; + private static final int IPV4_TOTAL_LENGTH_OFFSET = ETH_HEADER_LEN + 2; private static final int IPV4_PROTOCOL_OFFSET = ETH_HEADER_LEN + 9; private static final int IPV4_SRC_ADDR_OFFSET = ETH_HEADER_LEN + 12; private static final int IPV4_DEST_ADDR_OFFSET = ETH_HEADER_LEN + 16; diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index 2687c682b28a..8778e30e0498 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -161,6 +161,8 @@ <!-- Permission needed to run network tests in CTS --> <uses-permission android:name="android.permission.MANAGE_TEST_NETWORKS" /> + <!-- Permission needed to test tcp keepalive offload. --> + <uses-permission android:name="android.permission.PACKET_KEEPALIVE_OFFLOAD" /> <application android:label="@string/app_label" android:defaultToDeviceProtectedStorage="true" diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java index a9ff21fef99c..1060c7b7ce79 100644 --- a/packages/Shell/src/com/android/shell/BugreportProgressService.java +++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java @@ -1095,6 +1095,7 @@ public class BugreportProgressService extends Service { new AsyncTask<Void, Void, Void>() { @Override protected Void doInBackground(Void... params) { + Looper.prepare(); zipBugreport(info); sendBugreportNotification(info, takingScreenshot); return null; diff --git a/packages/Shell/tests/Android.mk b/packages/Shell/tests/Android.mk index b93ddde16e4a..44ff3383d566 100644 --- a/packages/Shell/tests/Android.mk +++ b/packages/Shell/tests/Android.mk @@ -9,7 +9,7 @@ LOCAL_SRC_FILES := $(call all-java-files-under, src) LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base android.test.mock LOCAL_STATIC_JAVA_LIBRARIES := \ - android-support-test \ + androidx.test.rules \ mockito-target-minus-junit4 \ ub-uiautomator \ junit \ diff --git a/packages/Shell/tests/AndroidManifest.xml b/packages/Shell/tests/AndroidManifest.xml index 6d564c640fcd..e845ef95b28e 100644 --- a/packages/Shell/tests/AndroidManifest.xml +++ b/packages/Shell/tests/AndroidManifest.xml @@ -36,7 +36,7 @@ </activity> </application> - <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner" + <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" android:targetPackage="com.android.shell" android:label="Tests for Shell" /> diff --git a/packages/Shell/tests/AndroidTest.xml b/packages/Shell/tests/AndroidTest.xml index e592d82bfaf7..e03b68a03d0e 100644 --- a/packages/Shell/tests/AndroidTest.xml +++ b/packages/Shell/tests/AndroidTest.xml @@ -22,7 +22,7 @@ <option name="test-tag" value="ShellTests" /> <test class="com.android.tradefed.testtype.AndroidJUnitTest" > <option name="package" value="com.android.shell.tests" /> - <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" /> + <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" /> <option name="hidden-api-checks" value="false"/> </test> </configuration> diff --git a/packages/Shell/tests/src/com/android/shell/BugreportProgressServiceTest.java b/packages/Shell/tests/src/com/android/shell/BugreportProgressServiceTest.java index cef74ae39c60..433eca23080e 100644 --- a/packages/Shell/tests/src/com/android/shell/BugreportProgressServiceTest.java +++ b/packages/Shell/tests/src/com/android/shell/BugreportProgressServiceTest.java @@ -20,7 +20,6 @@ import static com.android.shell.BugreportProgressService.findSendToAccount; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNull; -import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.when; @@ -29,12 +28,12 @@ import android.accounts.AccountManager; import android.content.Context; import android.os.UserHandle; import android.os.UserManager; -import android.support.test.filters.SmallTest; -import android.support.test.runner.AndroidJUnit4; import android.test.mock.MockContext; import android.util.Pair; -import org.junit.Before; +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; diff --git a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java index e69b0a81b97e..3a71632cf1ca 100644 --- a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java +++ b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java @@ -42,34 +42,6 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import java.io.BufferedOutputStream; -import java.io.BufferedWriter; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStreamWriter; -import java.io.Writer; -import java.text.NumberFormat; -import java.util.ArrayList; -import java.util.List; -import java.util.SortedSet; -import java.util.TreeSet; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; -import java.util.zip.ZipOutputStream; - -import libcore.io.Streams; - -import org.junit.After; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TestName; -import org.junit.runner.RunWith; - import android.app.ActivityManager; import android.app.ActivityManager.RunningServiceInfo; import android.app.Instrumentation; @@ -82,9 +54,6 @@ import android.os.Bundle; import android.os.SystemClock; import android.os.SystemProperties; import android.service.notification.StatusBarNotification; -import android.support.test.InstrumentationRegistry; -import android.support.test.filters.LargeTest; -import android.support.test.runner.AndroidJUnit4; import android.support.test.uiautomator.UiDevice; import android.support.test.uiautomator.UiObject; import android.support.test.uiautomator.UiObjectNotFoundException; @@ -92,8 +61,39 @@ import android.text.TextUtils; import android.text.format.DateUtils; import android.util.Log; +import androidx.test.InstrumentationRegistry; +import androidx.test.filters.LargeTest; +import androidx.test.runner.AndroidJUnit4; + import com.android.shell.ActionSendMultipleConsumerActivity.CustomActionSendMultipleListener; +import libcore.io.Streams; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestName; +import org.junit.runner.RunWith; + +import java.io.BufferedOutputStream; +import java.io.BufferedWriter; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.text.NumberFormat; +import java.util.ArrayList; +import java.util.List; +import java.util.SortedSet; +import java.util.TreeSet; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; +import java.util.zip.ZipOutputStream; + /** * Integration tests for {@link BugreportReceiver}. * <p> diff --git a/packages/SystemUI/OWNERS b/packages/SystemUI/OWNERS index 3f6ebf0fe09d..99c48cb0eaec 100644 --- a/packages/SystemUI/OWNERS +++ b/packages/SystemUI/OWNERS @@ -20,6 +20,7 @@ juliacr@google.com juliatuttle@google.com kozynski@google.com kprevas@google.com +lynhan@google.com madym@google.com mankoff@google.com nbenbernou@google.com diff --git a/packages/SystemUI/src/com/android/systemui/media/OWNERS b/packages/SystemUI/src/com/android/systemui/media/OWNERS new file mode 100644 index 000000000000..69ea57bfd397 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/media/OWNERS @@ -0,0 +1 @@ +per-file MediaProjectionPermissionActivity.java = michaelwr@google.com diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java index b83fa6252a27..b4f0fec90fb0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java @@ -17,6 +17,9 @@ package com.android.systemui.statusbar.policy; import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; +import static android.telephony.PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE; + +import static com.android.internal.telephony.PhoneConstants.MAX_PHONE_COUNT_DUAL_SIM; import android.content.BroadcastReceiver; import android.content.Context; @@ -35,6 +38,7 @@ import android.os.Looper; import android.os.PersistableBundle; import android.provider.Settings; import android.telephony.CarrierConfigManager; +import android.telephony.PhoneStateListener; import android.telephony.ServiceState; import android.telephony.SignalStrength; import android.telephony.SubscriptionInfo; @@ -96,6 +100,16 @@ public class NetworkControllerImpl extends BroadcastReceiver private final CurrentUserTracker mUserTracker; private Config mConfig; + private PhoneStateListener mPhoneStateListener = new PhoneStateListener() { + @Override + public void onActiveDataSubscriptionIdChanged(int subId) { + mActiveMobileDataSubscription = subId; + doUpdateMobileControllers(); + } + }; + + private int mActiveMobileDataSubscription = SubscriptionManager.INVALID_SUBSCRIPTION_ID; + // Subcontrollers. @VisibleForTesting final WifiSignalController mWifiSignalController; @@ -269,6 +283,7 @@ public class NetworkControllerImpl extends BroadcastReceiver mSubscriptionListener = new SubListener(); } mSubscriptionManager.addOnSubscriptionsChangedListener(mSubscriptionListener); + mPhone.listen(mPhoneStateListener, LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE); // broadcasts IntentFilter filter = new IntentFilter(); @@ -513,6 +528,7 @@ public class NetworkControllerImpl extends BroadcastReceiver @VisibleForTesting void handleConfigurationChanged() { + updateMobileControllers(); for (int i = 0; i < mMobileSignalControllers.size(); i++) { MobileSignalController controller = mMobileSignalControllers.valueAt(i); controller.setConfiguration(mConfig); @@ -527,13 +543,39 @@ public class NetworkControllerImpl extends BroadcastReceiver doUpdateMobileControllers(); } + private void filterMobileSubscriptionInSameGroup(List<SubscriptionInfo> subscriptions) { + if (subscriptions.size() == MAX_PHONE_COUNT_DUAL_SIM) { + SubscriptionInfo info1 = subscriptions.get(0); + SubscriptionInfo info2 = subscriptions.get(1); + if (info1.getGroupUuid() != null && info1.getGroupUuid().equals(info2.getGroupUuid())) { + // If both subscriptions are primary, show both. + if (!info1.isOpportunistic() && !info2.isOpportunistic()) return; + + // If carrier required, always show signal bar of primary subscription. + // Otherwise, show whichever subscription is currently active for Internet. + boolean alwaysShowPrimary = CarrierConfigManager.getDefaultConfig() + .getBoolean(CarrierConfigManager + .KEY_ALWAYS_SHOW_PRIMARY_SIGNAL_BAR_IN_OPPORTUNISTIC_NETWORK_BOOLEAN); + if (alwaysShowPrimary) { + subscriptions.remove(info1.isOpportunistic() ? info1 : info2); + } else { + subscriptions.remove(info1.getSubscriptionId() == mActiveMobileDataSubscription + ? info2 : info1); + } + } + } + } + @VisibleForTesting void doUpdateMobileControllers() { List<SubscriptionInfo> subscriptions = mSubscriptionManager - .getActiveSubscriptionInfoList(true); + .getActiveSubscriptionInfoList(false); if (subscriptions == null) { subscriptions = Collections.emptyList(); } + + filterMobileSubscriptionInSameGroup(subscriptions); + // If there have been no relevant changes to any of the subscriptions, we can leave as is. if (hasCorrectMobileControllers(subscriptions)) { // Even if the controllers are correct, make sure we have the right no sims state. diff --git a/services/core/Android.bp b/services/core/Android.bp index 48b69b029643..75c6849208f7 100644 --- a/services/core/Android.bp +++ b/services/core/Android.bp @@ -20,6 +20,7 @@ java_library_static { ":mediaupdateservice_aidl", "java/com/android/server/EventLogTags.logtags", "java/com/android/server/am/EventLogTags.logtags", + "java/com/android/server/policy/EventLogTags.logtags", ], libs: [ @@ -48,6 +49,7 @@ java_library_static { "android.hardware.configstore-V1.0-java", "android.hardware.contexthub-V1.0-java", "android.hidl.manager-V1.2-java", + "dnsresolver_aidl_interface-java", "netd_aidl_interface-java", "netd_event_listener_interface-java", ], diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java index 50f15ca0739f..3b78fdafbd94 100644 --- a/services/core/java/com/android/server/BatteryService.java +++ b/services/core/java/com/android/server/BatteryService.java @@ -356,10 +356,27 @@ public final class BatteryService extends SystemService { && (oldPlugged || mLastBatteryLevel > mLowBatteryWarningLevel); } + private boolean shouldShutdownLocked() { + if (mHealthInfo.batteryLevel > 0) { + return false; + } + + // Battery-less devices should not shutdown. + if (!mHealthInfo.batteryPresent) { + return false; + } + + // If battery state is not CHARGING, shutdown. + // - If battery present and state == unknown, this is an unexpected error state. + // - If level <= 0 and state == full, this is also an unexpected state + // - All other states (NOT_CHARGING, DISCHARGING) means it is not charging. + return mHealthInfo.batteryStatus != BatteryManager.BATTERY_STATUS_CHARGING; + } + private void shutdownIfNoPowerLocked() { // shut down gracefully if our battery is critically low and we are not powered. // wait until the system has booted before attempting to display the shutdown dialog. - if (mHealthInfo.batteryLevel == 0 && !isPoweredLocked(BatteryManager.BATTERY_PLUGGED_ANY)) { + if (shouldShutdownLocked()) { mHandler.post(new Runnable() { @Override public void run() { diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 2d70f3555ac7..699cf605bcec 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -63,6 +63,7 @@ import android.net.ConnectionInfo; import android.net.ConnectivityManager; import android.net.ICaptivePortal; import android.net.IConnectivityManager; +import android.net.IDnsResolver; import android.net.IIpConnectivityMetrics; import android.net.INetd; import android.net.INetdEventCallback; @@ -294,6 +295,8 @@ public class ConnectivityService extends IConnectivityManager.Stub private INetworkManagementService mNMS; @VisibleForTesting + protected IDnsResolver mDnsResolver; + @VisibleForTesting protected INetd mNetd; private INetworkStatsService mStatsService; private INetworkPolicyManager mPolicyManager; @@ -525,6 +528,11 @@ public class ConnectivityService extends IConnectivityManager.Stub return sMagicDecoderRing.get(what, Integer.toString(what)); } + private static IDnsResolver getDnsResolver() { + return IDnsResolver.Stub + .asInterface(ServiceManager.getService("dnsresolver")); + } + /** Handler thread used for both of the handlers below. */ @VisibleForTesting protected final HandlerThread mHandlerThread; @@ -810,13 +818,14 @@ public class ConnectivityService extends IConnectivityManager.Stub public ConnectivityService(Context context, INetworkManagementService netManager, INetworkStatsService statsService, INetworkPolicyManager policyManager) { - this(context, netManager, statsService, policyManager, new IpConnectivityLog()); + this(context, netManager, statsService, policyManager, + getDnsResolver(), new IpConnectivityLog()); } @VisibleForTesting protected ConnectivityService(Context context, INetworkManagementService netManager, INetworkStatsService statsService, INetworkPolicyManager policyManager, - IpConnectivityLog logger) { + IDnsResolver dnsresolver, IpConnectivityLog logger) { if (DBG) log("ConnectivityService starting up"); mSystemProperties = getSystemProperties(); @@ -853,6 +862,7 @@ public class ConnectivityService extends IConnectivityManager.Stub mPolicyManagerInternal = checkNotNull( LocalServices.getService(NetworkPolicyManagerInternal.class), "missing NetworkPolicyManagerInternal"); + mDnsResolver = checkNotNull(dnsresolver, "missing IDnsResolver"); mProxyTracker = makeProxyTracker(); mNetd = NetdService.getInstance(); @@ -988,7 +998,7 @@ public class ConnectivityService extends IConnectivityManager.Stub mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); - mKeepaliveTracker = new KeepaliveTracker(mHandler); + mKeepaliveTracker = new KeepaliveTracker(mContext, mHandler); mNotifier = new NetworkNotificationManager(mContext, mTelephonyManager, mContext.getSystemService(NotificationManager.class)); @@ -1006,7 +1016,7 @@ public class ConnectivityService extends IConnectivityManager.Stub mMultipathPolicyTracker = new MultipathPolicyTracker(mContext, mHandler); - mDnsManager = new DnsManager(mContext, mNMS, mSystemProperties); + mDnsManager = new DnsManager(mContext, mDnsResolver, mSystemProperties); registerPrivateDnsSettingsCallbacks(); } @@ -3021,9 +3031,9 @@ public class ConnectivityService extends IConnectivityManager.Stub // NetworkFactories, so network traffic isn't interrupted for an unnecessarily // long time. try { - mNMS.removeNetwork(nai.network.netId); - } catch (Exception e) { - loge("Exception removing network: " + e); + mNetd.networkDestroy(nai.network.netId); + } catch (RemoteException | ServiceSpecificException e) { + loge("Exception destroying network: " + e); } mDnsManager.removeNetwork(nai.network); } @@ -3475,8 +3485,12 @@ public class ConnectivityService extends IConnectivityManager.Stub return mMultinetworkPolicyTracker.getAvoidBadWifi(); } - @Override - public boolean getAvoidBadWifi() { + /** + * Return whether the device should maintain continuous, working connectivity by switching away + * from WiFi networks having no connectivity. + * @see MultinetworkPolicyTracker#getAvoidBadWifi() + */ + public boolean shouldAvoidBadWifi() { if (!checkNetworkStackPermission()) { throw new SecurityException("avoidBadWifi requires NETWORK_STACK permission"); } @@ -4295,7 +4309,7 @@ public class ConnectivityService extends IConnectivityManager.Stub /** * @return VPN information for accounting, or null if we can't retrieve all required - * information, e.g primary underlying iface. + * information, e.g underlying ifaces. */ @Nullable private VpnInfo createVpnInfo(Vpn vpn) { @@ -4307,17 +4321,24 @@ public class ConnectivityService extends IConnectivityManager.Stub // see VpnService.setUnderlyingNetworks()'s javadoc about how to interpret // the underlyingNetworks list. if (underlyingNetworks == null) { - NetworkAgentInfo defaultNetwork = getDefaultNetwork(); - if (defaultNetwork != null && defaultNetwork.linkProperties != null) { - info.primaryUnderlyingIface = getDefaultNetwork().linkProperties.getInterfaceName(); + NetworkAgentInfo defaultNai = getDefaultNetwork(); + if (defaultNai != null && defaultNai.linkProperties != null) { + underlyingNetworks = new Network[] { defaultNai.network }; } - } else if (underlyingNetworks.length > 0) { - LinkProperties linkProperties = getLinkProperties(underlyingNetworks[0]); - if (linkProperties != null) { - info.primaryUnderlyingIface = linkProperties.getInterfaceName(); + } + if (underlyingNetworks != null && underlyingNetworks.length > 0) { + List<String> interfaces = new ArrayList<>(); + for (Network network : underlyingNetworks) { + LinkProperties lp = getLinkProperties(network); + if (lp != null) { + interfaces.add(lp.getInterfaceName()); + } + } + if (!interfaces.isEmpty()) { + info.underlyingIfaces = interfaces.toArray(new String[interfaces.size()]); } } - return info.primaryUnderlyingIface == null ? null : info; + return info.underlyingIfaces == null ? null : info; } /** @@ -5368,8 +5389,8 @@ public class ConnectivityService extends IConnectivityManager.Stub final NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities); final NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(), new Network(reserveNetId()), new NetworkInfo(networkInfo), lp, nc, currentScore, - mContext, mTrackerHandler, new NetworkMisc(networkMisc), this, mNetd, mNMS, - factorySerialNumber); + mContext, mTrackerHandler, new NetworkMisc(networkMisc), this, mNetd, mDnsResolver, + mNMS, factorySerialNumber); // Make sure the network capabilities reflect what the agent info says. nai.networkCapabilities = mixInCapabilities(nai, nc); final String extraInfo = networkInfo.getExtraInfo(); @@ -6688,7 +6709,9 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public String getCaptivePortalServerUrl() { enforceConnectivityInternalPermission(); - return NetworkMonitorUtils.getCaptivePortalServerHttpUrl(mContext); + final String defaultUrl = mContext.getResources().getString( + R.string.config_networkDefaultCaptivePortalServerUrl); + return NetworkMonitorUtils.getCaptivePortalServerHttpUrl(mContext, defaultUrl); } @Override @@ -6696,7 +6719,7 @@ public class ConnectivityService extends IConnectivityManager.Stub ISocketKeepaliveCallback cb, String srcAddr, int srcPort, String dstAddr) { enforceKeepalivePermission(); mKeepaliveTracker.startNattKeepalive( - getNetworkAgentInfoForNetwork(network), + getNetworkAgentInfoForNetwork(network), null /* fd */, intervalSeconds, cb, srcAddr, srcPort, dstAddr, NattSocketKeepalive.NATT_PORT); } @@ -6705,7 +6728,6 @@ public class ConnectivityService extends IConnectivityManager.Stub public void startNattKeepaliveWithFd(Network network, FileDescriptor fd, int resourceId, int intervalSeconds, ISocketKeepaliveCallback cb, String srcAddr, String dstAddr) { - enforceKeepalivePermission(); mKeepaliveTracker.startNattKeepalive( getNetworkAgentInfoForNetwork(network), fd, resourceId, intervalSeconds, cb, diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java index 06b85daf2023..0a91721f31d6 100644 --- a/services/core/java/com/android/server/NetworkManagementService.java +++ b/services/core/java/com/android/server/NetworkManagementService.java @@ -1605,20 +1605,6 @@ public class NetworkManagementService extends INetworkManagementService.Stub { } @Override - public void setDnsConfigurationForNetwork(int netId, String[] servers, String[] domains, - int[] params, String tlsHostname, String[] tlsServers) { - mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); - - final String[] tlsFingerprints = new String[0]; - try { - mNetdService.setResolverConfiguration( - netId, servers, domains, params, tlsHostname, tlsServers, tlsFingerprints); - } catch (RemoteException e) { - throw new RuntimeException(e); - } - } - - @Override public void addVpnUidRanges(int netId, UidRange[] ranges) { mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); @@ -2076,21 +2062,6 @@ public class NetworkManagementService extends INetworkManagementService.Stub { } @Override - public void removeNetwork(int netId) { - mContext.enforceCallingOrSelfPermission(NETWORK_STACK, TAG); - - try { - mNetdService.networkDestroy(netId); - } catch (ServiceSpecificException e) { - Log.w(TAG, "removeNetwork(" + netId + "): ", e); - throw e; - } catch (RemoteException e) { - Log.w(TAG, "removeNetwork(" + netId + "): ", e); - throw e.rethrowAsRuntimeException(); - } - } - - @Override public void addInterfaceToNetwork(String iface, int netId) { modifyInterfaceInNetwork(MODIFY_OPERATION_ADD, netId, iface); } diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java index fdd698f19991..9c5c152726dd 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -627,11 +627,6 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { r.callingPackage = callingPackage; r.callerUid = Binder.getCallingUid(); r.callerPid = Binder.getCallingPid(); - if (r.subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID && r.subId != subId) { - throw new IllegalArgumentException( - "PhoneStateListener cannot concurrently listen on multiple " + - "subscriptions. Previously registered on subId: " + r.subId); - } // Legacy applications pass SubscriptionManager.DEFAULT_SUB_ID, // force all illegal subId to SubscriptionManager.DEFAULT_SUB_ID if (!SubscriptionManager.isValidSubscriptionId(subId)) { @@ -1888,7 +1883,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { pw.println("mDataConnectionState=" + mDataConnectionState[i]); pw.println("mCellLocation=" + mCellLocation[i]); pw.println("mCellInfo=" + mCellInfo.get(i)); - pw.println("mImsCallDisconnectCause=" + mImsReasonInfo.get(i).toString()); + pw.println("mImsCallDisconnectCause=" + mImsReasonInfo.get(i)); pw.decreaseIndent(); } pw.println("mCallNetworkType=" + mCallNetworkType); diff --git a/services/core/java/com/android/server/connectivity/DnsManager.java b/services/core/java/com/android/server/connectivity/DnsManager.java index d8bb635f2ce8..1913635f80e2 100644 --- a/services/core/java/com/android/server/connectivity/DnsManager.java +++ b/services/core/java/com/android/server/connectivity/DnsManager.java @@ -30,13 +30,15 @@ import static android.provider.Settings.Global.PRIVATE_DNS_SPECIFIER; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; +import android.net.IDnsResolver; import android.net.LinkProperties; import android.net.Network; import android.net.NetworkUtils; import android.net.Uri; import android.net.shared.PrivateDnsConfig; import android.os.Binder; -import android.os.INetworkManagementService; +import android.os.RemoteException; +import android.os.ServiceSpecificException; import android.os.UserHandle; import android.provider.Settings; import android.text.TextUtils; @@ -229,7 +231,7 @@ public class DnsManager { private final Context mContext; private final ContentResolver mContentResolver; - private final INetworkManagementService mNMS; + private final IDnsResolver mDnsResolver; private final MockableSystemProperties mSystemProperties; // TODO: Replace these Maps with SparseArrays. private final Map<Integer, PrivateDnsConfig> mPrivateDnsMap; @@ -243,10 +245,10 @@ public class DnsManager { private String mPrivateDnsMode; private String mPrivateDnsSpecifier; - public DnsManager(Context ctx, INetworkManagementService nms, MockableSystemProperties sp) { + public DnsManager(Context ctx, IDnsResolver dnsResolver, MockableSystemProperties sp) { mContext = ctx; mContentResolver = mContext.getContentResolver(); - mNMS = nms; + mDnsResolver = dnsResolver; mSystemProperties = sp; mPrivateDnsMap = new HashMap<>(); mPrivateDnsValidationMap = new HashMap<>(); @@ -260,6 +262,12 @@ public class DnsManager { } public void removeNetwork(Network network) { + try { + mDnsResolver.clearResolverConfiguration(network.netId); + } catch (RemoteException | ServiceSpecificException e) { + Slog.e(TAG, "Error clearing DNS configuration: " + e); + return; + } mPrivateDnsMap.remove(network.netId); mPrivateDnsValidationMap.remove(network.netId); } @@ -344,10 +352,12 @@ public class DnsManager { Slog.d(TAG, String.format("setDnsConfigurationForNetwork(%d, %s, %s, %s, %s, %s)", netId, Arrays.toString(assignedServers), Arrays.toString(domainStrs), Arrays.toString(params), tlsHostname, Arrays.toString(tlsServers))); + final String[] tlsFingerprints = new String[0]; try { - mNMS.setDnsConfigurationForNetwork( - netId, assignedServers, domainStrs, params, tlsHostname, tlsServers); - } catch (Exception e) { + mDnsResolver.setResolverConfiguration( + netId, assignedServers, domainStrs, params, + tlsHostname, tlsServers, tlsFingerprints); + } catch (RemoteException | ServiceSpecificException e) { Slog.e(TAG, "Error setting DNS configuration: " + e); return; } diff --git a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java index 0e3d82c0a660..d7a57b992eef 100644 --- a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java +++ b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java @@ -16,6 +16,7 @@ package com.android.server.connectivity; +import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.net.NattSocketKeepalive.NATT_PORT; import static android.net.NetworkAgent.CMD_ADD_KEEPALIVE_PACKET_FILTER; import static android.net.NetworkAgent.CMD_REMOVE_KEEPALIVE_PACKET_FILTER; @@ -23,6 +24,7 @@ import static android.net.NetworkAgent.CMD_START_SOCKET_KEEPALIVE; import static android.net.NetworkAgent.CMD_STOP_SOCKET_KEEPALIVE; import static android.net.SocketKeepalive.BINDER_DIED; import static android.net.SocketKeepalive.DATA_RECEIVED; +import static android.net.SocketKeepalive.ERROR_INSUFFICIENT_RESOURCES; import static android.net.SocketKeepalive.ERROR_INVALID_INTERVAL; import static android.net.SocketKeepalive.ERROR_INVALID_IP_ADDRESS; import static android.net.SocketKeepalive.ERROR_INVALID_NETWORK; @@ -34,6 +36,7 @@ import static android.net.SocketKeepalive.SUCCESS; import android.annotation.NonNull; import android.annotation.Nullable; +import android.content.Context; import android.net.ISocketKeepaliveCallback; import android.net.KeepalivePacketData; import android.net.NattKeepalivePacketData; @@ -84,10 +87,13 @@ public class KeepaliveTracker { private final Handler mConnectivityServiceHandler; @NonNull private final TcpKeepaliveController mTcpController; + @NonNull + private final Context mContext; - public KeepaliveTracker(Handler handler) { + public KeepaliveTracker(Context context, Handler handler) { mConnectivityServiceHandler = handler; mTcpController = new TcpKeepaliveController(handler); + mContext = context; } /** @@ -101,6 +107,7 @@ public class KeepaliveTracker { private final ISocketKeepaliveCallback mCallback; private final int mUid; private final int mPid; + private final boolean mPrivileged; private final NetworkAgentInfo mNai; private final int mType; private final FileDescriptor mFd; @@ -108,6 +115,11 @@ public class KeepaliveTracker { public static final int TYPE_NATT = 1; public static final int TYPE_TCP = 2; + // Max allowed unprivileged keepalive slots per network. Caller's permission will be + // enforced if number of existing keepalives reach this limit. + // TODO: consider making this limit configurable via resources. + private static final int MAX_UNPRIVILEGED_SLOTS = 3; + // Keepalive slot. A small integer that identifies this keepalive among the ones handled // by this network. private int mSlot = NO_KEEPALIVE; @@ -127,16 +139,40 @@ public class KeepaliveTracker { @NonNull KeepalivePacketData packet, int interval, int type, - @NonNull FileDescriptor fd) { + @Nullable FileDescriptor fd) throws InvalidSocketException { mCallback = callback; mPid = Binder.getCallingPid(); mUid = Binder.getCallingUid(); + mPrivileged = (PERMISSION_GRANTED == mContext.checkPermission(PERMISSION, mPid, mUid)); mNai = nai; mPacket = packet; mInterval = interval; mType = type; - mFd = fd; + + // For SocketKeepalive, a dup of fd is kept in mFd so the source port from which the + // keepalives are sent cannot be reused by another app even if the fd gets closed by + // the user. A null is acceptable here for backward compatibility of PacketKeepalive + // API. + try { + if (fd != null) { + mFd = Os.dup(fd); + } else { + Log.d(TAG, toString() + " calls with null fd"); + if (!mPrivileged) { + throw new SecurityException( + "null fd is not allowed for unprivileged access."); + } + if (mType == TYPE_TCP) { + throw new IllegalArgumentException( + "null fd is not allowed for tcp socket keepalives."); + } + mFd = null; + } + } catch (ErrnoException e) { + Log.e(TAG, "Cannot dup fd: ", e); + throw new InvalidSocketException(ERROR_INVALID_SOCKET, e); + } try { mCallback.asBinder().linkToDeath(this, 0); @@ -167,7 +203,7 @@ public class KeepaliveTracker { + "->" + IpUtils.addressAndPortToString(mPacket.dstAddress, mPacket.dstPort) + " interval=" + mInterval - + " uid=" + mUid + " pid=" + mPid + + " uid=" + mUid + " pid=" + mPid + " privileged=" + mPrivileged + " packetData=" + HexDump.toHexString(mPacket.getPacket()) + " ]"; } @@ -207,9 +243,27 @@ public class KeepaliveTracker { return SUCCESS; } + private int checkPermission() { + final HashMap<Integer, KeepaliveInfo> networkKeepalives = mKeepalives.get(mNai); + int unprivilegedCount = 0; + if (networkKeepalives == null) { + return ERROR_INVALID_NETWORK; + } + for (KeepaliveInfo ki : networkKeepalives.values()) { + if (!ki.mPrivileged) { + unprivilegedCount++; + } + if (unprivilegedCount >= MAX_UNPRIVILEGED_SLOTS) { + return mPrivileged ? SUCCESS : ERROR_INSUFFICIENT_RESOURCES; + } + } + return SUCCESS; + } + private int isValid() { synchronized (mNai) { int error = checkInterval(); + if (error == SUCCESS) error = checkPermission(); if (error == SUCCESS) error = checkNetworkConnected(); if (error == SUCCESS) error = checkSourceAddress(); return error; @@ -272,6 +326,18 @@ public class KeepaliveTracker { } } + // Close the duplicated fd that maintains the lifecycle of socket whenever + // keepalive is running. + if (mFd != null) { + try { + Os.close(mFd); + } catch (ErrnoException e) { + // This should not happen since system server controls the lifecycle of fd when + // keepalive offload is running. + Log.wtf(TAG, "Error closing fd for keepalive " + mSlot + ": " + e); + } + } + if (reason == SUCCESS) { try { mCallback.onStopped(); @@ -355,8 +421,9 @@ public class KeepaliveTracker { return; } ki.stop(reason); - Log.d(TAG, "Stopped keepalive " + slot + " on " + networkName); networkKeepalives.remove(slot); + Log.d(TAG, "Stopped keepalive " + slot + " on " + networkName + ", " + + networkKeepalives.size() + " remains."); if (networkKeepalives.isEmpty()) { mKeepalives.remove(nai); } @@ -389,7 +456,8 @@ public class KeepaliveTracker { ki = mKeepalives.get(nai).get(slot); } catch(NullPointerException e) {} if (ki == null) { - Log.e(TAG, "Event for unknown keepalive " + slot + " on " + nai.name()); + Log.e(TAG, "Event " + message.what + " for unknown keepalive " + slot + " on " + + nai.name()); return; } @@ -419,7 +487,6 @@ public class KeepaliveTracker { } } else { // Keepalive successfully stopped, or error. - ki.mStartedState = KeepaliveInfo.NOT_STARTED; if (reason == SUCCESS) { // The message indicated success stopping : don't call handleStopKeepalive. if (DBG) Log.d(TAG, "Successfully stopped keepalive " + slot + " on " + nai.name()); @@ -429,6 +496,7 @@ public class KeepaliveTracker { handleStopKeepalive(nai, slot, reason); if (DBG) Log.d(TAG, "Keepalive " + slot + " on " + nai.name() + " error " + reason); } + ki.mStartedState = KeepaliveInfo.NOT_STARTED; } } @@ -437,6 +505,7 @@ public class KeepaliveTracker { * {@link android.net.SocketKeepalive}. **/ public void startNattKeepalive(@Nullable NetworkAgentInfo nai, + @Nullable FileDescriptor fd, int intervalSeconds, @NonNull ISocketKeepaliveCallback cb, @NonNull String srcAddrString, @@ -465,8 +534,15 @@ public class KeepaliveTracker { notifyErrorCallback(cb, e.error); return; } - KeepaliveInfo ki = new KeepaliveInfo(cb, nai, packet, intervalSeconds, - KeepaliveInfo.TYPE_NATT, null); + KeepaliveInfo ki = null; + try { + ki = new KeepaliveInfo(cb, nai, packet, intervalSeconds, + KeepaliveInfo.TYPE_NATT, fd); + } catch (InvalidSocketException | IllegalArgumentException | SecurityException e) { + Log.e(TAG, "Fail to construct keepalive", e); + notifyErrorCallback(cb, ERROR_INVALID_SOCKET); + return; + } Log.d(TAG, "Created keepalive: " + ki.toString()); mConnectivityServiceHandler.obtainMessage( NetworkAgent.CMD_START_SOCKET_KEEPALIVE, ki).sendToTarget(); @@ -498,9 +574,15 @@ public class KeepaliveTracker { notifyErrorCallback(cb, e.error); return; } - - KeepaliveInfo ki = new KeepaliveInfo(cb, nai, packet, intervalSeconds, - KeepaliveInfo.TYPE_TCP, fd); + KeepaliveInfo ki = null; + try { + ki = new KeepaliveInfo(cb, nai, packet, intervalSeconds, + KeepaliveInfo.TYPE_TCP, fd); + } catch (InvalidSocketException | IllegalArgumentException | SecurityException e) { + Log.e(TAG, "Fail to construct keepalive e=" + e); + notifyErrorCallback(cb, ERROR_INVALID_SOCKET); + return; + } Log.d(TAG, "Created keepalive: " + ki.toString()); mConnectivityServiceHandler.obtainMessage(CMD_START_SOCKET_KEEPALIVE, ki).sendToTarget(); } @@ -535,7 +617,7 @@ public class KeepaliveTracker { } // Forward request to old API. - startNattKeepalive(nai, intervalSeconds, cb, srcAddrString, srcPort, + startNattKeepalive(nai, fd, intervalSeconds, cb, srcAddrString, srcPort, dstAddrString, dstPort); } diff --git a/services/core/java/com/android/server/connectivity/Nat464Xlat.java b/services/core/java/com/android/server/connectivity/Nat464Xlat.java index 262ba7a475bb..66bd27c1a76b 100644 --- a/services/core/java/com/android/server/connectivity/Nat464Xlat.java +++ b/services/core/java/com/android/server/connectivity/Nat464Xlat.java @@ -17,6 +17,7 @@ package com.android.server.connectivity; import android.net.ConnectivityManager; +import android.net.IDnsResolver; import android.net.INetd; import android.net.InetAddresses; import android.net.InterfaceConfiguration; @@ -65,6 +66,7 @@ public class Nat464Xlat extends BaseNetworkObserver { NetworkInfo.State.SUSPENDED, }; + private final IDnsResolver mDnsResolver; private final INetd mNetd; private final INetworkManagementService mNMService; @@ -84,7 +86,9 @@ public class Nat464Xlat extends BaseNetworkObserver { private Inet6Address mIPv6Address; private State mState = State.IDLE; - public Nat464Xlat(NetworkAgentInfo nai, INetd netd, INetworkManagementService nmService) { + public Nat464Xlat(NetworkAgentInfo nai, INetd netd, IDnsResolver dnsResolver, + INetworkManagementService nmService) { + mDnsResolver = dnsResolver; mNetd = netd; mNMService = nmService; mNetwork = nai; @@ -269,7 +273,7 @@ public class Nat464Xlat extends BaseNetworkObserver { private void startPrefixDiscovery() { try { - mNetd.resolverStartPrefix64Discovery(getNetId()); + mDnsResolver.startPrefix64Discovery(getNetId()); mState = State.DISCOVERING; } catch (RemoteException | ServiceSpecificException e) { Slog.e(TAG, "Error starting prefix discovery on netId " + getNetId() + ": " + e); @@ -278,7 +282,7 @@ public class Nat464Xlat extends BaseNetworkObserver { private void stopPrefixDiscovery() { try { - mNetd.resolverStopPrefix64Discovery(getNetId()); + mDnsResolver.stopPrefix64Discovery(getNetId()); } catch (RemoteException | ServiceSpecificException e) { Slog.e(TAG, "Error stopping prefix discovery on netId " + getNetId() + ": " + e); } diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java index 8f2825ca72d8..e3fdbe84a1d3 100644 --- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java +++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java @@ -17,6 +17,7 @@ package com.android.server.connectivity; import android.content.Context; +import android.net.IDnsResolver; import android.net.INetd; import android.net.INetworkMonitor; import android.net.LinkProperties; @@ -255,7 +256,7 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { public NetworkAgentInfo(Messenger messenger, AsyncChannel ac, Network net, NetworkInfo info, LinkProperties lp, NetworkCapabilities nc, int score, Context context, Handler handler, NetworkMisc misc, ConnectivityService connService, INetd netd, - INetworkManagementService nms, int factorySerialNumber) { + IDnsResolver dnsResolver, INetworkManagementService nms, int factorySerialNumber) { this.messenger = messenger; asyncChannel = ac; network = net; @@ -263,7 +264,7 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { linkProperties = lp; networkCapabilities = nc; currentScore = score; - clatd = new Nat464Xlat(this, netd, nms); + clatd = new Nat464Xlat(this, netd, dnsResolver, nms); mConnService = connService; mContext = context; mHandler = handler; diff --git a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java index 828a1e58868a..ac3d6def6f80 100644 --- a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java +++ b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java @@ -19,6 +19,7 @@ package com.android.server.connectivity; import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_WIFI; +import static android.telephony.SubscriptionManager.DEFAULT_SUBSCRIPTION_ID; import android.app.Notification; import android.app.NotificationManager; @@ -26,9 +27,12 @@ import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.content.res.Resources; +import android.net.NetworkSpecifier; +import android.net.StringNetworkSpecifier; import android.net.wifi.WifiInfo; import android.os.UserHandle; import android.telephony.AccessNetworkConstants.TransportType; +import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.Slog; @@ -195,7 +199,20 @@ public class NetworkNotificationManager { title = r.getString(R.string.network_available_sign_in, 0); // TODO: Change this to pull from NetworkInfo once a printable // name has been added to it - details = mTelephonyManager.getNetworkOperatorName(); + NetworkSpecifier specifier = nai.networkCapabilities.getNetworkSpecifier(); + int subId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID; + if (specifier instanceof StringNetworkSpecifier) { + try { + subId = Integer.parseInt( + ((StringNetworkSpecifier) specifier).specifier); + } catch (NumberFormatException e) { + Slog.e(TAG, "NumberFormatException on " + + ((StringNetworkSpecifier) specifier).specifier); + } + } + + details = mTelephonyManager.createForSubscriptionId(subId) + .getNetworkOperatorName(); break; default: title = r.getString(R.string.network_available_sign_in, 0); diff --git a/services/core/java/com/android/server/connectivity/PermissionMonitor.java b/services/core/java/com/android/server/connectivity/PermissionMonitor.java index 123564eb4fdb..0c559346bc42 100644 --- a/services/core/java/com/android/server/connectivity/PermissionMonitor.java +++ b/services/core/java/com/android/server/connectivity/PermissionMonitor.java @@ -22,6 +22,7 @@ import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS; import static android.Manifest.permission.INTERNET; import static android.Manifest.permission.NETWORK_STACK; import static android.Manifest.permission.UPDATE_DEVICE_STATS; +import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED; import static android.content.pm.PackageManager.GET_PERMISSIONS; import static android.content.pm.PackageManager.MATCH_ANY_USER; import static android.os.Process.INVALID_UID; @@ -42,13 +43,15 @@ import android.os.INetworkManagementService; import android.os.RemoteException; import android.os.UserHandle; import android.os.UserManager; +import android.util.ArraySet; import android.util.Log; -import android.util.Slog; +import android.util.SparseArray; import android.util.SparseIntArray; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; import com.android.server.LocalServices; +import com.android.server.SystemConfig; import java.util.ArrayList; import java.util.HashMap; @@ -83,41 +86,32 @@ public class PermissionMonitor { private final Map<Integer, Boolean> mApps = new HashMap<>(); private class PackageListObserver implements PackageManagerInternal.PackageListObserver { - @Override - public void onPackageAdded(String packageName, int uid) { - final PackageInfo app = getPackageInfo(packageName); - if (app == null) { - Slog.wtf(TAG, "Failed to get information of installed package: " + packageName); - return; - } - if (uid == INVALID_UID) { - Slog.wtf(TAG, "Failed to get the uid of installed package: " + packageName - + "uid: " + uid); - return; - } - if (app.requestedPermissions == null) { - return; - } - sendPackagePermissionsForUid(uid, - getNetdPermissionMask(app.requestedPermissions)); - } - @Override - public void onPackageRemoved(String packageName, int uid) { + private int getPermissionForUid(int uid) { int permission = 0; - // If there are still packages remain under the same uid, check the permission of the - // remaining packages. We only remove the permission for a given uid when all packages - // for that uid no longer have that permission. + // Check all the packages for this UID. The UID has the permission if any of the + // packages in it has the permission. String[] packages = mPackageManager.getPackagesForUid(uid); if (packages != null && packages.length > 0) { for (String name : packages) { final PackageInfo app = getPackageInfo(name); if (app != null && app.requestedPermissions != null) { - permission |= getNetdPermissionMask(app.requestedPermissions); + permission |= getNetdPermissionMask(app.requestedPermissions, + app.requestedPermissionsFlags); } } } - sendPackagePermissionsForUid(uid, permission); + return permission; + } + + @Override + public void onPackageAdded(String packageName, int uid) { + sendPackagePermissionsForUid(uid, getPermissionForUid(uid)); + } + + @Override + public void onPackageRemoved(String packageName, int uid) { + sendPackagePermissionsForUid(uid, getPermissionForUid(uid)); } } @@ -167,12 +161,9 @@ public class PermissionMonitor { } //TODO: unify the management of the permissions into one codepath. - if (app.requestedPermissions != null) { - int otherNetdPerms = getNetdPermissionMask(app.requestedPermissions); - if (otherNetdPerms != 0) { - netdPermsUids.put(uid, netdPermsUids.get(uid) | otherNetdPerms); - } - } + int otherNetdPerms = getNetdPermissionMask(app.requestedPermissions, + app.requestedPermissionsFlags); + netdPermsUids.put(uid, netdPermsUids.get(uid) | otherNetdPerms); } List<UserInfo> users = mUserManager.getUsers(true); // exclude dying users @@ -182,6 +173,23 @@ public class PermissionMonitor { } } + final SparseArray<ArraySet<String>> systemPermission = + SystemConfig.getInstance().getSystemPermissions(); + for (int i = 0; i < systemPermission.size(); i++) { + ArraySet<String> perms = systemPermission.valueAt(i); + int uid = systemPermission.keyAt(i); + int netdPermission = 0; + // Get the uids of native services that have UPDATE_DEVICE_STATS permission. + if (perms != null) { + netdPermission |= perms.contains(UPDATE_DEVICE_STATS) + ? INetd.PERMISSION_UPDATE_DEVICE_STATS : 0; + } + // For internet permission, the native services have their own selinux domains and + // sepolicy will control the socket creation during run time. netd cannot block the + // socket creation based on the permission information here. + netdPermission |= INetd.PERMISSION_INTERNET; + netdPermsUids.put(uid, netdPermsUids.get(uid) | netdPermission); + } log("Users: " + mUsers.size() + ", Apps: " + mApps.size()); update(mUsers, mApps, true); sendPackagePermissionsToNetd(netdPermsUids); @@ -403,13 +411,17 @@ public class PermissionMonitor { } } - private static int getNetdPermissionMask(String[] requestedPermissions) { + private static int getNetdPermissionMask(String[] requestedPermissions, + int[] requestedPermissionsFlags) { int permissions = 0; - for (String permissionName : requestedPermissions) { - if (permissionName.equals(INTERNET)) { + if (requestedPermissions == null || requestedPermissionsFlags == null) return permissions; + for (int i = 0; i < requestedPermissions.length; i++) { + if (requestedPermissions[i].equals(INTERNET) + && ((requestedPermissionsFlags[i] & REQUESTED_PERMISSION_GRANTED) != 0)) { permissions |= INetd.PERMISSION_INTERNET; } - if (permissionName.equals(UPDATE_DEVICE_STATS)) { + if (requestedPermissions[i].equals(UPDATE_DEVICE_STATS) + && ((requestedPermissionsFlags[i] & REQUESTED_PERMISSION_GRANTED) != 0)) { permissions |= INetd.PERMISSION_UPDATE_DEVICE_STATS; } } diff --git a/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java b/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java index f4d9006a7068..e570ef1e9bf2 100644 --- a/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java +++ b/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java @@ -16,14 +16,17 @@ package com.android.server.connectivity; import static android.net.SocketKeepalive.DATA_RECEIVED; -import static android.net.SocketKeepalive.ERROR_HARDWARE_UNSUPPORTED; import static android.net.SocketKeepalive.ERROR_INVALID_SOCKET; import static android.net.SocketKeepalive.ERROR_SOCKET_NOT_IDLE; +import static android.net.SocketKeepalive.ERROR_UNSUPPORTED; import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_ERROR; import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT; import static android.system.OsConstants.ENOPROTOOPT; import static android.system.OsConstants.FIONREAD; +import static android.system.OsConstants.IPPROTO_IP; import static android.system.OsConstants.IPPROTO_TCP; +import static android.system.OsConstants.IP_TOS; +import static android.system.OsConstants.IP_TTL; import static android.system.OsConstants.TIOCOUTQ; import android.annotation.NonNull; @@ -193,12 +196,18 @@ public class TcpKeepaliveController { trw = NetworkUtils.getTcpRepairWindow(fd); tcpDetails.rcvWnd = trw.rcvWnd; tcpDetails.rcvWndScale = trw.rcvWndScale; + if (tcpDetails.srcAddress.length == 4 /* V4 address length */) { + // Query TOS. + tcpDetails.tos = Os.getsockoptInt(fd, IPPROTO_IP, IP_TOS); + // Query TTL. + tcpDetails.ttl = Os.getsockoptInt(fd, IPPROTO_IP, IP_TTL); + } } catch (ErrnoException e) { Log.e(TAG, "Exception reading TCP state from socket", e); if (e.errno == ENOPROTOOPT) { // ENOPROTOOPT may happen in kernel version lower than 4.8. - // Treat it as ERROR_HARDWARE_UNSUPPORTED. - throw new InvalidSocketException(ERROR_HARDWARE_UNSUPPORTED, e); + // Treat it as ERROR_UNSUPPORTED. + throw new InvalidSocketException(ERROR_UNSUPPORTED, e); } else { throw new InvalidSocketException(ERROR_INVALID_SOCKET, e); } diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java index 35704d404ff3..99868099ad4d 100644 --- a/services/core/java/com/android/server/connectivity/Tethering.java +++ b/services/core/java/com/android/server/connectivity/Tethering.java @@ -82,7 +82,6 @@ import android.os.Handler; import android.os.INetworkManagementService; import android.os.Looper; import android.os.Message; -import android.os.Parcel; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.ResultReceiver; @@ -230,8 +229,15 @@ public class Tethering extends BaseNetworkObserver { IntentFilter filter = new IntentFilter(); filter.addAction(ACTION_CARRIER_CONFIG_CHANGED); - mEntitlementMgr = mDeps.getEntitlementManager(mContext, mTetherMasterSM, - mLog, systemProperties); + // EntitlementManager will send EVENT_UPSTREAM_PERMISSION_CHANGED when cellular upstream + // permission is changed according to entitlement check result. + mEntitlementMgr = mDeps.getEntitlementManager(mContext, mTetherMasterSM, mLog, + TetherMasterSM.EVENT_UPSTREAM_PERMISSION_CHANGED, systemProperties); + mEntitlementMgr.setOnUiEntitlementFailedListener((int downstream) -> { + mLog.log("OBSERVED UiEnitlementFailed"); + stopTethering(downstream); + }); + mCarrierConfigChange = new VersionedBroadcastListener( "CarrierConfigChangeListener", mContext, mHandler, filter, (Intent ignored) -> { @@ -247,7 +253,14 @@ public class Tethering extends BaseNetworkObserver { (Intent ignored) -> { mLog.log("OBSERVED default data subscription change"); updateConfiguration(); - mEntitlementMgr.reevaluateSimCardProvisioning(); + // To avoid launch unexpected provisioning checks, ignore re-provisioning when + // no CarrierConfig loaded yet. Assume reevaluateSimCardProvisioning() will be + // triggered again when CarrierConfig is loaded. + if (mEntitlementMgr.getCarrierConfig() != null) { + mEntitlementMgr.reevaluateSimCardProvisioning(); + } else { + mLog.log("IGNORED reevaluate provisioning due to no carrier config loaded"); + } }); mStateReceiver = new StateReceiver(); @@ -356,55 +369,28 @@ public class Tethering extends BaseNetworkObserver { } public void startTethering(int type, ResultReceiver receiver, boolean showProvisioningUi) { - mEntitlementMgr.startTethering(type); - if (!mEntitlementMgr.isTetherProvisioningRequired()) { - enableTetheringInternal(type, true, receiver); - return; - } - - final ResultReceiver proxyReceiver = getProxyReceiver(type, receiver); - if (showProvisioningUi) { - mEntitlementMgr.runUiTetherProvisioningAndEnable(type, proxyReceiver); - } else { - mEntitlementMgr.runSilentTetherProvisioningAndEnable(type, proxyReceiver); - } + mEntitlementMgr.startProvisioningIfNeeded(type, showProvisioningUi); + enableTetheringInternal(type, true /* enabled */, receiver); } public void stopTethering(int type) { - enableTetheringInternal(type, false, null); - mEntitlementMgr.stopTethering(type); - if (mEntitlementMgr.isTetherProvisioningRequired()) { - // There are lurking bugs where the notion of "provisioning required" or - // "tethering supported" may change without notifying tethering properly, then - // tethering can't shutdown correctly. - // TODO: cancel re-check all the time - if (mDeps.isTetheringSupported()) { - mEntitlementMgr.cancelTetherProvisioningRechecks(type); - } - } + enableTetheringInternal(type, false /* disabled */, null); + mEntitlementMgr.stopProvisioningIfNeeded(type); } /** - * Enables or disables tethering for the given type. This should only be called once - * provisioning has succeeded or is not necessary. It will also schedule provisioning rechecks - * for the specified interface. + * Enables or disables tethering for the given type. If provisioning is required, it will + * schedule provisioning rechecks for the specified interface. */ private void enableTetheringInternal(int type, boolean enable, ResultReceiver receiver) { - boolean isProvisioningRequired = enable && mEntitlementMgr.isTetherProvisioningRequired(); int result; switch (type) { case TETHERING_WIFI: result = setWifiTethering(enable); - if (isProvisioningRequired && result == TETHER_ERROR_NO_ERROR) { - mEntitlementMgr.scheduleProvisioningRechecks(type); - } sendTetherResult(receiver, result); break; case TETHERING_USB: result = setUsbTethering(enable); - if (isProvisioningRequired && result == TETHER_ERROR_NO_ERROR) { - mEntitlementMgr.scheduleProvisioningRechecks(type); - } sendTetherResult(receiver, result); break; case TETHERING_BLUETOOTH: @@ -462,46 +448,11 @@ public class Tethering extends BaseNetworkObserver { ? TETHER_ERROR_NO_ERROR : TETHER_ERROR_MASTER_ERROR; sendTetherResult(receiver, result); - if (enable && mEntitlementMgr.isTetherProvisioningRequired()) { - mEntitlementMgr.scheduleProvisioningRechecks(TETHERING_BLUETOOTH); - } adapter.closeProfileProxy(BluetoothProfile.PAN, proxy); } }, BluetoothProfile.PAN); } - /** - * Creates a proxy {@link ResultReceiver} which enables tethering if the provisioning result - * is successful before firing back up to the wrapped receiver. - * - * @param type The type of tethering being enabled. - * @param receiver A ResultReceiver which will be called back with an int resultCode. - * @return The proxy receiver. - */ - private ResultReceiver getProxyReceiver(final int type, final ResultReceiver receiver) { - ResultReceiver rr = new ResultReceiver(null) { - @Override - protected void onReceiveResult(int resultCode, Bundle resultData) { - // If provisioning is successful, enable tethering, otherwise just send the error. - if (resultCode == TETHER_ERROR_NO_ERROR) { - enableTetheringInternal(type, true, receiver); - } else { - sendTetherResult(receiver, resultCode); - } - mEntitlementMgr.updateEntitlementCacheValue(type, resultCode); - } - }; - - // The following is necessary to avoid unmarshalling issues when sending the receiver - // across processes. - Parcel parcel = Parcel.obtain(); - rr.writeToParcel(parcel,0); - parcel.setDataPosition(0); - ResultReceiver receiverForSending = ResultReceiver.CREATOR.createFromParcel(parcel); - parcel.recycle(); - return receiverForSending; - } - public int tether(String iface) { return tether(iface, IpServer.STATE_TETHERED); } @@ -780,6 +731,7 @@ public class Tethering extends BaseNetworkObserver { if (!usbConnected && mRndisEnabled) { // Turn off tethering if it was enabled and there is a disconnect. tetherMatchingInterfaces(IpServer.STATE_AVAILABLE, TETHERING_USB); + mEntitlementMgr.stopProvisioningIfNeeded(TETHERING_USB); } else if (usbConfigured && rndisEnabled) { // Tether if rndis is enabled and usb is configured. tetherMatchingInterfaces(IpServer.STATE_TETHERED, TETHERING_USB); @@ -806,6 +758,7 @@ public class Tethering extends BaseNetworkObserver { case WifiManager.WIFI_AP_STATE_FAILED: default: disableWifiIpServingLocked(ifname, curState); + mEntitlementMgr.stopProvisioningIfNeeded(TETHERING_WIFI); break; } } @@ -1083,6 +1036,8 @@ public class Tethering extends BaseNetworkObserver { // we treated the error and want now to clear it static final int CMD_CLEAR_ERROR = BASE_MASTER + 6; static final int EVENT_IFACE_UPDATE_LINKPROPERTIES = BASE_MASTER + 7; + // Events from EntitlementManager to choose upstream again. + static final int EVENT_UPSTREAM_PERMISSION_CHANGED = BASE_MASTER + 8; private final State mInitialState; private final State mTetherModeAliveState; @@ -1497,6 +1452,7 @@ public class Tethering extends BaseNetworkObserver { } break; } + case EVENT_UPSTREAM_PERMISSION_CHANGED: case CMD_UPSTREAM_CHANGED: updateUpstreamWanted(); if (!mUpstreamWanted) break; @@ -1687,7 +1643,8 @@ public class Tethering extends BaseNetworkObserver { } public void systemReady() { - mUpstreamNetworkMonitor.startTrackDefaultNetwork(mDeps.getDefaultNetworkRequest()); + mUpstreamNetworkMonitor.startTrackDefaultNetwork(mDeps.getDefaultNetworkRequest(), + mEntitlementMgr); } /** Get the latest value of the tethering entitlement check. */ @@ -1748,6 +1705,11 @@ public class Tethering extends BaseNetworkObserver { cfg.dump(pw); pw.decreaseIndent(); + pw.println("Entitlement:"); + pw.increaseIndent(); + mEntitlementMgr.dump(pw); + pw.decreaseIndent(); + synchronized (mPublicSync) { pw.println("Tether state:"); pw.increaseIndent(); diff --git a/services/core/java/com/android/server/connectivity/tethering/EntitlementManager.java b/services/core/java/com/android/server/connectivity/tethering/EntitlementManager.java index 65cc51610e72..764a6ebc2d98 100644 --- a/services/core/java/com/android/server/connectivity/tethering/EntitlementManager.java +++ b/services/core/java/com/android/server/connectivity/tethering/EntitlementManager.java @@ -18,9 +18,11 @@ package com.android.server.connectivity.tethering; import static android.net.ConnectivityManager.EXTRA_ADD_TETHER_TYPE; import static android.net.ConnectivityManager.EXTRA_PROVISION_CALLBACK; -import static android.net.ConnectivityManager.EXTRA_REM_TETHER_TYPE; import static android.net.ConnectivityManager.EXTRA_RUN_PROVISION; -import static android.net.ConnectivityManager.EXTRA_SET_ALARM; +import static android.net.ConnectivityManager.TETHERING_BLUETOOTH; +import static android.net.ConnectivityManager.TETHERING_INVALID; +import static android.net.ConnectivityManager.TETHERING_USB; +import static android.net.ConnectivityManager.TETHERING_WIFI; import static android.net.ConnectivityManager.TETHER_ERROR_ENTITLEMENT_UNKONWN; import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR; import static android.net.ConnectivityManager.TETHER_ERROR_PROVISION_FAILED; @@ -28,17 +30,24 @@ import static android.net.ConnectivityManager.TETHER_ERROR_PROVISION_FAILED; import static com.android.internal.R.string.config_wifi_tether_enable; import android.annotation.Nullable; +import android.app.AlarmManager; +import android.app.PendingIntent; +import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.content.res.Resources; import android.net.util.SharedLog; import android.os.Binder; import android.os.Bundle; import android.os.Handler; +import android.os.Looper; +import android.os.Message; import android.os.Parcel; import android.os.PersistableBundle; import android.os.ResultReceiver; +import android.os.SystemClock; import android.os.UserHandle; import android.provider.Settings; import android.telephony.CarrierConfigManager; @@ -46,48 +55,93 @@ import android.util.ArraySet; import android.util.Log; import android.util.SparseIntArray; -import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.StateMachine; import com.android.server.connectivity.MockableSystemProperties; +import java.io.PrintWriter; + /** - * This class encapsulates entitlement/provisioning mechanics - * provisioning check only applies to the use of the mobile network as an upstream + * Re-check tethering provisioning for enabled downstream tether types. + * Reference ConnectivityManager.TETHERING_{@code *} for each tether type. * + * All methods of this class must be accessed from the thread of tethering + * state machine. * @hide */ public class EntitlementManager { private static final String TAG = EntitlementManager.class.getSimpleName(); private static final boolean DBG = false; + @VisibleForTesting + protected static final String DISABLE_PROVISIONING_SYSPROP_KEY = "net.tethering.noprovisioning"; + private static final String ACTION_PROVISIONING_ALARM = + "com.android.server.connectivity.tethering.PROVISIONING_RECHECK_ALARM"; + // {@link ComponentName} of the Service used to run tether provisioning. private static final ComponentName TETHER_SERVICE = ComponentName.unflattenFromString( Resources.getSystem().getString(config_wifi_tether_enable)); - protected static final String DISABLE_PROVISIONING_SYSPROP_KEY = "net.tethering.noprovisioning"; + private static final int MS_PER_HOUR = 60 * 60 * 1000; + private static final int EVENT_START_PROVISIONING = 0; + private static final int EVENT_STOP_PROVISIONING = 1; + private static final int EVENT_UPSTREAM_CHANGED = 2; + private static final int EVENT_MAYBE_RUN_PROVISIONING = 3; + private static final int EVENT_GET_ENTITLEMENT_VALUE = 4; + // The ArraySet contains enabled downstream types, ex: // {@link ConnectivityManager.TETHERING_WIFI} // {@link ConnectivityManager.TETHERING_USB} // {@link ConnectivityManager.TETHERING_BLUETOOTH} - @GuardedBy("mCurrentTethers") private final ArraySet<Integer> mCurrentTethers; private final Context mContext; + private final int mPermissionChangeMessageCode; private final MockableSystemProperties mSystemProperties; private final SharedLog mLog; - private final Handler mMasterHandler; private final SparseIntArray mEntitlementCacheValue; - @Nullable - private TetheringConfiguration mConfig; + private final EntitlementHandler mHandler; + private @Nullable TetheringConfiguration mConfig; + private final StateMachine mTetherMasterSM; + // Key: ConnectivityManager.TETHERING_*(downstream). + // Value: ConnectivityManager.TETHER_ERROR_{NO_ERROR or PROVISION_FAILED}(provisioning result). + private final SparseIntArray mCellularPermitted; + private PendingIntent mProvisioningRecheckAlarm; + private boolean mCellularUpstreamPermitted = true; + private boolean mUsingCellularAsUpstream = false; + private boolean mNeedReRunProvisioningUi = false; + private OnUiEntitlementFailedListener mListener; public EntitlementManager(Context ctx, StateMachine tetherMasterSM, SharedLog log, - MockableSystemProperties systemProperties) { + int permissionChangeMessageCode, MockableSystemProperties systemProperties) { + mContext = ctx; mLog = log.forSubComponent(TAG); mCurrentTethers = new ArraySet<Integer>(); + mCellularPermitted = new SparseIntArray(); mSystemProperties = systemProperties; mEntitlementCacheValue = new SparseIntArray(); - mMasterHandler = tetherMasterSM.getHandler(); + mTetherMasterSM = tetherMasterSM; + mPermissionChangeMessageCode = permissionChangeMessageCode; + final Handler masterHandler = tetherMasterSM.getHandler(); + // Create entitlement's own handler which is associated with TetherMaster thread + // let all entitlement processes run in the same thread. + mHandler = new EntitlementHandler(masterHandler.getLooper()); + mContext.registerReceiver(mReceiver, new IntentFilter(ACTION_PROVISIONING_ALARM), + null, mHandler); + } + + public void setOnUiEntitlementFailedListener(final OnUiEntitlementFailedListener listener) { + mListener = listener; + } + + /** Callback fired when UI entitlement failed. */ + public interface OnUiEntitlementFailedListener { + /** + * Ui entitlement check fails in |downstream|. + * + * @param downstream tethering type from ConnectivityManager.TETHERING_{@code *}. + */ + void onUiEntitlementFailed(int downstream); } /** @@ -99,24 +153,118 @@ public class EntitlementManager { } /** - * Tell EntitlementManager that a given type of tethering has been enabled + * Check if cellular upstream is permitted. + */ + public boolean isCellularUpstreamPermitted() { + return mCellularUpstreamPermitted; + } + + /** + * This is called when tethering starts. + * Launch provisioning app if upstream is cellular. * - * @param type Tethering type + * @param downstreamType tethering type from ConnectivityManager.TETHERING_{@code *} + * @param showProvisioningUi a boolean indicating whether to show the + * provisioning app UI if there is one. */ - public void startTethering(int type) { - synchronized (mCurrentTethers) { - mCurrentTethers.add(type); + public void startProvisioningIfNeeded(int downstreamType, boolean showProvisioningUi) { + mHandler.sendMessage(mHandler.obtainMessage(EVENT_START_PROVISIONING, + downstreamType, encodeBool(showProvisioningUi))); + } + + private void handleStartProvisioningIfNeeded(int type, boolean showProvisioningUi) { + if (!isValidDownstreamType(type)) return; + + if (!mCurrentTethers.contains(type)) mCurrentTethers.add(type); + + if (isTetherProvisioningRequired()) { + // If provisioning is required and the result is not available yet, + // cellular upstream should not be allowed. + if (mCellularPermitted.size() == 0) { + mCellularUpstreamPermitted = false; + } + // If upstream is not cellular, provisioning app would not be launched + // till upstream change to cellular. + if (mUsingCellularAsUpstream) { + if (showProvisioningUi) { + runUiTetherProvisioning(type); + } else { + runSilentTetherProvisioning(type); + } + mNeedReRunProvisioningUi = false; + } else { + mNeedReRunProvisioningUi |= showProvisioningUi; + } + } else { + mCellularUpstreamPermitted = true; } } /** * Tell EntitlementManager that a given type of tethering has been disabled * - * @param type Tethering type + * @param type tethering type from ConnectivityManager.TETHERING_{@code *} + */ + public void stopProvisioningIfNeeded(int type) { + mHandler.sendMessage(mHandler.obtainMessage(EVENT_STOP_PROVISIONING, type, 0)); + } + + private void handleStopProvisioningIfNeeded(int type) { + if (!isValidDownstreamType(type)) return; + + mCurrentTethers.remove(type); + // There are lurking bugs where the notion of "provisioning required" or + // "tethering supported" may change without without tethering being notified properly. + // Remove the mapping all the time no matter provisioning is required or not. + removeDownstreamMapping(type); + } + + /** + * Notify EntitlementManager if upstream is cellular or not. + * + * @param isCellular whether tethering upstream is cellular. */ - public void stopTethering(int type) { - synchronized (mCurrentTethers) { - mCurrentTethers.remove(type); + public void notifyUpstream(boolean isCellular) { + mHandler.sendMessage(mHandler.obtainMessage( + EVENT_UPSTREAM_CHANGED, encodeBool(isCellular), 0)); + } + + private void handleNotifyUpstream(boolean isCellular) { + if (DBG) { + Log.d(TAG, "notifyUpstream: " + isCellular + + ", mCellularUpstreamPermitted: " + mCellularUpstreamPermitted + + ", mNeedReRunProvisioningUi: " + mNeedReRunProvisioningUi); + } + mUsingCellularAsUpstream = isCellular; + + if (mUsingCellularAsUpstream) { + handleMaybeRunProvisioning(); + } + } + + /** Run provisioning if needed */ + public void maybeRunProvisioning() { + mHandler.sendMessage(mHandler.obtainMessage(EVENT_MAYBE_RUN_PROVISIONING)); + } + + private void handleMaybeRunProvisioning() { + if (mCurrentTethers.size() == 0 || !isTetherProvisioningRequired()) { + return; + } + + // Whenever any entitlement value changes, all downstreams will re-evaluate whether they + // are allowed. Therefore even if the silent check here ends in a failure and the UI later + // yields success, then the downstream that got a failure will re-evaluate as a result of + // the change and get the new correct value. + for (Integer downstream : mCurrentTethers) { + if (mCellularPermitted.indexOfKey(downstream) < 0) { + if (mNeedReRunProvisioningUi) { + mNeedReRunProvisioningUi = false; + runUiTetherProvisioning(downstream); + } else { + runSilentTetherProvisioning(downstream); + } + } } } @@ -138,24 +286,48 @@ public class EntitlementManager { } /** - * Re-check tethering provisioning for enabled downstream tether types. + * Re-check tethering provisioning for all enabled tether types. * Reference ConnectivityManager.TETHERING_{@code *} for each tether type. + * + * Note: this method is only called from TetherMaster on the handler thread. + * If there are new callers from different threads, the logic should move to + * masterHandler to avoid race conditions. */ public void reevaluateSimCardProvisioning() { - synchronized (mEntitlementCacheValue) { - mEntitlementCacheValue.clear(); + if (DBG) Log.d(TAG, "reevaluateSimCardProvisioning"); + + if (!mHandler.getLooper().isCurrentThread()) { + // Except for test, this log should not appear in normal flow. + mLog.log("reevaluateSimCardProvisioning() don't run in TetherMaster thread"); } + mEntitlementCacheValue.clear(); + mCellularPermitted.clear(); - if (!mConfig.hasMobileHotspotProvisionApp()) return; - if (carrierConfigAffirmsEntitlementCheckNotRequired()) return; + // TODO: refine provisioning check to isTetherProvisioningRequired() ?? + if (!mConfig.hasMobileHotspotProvisionApp() + || carrierConfigAffirmsEntitlementCheckNotRequired()) { + evaluateCellularPermission(); + return; + } - final ArraySet<Integer> reevaluateType; - synchronized (mCurrentTethers) { - reevaluateType = new ArraySet<Integer>(mCurrentTethers); + if (mUsingCellularAsUpstream) { + handleMaybeRunProvisioning(); } - for (Integer type : reevaluateType) { - startProvisionIntent(type); + } + + /** Get carrier configuration bundle. */ + public PersistableBundle getCarrierConfig() { + final CarrierConfigManager configManager = (CarrierConfigManager) mContext + .getSystemService(Context.CARRIER_CONFIG_SERVICE); + if (configManager == null) return null; + + final PersistableBundle carrierConfig = configManager.getConfig(); + + if (CarrierConfigManager.isConfigForIdentifiedCarrier(carrierConfig)) { + return carrierConfig; } + + return null; } // The logic here is aimed solely at confirming that a CarrierConfig exists @@ -165,11 +337,7 @@ public class EntitlementManager { // entirely so that this is more intuitive. private boolean carrierConfigAffirmsEntitlementCheckNotRequired() { // Check carrier config for entitlement checks - final CarrierConfigManager configManager = (CarrierConfigManager) mContext - .getSystemService(Context.CARRIER_CONFIG_SERVICE); - if (configManager == null) return false; - - final PersistableBundle carrierConfig = configManager.getConfig(); + final PersistableBundle carrierConfig = getCarrierConfig(); if (carrierConfig == null) return false; // A CarrierConfigManager was found and it has a config. @@ -178,7 +346,16 @@ public class EntitlementManager { return !isEntitlementCheckRequired; } - public void runSilentTetherProvisioningAndEnable(int type, ResultReceiver receiver) { + /** + * Run no UI tethering provisioning check. + * @param type tethering type from ConnectivityManager.TETHERING_{@code *} + */ + protected void runSilentTetherProvisioning(int type) { + if (DBG) Log.d(TAG, "runSilentTetherProvisioning: " + type); + // For silent provisioning, settings would stop tethering when entitlement fail. + ResultReceiver receiver = buildProxyReceiver(type, + false/* notifyFail */, null); + Intent intent = new Intent(); intent.putExtra(EXTRA_ADD_TETHER_TYPE, type); intent.putExtra(EXTRA_RUN_PROVISION, true); @@ -192,12 +369,21 @@ public class EntitlementManager { } } - public void runUiTetherProvisioningAndEnable(int type, ResultReceiver receiver) { + /** + * Run the UI-enabled tethering provisioning check. + * @param type tethering type from ConnectivityManager.TETHERING_{@code *} + */ + @VisibleForTesting + protected void runUiTetherProvisioning(int type) { + ResultReceiver receiver = buildProxyReceiver(type, + true/* notifyFail */, null); runUiTetherProvisioning(type, receiver); } @VisibleForTesting protected void runUiTetherProvisioning(int type, ResultReceiver receiver) { + if (DBG) Log.d(TAG, "runUiTetherProvisioning: " + type); + Intent intent = new Intent(Settings.ACTION_TETHER_PROVISIONING); intent.putExtra(EXTRA_ADD_TETHER_TYPE, type); intent.putExtra(EXTRA_PROVISION_CALLBACK, receiver); @@ -210,56 +396,210 @@ public class EntitlementManager { } } - // Used by the SIM card change observation code. - // TODO: De-duplicate with above code, where possible. - private void startProvisionIntent(int tetherType) { - final Intent startProvIntent = new Intent(); - startProvIntent.putExtra(EXTRA_ADD_TETHER_TYPE, tetherType); - startProvIntent.putExtra(EXTRA_RUN_PROVISION, true); - startProvIntent.setComponent(TETHER_SERVICE); - mContext.startServiceAsUser(startProvIntent, UserHandle.CURRENT); + // Not needed to check if this don't run on the handler thread because it's private. + private void scheduleProvisioningRechecks() { + if (mProvisioningRecheckAlarm == null) { + final int period = mConfig.provisioningCheckPeriod; + if (period <= 0) return; + + Intent intent = new Intent(ACTION_PROVISIONING_ALARM); + mProvisioningRecheckAlarm = PendingIntent.getBroadcast(mContext, 0, intent, 0); + AlarmManager alarmManager = (AlarmManager) mContext.getSystemService( + Context.ALARM_SERVICE); + long periodMs = period * MS_PER_HOUR; + long firstAlarmTime = SystemClock.elapsedRealtime() + periodMs; + alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME, firstAlarmTime, periodMs, + mProvisioningRecheckAlarm); + } + } + + private void cancelTetherProvisioningRechecks() { + if (mProvisioningRecheckAlarm != null) { + AlarmManager alarmManager = (AlarmManager) mContext.getSystemService( + Context.ALARM_SERVICE); + alarmManager.cancel(mProvisioningRecheckAlarm); + mProvisioningRecheckAlarm = null; + } } - public void scheduleProvisioningRechecks(int type) { - Intent intent = new Intent(); - intent.putExtra(EXTRA_ADD_TETHER_TYPE, type); - intent.putExtra(EXTRA_SET_ALARM, true); - intent.setComponent(TETHER_SERVICE); - final long ident = Binder.clearCallingIdentity(); - try { - mContext.startServiceAsUser(intent, UserHandle.CURRENT); - } finally { - Binder.restoreCallingIdentity(ident); + private void evaluateCellularPermission() { + final boolean oldPermitted = mCellularUpstreamPermitted; + mCellularUpstreamPermitted = (!isTetherProvisioningRequired() + || mCellularPermitted.indexOfValue(TETHER_ERROR_NO_ERROR) > -1); + + if (DBG) { + Log.d(TAG, "Cellular permission change from " + oldPermitted + + " to " + mCellularUpstreamPermitted); + } + + if (mCellularUpstreamPermitted != oldPermitted) { + mLog.log("Cellular permission change: " + mCellularUpstreamPermitted); + mTetherMasterSM.sendMessage(mPermissionChangeMessageCode); + } + // Only schedule periodic re-check when tether is provisioned + // and the result is ok. + if (mCellularUpstreamPermitted && mCellularPermitted.size() > 0) { + scheduleProvisioningRechecks(); + } else { + cancelTetherProvisioningRechecks(); } } - public void cancelTetherProvisioningRechecks(int type) { - Intent intent = new Intent(); - intent.putExtra(EXTRA_REM_TETHER_TYPE, type); - intent.setComponent(TETHER_SERVICE); - final long ident = Binder.clearCallingIdentity(); - try { - mContext.startServiceAsUser(intent, UserHandle.CURRENT); - } finally { - Binder.restoreCallingIdentity(ident); + /** + * Add the mapping between provisioning result and tethering type. + * Notify UpstreamNetworkMonitor if Cellular permission changes. + * + * @param type tethering type from ConnectivityManager.TETHERING_{@code *} + * @param resultCode Provisioning result + */ + protected void addDownstreamMapping(int type, int resultCode) { + if (DBG) { + Log.d(TAG, "addDownstreamMapping: " + type + ", result: " + resultCode + + " ,TetherTypeRequested: " + mCurrentTethers.contains(type)); } + if (!mCurrentTethers.contains(type)) return; + + mCellularPermitted.put(type, resultCode); + evaluateCellularPermission(); } - private ResultReceiver buildProxyReceiver(int type, final ResultReceiver receiver) { - ResultReceiver rr = new ResultReceiver(mMasterHandler) { + /** + * Remove the mapping for input tethering type. + * @param type tethering type from ConnectivityManager.TETHERING_{@code *} + */ + protected void removeDownstreamMapping(int type) { + if (DBG) Log.d(TAG, "removeDownstreamMapping: " + type); + mCellularPermitted.delete(type); + evaluateCellularPermission(); + } + + private final BroadcastReceiver mReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (ACTION_PROVISIONING_ALARM.equals(intent.getAction())) { + mLog.log("Received provisioning alarm"); + reevaluateSimCardProvisioning(); + } + } + }; + + private class EntitlementHandler extends Handler { + EntitlementHandler(Looper looper) { + super(looper); + } + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case EVENT_START_PROVISIONING: + handleStartProvisioningIfNeeded(msg.arg1, toBool(msg.arg2)); + break; + case EVENT_STOP_PROVISIONING: + handleStopProvisioningIfNeeded(msg.arg1); + break; + case EVENT_UPSTREAM_CHANGED: + handleNotifyUpstream(toBool(msg.arg1)); + break; + case EVENT_MAYBE_RUN_PROVISIONING: + handleMaybeRunProvisioning(); + break; + case EVENT_GET_ENTITLEMENT_VALUE: + handleGetLatestTetheringEntitlementValue(msg.arg1, (ResultReceiver) msg.obj, + toBool(msg.arg2)); + break; + default: + mLog.log("Unknown event: " + msg.what); + break; + } + } + } + + private static boolean toBool(int encodedBoolean) { + return encodedBoolean != 0; + } + + private static int encodeBool(boolean b) { + return b ? 1 : 0; + } + + private static boolean isValidDownstreamType(int type) { + switch (type) { + case TETHERING_BLUETOOTH: + case TETHERING_USB: + case TETHERING_WIFI: + return true; + default: + return false; + } + } + + /** + * Dump the infromation of EntitlementManager. + * @param pw {@link PrintWriter} is used to print formatted + */ + public void dump(PrintWriter pw) { + pw.print("mCellularUpstreamPermitted: "); + pw.println(mCellularUpstreamPermitted); + for (Integer type : mCurrentTethers) { + pw.print("Type: "); + pw.print(typeString(type)); + if (mCellularPermitted.indexOfKey(type) > -1) { + pw.print(", Value: "); + pw.println(errorString(mCellularPermitted.get(type))); + } else { + pw.println(", Value: empty"); + } + } + } + + private static String typeString(int type) { + switch (type) { + case TETHERING_BLUETOOTH: return "TETHERING_BLUETOOTH"; + case TETHERING_INVALID: return "TETHERING_INVALID"; + case TETHERING_USB: return "TETHERING_USB"; + case TETHERING_WIFI: return "TETHERING_WIFI"; + default: + return String.format("TETHERING UNKNOWN TYPE (%d)", type); + } + } + + private static String errorString(int value) { + switch (value) { + case TETHER_ERROR_ENTITLEMENT_UNKONWN: return "TETHER_ERROR_ENTITLEMENT_UNKONWN"; + case TETHER_ERROR_NO_ERROR: return "TETHER_ERROR_NO_ERROR"; + case TETHER_ERROR_PROVISION_FAILED: return "TETHER_ERROR_PROVISION_FAILED"; + default: + return String.format("UNKNOWN ERROR (%d)", value); + } + } + + private ResultReceiver buildProxyReceiver(int type, boolean notifyFail, + final ResultReceiver receiver) { + ResultReceiver rr = new ResultReceiver(mHandler) { @Override protected void onReceiveResult(int resultCode, Bundle resultData) { int updatedCacheValue = updateEntitlementCacheValue(type, resultCode); - receiver.send(updatedCacheValue, null); + addDownstreamMapping(type, updatedCacheValue); + if (updatedCacheValue == TETHER_ERROR_PROVISION_FAILED && notifyFail) { + mListener.onUiEntitlementFailed(type); + } + if (receiver != null) receiver.send(updatedCacheValue, null); } }; return writeToParcel(rr); } + // Instances of ResultReceiver need to be public classes for remote processes to be able + // to load them (otherwise, ClassNotFoundException). For private classes, this method + // performs a trick : round-trip parceling any instance of ResultReceiver will return a + // vanilla instance of ResultReceiver sharing the binder token with the original receiver. + // The binder token has a reference to the original instance of the private class and will + // still call its methods, and can be sent over. However it cannot be used for anything + // else than sending over a Binder call. + // While round-trip parceling is not great, there is currently no other way of generating + // a vanilla instance of ResultReceiver because all its fields are private. private ResultReceiver writeToParcel(final ResultReceiver receiver) { - // This is necessary to avoid unmarshalling issues when sending the receiver - // across processes. Parcel parcel = Parcel.obtain(); receiver.writeToParcel(parcel, 0); parcel.setDataPosition(0); @@ -275,38 +615,41 @@ public class EntitlementManager { * @param resultCode last entitlement value * @return the last updated entitlement value */ - public int updateEntitlementCacheValue(int type, int resultCode) { + private int updateEntitlementCacheValue(int type, int resultCode) { if (DBG) { Log.d(TAG, "updateEntitlementCacheValue: " + type + ", result: " + resultCode); } - synchronized (mEntitlementCacheValue) { - if (resultCode == TETHER_ERROR_NO_ERROR) { - mEntitlementCacheValue.put(type, resultCode); - return resultCode; - } else { - mEntitlementCacheValue.put(type, TETHER_ERROR_PROVISION_FAILED); - return TETHER_ERROR_PROVISION_FAILED; - } + if (resultCode == TETHER_ERROR_NO_ERROR) { + mEntitlementCacheValue.put(type, resultCode); + return resultCode; + } else { + mEntitlementCacheValue.put(type, TETHER_ERROR_PROVISION_FAILED); + return TETHER_ERROR_PROVISION_FAILED; } } /** Get the last value of the tethering entitlement check. */ public void getLatestTetheringEntitlementResult(int downstream, ResultReceiver receiver, boolean showEntitlementUi) { + mHandler.sendMessage(mHandler.obtainMessage(EVENT_GET_ENTITLEMENT_VALUE, + downstream, encodeBool(showEntitlementUi), receiver)); + + } + + private void handleGetLatestTetheringEntitlementValue(int downstream, ResultReceiver receiver, + boolean showEntitlementUi) { + if (!isTetherProvisioningRequired()) { receiver.send(TETHER_ERROR_NO_ERROR, null); return; } - final int cacheValue; - synchronized (mEntitlementCacheValue) { - cacheValue = mEntitlementCacheValue.get( + final int cacheValue = mEntitlementCacheValue.get( downstream, TETHER_ERROR_ENTITLEMENT_UNKONWN); - } if (cacheValue == TETHER_ERROR_NO_ERROR || !showEntitlementUi) { receiver.send(cacheValue, null); } else { - ResultReceiver proxy = buildProxyReceiver(downstream, receiver); + ResultReceiver proxy = buildProxyReceiver(downstream, false/* notifyFail */, receiver); runUiTetherProvisioning(downstream, proxy); } } diff --git a/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java b/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java index 935b79546d63..8427b6eceab9 100644 --- a/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java +++ b/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java @@ -30,6 +30,7 @@ import static com.android.internal.R.array.config_tether_upstream_types; import static com.android.internal.R.array.config_tether_usb_regexs; import static com.android.internal.R.array.config_tether_wifi_regexs; import static com.android.internal.R.bool.config_tether_upstream_automatic; +import static com.android.internal.R.integer.config_mobile_hotspot_provision_check_period; import static com.android.internal.R.string.config_mobile_hotspot_provision_app_no_ui; import android.content.ContentResolver; @@ -94,6 +95,7 @@ public class TetheringConfiguration { public final String[] provisioningApp; public final String provisioningAppNoUi; + public final int provisioningCheckPeriod; public final int subId; @@ -121,6 +123,9 @@ public class TetheringConfiguration { provisioningApp = getResourceStringArray(res, config_mobile_hotspot_provision_app); provisioningAppNoUi = getProvisioningAppNoUi(res); + provisioningCheckPeriod = getResourceInteger(res, + config_mobile_hotspot_provision_check_period, + 0 /* No periodic re-check */); configLog.log(toString()); } @@ -311,6 +316,14 @@ public class TetheringConfiguration { } } + private static int getResourceInteger(Resources res, int resId, int defaultValue) { + try { + return res.getInteger(resId); + } catch (Resources.NotFoundException e404) { + return defaultValue; + } + } + private static boolean getEnableLegacyDhcpServer(Context ctx) { final ContentResolver cr = ctx.getContentResolver(); final int intVal = Settings.Global.getInt(cr, TETHER_ENABLE_LEGACY_DHCP_SERVER, 0); diff --git a/services/core/java/com/android/server/connectivity/tethering/TetheringDependencies.java b/services/core/java/com/android/server/connectivity/tethering/TetheringDependencies.java index 173d7860e4ac..a0aad7c50481 100644 --- a/services/core/java/com/android/server/connectivity/tethering/TetheringDependencies.java +++ b/services/core/java/com/android/server/connectivity/tethering/TetheringDependencies.java @@ -83,8 +83,8 @@ public class TetheringDependencies { * Get a reference to the EntitlementManager to be used by tethering. */ public EntitlementManager getEntitlementManager(Context ctx, StateMachine target, - SharedLog log, MockableSystemProperties systemProperties) { - return new EntitlementManager(ctx, target, log, systemProperties); + SharedLog log, int what, MockableSystemProperties systemProperties) { + return new EntitlementManager(ctx, target, log, what, systemProperties); } /** diff --git a/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java b/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java index 3ac311b3e13a..3a9e21f943d8 100644 --- a/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java +++ b/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java @@ -16,36 +16,32 @@ package com.android.server.connectivity.tethering; -import static android.net.ConnectivityManager.getNetworkTypeName; -import static android.net.ConnectivityManager.TYPE_NONE; import static android.net.ConnectivityManager.TYPE_MOBILE_DUN; import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI; +import static android.net.ConnectivityManager.TYPE_NONE; +import static android.net.ConnectivityManager.getNetworkTypeName; import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import android.content.Context; -import android.os.Handler; -import android.os.Looper; -import android.os.Process; import android.net.ConnectivityManager; import android.net.ConnectivityManager.NetworkCallback; import android.net.IpPrefix; -import android.net.LinkAddress; import android.net.LinkProperties; import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkRequest; import android.net.NetworkState; -import android.net.util.NetworkConstants; import android.net.util.PrefixUtils; import android.net.util.SharedLog; +import android.os.Handler; +import android.os.Process; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.StateMachine; -import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Set; @@ -97,10 +93,13 @@ public class UpstreamNetworkMonitor { private final HashMap<Network, NetworkState> mNetworkMap = new HashMap<>(); private HashSet<IpPrefix> mLocalPrefixes; private ConnectivityManager mCM; + private EntitlementManager mEntitlementMgr; private NetworkCallback mListenAllCallback; private NetworkCallback mDefaultNetworkCallback; private NetworkCallback mMobileNetworkCallback; private boolean mDunRequired; + // Whether the current default upstream is mobile or not. + private boolean mIsDefaultCellularUpstream; // The current system default network (not really used yet). private Network mDefaultInternetNetwork; // The current upstream network used for tethering. @@ -113,6 +112,7 @@ public class UpstreamNetworkMonitor { mLog = log.forSubComponent(TAG); mWhat = what; mLocalPrefixes = new HashSet<>(); + mIsDefaultCellularUpstream = false; } @VisibleForTesting @@ -122,7 +122,15 @@ public class UpstreamNetworkMonitor { mCM = cm; } - public void startTrackDefaultNetwork(NetworkRequest defaultNetworkRequest) { + /** + * Tracking the system default network. This method should be called when system is ready. + * + * @param defaultNetworkRequest should be the same as ConnectivityService default request + * @param entitle a EntitlementManager object to communicate between EntitlementManager and + * UpstreamNetworkMonitor + */ + public void startTrackDefaultNetwork(NetworkRequest defaultNetworkRequest, + EntitlementManager entitle) { // This is not really a "request", just a way of tracking the system default network. // It's guaranteed not to actually bring up any networks because it's the same request // as the ConnectivityService default request, and thus shares fate with it. We can't @@ -133,6 +141,9 @@ public class UpstreamNetworkMonitor { mDefaultNetworkCallback = new UpstreamNetworkCallback(CALLBACK_DEFAULT_INTERNET); cm().requestNetwork(trackDefaultRequest, mDefaultNetworkCallback, mHandler); } + if (mEntitlementMgr == null) { + mEntitlementMgr = entitle; + } } public void startObserveAllNetworks() { @@ -168,11 +179,15 @@ public class UpstreamNetworkMonitor { } public void registerMobileNetworkRequest() { + if (!isCellularUpstreamPermitted()) { + mLog.i("registerMobileNetworkRequest() is not permitted"); + releaseMobileNetworkRequest(); + return; + } if (mMobileNetworkCallback != null) { mLog.e("registerMobileNetworkRequest() already registered"); return; } - // The following use of the legacy type system cannot be removed until // after upstream selection no longer finds networks by legacy type. // See also http://b/34364553 . @@ -206,29 +221,32 @@ public class UpstreamNetworkMonitor { // becomes available and useful we (a) file a request to keep it up as // necessary and (b) change all upstream tracking state accordingly (by // passing LinkProperties up to Tethering). - // - // Next TODO: return NetworkState instead of just the type. public NetworkState selectPreferredUpstreamType(Iterable<Integer> preferredTypes) { final TypeStatePair typeStatePair = findFirstAvailableUpstreamByType( - mNetworkMap.values(), preferredTypes); + mNetworkMap.values(), preferredTypes, isCellularUpstreamPermitted()); mLog.log("preferred upstream type: " + getNetworkTypeName(typeStatePair.type)); switch (typeStatePair.type) { case TYPE_MOBILE_DUN: case TYPE_MOBILE_HIPRI: + // Tethering just selected mobile upstream in spite of the default network being + // not mobile. This can happen because of the priority list. + // Notify EntitlementManager to check permission for using mobile upstream. + if (!mIsDefaultCellularUpstream) { + mEntitlementMgr.maybeRunProvisioning(); + } // If we're on DUN, put our own grab on it. registerMobileNetworkRequest(); break; case TYPE_NONE: + // If we found NONE and mobile upstream is permitted we don't want to do this + // as we want any previous requests to keep trying to bring up something we can use. + if (!isCellularUpstreamPermitted()) releaseMobileNetworkRequest(); break; default: - /* If we've found an active upstream connection that's not DUN/HIPRI - * we should stop any outstanding DUN/HIPRI requests. - * - * If we found NONE we don't want to do this as we want any previous - * requests to keep trying to bring up something we can use. - */ + // If we've found an active upstream connection that's not DUN/HIPRI + // we should stop any outstanding DUN/HIPRI requests. releaseMobileNetworkRequest(); break; } @@ -241,10 +259,12 @@ public class UpstreamNetworkMonitor { final NetworkState dfltState = (mDefaultInternetNetwork != null) ? mNetworkMap.get(mDefaultInternetNetwork) : null; - if (!mDunRequired) return dfltState; - if (isNetworkUsableAndNotCellular(dfltState)) return dfltState; + if (!isCellularUpstreamPermitted()) return null; + + if (!mDunRequired) return dfltState; + // Find a DUN network. Note that code in Tethering causes a DUN request // to be filed, but this might be moved into this class in future. return findFirstDunNetwork(mNetworkMap.values()); @@ -258,6 +278,15 @@ public class UpstreamNetworkMonitor { return (Set<IpPrefix>) mLocalPrefixes.clone(); } + private boolean isCellularUpstreamPermitted() { + if (mEntitlementMgr != null) { + return mEntitlementMgr.isCellularUpstreamPermitted(); + } else { + // This flow should only happens in testing. + return true; + } + } + private void handleAvailable(Network network) { if (mNetworkMap.containsKey(network)) return; @@ -388,8 +417,14 @@ public class UpstreamNetworkMonitor { public void onCapabilitiesChanged(Network network, NetworkCapabilities newNc) { if (mCallbackType == CALLBACK_DEFAULT_INTERNET) { mDefaultInternetNetwork = network; + final boolean newIsCellular = isCellular(newNc); + if (mIsDefaultCellularUpstream != newIsCellular) { + mIsDefaultCellularUpstream = newIsCellular; + mEntitlementMgr.notifyUpstream(newIsCellular); + } return; } + handleNetCap(network, newNc); } @@ -424,8 +459,11 @@ public class UpstreamNetworkMonitor { public void onLost(Network network) { if (mCallbackType == CALLBACK_DEFAULT_INTERNET) { mDefaultInternetNetwork = null; + mIsDefaultCellularUpstream = false; + mEntitlementMgr.notifyUpstream(false); return; } + handleLost(network); // Any non-LISTEN_ALL callback will necessarily concern a network that will // also match the LISTEN_ALL callback by construction of the LISTEN_ALL callback. @@ -454,7 +492,8 @@ public class UpstreamNetworkMonitor { } private static TypeStatePair findFirstAvailableUpstreamByType( - Iterable<NetworkState> netStates, Iterable<Integer> preferredTypes) { + Iterable<NetworkState> netStates, Iterable<Integer> preferredTypes, + boolean isCellularUpstreamPermitted) { final TypeStatePair result = new TypeStatePair(); for (int type : preferredTypes) { @@ -466,6 +505,10 @@ public class UpstreamNetworkMonitor { ConnectivityManager.getNetworkTypeName(type)); continue; } + if (!isCellularUpstreamPermitted && isCellular(nc)) { + continue; + } + nc.setSingleUid(Process.myUid()); for (NetworkState value : netStates) { diff --git a/services/core/java/com/android/server/media/projection/OWNERS b/services/core/java/com/android/server/media/projection/OWNERS new file mode 100644 index 000000000000..7e7335d68d3b --- /dev/null +++ b/services/core/java/com/android/server/media/projection/OWNERS @@ -0,0 +1 @@ +michaelwr@google.com diff --git a/services/core/java/com/android/server/net/NetworkStatsRecorder.java b/services/core/java/com/android/server/net/NetworkStatsRecorder.java index a2e7e0cae96b..bdff50053fae 100644 --- a/services/core/java/com/android/server/net/NetworkStatsRecorder.java +++ b/services/core/java/com/android/server/net/NetworkStatsRecorder.java @@ -41,10 +41,10 @@ import com.android.internal.net.VpnInfo; import com.android.internal.util.FileRotator; import com.android.internal.util.IndentingPrintWriter; -import libcore.io.IoUtils; - import com.google.android.collect.Sets; +import libcore.io.IoUtils; + import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.File; @@ -234,7 +234,7 @@ public class NetworkStatsRecorder { if (vpnArray != null) { for (VpnInfo info : vpnArray) { - delta.migrateTun(info.ownerUid, info.vpnIface, info.primaryUnderlyingIface); + delta.migrateTun(info.ownerUid, info.vpnIface, info.underlyingIfaces); } } diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 8fa435cd9381..4c076781731c 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -292,6 +292,22 @@ public class NetworkStatsService extends INetworkStatsService.Stub { /** Data layer operation counters for splicing into other structures. */ private NetworkStats mUidOperations = new NetworkStats(0L, 10); + /** + * Snapshot containing most recent network stats for all UIDs across all interfaces and tags + * since boot. + * + * <p>Maintains migrated VPN stats which are result of performing TUN migration on {@link + * #mLastUidDetailSnapshot}. + */ + @GuardedBy("mStatsLock") + private NetworkStats mTunAdjustedStats; + /** + * Used by {@link #mTunAdjustedStats} to migrate VPN traffic over delta between this snapshot + * and latest snapshot. + */ + @GuardedBy("mStatsLock") + private NetworkStats mLastUidDetailSnapshot; + /** Must be set in factory by calling #setHandler. */ private Handler mHandler; private Handler.Callback mHandlerCallback; @@ -805,15 +821,39 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public NetworkStats getDetailedUidStats(String[] requiredIfaces) { try { + // Get the latest snapshot from NetworkStatsFactory. + // TODO: Querying for INTERFACES_ALL may incur performance penalty. Consider restricting + // this to limited set of ifaces. + NetworkStats uidDetailStats = getNetworkStatsUidDetail(INTERFACES_ALL); + + // Migrate traffic from VPN UID over delta and update mTunAdjustedStats. + NetworkStats result; + synchronized (mStatsLock) { + migrateTunTraffic(uidDetailStats, mVpnInfos); + result = mTunAdjustedStats.clone(); + } + + // Apply filter based on ifacesToQuery. final String[] ifacesToQuery = NetworkStatsFactory.augmentWithStackedInterfaces(requiredIfaces); - return getNetworkStatsUidDetail(ifacesToQuery); + result.filter(UID_ALL, ifacesToQuery, TAG_ALL); + return result; } catch (RemoteException e) { Log.wtf(TAG, "Error compiling UID stats", e); return new NetworkStats(0L, 0); } } + @VisibleForTesting + NetworkStats getTunAdjustedStats() { + synchronized (mStatsLock) { + if (mTunAdjustedStats == null) { + return null; + } + return mTunAdjustedStats.clone(); + } + } + @Override public String[] getMobileIfaces() { return mMobileIfaces; @@ -1288,6 +1328,34 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // a race condition between the service handler thread and the observer's mStatsObservers.updateStats(xtSnapshot, uidSnapshot, new ArrayMap<>(mActiveIfaces), new ArrayMap<>(mActiveUidIfaces), vpnArray, currentTime); + + migrateTunTraffic(uidSnapshot, vpnArray); + } + + /** + * Updates {@link #mTunAdjustedStats} with the delta containing traffic migrated off of VPNs. + */ + @GuardedBy("mStatsLock") + private void migrateTunTraffic(NetworkStats uidDetailStats, VpnInfo[] vpnInfoArray) { + if (mTunAdjustedStats == null) { + // Either device booted or system server restarted, hence traffic cannot be migrated + // correctly without knowing the past state of VPN's underlying networks. + mTunAdjustedStats = uidDetailStats; + mLastUidDetailSnapshot = uidDetailStats; + return; + } + // Migrate delta traffic from VPN to other apps. + NetworkStats delta = uidDetailStats.subtract(mLastUidDetailSnapshot); + for (VpnInfo info : vpnInfoArray) { + delta.migrateTun(info.ownerUid, info.vpnIface, info.underlyingIfaces); + } + // Filter out debug entries as that may lead to over counting. + delta.filterDebugEntries(); + // Update #mTunAdjustedStats with migrated delta. + mTunAdjustedStats.combineAllValues(delta); + mTunAdjustedStats.setElapsedRealtime(uidDetailStats.getElapsedRealtime()); + // Update last snapshot. + mLastUidDetailSnapshot = uidDetailStats; } /** diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java index da6e9c02c96a..abd85cd35f57 100644 --- a/services/core/java/com/android/server/notification/RankingHelper.java +++ b/services/core/java/com/android/server/notification/RankingHelper.java @@ -1401,11 +1401,14 @@ public class RankingHelper implements RankingConfig { } // Package upgrade try { - Record fullRecord = getRecord(pkg, - mPm.getPackageUidAsUser(pkg, changeUserId)); - if (fullRecord != null) { - createDefaultChannelIfNeeded(fullRecord); - deleteDefaultChannelIfNeeded(fullRecord); + synchronized (mRecords) { + final String key = recordKey(pkg, + mPm.getPackageUidAsUser(pkg, changeUserId)); + Record fullRecord = mRecords.get(key); + if (fullRecord != null) { + createDefaultChannelIfNeeded(fullRecord); + deleteDefaultChannelIfNeeded(fullRecord); + } } } catch (NameNotFoundException e) {} } diff --git a/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java b/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java index 5c0874d7977a..c98a79ad4ed9 100644 --- a/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java +++ b/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java @@ -174,7 +174,11 @@ class BugreportManagerServiceImpl extends IDumpstate.Stub { ds.startBugreport(callingUid, callingPackage, bugreportFd, screenshotFd, bugreportMode, myListener); } catch (RemoteException e) { - reportError(listener, IDumpstateListener.BUGREPORT_ERROR_RUNTIME_ERROR); + // bugreportd service is already started now. We need to kill it to manage the + // lifecycle correctly. If we don't subsequent callers will get + // BUGREPORT_ERROR_ANOTHER_REPORT_IN_PROGRESS error. + // Note that listener will be notified by the death recipient below. + cancelBugreport(); } } diff --git a/services/core/java/com/android/server/policy/EventLogTags.logtags b/services/core/java/com/android/server/policy/EventLogTags.logtags new file mode 100644 index 000000000000..75633820d01f --- /dev/null +++ b/services/core/java/com/android/server/policy/EventLogTags.logtags @@ -0,0 +1,8 @@ +# See system/core/logcat/event.logtags for a description of the format of this file. + +option java_package com.android.server.policy + + +# 0 for screen off, 1 for screen on +70000 screen_toggled (screen_state|1|5) +70001 intercept_power (action|3),(mPowerKeyHandled|1),(mPowerKeyPressCounter|1) diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 9a741bcfc3d6..0149d30da6bd 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -225,7 +225,6 @@ import android.speech.RecognizerIntent; import android.telecom.TelecomManager; import android.util.ArraySet; import android.util.DisplayMetrics; -import android.util.EventLog; import android.util.Log; import android.util.LongSparseArray; import android.util.MutableBoolean; @@ -270,12 +269,11 @@ import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto; import com.android.internal.policy.IKeyguardDismissCallback; import com.android.internal.policy.IShortcutService; -import com.android.internal.policy.KeyguardDismissCallback; import com.android.internal.policy.PhoneWindow; import com.android.internal.statusbar.IStatusBarService; import com.android.internal.util.ArrayUtils; -import com.android.internal.util.ScreenshotHelper; import com.android.internal.util.ScreenShapeHelper; +import com.android.internal.util.ScreenshotHelper; import com.android.internal.widget.PointerLocationView; import com.android.server.GestureLauncherService; import com.android.server.LocalServices; @@ -6247,6 +6245,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { } case KeyEvent.KEYCODE_POWER: { + EventLogTags.writeInterceptPower( + KeyEvent.actionToString(event.getAction()), + mPowerKeyHandled ? 1 : 0, mPowerKeyPressCounter); // Any activity on the power button stops the accessibility shortcut cancelPendingAccessibilityShortcutAction(); result &= ~ACTION_PASS_TO_USER; @@ -6785,7 +6786,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { // Called on the PowerManager's Notifier thread. @Override public void finishedGoingToSleep(int why) { - EventLog.writeEvent(70000, 0); + EventLogTags.writeScreenToggled(0); if (DEBUG_WAKEUP) Slog.i(TAG, "Finished going to sleep... (why=" + why + ")"); MetricsLogger.histogram(mContext, "screen_timeout", mLockScreenTimeout / 1000); @@ -6810,7 +6811,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { // Called on the PowerManager's Notifier thread. @Override public void startedWakingUp() { - EventLog.writeEvent(70000, 1); + EventLogTags.writeScreenToggled(1); if (DEBUG_WAKEUP) Slog.i(TAG, "Started waking up..."); // Since goToSleep performs these functions synchronously, we must diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java index bf349efba11f..c62be3ba2a05 100644 --- a/services/core/java/com/android/server/stats/StatsCompanionService.java +++ b/services/core/java/com/android/server/stats/StatsCompanionService.java @@ -32,6 +32,7 @@ import android.content.IntentSender; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.UserInfo; +import android.net.INetworkStatsService; import android.net.NetworkStats; import android.net.wifi.IWifiManager; import android.net.wifi.WifiActivityEnergyInfo; @@ -63,7 +64,6 @@ import android.util.Slog; import android.util.StatsLog; import com.android.internal.annotations.GuardedBy; -import com.android.internal.net.NetworkStatsFactory; import com.android.internal.os.KernelCpuSpeedReader; import com.android.internal.os.KernelUidCpuTimeReader; import com.android.internal.os.KernelUidCpuClusterTimeReader; @@ -123,6 +123,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { private final Context mContext; private final AlarmManager mAlarmManager; + private final INetworkStatsService mNetworkStatsService; @GuardedBy("sStatsdLock") private static IStatsManager sStatsd; private static final Object sStatsdLock = new Object(); @@ -162,6 +163,8 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { super(); mContext = context; mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); + mNetworkStatsService = INetworkStatsService.Stub.asInterface( + ServiceManager.getService(Context.NETWORK_STATS_SERVICE)); mAnomalyAlarmIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(mContext, AnomalyAlarmReceiver.class), 0); @@ -651,13 +654,14 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { if (ifaces.length == 0) { return; } - NetworkStatsFactory nsf = new NetworkStatsFactory(); + if (mNetworkStatsService == null) { + Slog.e(TAG, "NetworkStats Service is not available!"); + return; + } // Combine all the metrics per Uid into one record. - NetworkStats stats = - nsf.readNetworkStatsDetail(NetworkStats.UID_ALL, ifaces, NetworkStats.TAG_NONE, null) - .groupedByUid(); + NetworkStats stats = mNetworkStatsService.getDetailedUidStats(ifaces).groupedByUid(); addNetworkStats(tagId, pulledData, stats, false); - } catch (java.io.IOException e) { + } catch (RemoteException e) { Slog.e(TAG, "Pulling netstats for wifi bytes has error", e); } finally { Binder.restoreCallingIdentity(token); @@ -672,11 +676,14 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { if (ifaces.length == 0) { return; } - NetworkStatsFactory nsf = new NetworkStatsFactory(); + if (mNetworkStatsService == null) { + Slog.e(TAG, "NetworkStats Service is not available!"); + return; + } NetworkStats stats = rollupNetworkStatsByFGBG( - nsf.readNetworkStatsDetail(NetworkStats.UID_ALL, ifaces, NetworkStats.TAG_NONE, null)); + mNetworkStatsService.getDetailedUidStats(ifaces)); addNetworkStats(tagId, pulledData, stats, true); - } catch (java.io.IOException e) { + } catch (RemoteException e) { Slog.e(TAG, "Pulling netstats for wifi bytes w/ fg/bg has error", e); } finally { Binder.restoreCallingIdentity(token); @@ -691,13 +698,14 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { if (ifaces.length == 0) { return; } - NetworkStatsFactory nsf = new NetworkStatsFactory(); + if (mNetworkStatsService == null) { + Slog.e(TAG, "NetworkStats Service is not available!"); + return; + } // Combine all the metrics per Uid into one record. - NetworkStats stats = - nsf.readNetworkStatsDetail(NetworkStats.UID_ALL, ifaces, NetworkStats.TAG_NONE, null) - .groupedByUid(); + NetworkStats stats = mNetworkStatsService.getDetailedUidStats(ifaces).groupedByUid(); addNetworkStats(tagId, pulledData, stats, false); - } catch (java.io.IOException e) { + } catch (RemoteException e) { Slog.e(TAG, "Pulling netstats for mobile bytes has error", e); } finally { Binder.restoreCallingIdentity(token); @@ -726,11 +734,14 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { if (ifaces.length == 0) { return; } - NetworkStatsFactory nsf = new NetworkStatsFactory(); + if (mNetworkStatsService == null) { + Slog.e(TAG, "NetworkStats Service is not available!"); + return; + } NetworkStats stats = rollupNetworkStatsByFGBG( - nsf.readNetworkStatsDetail(NetworkStats.UID_ALL, ifaces, NetworkStats.TAG_NONE, null)); + mNetworkStatsService.getDetailedUidStats(ifaces)); addNetworkStats(tagId, pulledData, stats, true); - } catch (java.io.IOException e) { + } catch (RemoteException e) { Slog.e(TAG, "Pulling netstats for mobile bytes w/ fg/bg has error", e); } finally { Binder.restoreCallingIdentity(token); diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 22ac65df4337..1fb28e1969a8 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -3703,13 +3703,19 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo .show(mSplitScreenDividerAnchor); scheduleAnimation(); } else { - mAppAnimationLayer.destroy(); + // At this time mBoostedAppAnimationLayer may be used for animating, + // and ResizeableActivity is in it. mBoostedAppAnimationLayer.destroy() + // can also destroy the surface of ResizeableActivity, but the surface will + // be used after. So change to use transaction to call destroy to delay it, + // and ResizeableActivity is not in mBoostedAppAnimationLayer. + getPendingTransaction() + .destroy(mAppAnimationLayer) + .destroy(mBoostedAppAnimationLayer) + .destroy(mHomeAppAnimationLayer) + .destroy(mSplitScreenDividerAnchor); mAppAnimationLayer = null; - mBoostedAppAnimationLayer.destroy(); mBoostedAppAnimationLayer = null; - mHomeAppAnimationLayer.destroy(); mHomeAppAnimationLayer = null; - mSplitScreenDividerAnchor.destroy(); mSplitScreenDividerAnchor = null; } } diff --git a/services/core/xsd/Android.bp b/services/core/xsd/Android.bp index 5e1ea897b86e..98e4343e6e57 100644 --- a/services/core/xsd/Android.bp +++ b/services/core/xsd/Android.bp @@ -2,5 +2,5 @@ xsd_config { name: "default-permissions", srcs: ["default-permissions.xsd"], api_dir: "schema", - package_name: "com.android.server.pm.permission", + package_name: "com.android.server.pm.permission.configfile", } diff --git a/services/core/xsd/default-permissions.xsd b/services/core/xsd/default-permissions.xsd index d800a26cdceb..2e32be0009ba 100644 --- a/services/core/xsd/default-permissions.xsd +++ b/services/core/xsd/default-permissions.xsd @@ -27,7 +27,7 @@ </xs:element> <xs:complexType name="exception"> <xs:sequence> - <xs:element name="permission" type="permission"/> + <xs:element name="permission" type="permission" maxOccurs="unbounded"/> </xs:sequence> <xs:attribute name="package" type="xs:string"/> <xs:attribute name="sha256-cert-digest" type="xs:string"/> diff --git a/services/core/xsd/schema/current.txt b/services/core/xsd/schema/current.txt index 4e67e5c235a0..a2092e3a99dc 100644 --- a/services/core/xsd/schema/current.txt +++ b/services/core/xsd/schema/current.txt @@ -1,21 +1,20 @@ // Signature format: 2.0 -package com.android.server.pm.permission { +package com.android.server.pm.permission.configfile { public class Exception { ctor public Exception(); method public String getBrand(); - method public com.android.server.pm.permission.Permission getPermission(); + method public java.util.List<com.android.server.pm.permission.configfile.Permission> getPermission(); method public String getSha256CertDigest(); method public String get_package(); method public void setBrand(String); - method public void setPermission(com.android.server.pm.permission.Permission); method public void setSha256CertDigest(String); method public void set_package(String); } public class Exceptions { ctor public Exceptions(); - method public java.util.List<com.android.server.pm.permission.Exception> getException(); + method public java.util.List<com.android.server.pm.permission.configfile.Exception> getException(); } public class Permission { @@ -28,7 +27,7 @@ package com.android.server.pm.permission { public class XmlParser { ctor public XmlParser(); - method public static com.android.server.pm.permission.Exceptions read(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException; + method public static com.android.server.pm.permission.configfile.Exceptions read(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException; method public static String readText(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; method public static void skip(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; } diff --git a/services/net/Android.bp b/services/net/Android.bp index 9e1d44b9faff..8f48f5b3d292 100644 --- a/services/net/Android.bp +++ b/services/net/Android.bp @@ -25,7 +25,6 @@ aidl_interface { local_include_dir: "java", include_dirs: ["frameworks/base/core/java"], // For framework parcelables. srcs: [ - "java/android/net/ApfCapabilitiesParcelable.aidl", "java/android/net/DhcpResultsParcelable.aidl", "java/android/net/IIpMemoryStore.aidl", "java/android/net/IIpMemoryStoreCallbacks.aidl", @@ -36,7 +35,6 @@ aidl_interface { "java/android/net/InitialConfigurationParcelable.aidl", "java/android/net/PrivateDnsConfigParcel.aidl", "java/android/net/ProvisioningConfigurationParcelable.aidl", - "java/android/net/StaticIpConfigurationParcelable.aidl", "java/android/net/TcpKeepalivePacketDataParcelable.aidl", "java/android/net/dhcp/DhcpServingParamsParcel.aidl", "java/android/net/dhcp/IDhcpServer.aidl", @@ -60,6 +58,7 @@ java_library_static { name: "services.net", srcs: ["java/**/*.java"], static_libs: [ + "dnsresolver_aidl_interface-java", "netd_aidl_interface-java", "networkstack-aidl-interfaces-java", ] @@ -71,7 +70,7 @@ java_library_static { srcs: [ ":framework-annotations", "java/android/net/IpMemoryStoreClient.java", - "java/android/net/ipmemorystore/**.java", + "java/android/net/ipmemorystore/**/*.java", ], static_libs: [ "ipmemorystore-aidl-interfaces-java", diff --git a/services/net/java/android/net/DhcpResultsParcelable.aidl b/services/net/java/android/net/DhcpResultsParcelable.aidl index cf5629b6f792..978638b51ad1 100644 --- a/services/net/java/android/net/DhcpResultsParcelable.aidl +++ b/services/net/java/android/net/DhcpResultsParcelable.aidl @@ -16,10 +16,10 @@ package android.net; -import android.net.StaticIpConfigurationParcelable; +import android.net.StaticIpConfiguration; parcelable DhcpResultsParcelable { - StaticIpConfigurationParcelable baseConfiguration; + StaticIpConfiguration baseConfiguration; int leaseDuration; int mtu; String serverAddress; diff --git a/services/net/java/android/net/ProvisioningConfigurationParcelable.aidl b/services/net/java/android/net/ProvisioningConfigurationParcelable.aidl index 5b46d7f55ee3..99606fb4b7a2 100644 --- a/services/net/java/android/net/ProvisioningConfigurationParcelable.aidl +++ b/services/net/java/android/net/ProvisioningConfigurationParcelable.aidl @@ -17,10 +17,10 @@ package android.net; -import android.net.ApfCapabilitiesParcelable; import android.net.InitialConfigurationParcelable; import android.net.Network; -import android.net.StaticIpConfigurationParcelable; +import android.net.StaticIpConfiguration; +import android.net.apf.ApfCapabilities; parcelable ProvisioningConfigurationParcelable { boolean enableIPv4; @@ -29,8 +29,8 @@ parcelable ProvisioningConfigurationParcelable { boolean usingIpReachabilityMonitor; int requestedPreDhcpActionMs; InitialConfigurationParcelable initialConfig; - StaticIpConfigurationParcelable staticIpConfig; - ApfCapabilitiesParcelable apfCapabilities; + StaticIpConfiguration staticIpConfig; + ApfCapabilities apfCapabilities; int provisioningTimeoutMs; int ipv6AddrGenMode; Network network; diff --git a/services/net/java/android/net/TcpKeepalivePacketData.java b/services/net/java/android/net/TcpKeepalivePacketData.java index d79ad1fe41a9..7f2f499ab21f 100644 --- a/services/net/java/android/net/TcpKeepalivePacketData.java +++ b/services/net/java/android/net/TcpKeepalivePacketData.java @@ -38,7 +38,7 @@ import java.util.Objects; public class TcpKeepalivePacketData extends KeepalivePacketData implements Parcelable { private static final String TAG = "TcpKeepalivePacketData"; - /** TCP sequence number. */ + /** TCP sequence number. */ public final int tcpSeq; /** TCP ACK number. */ @@ -50,6 +50,12 @@ public class TcpKeepalivePacketData extends KeepalivePacketData implements Parce /** TCP RCV window scale. */ public final int tcpWndScale; + /** IP TOS. */ + public final int ipTos; + + /** IP TTL. */ + public final int ipTtl; + private static final int IPV4_HEADER_LENGTH = 20; private static final int IPV6_HEADER_LENGTH = 40; private static final int TCP_HEADER_LENGTH = 20; @@ -65,6 +71,8 @@ public class TcpKeepalivePacketData extends KeepalivePacketData implements Parce // In the packet, the window is shifted right by the window scale. tcpWnd = tcpDetails.rcvWnd; tcpWndScale = tcpDetails.rcvWndScale; + ipTos = tcpDetails.tos; + ipTtl = tcpDetails.ttl; } /** @@ -98,12 +106,11 @@ public class TcpKeepalivePacketData extends KeepalivePacketData implements Parce final int length = IPV4_HEADER_LENGTH + TCP_HEADER_LENGTH; ByteBuffer buf = ByteBuffer.allocate(length); buf.order(ByteOrder.BIG_ENDIAN); - // IP version and TOS. TODO : fetch this from getsockopt(SOL_IP, IP_TOS) - buf.putShort((short) 0x4500); + buf.put((byte) 0x45); // IP version and IHL + buf.put((byte) tcpDetails.tos); // TOS buf.putShort((short) length); - buf.putInt(0x4000); // ID, flags=DF, offset - // TODO : fetch TTL from getsockopt(SOL_IP, IP_TTL) - buf.put((byte) 64); + buf.putInt(0x00004000); // ID, flags=DF, offset + buf.put((byte) tcpDetails.ttl); // TTL buf.put((byte) OsConstants.IPPROTO_TCP); final int ipChecksumOffset = buf.position(); buf.putShort((short) 0); // IP checksum @@ -117,7 +124,9 @@ public class TcpKeepalivePacketData extends KeepalivePacketData implements Parce buf.putShort((short) (tcpDetails.rcvWnd >> tcpDetails.rcvWndScale)); // Window size final int tcpChecksumOffset = buf.position(); buf.putShort((short) 0); // TCP checksum - // URG is not set therefore the urgent pointer is not included + // URG is not set therefore the urgent pointer is zero. + buf.putShort((short) 0); // Urgent pointer + buf.putShort(ipChecksumOffset, IpUtils.ipChecksum(buf, 0)); buf.putShort(tcpChecksumOffset, IpUtils.tcpChecksum( buf, 0, IPV4_HEADER_LENGTH, TCP_HEADER_LENGTH)); @@ -138,13 +147,15 @@ public class TcpKeepalivePacketData extends KeepalivePacketData implements Parce && this.tcpAck == other.tcpAck && this.tcpSeq == other.tcpSeq && this.tcpWnd == other.tcpWnd - && this.tcpWndScale == other.tcpWndScale; + && this.tcpWndScale == other.tcpWndScale + && this.ipTos == other.ipTos + && this.ipTtl == other.ipTtl; } @Override public int hashCode() { return Objects.hash(srcAddress, dstAddress, srcPort, dstPort, tcpAck, tcpSeq, tcpWnd, - tcpWndScale); + tcpWndScale, ipTos, ipTtl); } /** @@ -164,6 +175,8 @@ public class TcpKeepalivePacketData extends KeepalivePacketData implements Parce out.writeInt(tcpAck); out.writeInt(tcpWnd); out.writeInt(tcpWndScale); + out.writeInt(ipTos); + out.writeInt(ipTtl); } private TcpKeepalivePacketData(Parcel in) { @@ -172,6 +185,8 @@ public class TcpKeepalivePacketData extends KeepalivePacketData implements Parce tcpAck = in.readInt(); tcpWnd = in.readInt(); tcpWndScale = in.readInt(); + ipTos = in.readInt(); + ipTtl = in.readInt(); } /** Parcelable Creator. */ @@ -200,6 +215,8 @@ public class TcpKeepalivePacketData extends KeepalivePacketData implements Parce parcel.ack = tcpAck; parcel.rcvWnd = tcpWnd; parcel.rcvWndScale = tcpWndScale; + parcel.tos = ipTos; + parcel.ttl = ipTtl; return parcel; } @@ -212,6 +229,8 @@ public class TcpKeepalivePacketData extends KeepalivePacketData implements Parce + " seq: " + tcpSeq + " ack: " + tcpAck + " wnd: " + tcpWnd - + " wndScale: " + tcpWndScale; + + " wndScale: " + tcpWndScale + + " tos: " + ipTos + + " ttl: " + ipTtl; } } diff --git a/services/net/java/android/net/TcpKeepalivePacketDataParcelable.aidl b/services/net/java/android/net/TcpKeepalivePacketDataParcelable.aidl index d66b6ae3ab54..e25168d588e7 100644 --- a/services/net/java/android/net/TcpKeepalivePacketDataParcelable.aidl +++ b/services/net/java/android/net/TcpKeepalivePacketDataParcelable.aidl @@ -25,4 +25,6 @@ parcelable TcpKeepalivePacketDataParcelable { int ack; int rcvWnd; int rcvWndScale; + int tos; + int ttl; } diff --git a/services/net/java/android/net/shared/IpConfigurationParcelableUtil.java b/services/net/java/android/net/shared/IpConfigurationParcelableUtil.java index 6b5826f8b095..44d8e0ce3635 100644 --- a/services/net/java/android/net/shared/IpConfigurationParcelableUtil.java +++ b/services/net/java/android/net/shared/IpConfigurationParcelableUtil.java @@ -16,17 +16,10 @@ package android.net.shared; -import static android.net.shared.ParcelableUtil.fromParcelableArray; -import static android.net.shared.ParcelableUtil.toParcelableArray; - import android.annotation.Nullable; -import android.net.ApfCapabilitiesParcelable; import android.net.DhcpResults; import android.net.DhcpResultsParcelable; import android.net.InetAddresses; -import android.net.StaticIpConfiguration; -import android.net.StaticIpConfigurationParcelable; -import android.net.apf.ApfCapabilities; import java.net.Inet4Address; import java.net.InetAddress; @@ -38,44 +31,12 @@ import java.net.InetAddress; */ public final class IpConfigurationParcelableUtil { /** - * Convert a StaticIpConfiguration to a StaticIpConfigurationParcelable. - */ - public static StaticIpConfigurationParcelable toStableParcelable( - @Nullable StaticIpConfiguration config) { - if (config == null) return null; - final StaticIpConfigurationParcelable p = new StaticIpConfigurationParcelable(); - p.ipAddress = config.getIpAddress(); - p.gateway = parcelAddress(config.getGateway()); - p.dnsServers = toParcelableArray( - config.getDnsServers(), IpConfigurationParcelableUtil::parcelAddress, String.class); - p.domains = config.getDomains(); - return p; - } - - /** - * Convert a StaticIpConfigurationParcelable to a StaticIpConfiguration. - */ - public static StaticIpConfiguration fromStableParcelable( - @Nullable StaticIpConfigurationParcelable p) { - if (p == null) return null; - final StaticIpConfiguration config = new StaticIpConfiguration(); - config.setIpAddress(p.ipAddress); - config.setGateway(unparcelAddress(p.gateway)); - for (InetAddress addr : fromParcelableArray( - p.dnsServers, IpConfigurationParcelableUtil::unparcelAddress)) { - config.addDnsServer(addr); - } - config.setDomains(p.domains); - return config; - } - - /** * Convert DhcpResults to a DhcpResultsParcelable. */ public static DhcpResultsParcelable toStableParcelable(@Nullable DhcpResults results) { if (results == null) return null; final DhcpResultsParcelable p = new DhcpResultsParcelable(); - p.baseConfiguration = toStableParcelable(results.toStaticIpConfiguration()); + p.baseConfiguration = results.toStaticIpConfiguration(); p.leaseDuration = results.leaseDuration; p.mtu = results.mtu; p.serverAddress = parcelAddress(results.serverAddress); @@ -88,7 +49,7 @@ public final class IpConfigurationParcelableUtil { */ public static DhcpResults fromStableParcelable(@Nullable DhcpResultsParcelable p) { if (p == null) return null; - final DhcpResults results = new DhcpResults(fromStableParcelable(p.baseConfiguration)); + final DhcpResults results = new DhcpResults(p.baseConfiguration); results.leaseDuration = p.leaseDuration; results.mtu = p.mtu; results.serverAddress = (Inet4Address) unparcelAddress(p.serverAddress); @@ -97,27 +58,6 @@ public final class IpConfigurationParcelableUtil { } /** - * Convert ApfCapabilities to ApfCapabilitiesParcelable. - */ - public static ApfCapabilitiesParcelable toStableParcelable(@Nullable ApfCapabilities caps) { - if (caps == null) return null; - final ApfCapabilitiesParcelable p = new ApfCapabilitiesParcelable(); - p.apfVersionSupported = caps.apfVersionSupported; - p.maximumApfProgramSize = caps.maximumApfProgramSize; - p.apfPacketFormat = caps.apfPacketFormat; - return p; - } - - /** - * Convert ApfCapabilitiesParcelable toApfCapabilities. - */ - public static ApfCapabilities fromStableParcelable(@Nullable ApfCapabilitiesParcelable p) { - if (p == null) return null; - return new ApfCapabilities( - p.apfVersionSupported, p.maximumApfProgramSize, p.apfPacketFormat); - } - - /** * Convert InetAddress to String. * TODO: have an InetAddressParcelable */ diff --git a/services/net/java/android/net/shared/NetworkMonitorUtils.java b/services/net/java/android/net/shared/NetworkMonitorUtils.java index 3d2a2de45539..a17cb4647158 100644 --- a/services/net/java/android/net/shared/NetworkMonitorUtils.java +++ b/services/net/java/android/net/shared/NetworkMonitorUtils.java @@ -44,18 +44,14 @@ public class NetworkMonitorUtils { public static final String PERMISSION_ACCESS_NETWORK_CONDITIONS = "android.permission.ACCESS_NETWORK_CONDITIONS"; - // TODO: once the URL is a resource overlay, remove and have the resource define the default - private static final String DEFAULT_HTTP_URL = - "http://connectivitycheck.gstatic.com/generate_204"; - /** * Get the captive portal server HTTP URL that is configured on the device. */ - public static String getCaptivePortalServerHttpUrl(Context context) { + public static String getCaptivePortalServerHttpUrl(Context context, String defaultUrl) { final String settingUrl = Settings.Global.getString( context.getContentResolver(), Settings.Global.CAPTIVE_PORTAL_HTTP_URL); - return settingUrl != null ? settingUrl : DEFAULT_HTTP_URL; + return settingUrl != null ? settingUrl : defaultUrl; } /** diff --git a/services/net/java/android/net/shared/ProvisioningConfiguration.java b/services/net/java/android/net/shared/ProvisioningConfiguration.java index 0aceb2278660..6f9c2949d864 100644 --- a/services/net/java/android/net/shared/ProvisioningConfiguration.java +++ b/services/net/java/android/net/shared/ProvisioningConfiguration.java @@ -235,8 +235,10 @@ public class ProvisioningConfiguration { p.usingIpReachabilityMonitor = mUsingIpReachabilityMonitor; p.requestedPreDhcpActionMs = mRequestedPreDhcpActionMs; p.initialConfig = mInitialConfig == null ? null : mInitialConfig.toStableParcelable(); - p.staticIpConfig = IpConfigurationParcelableUtil.toStableParcelable(mStaticIpConfig); - p.apfCapabilities = IpConfigurationParcelableUtil.toStableParcelable(mApfCapabilities); + p.staticIpConfig = mStaticIpConfig == null + ? null + : new StaticIpConfiguration(mStaticIpConfig); + p.apfCapabilities = mApfCapabilities; // ApfCapabilities is immutable p.provisioningTimeoutMs = mProvisioningTimeoutMs; p.ipv6AddrGenMode = mIPv6AddrGenMode; p.network = mNetwork; @@ -257,10 +259,10 @@ public class ProvisioningConfiguration { config.mUsingIpReachabilityMonitor = p.usingIpReachabilityMonitor; config.mRequestedPreDhcpActionMs = p.requestedPreDhcpActionMs; config.mInitialConfig = InitialConfiguration.fromStableParcelable(p.initialConfig); - config.mStaticIpConfig = IpConfigurationParcelableUtil.fromStableParcelable( - p.staticIpConfig); - config.mApfCapabilities = IpConfigurationParcelableUtil.fromStableParcelable( - p.apfCapabilities); + config.mStaticIpConfig = p.staticIpConfig == null + ? null + : new StaticIpConfiguration(p.staticIpConfig); + config.mApfCapabilities = p.apfCapabilities; // ApfCapabilities is immutable config.mProvisioningTimeoutMs = p.provisioningTimeoutMs; config.mIPv6AddrGenMode = p.ipv6AddrGenMode; config.mNetwork = p.network; diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityLaunchParamsModifierTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityLaunchParamsModifierTests.java index d75a3fc8d20b..01644737f55f 100644 --- a/services/tests/servicestests/src/com/android/server/am/ActivityLaunchParamsModifierTests.java +++ b/services/tests/servicestests/src/com/android/server/am/ActivityLaunchParamsModifierTests.java @@ -43,8 +43,11 @@ import org.junit.runner.RunWith; /** * Tests for exercising resizing bounds due to activity options. * - * Build/Install/Run: + * <p>Build/Install/Run: * atest FrameworksServicesTests:ActivityLaunchParamsModifierTests + * + * <p>This test class is a part of Window Manager Service tests and specified in + * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}. */ @MediumTest @Presubmit diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java index 5ee7477b486c..af0aaf31cd59 100644 --- a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java +++ b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java @@ -30,16 +30,15 @@ import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_BOTTOM; import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_LEFT; import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_RIGHT; -import static junit.framework.TestCase.assertNotNull; - import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.anyInt; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.eq; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -62,8 +61,11 @@ import org.mockito.invocation.InvocationOnMock; /** * Tests for the {@link ActivityRecord} class. * - * Build/Install/Run: + * <p>Build/Install/Run: * atest FrameworksServicesTests:com.android.server.am.ActivityRecordTests + * + * <p>This test class is a part of Window Manager Service tests and specified in + * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}. */ @MediumTest @Presubmit diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java index f36c57973240..b0f949132c3e 100644 --- a/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java +++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java @@ -27,15 +27,14 @@ import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE; import static android.content.pm.ActivityInfo.FLAG_SHOW_WHEN_LOCKED; import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_DESTROYING; -import static com.android.server.am.ActivityStackSupervisor - .MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE; +import static com.android.server.am.ActivityStackSupervisor.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Matchers.anyInt; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; @@ -62,8 +61,11 @@ import java.util.ArrayList; /** * Tests for the {@link ActivityStackSupervisor} class. * - * Build/Install/Run: + * <p>Build/Install/Run: * atest FrameworksServicesTests:com.android.server.am.ActivityStackSupervisorTests + * + * <p>This test class is a part of Window Manager Service tests and specified in + * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}. */ @MediumTest @Presubmit diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java index be0c689ab89f..d89bc976e73f 100644 --- a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java +++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java @@ -33,7 +33,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.anyInt; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; @@ -51,8 +51,11 @@ import org.junit.runner.RunWith; /** * Tests for the {@link ActivityStack} class. * - * Build/Install/Run: + * <p>Build/Install/Run: * atest FrameworksServicesTests:com.android.server.am.ActivityStackTests + * + * <p>This test class is a part of Window Manager Service tests and specified in + * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}. */ @SmallTest @Presubmit diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStartControllerTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStartControllerTests.java index 3464ac2a3044..e84e354dbb8f 100644 --- a/services/tests/servicestests/src/com/android/server/am/ActivityStartControllerTests.java +++ b/services/tests/servicestests/src/com/android/server/am/ActivityStartControllerTests.java @@ -19,8 +19,8 @@ package com.android.server.am; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; @@ -43,8 +43,11 @@ import java.util.Random; /** * Tests for the {@link ActivityStartController} class. * - * Build/Install/Run: + * <p>Build/Install/Run: * atest FrameworksServicesTests:ActivityStartControllerTests + * + * <p>This test class is a part of Window Manager Service tests and specified in + * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}. */ @SmallTest @Presubmit diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStartInterceptorTest.java b/services/tests/servicestests/src/com/android/server/am/ActivityStartInterceptorTest.java index d1550d736e0b..1c83ded3cb9e 100644 --- a/services/tests/servicestests/src/com/android/server/am/ActivityStartInterceptorTest.java +++ b/services/tests/servicestests/src/com/android/server/am/ActivityStartInterceptorTest.java @@ -55,8 +55,11 @@ import org.mockito.MockitoAnnotations; /** * Unit tests for {@link ActivityStartInterceptorTest}. * - * Build/Install/Run: - * bit FrameworksServicesTests:com.android.server.am.ActivityStartInterceptorTest + * <p>Build/Install/Run: + * atest FrameworksServicesTests:ActivityStartInterceptorTest + * + * <p>This test class is a part of Window Manager Service tests and specified in + * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}. */ @SmallTest public class ActivityStartInterceptorTest { diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java index f956a364315b..1e127a9863e6 100644 --- a/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java +++ b/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java @@ -39,14 +39,14 @@ import static com.android.server.am.ActivityManagerService.ANIMATE; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.anyBoolean; -import static org.mockito.Mockito.anyInt; -import static org.mockito.Mockito.anyObject; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyObject; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; @@ -80,8 +80,11 @@ import org.junit.runner.RunWith; /** * Tests for the {@link ActivityStarter} class. * - * Build/Install/Run: + * <p>Build/Install/Run: * atest FrameworksServicesTests:ActivityStarterTests + * + * <p>This test class is a part of Window Manager Service tests and specified in + * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}. */ @SmallTest @Presubmit diff --git a/services/tests/servicestests/src/com/android/server/am/AssistDataRequesterTest.java b/services/tests/servicestests/src/com/android/server/am/AssistDataRequesterTest.java index d985364a7cee..2e1155e0a905 100644 --- a/services/tests/servicestests/src/com/android/server/am/AssistDataRequesterTest.java +++ b/services/tests/servicestests/src/com/android/server/am/AssistDataRequesterTest.java @@ -64,7 +64,11 @@ import java.util.concurrent.TimeUnit; * Note: Currently, we only support fetching the screenshot for the current application, so the * screenshot checks are hardcoded accordingly. * - * runtest --path frameworks/base/services/tests/servicestests/src/com/android/server/am/AssistDataRequesterTest.java + * <p>Build/Install/Run: + * atest FrameworksServicesTests:AssistDataRequesterTest + * + * <p>This test class is a part of Window Manager Service tests and specified in + * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}. */ @MediumTest @FlakyTest(bugId = 113616538) diff --git a/services/tests/servicestests/src/com/android/server/am/ClientLifecycleManagerTests.java b/services/tests/servicestests/src/com/android/server/am/ClientLifecycleManagerTests.java index b4ad183db386..f882b63acfce 100644 --- a/services/tests/servicestests/src/com/android/server/am/ClientLifecycleManagerTests.java +++ b/services/tests/servicestests/src/com/android/server/am/ClientLifecycleManagerTests.java @@ -16,6 +16,15 @@ import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; +/** + * Tests for {@link ClientLifecycleManager}. + * + * <p>Build/Install/Run: + * atest FrameworksServicesTests:ClientLifecycleManagerTests + * + * <p>This test class is a part of Window Manager Service tests and specified in + * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}. + */ @RunWith(AndroidJUnit4.class) @SmallTest @Presubmit diff --git a/services/tests/servicestests/src/com/android/server/am/LaunchParamsControllerTests.java b/services/tests/servicestests/src/com/android/server/am/LaunchParamsControllerTests.java index 8d675dd3032d..d24991ebc539 100644 --- a/services/tests/servicestests/src/com/android/server/am/LaunchParamsControllerTests.java +++ b/services/tests/servicestests/src/com/android/server/am/LaunchParamsControllerTests.java @@ -24,10 +24,10 @@ import static com.android.server.am.LaunchParamsController.LaunchParamsModifier. import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.anyInt; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; @@ -51,8 +51,11 @@ import org.junit.runner.RunWith; /** * Tests for exercising {@link LaunchParamsController}. * - * Build/Install/Run: + * <p>Build/Install/Run: * atest FrameworksServicesTests:LaunchParamsControllerTests + * + * <p>This test class is a part of Window Manager Service tests and specified in + * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}. */ @MediumTest @Presubmit diff --git a/services/tests/servicestests/src/com/android/server/am/PendingRemoteAnimationRegistryTest.java b/services/tests/servicestests/src/com/android/server/am/PendingRemoteAnimationRegistryTest.java index f5f507f8b210..b52ce1702488 100644 --- a/services/tests/servicestests/src/com/android/server/am/PendingRemoteAnimationRegistryTest.java +++ b/services/tests/servicestests/src/com/android/server/am/PendingRemoteAnimationRegistryTest.java @@ -38,7 +38,13 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; /** - * atest PendingRemoteAnimationRegistryTest + * Tests for {@link PendingRemoteAnimationRegistry}. + * + * <p>Build/Install/Run: + * atest PendingRemoteAnimationRegistryTest + * + * <p>This test class is a part of Window Manager Service tests and specified in + * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}. */ @SmallTest @Presubmit diff --git a/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java b/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java index aa9123b16aa7..c61054099282 100644 --- a/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java +++ b/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java @@ -76,7 +76,13 @@ import java.util.Random; import java.util.Set; /** - * atest FrameworksServicesTests:RecentTasksTest + * Tests for {@link RecentTasks}. + * + * <p>Build/Install/Run: + * atest FrameworksServicesTests:RecentTasksTest + * + * <p>This test class is a part of Window Manager Service tests and specified in + * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}. */ @MediumTest @Presubmit diff --git a/services/tests/servicestests/src/com/android/server/am/RecentsAnimationTest.java b/services/tests/servicestests/src/com/android/server/am/RecentsAnimationTest.java index fa6a95ce275c..edc623589f4b 100644 --- a/services/tests/servicestests/src/com/android/server/am/RecentsAnimationTest.java +++ b/services/tests/servicestests/src/com/android/server/am/RecentsAnimationTest.java @@ -22,9 +22,9 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_IN_PLACE; -import static org.mockito.Mockito.any; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -46,7 +46,13 @@ import org.junit.Test; import org.junit.runner.RunWith; /** - * atest FrameworksServicesTests:RecentsAnimationTest + * Tests for recent tasks animation. + * + * <p>Build/Install/Run: + * atest FrameworksServicesTests:RecentsAnimationTest + * + * <p>This test class is a part of Window Manager Service tests and specified in + * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}. */ @MediumTest @Presubmit diff --git a/services/tests/servicestests/src/com/android/server/am/RunningTasksTest.java b/services/tests/servicestests/src/com/android/server/am/RunningTasksTest.java index 19288a9c28d7..c38a594c1038 100644 --- a/services/tests/servicestests/src/com/android/server/am/RunningTasksTest.java +++ b/services/tests/servicestests/src/com/android/server/am/RunningTasksTest.java @@ -43,7 +43,13 @@ import org.junit.runner.RunWith; import java.util.ArrayList; /** - * runtest --path frameworks/base/services/tests/servicestests/src/com/android/server/am/RunningTasksTest.java + * Tests for {@link RunningTasks}. + * + * <p>Build/Install/Run: + * atest FrameworksServicesTests:RunningTasksTest + * + * <p>This test class is a part of Window Manager Service tests and specified in + * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}. */ @MediumTest @Presubmit @@ -124,4 +130,4 @@ public class RunningTasksTest extends ActivityTestsBase { .build(); return task; } -}
\ No newline at end of file +} diff --git a/services/tests/servicestests/src/com/android/server/am/SafeActivityOptionsTest.java b/services/tests/servicestests/src/com/android/server/am/SafeActivityOptionsTest.java index 8e4e7e6b63c3..03d17375298f 100644 --- a/services/tests/servicestests/src/com/android/server/am/SafeActivityOptionsTest.java +++ b/services/tests/servicestests/src/com/android/server/am/SafeActivityOptionsTest.java @@ -28,6 +28,15 @@ import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; +/** + * Tests for {@link SafeActivityOptions}. + * + * <p>Build/Install/Run: + * atest FrameworksServicesTests:SafeActivityOptionsTest + * + * <p>This test class is a part of Window Manager Service tests and specified in + * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}. + */ @MediumTest @Presubmit @FlakyTest diff --git a/services/tests/servicestests/src/com/android/server/am/TaskLaunchParamsModifierTests.java b/services/tests/servicestests/src/com/android/server/am/TaskLaunchParamsModifierTests.java index eec55b162b3e..fc9db14d5834 100644 --- a/services/tests/servicestests/src/com/android/server/am/TaskLaunchParamsModifierTests.java +++ b/services/tests/servicestests/src/com/android/server/am/TaskLaunchParamsModifierTests.java @@ -38,8 +38,11 @@ import org.junit.runner.RunWith; /** * Tests for exercising resizing task bounds. * - * Build/Install/Run: + * <p>Build/Install/Run: * atest FrameworksServicesTests:TaskLaunchParamsModifierTests + * + * <p>This test class is a part of Window Manager Service tests and specified in + * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}. */ @MediumTest @Presubmit diff --git a/services/tests/servicestests/src/com/android/server/am/TaskPersisterTest.java b/services/tests/servicestests/src/com/android/server/am/TaskPersisterTest.java index 9e6055d55e0f..976e8355128e 100644 --- a/services/tests/servicestests/src/com/android/server/am/TaskPersisterTest.java +++ b/services/tests/servicestests/src/com/android/server/am/TaskPersisterTest.java @@ -30,7 +30,13 @@ import java.io.File; import java.util.Random; /** - * atest FrameworksServicesTests:TaskPersisterTest + * Tests for {@link TaskPersister}. + * + * <p>Build/Install/Run: + * atest FrameworksServicesTests:TaskPersisterTest + * + * <p>This test class is a part of Window Manager Service tests and specified in + * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}. */ public class TaskPersisterTest extends AndroidTestCase { private static final String TEST_USER_NAME = "AM-Test-User"; @@ -85,4 +91,4 @@ public class TaskPersisterTest extends AndroidTestCase { fail("Error while removing the test user: " + TEST_USER_NAME); } } -}
\ No newline at end of file +} diff --git a/services/tests/servicestests/src/com/android/server/am/TaskRecordTests.java b/services/tests/servicestests/src/com/android/server/am/TaskRecordTests.java index 5aecec005fdb..eada2ce4f004 100644 --- a/services/tests/servicestests/src/com/android/server/am/TaskRecordTests.java +++ b/services/tests/servicestests/src/com/android/server/am/TaskRecordTests.java @@ -59,8 +59,11 @@ import java.util.ArrayList; /** * Tests for exercising {@link TaskRecord}. * - * Build/Install/Run: + * <p>Build/Install/Run: * atest FrameworksServicesTests:com.android.server.am.TaskRecordTests + * + * <p>This test class is a part of Window Manager Service tests and specified in + * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}. */ @MediumTest @Presubmit diff --git a/services/tests/servicestests/src/com/android/server/am/TaskStackChangedListenerTest.java b/services/tests/servicestests/src/com/android/server/am/TaskStackChangedListenerTest.java index 9406160b52ca..814071445df8 100644 --- a/services/tests/servicestests/src/com/android/server/am/TaskStackChangedListenerTest.java +++ b/services/tests/servicestests/src/com/android/server/am/TaskStackChangedListenerTest.java @@ -52,6 +52,15 @@ import org.junit.runner.RunWith; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +/** + * Tests for {@link TaskStackListener}. + * + * <p>Build/Install/Run: + * atest FrameworksServicesTests:TaskStackChangedListenerTest + * + * <p>This test class is a part of Window Manager Service tests and specified in + * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}. + */ @MediumTest @RunWith(AndroidJUnit4.class) public class TaskStackChangedListenerTest { diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java index da682c6df621..e949e7490230 100644 --- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java +++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java @@ -855,7 +855,7 @@ public class UsbDeviceManager implements ActivityManagerInternal.ScreenObserver && status.isRoleCombinationSupported(UsbPort.POWER_ROLE_SOURCE, UsbPort.DATA_ROLE_DEVICE) && status.isRoleCombinationSupported(UsbPort.POWER_ROLE_SINK, - UsbPort.DATA_ROLE_HOST); + UsbPort.DATA_ROLE_DEVICE); args.recycle(); updateUsbNotification(false); diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java index 558d8d495d5c..06c85d27d880 100644 --- a/telecomm/java/android/telecom/TelecomManager.java +++ b/telecomm/java/android/telecom/TelecomManager.java @@ -33,7 +33,6 @@ import android.os.Build; import android.os.Bundle; import android.os.RemoteException; import android.os.ServiceManager; -import android.os.UserHandle; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.Log; @@ -45,7 +44,6 @@ import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.concurrent.Executor; /** * Provides access to information about active calls and registration/call-management functionality. @@ -477,6 +475,12 @@ public class TelecomManager { "android.telecom.extra.START_CALL_WITH_RTT"; /** + * A boolean extra set to indicate whether an app is eligible to be bound to when there are + * ongoing calls on the device. + */ + public static final String EXTRA_IS_ENABLED = "android.telecom.extra.IS_ENABLED"; + + /** * A boolean meta-data value indicating whether an {@link InCallService} implements an * in-call user interface. Dialer implementations (see {@link #getDefaultDialerPackage()}) which * would also like to replace the in-call interface should set this meta-data to {@code true} in @@ -487,9 +491,7 @@ public class TelecomManager { /** * A boolean meta-data value indicating whether an {@link InCallService} implements an * in-call user interface to be used while the device is in car-mode (see - * {@link android.content.res.Configuration.UI_MODE_TYPE_CAR}). - * - * @hide + * {@link android.content.res.Configuration#UI_MODE_TYPE_CAR}). */ public static final String METADATA_IN_CALL_SERVICE_CAR_MODE_UI = "android.telecom.IN_CALL_SERVICE_CAR_MODE_UI"; @@ -2041,7 +2043,6 @@ public class TelecomManager { } catch (RemoteException e) { Log.e(TAG, "RemoteException handleCallIntent: " + e); } - } private ITelecomService getTelecomService() { diff --git a/telephony/java/android/telephony/AccessNetworkConstants.java b/telephony/java/android/telephony/AccessNetworkConstants.java index 81553a3bc0f8..afa35b4d4de3 100644 --- a/telephony/java/android/telephony/AccessNetworkConstants.java +++ b/telephony/java/android/telephony/AccessNetworkConstants.java @@ -18,6 +18,7 @@ package android.telephony; import android.annotation.IntDef; import android.annotation.SystemApi; +import android.annotation.TestApi; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -51,6 +52,7 @@ public final class AccessNetworkConstants { * @hide */ @SystemApi + @TestApi public static final int TRANSPORT_TYPE_WWAN = 1; /** @@ -58,6 +60,7 @@ public final class AccessNetworkConstants { * @hide */ @SystemApi + @TestApi public static final int TRANSPORT_TYPE_WLAN = 2; /** @hide */ diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index 5e9d33a86760..4776aa179478 100755 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -1844,6 +1844,14 @@ public class CarrierConfigManager { "editable_wfc_roaming_mode_bool"; /** + * Flag specifying wether to show blocking pay phone option in blocked numbers screen. Only show + * the option if payphone call presentation represents in the carrier's region. + * @hide + */ + public static final java.lang.String KEY_SHOW_BLOCKING_PAY_PHONE_OPTION_BOOL = + "show_blocking_pay_phone_option_bool"; + + /** * Flag specifying whether the carrier will use the WFC home network mode in roaming network. * {@code false} - roaming preference can be selected separately from the home preference. * {@code true} - roaming preference is the same as home preference and @@ -2482,6 +2490,18 @@ public class CarrierConfigManager { "emergency_number_prefix_string_array"; /** + * Indicates when a carrier has a primary subscription and an opportunistic subscription active, + * and when Internet data is switched to opportunistic network, whether to still show + * signal bar of primary network. By default it will be false, meaning whenever data + * is going over opportunistic network, signal bar will reflect signal strength and rat + * icon of that network. + * + * @hide + */ + public static final String KEY_ALWAYS_SHOW_PRIMARY_SIGNAL_BAR_IN_OPPORTUNISTIC_NETWORK_BOOLEAN = + "always_show_primary_signal_bar_in_opportunistic_network_boolean"; + + /** * Determines whether the carrier wants to cancel the cs reject notification automatically * when the voice registration state changes. * If true, the notification will be automatically removed @@ -2826,6 +2846,7 @@ public class CarrierConfigManager { sDefaults.putBoolean(KEY_NOTIFY_VT_HANDOVER_TO_WIFI_FAILURE_BOOL, false); sDefaults.putStringArray(KEY_FILTERED_CNAP_NAMES_STRING_ARRAY, null); sDefaults.putBoolean(KEY_EDITABLE_WFC_ROAMING_MODE_BOOL, false); + sDefaults.putBoolean(KEY_SHOW_BLOCKING_PAY_PHONE_OPTION_BOOL, false); sDefaults.putBoolean(KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL, false); sDefaults.putBoolean(KEY_STK_DISABLE_LAUNCH_BROWSER_BOOL, false); sDefaults.putBoolean(KEY_PERSIST_LPP_MODE_BOOL, true); @@ -2894,14 +2915,14 @@ public class CarrierConfigManager { sDefaults.putBoolean(KEY_SUPPORT_CLIR_NETWORK_DEFAULT_BOOL, true); sDefaults.putBoolean(KEY_SUPPORT_EMERGENCY_DIALER_SHORTCUT_BOOL, true); sDefaults.putBoolean(KEY_ASCII_7_BIT_SUPPORT_FOR_LONG_MESSAGE_BOOL, false); - /* Default value is minimum RSRP level needed for SIGNAL_STRENGTH_GOOD */ - sDefaults.putInt(KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_RSRP_INT, -108); /* Default value is minimum RSRP level needed for SIGNAL_STRENGTH_MODERATE */ - sDefaults.putInt(KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_RSRP_INT, -118); - /* Default value is minimum RSSNR level needed for SIGNAL_STRENGTH_GOOD */ - sDefaults.putInt(KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_RSSNR_INT, 45); + sDefaults.putInt(KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_RSRP_INT, -118); + /* Default value is minimum RSRP level needed for SIGNAL_STRENGTH_POOR */ + sDefaults.putInt(KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_RSRP_INT, -128); /* Default value is minimum RSSNR level needed for SIGNAL_STRENGTH_MODERATE */ - sDefaults.putInt(KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_RSSNR_INT, 10); + sDefaults.putInt(KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_RSSNR_INT, 10); + /* Default value is minimum RSSNR level needed for SIGNAL_STRENGTH_POOR */ + sDefaults.putInt(KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_RSSNR_INT, -30); /* Default value is 1024 kbps */ sDefaults.putInt(KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_BANDWIDTH_INT, 1024); /* Default value is 10 seconds */ @@ -2916,6 +2937,8 @@ public class CarrierConfigManager { sDefaults.putString(KEY_5G_ICON_CONFIGURATION_STRING, "connected_mmwave:None,connected:5G,not_restricted:None,restricted:None"); sDefaults.putBoolean(KEY_AUTO_CANCEL_CS_REJECT_NOTIFICATION, false); + sDefaults.putBoolean(KEY_ALWAYS_SHOW_PRIMARY_SIGNAL_BAR_IN_OPPORTUNISTIC_NETWORK_BOOLEAN, + false); } /** diff --git a/telephony/java/android/telephony/DataSpecificRegistrationStates.java b/telephony/java/android/telephony/DataSpecificRegistrationInfo.java index c3387f3f112d..fbf488e590fd 100644 --- a/telephony/java/android/telephony/DataSpecificRegistrationStates.java +++ b/telephony/java/android/telephony/DataSpecificRegistrationInfo.java @@ -1,7 +1,24 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package android.telephony; import android.annotation.NonNull; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.os.Parcel; import android.os.Parcelable; @@ -13,7 +30,8 @@ import java.util.Objects; * @hide */ @SystemApi -public final class DataSpecificRegistrationStates implements Parcelable{ +@TestApi +public final class DataSpecificRegistrationInfo implements Parcelable { /** * @hide * The maximum number of simultaneous Data Calls that @@ -53,27 +71,27 @@ public final class DataSpecificRegistrationStates implements Parcelable{ /** * Provides network support info for LTE VoPS and LTE Emergency bearer support */ - private final LteVopsSupportInfo lteVopsSupportInfo; + private final LteVopsSupportInfo mLteVopsSupportInfo; /** * @hide */ - DataSpecificRegistrationStates( + DataSpecificRegistrationInfo( int maxDataCalls, boolean isDcNrRestricted, boolean isNrAvailable, boolean isEnDcAvailable, LteVopsSupportInfo lteVops) { this.maxDataCalls = maxDataCalls; this.isDcNrRestricted = isDcNrRestricted; this.isNrAvailable = isNrAvailable; this.isEnDcAvailable = isEnDcAvailable; - this.lteVopsSupportInfo = lteVops; + this.mLteVopsSupportInfo = lteVops; } - private DataSpecificRegistrationStates(Parcel source) { + private DataSpecificRegistrationInfo(Parcel source) { maxDataCalls = source.readInt(); isDcNrRestricted = source.readBoolean(); isNrAvailable = source.readBoolean(); isEnDcAvailable = source.readBoolean(); - lteVopsSupportInfo = LteVopsSupportInfo.CREATOR.createFromParcel(source); + mLteVopsSupportInfo = LteVopsSupportInfo.CREATOR.createFromParcel(source); } @Override @@ -82,7 +100,7 @@ public final class DataSpecificRegistrationStates implements Parcelable{ dest.writeBoolean(isDcNrRestricted); dest.writeBoolean(isNrAvailable); dest.writeBoolean(isEnDcAvailable); - lteVopsSupportInfo.writeToParcel(dest, flags); + mLteVopsSupportInfo.writeToParcel(dest, flags); } @Override @@ -98,7 +116,7 @@ public final class DataSpecificRegistrationStates implements Parcelable{ .append(" isDcNrRestricted = " + isDcNrRestricted) .append(" isNrAvailable = " + isNrAvailable) .append(" isEnDcAvailable = " + isEnDcAvailable) - .append(lteVopsSupportInfo.toString()) + .append(mLteVopsSupportInfo.toString()) .append(" }") .toString(); } @@ -106,41 +124,41 @@ public final class DataSpecificRegistrationStates implements Parcelable{ @Override public int hashCode() { return Objects.hash(maxDataCalls, isDcNrRestricted, isNrAvailable, isEnDcAvailable, - lteVopsSupportInfo); + mLteVopsSupportInfo); } @Override public boolean equals(Object o) { if (this == o) return true; - if (!(o instanceof DataSpecificRegistrationStates)) return false; + if (!(o instanceof DataSpecificRegistrationInfo)) return false; - DataSpecificRegistrationStates other = (DataSpecificRegistrationStates) o; + DataSpecificRegistrationInfo other = (DataSpecificRegistrationInfo) o; return this.maxDataCalls == other.maxDataCalls && this.isDcNrRestricted == other.isDcNrRestricted && this.isNrAvailable == other.isNrAvailable && this.isEnDcAvailable == other.isEnDcAvailable - && this.lteVopsSupportInfo.equals(other.lteVopsSupportInfo); + && this.mLteVopsSupportInfo.equals(other.mLteVopsSupportInfo); } - public static final Parcelable.Creator<DataSpecificRegistrationStates> CREATOR = - new Parcelable.Creator<DataSpecificRegistrationStates>() { + public static final @NonNull Parcelable.Creator<DataSpecificRegistrationInfo> CREATOR = + new Parcelable.Creator<DataSpecificRegistrationInfo>() { @Override - public DataSpecificRegistrationStates createFromParcel(Parcel source) { - return new DataSpecificRegistrationStates(source); + public DataSpecificRegistrationInfo createFromParcel(Parcel source) { + return new DataSpecificRegistrationInfo(source); } @Override - public DataSpecificRegistrationStates[] newArray(int size) { - return new DataSpecificRegistrationStates[size]; + public DataSpecificRegistrationInfo[] newArray(int size) { + return new DataSpecificRegistrationInfo[size]; } }; /** - * @return LteVopsSupportInfo + * @return The LTE VOPS (Voice over Packet Switched) support information */ @NonNull public LteVopsSupportInfo getLteVopsSupportInfo() { - return lteVopsSupportInfo; + return mLteVopsSupportInfo; } } diff --git a/telephony/java/android/telephony/LteVopsSupportInfo.java b/telephony/java/android/telephony/LteVopsSupportInfo.java index 0ae85c0dfa6c..fda20bd4cf12 100644 --- a/telephony/java/android/telephony/LteVopsSupportInfo.java +++ b/telephony/java/android/telephony/LteVopsSupportInfo.java @@ -18,6 +18,7 @@ package android.telephony; import android.annotation.IntDef; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.os.Parcel; import android.os.Parcelable; @@ -30,6 +31,7 @@ import java.util.Objects; * @hide */ @SystemApi +@TestApi public final class LteVopsSupportInfo implements Parcelable { /**@hide*/ diff --git a/telephony/java/android/telephony/NetworkRegistrationInfo.java b/telephony/java/android/telephony/NetworkRegistrationInfo.java index 9145b2532817..1dc29979dc61 100644 --- a/telephony/java/android/telephony/NetworkRegistrationInfo.java +++ b/telephony/java/android/telephony/NetworkRegistrationInfo.java @@ -20,6 +20,7 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.os.Parcel; import android.os.Parcelable; import android.telephony.AccessNetworkConstants.TransportType; @@ -38,6 +39,7 @@ import java.util.stream.Collectors; * @hide */ @SystemApi +@TestApi public final class NetworkRegistrationInfo implements Parcelable { /** * Network domain @@ -174,10 +176,10 @@ public final class NetworkRegistrationInfo implements Parcelable { private CellIdentity mCellIdentity; @Nullable - private VoiceSpecificRegistrationStates mVoiceSpecificStates; + private VoiceSpecificRegistrationInfo mVoiceSpecificInfo; @Nullable - private DataSpecificRegistrationStates mDataSpecificStates; + private DataSpecificRegistrationInfo mDataSpecificInfo; /** * @param domain Network domain. Must be a {@link Domain}. For transport type @@ -234,7 +236,7 @@ public final class NetworkRegistrationInfo implements Parcelable { this(domain, transportType, registrationState, accessNetworkTechnology, rejectCause, emergencyOnly, availableServices, cellIdentity); - mVoiceSpecificStates = new VoiceSpecificRegistrationStates(cssSupported, roamingIndicator, + mVoiceSpecificInfo = new VoiceSpecificRegistrationInfo(cssSupported, roamingIndicator, systemIsInPrl, defaultRoamingIndicator); } @@ -253,9 +255,9 @@ public final class NetworkRegistrationInfo implements Parcelable { this(domain, transportType, registrationState, accessNetworkTechnology, rejectCause, emergencyOnly, availableServices, cellIdentity); - mDataSpecificStates = new DataSpecificRegistrationStates( + mDataSpecificInfo = new DataSpecificRegistrationInfo( maxDataCalls, isDcNrRestricted, isNrAvailable, isEndcAvailable, lteVopsSupportInfo); - updateNrState(mDataSpecificStates); + updateNrState(mDataSpecificInfo); } private NetworkRegistrationInfo(Parcel source) { @@ -269,10 +271,10 @@ public final class NetworkRegistrationInfo implements Parcelable { mAvailableServices = new ArrayList<>(); source.readList(mAvailableServices, Integer.class.getClassLoader()); mCellIdentity = source.readParcelable(CellIdentity.class.getClassLoader()); - mVoiceSpecificStates = source.readParcelable( - VoiceSpecificRegistrationStates.class.getClassLoader()); - mDataSpecificStates = source.readParcelable( - DataSpecificRegistrationStates.class.getClassLoader()); + mVoiceSpecificInfo = source.readParcelable( + VoiceSpecificRegistrationInfo.class.getClassLoader()); + mDataSpecificInfo = source.readParcelable( + DataSpecificRegistrationInfo.class.getClassLoader()); mNrState = source.readInt(); } @@ -389,16 +391,16 @@ public final class NetworkRegistrationInfo implements Parcelable { * @hide */ @Nullable - public VoiceSpecificRegistrationStates getVoiceSpecificStates() { - return mVoiceSpecificStates; + public VoiceSpecificRegistrationInfo getVoiceSpecificInfo() { + return mVoiceSpecificInfo; } /** * @return Data registration related info */ @Nullable - public DataSpecificRegistrationStates getDataSpecificStates() { - return mDataSpecificStates; + public DataSpecificRegistrationInfo getDataSpecificInfo() { + return mDataSpecificInfo; } @Override @@ -474,8 +476,8 @@ public final class NetworkRegistrationInfo implements Parcelable { ? mAvailableServices.stream().map(type -> serviceTypeToString(type)) .collect(Collectors.joining(",")) : null) + "]") .append(" cellIdentity=").append(mCellIdentity) - .append(" voiceSpecificStates=").append(mVoiceSpecificStates) - .append(" dataSpecificStates=").append(mDataSpecificStates) + .append(" voiceSpecificInfo=").append(mVoiceSpecificInfo) + .append(" dataSpecificInfo=").append(mDataSpecificInfo) .append(" nrState=").append(nrStateToString(mNrState)) .append("}").toString(); } @@ -484,7 +486,7 @@ public final class NetworkRegistrationInfo implements Parcelable { public int hashCode() { return Objects.hash(mDomain, mTransportType, mRegistrationState, mRoamingType, mAccessNetworkTechnology, mRejectCause, mEmergencyOnly, mAvailableServices, - mCellIdentity, mVoiceSpecificStates, mDataSpecificStates, mNrState); + mCellIdentity, mVoiceSpecificInfo, mDataSpecificInfo, mNrState); } @Override @@ -505,8 +507,8 @@ public final class NetworkRegistrationInfo implements Parcelable { && mEmergencyOnly == other.mEmergencyOnly && mAvailableServices.equals(other.mAvailableServices) && Objects.equals(mCellIdentity, other.mCellIdentity) - && Objects.equals(mVoiceSpecificStates, other.mVoiceSpecificStates) - && Objects.equals(mDataSpecificStates, other.mDataSpecificStates) + && Objects.equals(mVoiceSpecificInfo, other.mVoiceSpecificInfo) + && Objects.equals(mDataSpecificInfo, other.mDataSpecificInfo) && mNrState == other.mNrState; } @@ -521,8 +523,8 @@ public final class NetworkRegistrationInfo implements Parcelable { dest.writeBoolean(mEmergencyOnly); dest.writeList(mAvailableServices); dest.writeParcelable(mCellIdentity, 0); - dest.writeParcelable(mVoiceSpecificStates, 0); - dest.writeParcelable(mDataSpecificStates, 0); + dest.writeParcelable(mVoiceSpecificInfo, 0); + dest.writeParcelable(mDataSpecificInfo, 0); dest.writeInt(mNrState); } @@ -543,7 +545,7 @@ public final class NetworkRegistrationInfo implements Parcelable { * * @param state data specific registration state contains the 5G NR indicators. */ - private void updateNrState(DataSpecificRegistrationStates state) { + private void updateNrState(DataSpecificRegistrationInfo state) { mNrState = NR_STATE_NONE; if (state.isEnDcAvailable) { if (!state.isDcNrRestricted && state.isNrAvailable) { diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java index a500eba9fa2b..caf27b79dc13 100644 --- a/telephony/java/android/telephony/ServiceState.java +++ b/telephony/java/android/telephony/ServiceState.java @@ -1132,7 +1132,7 @@ public class ServiceState implements Parcelable { } /** @hide */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) + @TestApi public void setVoiceRoamingType(@RoamingType int type) { NetworkRegistrationInfo regState = getNetworkRegistrationInfo( NetworkRegistrationInfo.DOMAIN_CS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); @@ -1153,7 +1153,7 @@ public class ServiceState implements Parcelable { } /** @hide */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) + @TestApi public void setDataRoamingType(@RoamingType int type) { NetworkRegistrationInfo regState = getNetworkRegistrationInfo( NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); @@ -1855,6 +1855,7 @@ public class ServiceState implements Parcelable { /** * @hide */ + @TestApi public void addNetworkRegistrationInfo(NetworkRegistrationInfo regState) { if (regState == null) return; diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java index c39f1f5613b0..4d1b89c0e8ce 100644 --- a/telephony/java/android/telephony/SmsManager.java +++ b/telephony/java/android/telephony/SmsManager.java @@ -22,10 +22,6 @@ import android.annotation.SystemApi; import android.annotation.UnsupportedAppUsage; import android.app.ActivityThread; import android.app.PendingIntent; -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothMapClient; -import android.bluetooth.BluetoothProfile; import android.content.ActivityNotFoundException; import android.content.ContentValues; import android.content.Context; @@ -36,7 +32,6 @@ import android.os.Build; import android.os.Bundle; import android.os.RemoteException; import android.os.ServiceManager; -import android.telecom.PhoneAccount; import android.text.TextUtils; import android.util.ArrayMap; import android.util.Log; @@ -66,7 +61,6 @@ import java.util.Map; */ public final class SmsManager { private static final String TAG = "SmsManager"; - private static final boolean DBG = false; /** * A psuedo-subId that represents the default subId at any given time. The actual subId it @@ -347,42 +341,11 @@ public final class SmsManager { throw new IllegalArgumentException("Invalid message body"); } - // A Manager code accessing another manager is *not* acceptable, in Android. - // In this particular case, it is unavoidable because of the following: - // If the subscription for this SmsManager instance belongs to a remote SIM - // then a listener to get BluetoothMapClient proxy needs to be started up. - // Doing that is possible only in a foreground thread or as a system user. - // i.e., Can't be done in ISms service. - // For that reason, SubscriptionManager needs to be accessed here to determine - // if the subscription belongs to a remote SIM. - // Ideally, there should be another API in ISms to service messages going thru - // remote SIM subscriptions (and ISms should be tweaked to be able to access - // BluetoothMapClient proxy) - Context context = ActivityThread.currentApplication().getApplicationContext(); - SubscriptionManager manager = (SubscriptionManager) context - .getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE); - int subId = getSubscriptionId(); - SubscriptionInfo info = manager.getActiveSubscriptionInfo(subId); - if (DBG) { - Log.d(TAG, "for subId: " + subId + ", subscription-info: " + info); - } - - /* If the Subscription associated with this SmsManager instance belongs to a remote-sim, - * then send the message thru the remote-sim subscription. - */ - if (info != null - && info.getSubscriptionType() == SubscriptionManager.SUBSCRIPTION_TYPE_REMOTE_SIM) { - if (DBG) Log.d(TAG, "sending message thru bluetooth"); - sendTextMessageBluetooth(destinationAddress, scAddress, text, sentIntent, - deliveryIntent, info); - return; - } - try { // If the subscription is invalid or default, we will use the default phone to send the // SMS and possibly fail later in the SMS sending process. - ISms iccISms = getISmsServiceOrThrow(); - iccISms.sendTextForSubscriber(subId, ActivityThread.currentPackageName(), + ISms iSms = getISmsServiceOrThrow(); + iSms.sendTextForSubscriber(getSubscriptionId(), ActivityThread.currentPackageName(), destinationAddress, scAddress, text, sentIntent, deliveryIntent, persistMessage); @@ -391,82 +354,6 @@ public final class SmsManager { } } - private void sendTextMessageBluetooth(String destAddr, String scAddress, - String text, PendingIntent sentIntent, PendingIntent deliveryIntent, - SubscriptionInfo info) { - BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter(); - if (btAdapter == null) { - // No bluetooth service on this platform? - sendErrorInPendingIntent(sentIntent, SmsManager.RESULT_ERROR_NO_SERVICE); - return; - } - BluetoothDevice device = btAdapter.getRemoteDevice(info.getIccId()); - if (device == null) { - if (DBG) Log.d(TAG, "Bluetooth device addr invalid: " + info.getIccId()); - sendErrorInPendingIntent(sentIntent, SmsManager.RESULT_ERROR_NO_SERVICE); - return; - } - btAdapter.getProfileProxy(ActivityThread.currentApplication().getApplicationContext(), - new MapMessageSender(destAddr, text, device, sentIntent, deliveryIntent), - BluetoothProfile.MAP_CLIENT); - } - - private class MapMessageSender implements BluetoothProfile.ServiceListener { - final Uri[] mDestAddr; - private String mMessage; - final BluetoothDevice mDevice; - final PendingIntent mSentIntent; - final PendingIntent mDeliveryIntent; - MapMessageSender(final String destAddr, final String message, final BluetoothDevice device, - final PendingIntent sentIntent, final PendingIntent deliveryIntent) { - super(); - mDestAddr = new Uri[] {new Uri.Builder() - .appendPath(destAddr) - .scheme(PhoneAccount.SCHEME_TEL) - .build()}; - mMessage = message; - mDevice = device; - mSentIntent = sentIntent; - mDeliveryIntent = deliveryIntent; - } - - @Override - public void onServiceConnected(int profile, BluetoothProfile proxy) { - if (DBG) Log.d(TAG, "Service connected"); - if (profile != BluetoothProfile.MAP_CLIENT) return; - BluetoothMapClient mapProfile = (BluetoothMapClient) proxy; - if (mMessage != null) { - if (DBG) Log.d(TAG, "Sending message thru bluetooth"); - mapProfile.sendMessage(mDevice, mDestAddr, mMessage, mSentIntent, mDeliveryIntent); - mMessage = null; - } - BluetoothAdapter.getDefaultAdapter() - .closeProfileProxy(BluetoothProfile.MAP_CLIENT, mapProfile); - } - - @Override - public void onServiceDisconnected(int profile) { - if (mMessage != null) { - if (DBG) Log.d(TAG, "Bluetooth disconnected before sending the message"); - sendErrorInPendingIntent(mSentIntent, SmsManager.RESULT_ERROR_NO_SERVICE); - mMessage = null; - } - } - } - - private void sendErrorInPendingIntent(PendingIntent intent, int errorCode) { - if (intent == null) { - return; - } - try { - intent.send(errorCode); - } catch (PendingIntent.CanceledException e) { - // PendingIntent is cancelled. ignore sending this error code back to - // caller. - if (DBG) Log.d(TAG, "PendingIntent.CanceledException: " + e.getMessage()); - } - } - /** * Send a text based SMS without writing it into the SMS Provider. * @@ -516,8 +403,8 @@ public final class SmsManager { } try { - ISms iccISms = getISmsServiceOrThrow(); - iccISms.sendTextForSubscriberWithSelfPermissions(getSubscriptionId(), + ISms iSms = getISmsServiceOrThrow(); + iSms.sendTextForSubscriberWithSelfPermissions(getSubscriptionId(), ActivityThread.currentPackageName(), destinationAddress, scAddress, text, sentIntent, deliveryIntent, persistMessage); @@ -600,9 +487,9 @@ public final class SmsManager { } try { - ISms iccISms = getISmsServiceOrThrow(); - if (iccISms != null) { - iccISms.sendTextForSubscriberWithOptions(getSubscriptionId(), + ISms iSms = getISmsServiceOrThrow(); + if (iSms != null) { + iSms.sendTextForSubscriberWithOptions(getSubscriptionId(), ActivityThread.currentPackageName(), destinationAddress, scAddress, text, sentIntent, deliveryIntent, persistMessage, priority, expectMore, validityPeriod); @@ -661,9 +548,9 @@ public final class SmsManager { "Invalid pdu format. format must be either 3gpp or 3gpp2"); } try { - ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms")); - if (iccISms != null) { - iccISms.injectSmsPduForSubscriber( + ISms iSms = ISms.Stub.asInterface(ServiceManager.getService("isms")); + if (iSms != null) { + iSms.injectSmsPduForSubscriber( getSubscriptionId(), pdu, format, receivedIntent); } } catch (RemoteException ex) { @@ -749,8 +636,8 @@ public final class SmsManager { if (parts.size() > 1) { try { - ISms iccISms = getISmsServiceOrThrow(); - iccISms.sendMultipartTextForSubscriber(getSubscriptionId(), + ISms iSms = getISmsServiceOrThrow(); + iSms.sendMultipartTextForSubscriber(getSubscriptionId(), ActivityThread.currentPackageName(), destinationAddress, scAddress, parts, sentIntents, deliveryIntents, persistMessage); @@ -881,9 +768,9 @@ public final class SmsManager { if (parts.size() > 1) { try { - ISms iccISms = getISmsServiceOrThrow(); - if (iccISms != null) { - iccISms.sendMultipartTextForSubscriberWithOptions(getSubscriptionId(), + ISms iSms = getISmsServiceOrThrow(); + if (iSms != null) { + iSms.sendMultipartTextForSubscriberWithOptions(getSubscriptionId(), ActivityThread.currentPackageName(), destinationAddress, scAddress, parts, sentIntents, deliveryIntents, persistMessage, priority, expectMore, validityPeriod); @@ -969,8 +856,8 @@ public final class SmsManager { } try { - ISms iccISms = getISmsServiceOrThrow(); - iccISms.sendDataForSubscriber(getSubscriptionId(), ActivityThread.currentPackageName(), + ISms iSms = getISmsServiceOrThrow(); + iSms.sendDataForSubscriber(getSubscriptionId(), ActivityThread.currentPackageName(), destinationAddress, scAddress, destinationPort & 0xFFFF, data, sentIntent, deliveryIntent); } catch (RemoteException ex) { @@ -996,8 +883,8 @@ public final class SmsManager { } try { - ISms iccISms = getISmsServiceOrThrow(); - iccISms.sendDataForSubscriberWithSelfPermissions(getSubscriptionId(), + ISms iSms = getISmsServiceOrThrow(); + iSms.sendDataForSubscriberWithSelfPermissions(getSubscriptionId(), ActivityThread.currentPackageName(), destinationAddress, scAddress, destinationPort & 0xFFFF, data, sentIntent, deliveryIntent); } catch (RemoteException ex) { @@ -1059,9 +946,9 @@ public final class SmsManager { boolean isSmsSimPickActivityNeeded = false; final Context context = ActivityThread.currentApplication().getApplicationContext(); try { - ISms iccISms = getISmsService(); - if (iccISms != null) { - isSmsSimPickActivityNeeded = iccISms.isSmsSimPickActivityNeeded(subId); + ISms iSms = getISmsService(); + if (iSms != null) { + isSmsSimPickActivityNeeded = iSms.isSmsSimPickActivityNeeded(subId); } } catch (RemoteException ex) { Log.e(TAG, "Exception in getSubscriptionId"); @@ -1092,11 +979,11 @@ public final class SmsManager { * the service does not exist. */ private static ISms getISmsServiceOrThrow() { - ISms iccISms = getISmsService(); - if (iccISms == null) { + ISms iSms = getISmsService(); + if (iSms == null) { throw new UnsupportedOperationException("Sms is not supported"); } - return iccISms; + return iSms; } private static ISms getISmsService() { @@ -1125,9 +1012,9 @@ public final class SmsManager { throw new IllegalArgumentException("pdu is NULL"); } try { - ISms iccISms = getISmsService(); - if (iccISms != null) { - success = iccISms.copyMessageToIccEfForSubscriber(getSubscriptionId(), + ISms iSms = getISmsService(); + if (iSms != null) { + success = iSms.copyMessageToIccEfForSubscriber(getSubscriptionId(), ActivityThread.currentPackageName(), status, pdu, smsc); } @@ -1156,9 +1043,9 @@ public final class SmsManager { Arrays.fill(pdu, (byte)0xff); try { - ISms iccISms = getISmsService(); - if (iccISms != null) { - success = iccISms.updateMessageOnIccEfForSubscriber(getSubscriptionId(), + ISms iSms = getISmsService(); + if (iSms != null) { + success = iSms.updateMessageOnIccEfForSubscriber(getSubscriptionId(), ActivityThread.currentPackageName(), messageIndex, STATUS_ON_ICC_FREE, pdu); } @@ -1188,9 +1075,9 @@ public final class SmsManager { boolean success = false; try { - ISms iccISms = getISmsService(); - if (iccISms != null) { - success = iccISms.updateMessageOnIccEfForSubscriber(getSubscriptionId(), + ISms iSms = getISmsService(); + if (iSms != null) { + success = iSms.updateMessageOnIccEfForSubscriber(getSubscriptionId(), ActivityThread.currentPackageName(), messageIndex, newStatus, pdu); } @@ -1215,9 +1102,9 @@ public final class SmsManager { List<SmsRawData> records = null; try { - ISms iccISms = getISmsService(); - if (iccISms != null) { - records = iccISms.getAllMessagesFromIccEfForSubscriber( + ISms iSms = getISmsService(); + if (iSms != null) { + records = iSms.getAllMessagesFromIccEfForSubscriber( getSubscriptionId(), ActivityThread.currentPackageName()); } @@ -1252,9 +1139,9 @@ public final class SmsManager { boolean success = false; try { - ISms iccISms = getISmsService(); - if (iccISms != null) { - success = iccISms.enableCellBroadcastForSubscriber( + ISms iSms = getISmsService(); + if (iSms != null) { + success = iSms.enableCellBroadcastForSubscriber( getSubscriptionId(), messageIdentifier, ranType); } } catch (RemoteException ex) { @@ -1288,9 +1175,9 @@ public final class SmsManager { boolean success = false; try { - ISms iccISms = getISmsService(); - if (iccISms != null) { - success = iccISms.disableCellBroadcastForSubscriber( + ISms iSms = getISmsService(); + if (iSms != null) { + success = iSms.disableCellBroadcastForSubscriber( getSubscriptionId(), messageIdentifier, ranType); } } catch (RemoteException ex) { @@ -1331,9 +1218,9 @@ public final class SmsManager { throw new IllegalArgumentException("endMessageId < startMessageId"); } try { - ISms iccISms = getISmsService(); - if (iccISms != null) { - success = iccISms.enableCellBroadcastRangeForSubscriber(getSubscriptionId(), + ISms iSms = getISmsService(); + if (iSms != null) { + success = iSms.enableCellBroadcastRangeForSubscriber(getSubscriptionId(), startMessageId, endMessageId, ranType); } } catch (RemoteException ex) { @@ -1374,9 +1261,9 @@ public final class SmsManager { throw new IllegalArgumentException("endMessageId < startMessageId"); } try { - ISms iccISms = getISmsService(); - if (iccISms != null) { - success = iccISms.disableCellBroadcastRangeForSubscriber(getSubscriptionId(), + ISms iSms = getISmsService(); + if (iSms != null) { + success = iSms.disableCellBroadcastRangeForSubscriber(getSubscriptionId(), startMessageId, endMessageId, ranType); } } catch (RemoteException ex) { @@ -1426,9 +1313,9 @@ public final class SmsManager { public boolean isImsSmsSupported() { boolean boSupported = false; try { - ISms iccISms = getISmsService(); - if (iccISms != null) { - boSupported = iccISms.isImsSmsSupportedForSubscriber(getSubscriptionId()); + ISms iSms = getISmsService(); + if (iSms != null) { + boSupported = iSms.isImsSmsSupportedForSubscriber(getSubscriptionId()); } } catch (RemoteException ex) { // ignore it @@ -1451,9 +1338,9 @@ public final class SmsManager { public String getImsSmsFormat() { String format = com.android.internal.telephony.SmsConstants.FORMAT_UNKNOWN; try { - ISms iccISms = getISmsService(); - if (iccISms != null) { - format = iccISms.getImsSmsFormatForSubscriber(getSubscriptionId()); + ISms iSms = getISmsService(); + if (iSms != null) { + format = iSms.getImsSmsFormatForSubscriber(getSubscriptionId()); } } catch (RemoteException ex) { // ignore it @@ -1467,10 +1354,10 @@ public final class SmsManager { * @return the default SMS subscription id */ public static int getDefaultSmsSubscriptionId() { - ISms iccISms = null; + ISms iSms = null; try { - iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms")); - return iccISms.getPreferredSmsSubscription(); + iSms = ISms.Stub.asInterface(ServiceManager.getService("isms")); + return iSms.getPreferredSmsSubscription(); } catch (RemoteException ex) { return -1; } catch (NullPointerException ex) { @@ -1486,10 +1373,10 @@ public final class SmsManager { */ @UnsupportedAppUsage public boolean isSMSPromptEnabled() { - ISms iccISms = null; + ISms iSms = null; try { - iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms")); - return iccISms.isSMSPromptEnabled(); + iSms = ISms.Stub.asInterface(ServiceManager.getService("isms")); + return iSms.isSMSPromptEnabled(); } catch (RemoteException ex) { return false; } catch (NullPointerException ex) { @@ -1966,8 +1853,8 @@ public final class SmsManager { throw new IllegalArgumentException("Empty message URI"); } try { - ISms iccISms = getISmsServiceOrThrow(); - iccISms.sendStoredText( + ISms iSms = getISmsServiceOrThrow(); + iSms.sendStoredText( getSubscriptionId(), ActivityThread.currentPackageName(), messageUri, scAddress, sentIntent, deliveryIntent); } catch (RemoteException ex) { @@ -2014,8 +1901,8 @@ public final class SmsManager { throw new IllegalArgumentException("Empty message URI"); } try { - ISms iccISms = getISmsServiceOrThrow(); - iccISms.sendStoredMultipartText( + ISms iSms = getISmsServiceOrThrow(); + iSms.sendStoredMultipartText( getSubscriptionId(), ActivityThread.currentPackageName(), messageUri, scAddress, sentIntents, deliveryIntents); } catch (RemoteException ex) { diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java index 58f12e2c427a..b781b109bdcc 100644 --- a/telephony/java/android/telephony/SubscriptionInfo.java +++ b/telephony/java/android/telephony/SubscriptionInfo.java @@ -467,7 +467,7 @@ public class SubscriptionInfo implements Parcelable { * @return group UUID a String of group UUID if it belongs to a group. Otherwise * it will return null. */ - public String getGroupUuid() { + public @Nullable String getGroupUuid() { return mGroupUUID; } diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java index 0bbf054d7563..d5862280b3b1 100644 --- a/telephony/java/android/telephony/SubscriptionManager.java +++ b/telephony/java/android/telephony/SubscriptionManager.java @@ -63,6 +63,7 @@ import com.android.internal.telephony.ISetOpportunisticDataCallback; import com.android.internal.telephony.ISub; import com.android.internal.telephony.ITelephonyRegistry; import com.android.internal.telephony.PhoneConstants; +import com.android.internal.util.Preconditions; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -1075,7 +1076,8 @@ public class SubscriptionManager { * @param listener that is to be unregistered. */ public void removeOnOpportunisticSubscriptionsChangedListener( - OnOpportunisticSubscriptionsChangedListener listener) { + @NonNull OnOpportunisticSubscriptionsChangedListener listener) { + Preconditions.checkNotNull(listener, "listener cannot be null"); String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>"; if (DBG) { logd("unregister OnOpportunisticSubscriptionsChangedListener pkgForDebug=" @@ -1269,7 +1271,7 @@ public class SubscriptionManager { if (!userVisibleOnly || activeList == null) { return activeList; } else { - return activeList.stream().filter(subInfo -> !shouldHideSubscription(subInfo)) + return activeList.stream().filter(subInfo -> isSubscriptionVisible(subInfo)) .collect(Collectors.toList()); } } @@ -2699,7 +2701,8 @@ public class SubscriptionManager { * @param callbackIntent pending intent that will be sent after operation is done. */ @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) - public void switchToSubscription(int subId, PendingIntent callbackIntent) { + public void switchToSubscription(int subId, @NonNull PendingIntent callbackIntent) { + Preconditions.checkNotNull(callbackIntent, "callbackIntent cannot be null"); EuiccManager euiccManager = new EuiccManager(mContext); euiccManager.switchToSubscription(subId, callbackIntent); } @@ -2874,32 +2877,27 @@ public class SubscriptionManager { } /** - * Whether system UI should hide a subscription. If it's a bundled opportunistic - * subscription, it shouldn't show up in anywhere in Settings app, dialer app, - * or status bar. Exception is if caller is carrier app, in which case they will + * Whether a subscription is visible to API caller. If it's a bundled opportunistic + * subscription, it should be hidden anywhere in Settings, dialer, status bar etc. + * Exception is if caller owns carrier privilege, in which case they will * want to see their own hidden subscriptions. * * @param info the subscriptionInfo to check against. - * @return true if this subscription should be hidden. + * @return true if this subscription should be visible to the API caller. * - * @hide */ - public boolean shouldHideSubscription(SubscriptionInfo info) { + private boolean isSubscriptionVisible(SubscriptionInfo info) { if (info == null) return false; - // If hasCarrierPrivileges or canManageSubscription returns true, it means caller - // has carrier privilege. - boolean hasCarrierPrivilegePermission = (info.isEmbedded() && canManageSubscription(info)) - || TelephonyManager.from(mContext).hasCarrierPrivileges(info.getSubscriptionId()); - - return isInvisibleSubscription(info) && !hasCarrierPrivilegePermission; - } + // If subscription is NOT grouped opportunistic subscription, it's visible. + if (TextUtils.isEmpty(info.getGroupUuid()) || !info.isOpportunistic()) return true; - /** - * @hide - */ - public static boolean isInvisibleSubscription(SubscriptionInfo info) { - return info != null && !TextUtils.isEmpty(info.getGroupUuid()) && info.isOpportunistic(); + // If the caller is the carrier app and owns the subscription, it should be visible + // to the caller. + boolean hasCarrierPrivilegePermission = TelephonyManager.from(mContext) + .hasCarrierPrivileges(info.getSubscriptionId()) + || (info.isEmbedded() && canManageSubscription(info)); + return hasCarrierPrivilegePermission; } /** @@ -2927,7 +2925,7 @@ public class SubscriptionManager { for (SubscriptionInfo info : availableList) { // Opportunistic subscriptions are considered invisible // to users so they should never be returned. - if (isInvisibleSubscription(info)) continue; + if (!isSubscriptionVisible(info)) continue; String groupUuid = info.getGroupUuid(); if (groupUuid == null) { @@ -2949,7 +2947,7 @@ public class SubscriptionManager { } /** - * Enabled or disable a subscription. This is currently used in the settings page. + * Enables or disables a subscription. This is currently used in the settings page. * * <p> * Permissions android.Manifest.permission.MODIFY_PHONE_STATE is required diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 857b4973dbd2..955977d63413 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -4755,22 +4755,18 @@ public class TelephonyManager { * Registers a listener object to receive notification of changes * in specified telephony states. * <p> - * To register a listener, pass a {@link PhoneStateListener} and specify at least one telephony - * state of interest in the events argument. - * - * At registration, and when a specified telephony state changes, the telephony manager invokes - * the appropriate callback method on the listener object and passes the current (updated) - * values. + * To register a listener, pass a {@link PhoneStateListener} + * and specify at least one telephony state of interest in + * the events argument. + * + * At registration, and when a specified telephony state + * changes, the telephony manager invokes the appropriate + * callback method on the listener object and passes the + * current (updated) values. * <p> - * To un-register a listener, pass the listener object and set the events argument to + * To unregister a listener, pass the listener object and set the + * events argument to * {@link PhoneStateListener#LISTEN_NONE LISTEN_NONE} (0). - * - * If this TelephonyManager object has been created with {@link #createForSubscriptionId}, - * applies to the given subId. Otherwise, applies to - * {@link SubscriptionManager#getDefaultSubscriptionId()}. To listen events for multiple subIds, - * pass a separate listener object to each TelephonyManager object created with - * {@link #createForSubscriptionId}. - * * Note: if you call this method while in the middle of a binder transaction, you <b>must</b> * call {@link android.os.Binder#clearCallingIdentity()} before calling this method. A * {@link SecurityException} will be thrown otherwise. @@ -4785,18 +4781,17 @@ public class TelephonyManager { if (mContext == null) return; try { boolean notifyNow = (getITelephony() != null); + // If the listener has not explicitly set the subId (for example, created with the + // default constructor), replace the subId so it will listen to the account the + // telephony manager is created with. + if (listener.mSubId == null) { + listener.mSubId = mSubId; + } + ITelephonyRegistry registry = getTelephonyRegistry(); if (registry != null) { - // listen to the subId the telephony manager is created with. Ignore subId in - // PhoneStateListener. - registry.listenForSubscriber(mSubId, getOpPackageName(), + registry.listenForSubscriber(listener.mSubId, getOpPackageName(), listener.callback, events, notifyNow); - // TODO: remove this once we remove PhoneStateListener constructor with subId. - if (events == PhoneStateListener.LISTEN_NONE) { - listener.mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; - } else { - listener.mSubId = mSubId; - } } else { Rlog.w(TAG, "telephony registry not ready."); } @@ -7107,10 +7102,21 @@ public class TelephonyManager { * @hide */ public boolean getTetherApnRequired() { + return getTetherApnRequired(getSubId(SubscriptionManager.getDefaultDataSubscriptionId())); + } + + /** + * Check whether DUN APN is required for tethering with subId. + * + * @param subId the id of the subscription to require tethering. + * @return {@code true} if DUN APN is required for tethering. + * @hide + */ + public boolean getTetherApnRequired(int subId) { try { ITelephony telephony = getITelephony(); if (telephony != null) - return telephony.getTetherApnRequired(); + return telephony.getTetherApnRequiredForSubscriber(subId); } catch (RemoteException ex) { Rlog.e(TAG, "hasMatchedTetherApnSetting RemoteException", ex); } catch (NullPointerException ex) { diff --git a/telephony/java/android/telephony/VoiceSpecificRegistrationStates.java b/telephony/java/android/telephony/VoiceSpecificRegistrationInfo.java index 871ee4d9f0a1..18a533a46273 100644 --- a/telephony/java/android/telephony/VoiceSpecificRegistrationStates.java +++ b/telephony/java/android/telephony/VoiceSpecificRegistrationInfo.java @@ -1,5 +1,22 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package android.telephony; +import android.annotation.NonNull; import android.os.Parcel; import android.os.Parcelable; @@ -10,14 +27,14 @@ import java.util.Objects; * Class that stores information specific to voice network registration. * @hide */ -public class VoiceSpecificRegistrationStates implements Parcelable{ +public class VoiceSpecificRegistrationInfo implements Parcelable{ /** * oncurrent services support indicator. if * registered on a CDMA system. * false - Concurrent services not supported, * true - Concurrent services supported */ - public final boolean cssSupported; + public final boolean cssSupported; /** * TSB-58 Roaming Indicator if registered @@ -40,15 +57,15 @@ public class VoiceSpecificRegistrationStates implements Parcelable{ */ public final int defaultRoamingIndicator; - VoiceSpecificRegistrationStates(boolean cssSupported, int roamingIndicator, int systemIsInPrl, - int defaultRoamingIndicator) { + VoiceSpecificRegistrationInfo(boolean cssSupported, int roamingIndicator, int systemIsInPrl, + int defaultRoamingIndicator) { this.cssSupported = cssSupported; this.roamingIndicator = roamingIndicator; this.systemIsInPrl = systemIsInPrl; this.defaultRoamingIndicator = defaultRoamingIndicator; } - private VoiceSpecificRegistrationStates(Parcel source) { + private VoiceSpecificRegistrationInfo(Parcel source) { this.cssSupported = source.readBoolean(); this.roamingIndicator = source.readInt(); this.systemIsInPrl = source.readInt(); @@ -70,7 +87,7 @@ public class VoiceSpecificRegistrationStates implements Parcelable{ @Override public String toString() { - return "VoiceSpecificRegistrationStates {" + return "VoiceSpecificRegistrationInfo {" + " mCssSupported=" + cssSupported + " mRoamingIndicator=" + roamingIndicator + " mSystemIsInPrl=" + systemIsInPrl @@ -87,11 +104,11 @@ public class VoiceSpecificRegistrationStates implements Parcelable{ public boolean equals(Object o) { if (this == o) return true; - if (o == null || !(o instanceof VoiceSpecificRegistrationStates)) { + if (o == null || !(o instanceof VoiceSpecificRegistrationInfo)) { return false; } - VoiceSpecificRegistrationStates other = (VoiceSpecificRegistrationStates) o; + VoiceSpecificRegistrationInfo other = (VoiceSpecificRegistrationInfo) o; return this.cssSupported == other.cssSupported && this.roamingIndicator == other.roamingIndicator && this.systemIsInPrl == other.systemIsInPrl @@ -99,16 +116,16 @@ public class VoiceSpecificRegistrationStates implements Parcelable{ } - public static final Parcelable.Creator<VoiceSpecificRegistrationStates> CREATOR = - new Parcelable.Creator<VoiceSpecificRegistrationStates>() { + public static final @NonNull Parcelable.Creator<VoiceSpecificRegistrationInfo> CREATOR = + new Parcelable.Creator<VoiceSpecificRegistrationInfo>() { @Override - public VoiceSpecificRegistrationStates createFromParcel(Parcel source) { - return new VoiceSpecificRegistrationStates(source); + public VoiceSpecificRegistrationInfo createFromParcel(Parcel source) { + return new VoiceSpecificRegistrationInfo(source); } @Override - public VoiceSpecificRegistrationStates[] newArray(int size) { - return new VoiceSpecificRegistrationStates[size]; + public VoiceSpecificRegistrationInfo[] newArray(int size) { + return new VoiceSpecificRegistrationInfo[size]; } }; -}
\ No newline at end of file +} diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java index ae2c1d1f1e72..4b9abc1e6f33 100644 --- a/telephony/java/android/telephony/data/ApnSetting.java +++ b/telephony/java/android/telephony/data/ApnSetting.java @@ -17,6 +17,7 @@ package android.telephony.data; import android.annotation.IntDef; import android.annotation.NonNull; +import android.annotation.Nullable; import android.content.ContentValues; import android.database.Cursor; import android.hardware.radio.V1_4.ApnTypes; @@ -1620,7 +1621,7 @@ public class ApnSetting implements Parcelable { * @param mvnoMatchData the MVNO match data for the APN * @hide */ - public Builder setMvnoMatchData(String mvnoMatchData) { + public Builder setMvnoMatchData(@Nullable String mvnoMatchData) { this.mMvnoMatchData = mvnoMatchData; return this; } @@ -1642,7 +1643,7 @@ public class ApnSetting implements Parcelable { * @param entryName the entry name to set for the APN */ @NonNull - public Builder setEntryName(String entryName) { + public Builder setEntryName(@Nullable String entryName) { this.mEntryName = entryName; return this; } @@ -1653,7 +1654,7 @@ public class ApnSetting implements Parcelable { * @param apnName the name to set for the APN */ @NonNull - public Builder setApnName(String apnName) { + public Builder setApnName(@Nullable String apnName) { this.mApnName = apnName; return this; } @@ -1684,7 +1685,7 @@ public class ApnSetting implements Parcelable { * @param proxy the proxy address to set for the APN */ @NonNull - public Builder setProxyAddress(String proxy) { + public Builder setProxyAddress(@Nullable String proxy) { this.mProxyAddress = proxy; return this; } @@ -1706,7 +1707,7 @@ public class ApnSetting implements Parcelable { * @param mmsc the MMSC Uri to set for the APN */ @NonNull - public Builder setMmsc(Uri mmsc) { + public Builder setMmsc(@Nullable Uri mmsc) { this.mMmsc = mmsc; return this; } @@ -1738,7 +1739,7 @@ public class ApnSetting implements Parcelable { * @param mmsProxy the MMS proxy address to set for the APN */ @NonNull - public Builder setMmsProxyAddress(String mmsProxy) { + public Builder setMmsProxyAddress(@Nullable String mmsProxy) { this.mMmsProxyAddress = mmsProxy; return this; } @@ -1760,7 +1761,7 @@ public class ApnSetting implements Parcelable { * @param user the APN username to set for the APN */ @NonNull - public Builder setUser(String user) { + public Builder setUser(@Nullable String user) { this.mUser = user; return this; } @@ -1772,7 +1773,7 @@ public class ApnSetting implements Parcelable { * @param password the APN password to set for the APN */ @NonNull - public Builder setPassword(String password) { + public Builder setPassword(@Nullable String password) { this.mPassword = password; return this; } @@ -1813,7 +1814,7 @@ public class ApnSetting implements Parcelable { * @param operatorNumeric the numeric operator ID to set for this entry */ @NonNull - public Builder setOperatorNumeric(String operatorNumeric) { + public Builder setOperatorNumeric(@Nullable String operatorNumeric) { this.mOperatorNumeric = operatorNumeric; return this; } diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index 209d35efe03e..c8dab272de3e 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -788,12 +788,13 @@ interface ITelephony { int getPreferredNetworkType(int subId); /** - * Check whether DUN APN is required for tethering. + * Check whether DUN APN is required for tethering with subId. * + * @param subId the id of the subscription to require tethering. * @return {@code true} if DUN APN is required for tethering. * @hide */ - boolean getTetherApnRequired(); + boolean getTetherApnRequiredForSubscriber(int subId); /** * Enables framework IMS and triggers IMS Registration. diff --git a/tests/net/java/android/net/NetworkStatsTest.java b/tests/net/java/android/net/NetworkStatsTest.java index b5b0384ca599..c16a0f446651 100644 --- a/tests/net/java/android/net/NetworkStatsTest.java +++ b/tests/net/java/android/net/NetworkStatsTest.java @@ -569,7 +569,7 @@ public class NetworkStatsTest { .addValues(underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L); - assertTrue(delta.toString(), delta.migrateTun(tunUid, tunIface, underlyingIface)); + delta.migrateTun(tunUid, tunIface, new String[] {underlyingIface}); assertEquals(20, delta.size()); // tunIface and TEST_IFACE entries are not changed. @@ -650,7 +650,7 @@ public class NetworkStatsTest { .addValues(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 75500L, 37L, 130000L, 70L, 0L); - assertTrue(delta.migrateTun(tunUid, tunIface, underlyingIface)); + delta.migrateTun(tunUid, tunIface, new String[]{underlyingIface}); assertEquals(9, delta.size()); // tunIface entries should not be changed. @@ -813,6 +813,37 @@ public class NetworkStatsTest { } @Test + public void testFilterDebugEntries() { + NetworkStats.Entry entry1 = new NetworkStats.Entry( + "test1", 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, + DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L); + + NetworkStats.Entry entry2 = new NetworkStats.Entry( + "test2", 10101, SET_DBG_VPN_IN, TAG_NONE, METERED_NO, ROAMING_NO, + DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L); + + NetworkStats.Entry entry3 = new NetworkStats.Entry( + "test2", 10101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, + DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L); + + NetworkStats.Entry entry4 = new NetworkStats.Entry( + "test2", 10101, SET_DBG_VPN_OUT, TAG_NONE, METERED_NO, ROAMING_NO, + DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L); + + NetworkStats stats = new NetworkStats(TEST_START, 4) + .addValues(entry1) + .addValues(entry2) + .addValues(entry3) + .addValues(entry4); + + stats.filterDebugEntries(); + + assertEquals(2, stats.size()); + assertEquals(entry1, stats.getValues(0, null)); + assertEquals(entry3, stats.getValues(1, null)); + } + + @Test public void testApply464xlatAdjustments() { final String v4Iface = "v4-wlan0"; final String baseIface = "wlan0"; diff --git a/tests/net/java/android/net/TcpKeepalivePacketDataTest.java b/tests/net/java/android/net/TcpKeepalivePacketDataTest.java index 372ffcd057b4..e0b722761c34 100644 --- a/tests/net/java/android/net/TcpKeepalivePacketDataTest.java +++ b/tests/net/java/android/net/TcpKeepalivePacketDataTest.java @@ -48,6 +48,8 @@ public final class TcpKeepalivePacketDataTest { final int ack = 0x22222222; final int wnd = 8000; final int wndScale = 2; + final int tos = 4; + final int ttl = 64; TcpKeepalivePacketData resultData = null; final TcpKeepalivePacketDataParcelable testInfo = new TcpKeepalivePacketDataParcelable(); testInfo.srcAddress = IPV4_KEEPALIVE_SRC_ADDR; @@ -58,6 +60,8 @@ public final class TcpKeepalivePacketDataTest { testInfo.ack = ack; testInfo.rcvWnd = wnd; testInfo.rcvWndScale = wndScale; + testInfo.tos = tos; + testInfo.ttl = ttl; try { resultData = TcpKeepalivePacketData.tcpKeepalivePacket(testInfo); } catch (InvalidPacketException e) { @@ -72,16 +76,21 @@ public final class TcpKeepalivePacketDataTest { assertEquals(testInfo.ack, resultData.tcpAck); assertEquals(testInfo.rcvWnd, resultData.tcpWnd); assertEquals(testInfo.rcvWndScale, resultData.tcpWndScale); + assertEquals(testInfo.tos, resultData.ipTos); + assertEquals(testInfo.ttl, resultData.ipTtl); TestUtils.assertParcelingIsLossless(resultData, TcpKeepalivePacketData.CREATOR); final byte[] packet = resultData.getPacket(); - // IP version and TOS. - ByteBuffer buf = ByteBuffer.wrap(packet); - assertEquals(buf.getShort(), 0x4500); + // IP version and IHL + assertEquals(packet[0], 0x45); + // TOS + assertEquals(packet[1], tos); + // TTL + assertEquals(packet[8], ttl); // Source IP address. byte[] ip = new byte[4]; - buf = ByteBuffer.wrap(packet, 12, 4); + ByteBuffer buf = ByteBuffer.wrap(packet, 12, 4); buf.get(ip); assertArrayEquals(ip, IPV4_KEEPALIVE_SRC_ADDR); // Destination IP address. @@ -113,6 +122,8 @@ public final class TcpKeepalivePacketDataTest { final int ack = 0x22222222; final int wnd = 48_000; final int wndScale = 2; + final int tos = 4; + final int ttl = 64; final TcpKeepalivePacketDataParcelable testInfo = new TcpKeepalivePacketDataParcelable(); testInfo.srcAddress = IPV4_KEEPALIVE_SRC_ADDR; testInfo.srcPort = srcPort; @@ -122,6 +133,8 @@ public final class TcpKeepalivePacketDataTest { testInfo.ack = ack; testInfo.rcvWnd = wnd; testInfo.rcvWndScale = wndScale; + testInfo.tos = tos; + testInfo.ttl = ttl; TcpKeepalivePacketData testData = null; TcpKeepalivePacketDataParcelable resultData = null; testData = TcpKeepalivePacketData.tcpKeepalivePacket(testInfo); @@ -134,5 +147,7 @@ public final class TcpKeepalivePacketDataTest { assertEquals(resultData.ack, ack); assertEquals(resultData.rcvWnd, wnd); assertEquals(resultData.rcvWndScale, wndScale); + assertEquals(resultData.tos, tos); + assertEquals(resultData.ttl, ttl); } } diff --git a/tests/net/java/android/net/shared/IpConfigurationParcelableUtilTest.java b/tests/net/java/android/net/shared/IpConfigurationParcelableUtilTest.java index 3e86e77183ec..21a4988950db 100644 --- a/tests/net/java/android/net/shared/IpConfigurationParcelableUtilTest.java +++ b/tests/net/java/android/net/shared/IpConfigurationParcelableUtilTest.java @@ -25,8 +25,6 @@ import static org.junit.Assert.assertEquals; import android.net.DhcpResults; import android.net.LinkAddress; -import android.net.StaticIpConfiguration; -import android.net.apf.ApfCapabilities; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; @@ -43,21 +41,16 @@ import java.net.Inet4Address; @RunWith(AndroidJUnit4.class) @SmallTest public class IpConfigurationParcelableUtilTest { - private StaticIpConfiguration mStaticIpConfiguration; private DhcpResults mDhcpResults; @Before public void setUp() { - mStaticIpConfiguration = new StaticIpConfiguration(); - mStaticIpConfiguration.ipAddress = new LinkAddress(parseNumericAddress("2001:db8::42"), 64); - mStaticIpConfiguration.gateway = parseNumericAddress("192.168.42.42"); - mStaticIpConfiguration.dnsServers.add(parseNumericAddress("2001:db8::43")); - mStaticIpConfiguration.dnsServers.add(parseNumericAddress("192.168.43.43")); - mStaticIpConfiguration.domains = "example.com"; - // Any added StaticIpConfiguration field must be included in equals() to be tested properly - assertFieldCountEquals(4, StaticIpConfiguration.class); - - mDhcpResults = new DhcpResults(mStaticIpConfiguration); + mDhcpResults = new DhcpResults(); + mDhcpResults.ipAddress = new LinkAddress(parseNumericAddress("2001:db8::42"), 64); + mDhcpResults.gateway = parseNumericAddress("192.168.42.42"); + mDhcpResults.dnsServers.add(parseNumericAddress("2001:db8::43")); + mDhcpResults.dnsServers.add(parseNumericAddress("192.168.43.43")); + mDhcpResults.domains = "example.com"; mDhcpResults.serverAddress = (Inet4Address) parseNumericAddress("192.168.44.44"); mDhcpResults.vendorInfo = "TEST_VENDOR_INFO"; mDhcpResults.leaseDuration = 3600; @@ -67,42 +60,31 @@ public class IpConfigurationParcelableUtilTest { } @Test - public void testParcelUnparcelStaticConfiguration() { - doStaticConfigurationParcelUnparcelTest(); - } - - @Test - public void testParcelUnparcelStaticConfiguration_NullIpAddress() { - mStaticIpConfiguration.ipAddress = null; - doStaticConfigurationParcelUnparcelTest(); + public void testParcelUnparcelDhcpResults() { + doDhcpResultsParcelUnparcelTest(); } @Test - public void testParcelUnparcelStaticConfiguration_NullGateway() { - mStaticIpConfiguration.gateway = null; - doStaticConfigurationParcelUnparcelTest(); + public void testParcelUnparcelDhcpResults_NullIpAddress() { + mDhcpResults.ipAddress = null; + doDhcpResultsParcelUnparcelTest(); } @Test - public void testParcelUnparcelStaticConfiguration_NullDomains() { - mStaticIpConfiguration.domains = null; - doStaticConfigurationParcelUnparcelTest(); + public void testParcelUnparcelDhcpResults_NullGateway() { + mDhcpResults.gateway = null; + doDhcpResultsParcelUnparcelTest(); } @Test - public void testParcelUnparcelStaticConfiguration_EmptyDomains() { - mStaticIpConfiguration.domains = ""; - doStaticConfigurationParcelUnparcelTest(); - } - - private void doStaticConfigurationParcelUnparcelTest() { - final StaticIpConfiguration unparceled = - fromStableParcelable(toStableParcelable(mStaticIpConfiguration)); - assertEquals(mStaticIpConfiguration, unparceled); + public void testParcelUnparcelDhcpResults_NullDomains() { + mDhcpResults.domains = null; + doDhcpResultsParcelUnparcelTest(); } @Test - public void testParcelUnparcelDhcpResults() { + public void testParcelUnparcelDhcpResults_EmptyDomains() { + mDhcpResults.domains = ""; doDhcpResultsParcelUnparcelTest(); } @@ -122,10 +104,4 @@ public class IpConfigurationParcelableUtilTest { final DhcpResults unparceled = fromStableParcelable(toStableParcelable(mDhcpResults)); assertEquals(mDhcpResults, unparceled); } - - @Test - public void testParcelUnparcelApfCapabilities() { - final ApfCapabilities caps = new ApfCapabilities(123, 456, 789); - assertEquals(caps, fromStableParcelable(toStableParcelable(caps))); - } } diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index d3616aa89f74..afefd5e4e6a9 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -104,6 +104,7 @@ import android.net.ConnectivityManager.PacketKeepalive; import android.net.ConnectivityManager.PacketKeepaliveCallback; import android.net.ConnectivityManager.TooManyRequestsException; import android.net.ConnectivityThread; +import android.net.IDnsResolver; import android.net.INetd; import android.net.INetworkMonitor; import android.net.INetworkMonitorCallbacks; @@ -144,12 +145,14 @@ import android.os.INetworkManagementService; import android.os.Looper; import android.os.Message; import android.os.Parcel; +import android.os.ParcelFileDescriptor; import android.os.Parcelable; import android.os.Process; import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; import android.provider.Settings; +import android.system.Os; import android.test.mock.MockContentResolver; import android.text.TextUtils; import android.util.ArraySet; @@ -188,6 +191,8 @@ import org.mockito.MockitoAnnotations; import org.mockito.Spy; import org.mockito.stubbing.Answer; +import java.io.IOException; +import java.net.DatagramSocket; import java.net.Inet4Address; import java.net.InetAddress; import java.net.InetSocketAddress; @@ -208,7 +213,6 @@ import java.util.concurrent.Executors; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.function.Consumer; import java.util.function.Predicate; /** @@ -237,6 +241,7 @@ public class ConnectivityServiceTest { private static final String CLAT_PREFIX = "v4-"; private static final String MOBILE_IFNAME = "test_rmnet_data0"; private static final String WIFI_IFNAME = "test_wlan0"; + private static final String[] EMPTY_STRING_ARRAY = new String[0]; private MockContext mServiceContext; private WrappedConnectivityService mService; @@ -253,6 +258,7 @@ public class ConnectivityServiceTest { @Mock INetworkManagementService mNetworkManagementService; @Mock INetworkStatsService mStatsService; @Mock INetworkPolicyManager mNpm; + @Mock IDnsResolver mMockDnsResolver; @Mock INetd mMockNetd; @Mock NetworkStackClient mNetworkStack; @@ -421,7 +427,7 @@ public class ConnectivityServiceTest { private final ConditionVariable mPreventReconnectReceived = new ConditionVariable(); private int mScore; private NetworkAgent mNetworkAgent; - private int mStartKeepaliveError = SocketKeepalive.ERROR_HARDWARE_UNSUPPORTED; + private int mStartKeepaliveError = SocketKeepalive.ERROR_UNSUPPORTED; private int mStopKeepaliveError = SocketKeepalive.NO_KEEPALIVE; private Integer mExpectedKeepaliveSlot = null; // Contains the redirectUrl from networkStatus(). Before reading, wait for @@ -495,7 +501,6 @@ public class ConnectivityServiceTest { try { doAnswer(validateAnswer).when(mNetworkMonitor).notifyNetworkConnected(); doAnswer(validateAnswer).when(mNetworkMonitor).forceReevaluation(anyInt()); - doAnswer(validateAnswer).when(mNetworkMonitor).setAcceptPartialConnectivity(); } catch (RemoteException e) { fail(e.getMessage()); } @@ -1051,8 +1056,8 @@ public class ConnectivityServiceTest { public WrappedConnectivityService(Context context, INetworkManagementService netManager, INetworkStatsService statsService, INetworkPolicyManager policyManager, - IpConnectivityLog log, INetd netd) { - super(context, netManager, statsService, policyManager, log); + IpConnectivityLog log, INetd netd, IDnsResolver dnsResolver) { + super(context, netManager, statsService, policyManager, dnsResolver, log); mNetd = netd; mLingerDelayMs = TEST_LINGER_DELAY_MS; } @@ -1216,7 +1221,8 @@ public class ConnectivityServiceTest { mStatsService, mNpm, mock(IpConnectivityLog.class), - mMockNetd); + mMockNetd, + mMockDnsResolver); final ArgumentCaptor<INetworkPolicyListener> policyListenerCaptor = ArgumentCaptor.forClass(INetworkPolicyListener.class); @@ -2550,8 +2556,7 @@ public class ConnectivityServiceTest { verifyActiveNetwork(TRANSPORT_CELLULAR); } - // TODO(b/128426024): deflake and re-enable - // @Test + @Test public void testPartialConnectivity() { // Register network callback. NetworkRequest request = new NetworkRequest.Builder() @@ -2575,20 +2580,24 @@ public class ConnectivityServiceTest { assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); callback.assertNoCallback(); + // With HTTPS probe disabled, NetworkMonitor should pass the network validation with http + // probe. + mWiFiNetworkAgent.setNetworkValid(); // If the user chooses yes to use this partial connectivity wifi, switch the default // network to wifi and check if wifi becomes valid or not. mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */, false /* always */); - // With https probe disabled, NetworkMonitor should pass the network validation with http - // probe. - mWiFiNetworkAgent.setNetworkValid(); + // If user accepts partial connectivity network, + // NetworkMonitor#setAcceptPartialConnectivity() should be called too. waitForIdle(); try { - verify(mWiFiNetworkAgent.mNetworkMonitor, - timeout(TIMEOUT_MS).times(1)).setAcceptPartialConnectivity(); + verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity(); } catch (RemoteException e) { fail(e.getMessage()); } + // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is + // validated. + mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true); callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent); NetworkCapabilities nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); @@ -2618,6 +2627,15 @@ public class ConnectivityServiceTest { // acceptUnvalidated is also used as setting for accepting partial networks. mWiFiNetworkAgent.explicitlySelected(true /* acceptUnvalidated */); mWiFiNetworkAgent.connect(true); + // If user accepted partial connectivity network before, + // NetworkMonitor#setAcceptPartialConnectivity() will be called in + // ConnectivityService#updateNetworkInfo(). + waitForIdle(); + try { + verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity(); + } catch (RemoteException e) { + fail(e.getMessage()); + } callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent); nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); @@ -2632,23 +2650,33 @@ public class ConnectivityServiceTest { // NET_CAPABILITY_PARTIAL_CONNECTIVITY. mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); mWiFiNetworkAgent.explicitlySelected(true /* acceptUnvalidated */); + // Current design cannot send multi-testResult from NetworkMonitor to ConnectivityService. + // So, if user accepts partial connectivity, NetworkMonitor will send PARTIAL_CONNECTIVITY + // to ConnectivityService first then send VALID. Once NetworkMonitor support + // multi-testResult, this test case also need to be changed to meet the new design. mWiFiNetworkAgent.connectWithPartialConnectivity(); - callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - // TODO: If the user accepted partial connectivity, we shouldn't switch to wifi until - // NetworkMonitor detects partial connectivity - assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - mWiFiNetworkAgent.setNetworkValid(); + // If user accepted partial connectivity network before, + // NetworkMonitor#setAcceptPartialConnectivity() will be called in + // ConnectivityService#updateNetworkInfo(). waitForIdle(); try { - verify(mWiFiNetworkAgent.mNetworkMonitor, - timeout(TIMEOUT_MS).times(1)).setAcceptPartialConnectivity(); + verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity(); } catch (RemoteException e) { fail(e.getMessage()); } + callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent); - callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent); - // Wifi should be the default network. + // TODO: If the user accepted partial connectivity, we shouldn't switch to wifi until + // NetworkMonitor detects partial connectivity assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); + callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent); + mWiFiNetworkAgent.setNetworkValid(); + // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is + // validated. + mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true); + callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); + mWiFiNetworkAgent.disconnect(); + callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); } @Test @@ -4018,8 +4046,13 @@ public class ConnectivityServiceTest { callback3.expectStopped(); } + @FunctionalInterface + private interface ThrowingConsumer<T> { + void accept(T t) throws Exception; + } + // Helper method to prepare the executor and run test - private void runTestWithSerialExecutors(Consumer<Executor> functor) { + private void runTestWithSerialExecutors(ThrowingConsumer<Executor> functor) throws Exception { final ExecutorService executorSingleThread = Executors.newSingleThreadExecutor(); final Executor executorInline = (Runnable r) -> r.run(); functor.accept(executorSingleThread); @@ -4028,20 +4061,15 @@ public class ConnectivityServiceTest { } @Test - public void testNattSocketKeepalives() { - runTestWithSerialExecutors(executor -> { - try { - doTestNattSocketKeepalivesWithExecutor(executor); - } catch (Exception e) { - fail(e.getMessage()); - } - }); + public void testNattSocketKeepalives() throws Exception { + runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesWithExecutor(executor)); + runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesFdWithExecutor(executor)); } private void doTestNattSocketKeepalivesWithExecutor(Executor executor) throws Exception { // TODO: 1. Move this outside of ConnectivityServiceTest. // 2. Make test to verify that Nat-T keepalive socket is created by IpSecService. - final int srcPort = 12345; + // 3. Mock ipsec service. final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129"); final InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35"); final InetAddress myIPv6 = InetAddress.getByName("2001:db8::1"); @@ -4052,7 +4080,8 @@ public class ConnectivityServiceTest { final int invalidKaInterval = 9; final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE); - final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket(srcPort); + final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket(); + final int srcPort = testSocket.getPort(); LinkProperties lp = new LinkProperties(); lp.setInterfaceName("wlan12"); @@ -4065,89 +4094,106 @@ public class ConnectivityServiceTest { Network myNet = connectKeepaliveNetwork(lp); TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor); - SocketKeepalive ka; // Attempt to start keepalives with invalid parameters and check for errors. // Invalid network. - ka = mCm.createSocketKeepalive(notMyNet, testSocket, myIPv4, dstIPv4, executor, callback); - ka.start(validKaInterval); - callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK); + try (SocketKeepalive ka = mCm.createSocketKeepalive( + notMyNet, testSocket, myIPv4, dstIPv4, executor, callback)) { + ka.start(validKaInterval); + callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK); + } // Invalid interval. - ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv4, dstIPv4, executor, callback); - ka.start(invalidKaInterval); - callback.expectError(SocketKeepalive.ERROR_INVALID_INTERVAL); + try (SocketKeepalive ka = mCm.createSocketKeepalive( + myNet, testSocket, myIPv4, dstIPv4, executor, callback)) { + ka.start(invalidKaInterval); + callback.expectError(SocketKeepalive.ERROR_INVALID_INTERVAL); + } // Invalid destination. - ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv4, dstIPv6, executor, callback); - ka.start(validKaInterval); - callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS); + try (SocketKeepalive ka = mCm.createSocketKeepalive( + myNet, testSocket, myIPv4, dstIPv6, executor, callback)) { + ka.start(validKaInterval); + callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS); + } // Invalid source; - ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv6, dstIPv4, executor, callback); - ka.start(validKaInterval); - callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS); + try (SocketKeepalive ka = mCm.createSocketKeepalive( + myNet, testSocket, myIPv6, dstIPv4, executor, callback)) { + ka.start(validKaInterval); + callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS); + } // NAT-T is only supported for IPv4. - ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv6, dstIPv6, executor, callback); - ka.start(validKaInterval); - callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS); + try (SocketKeepalive ka = mCm.createSocketKeepalive( + myNet, testSocket, myIPv6, dstIPv6, executor, callback)) { + ka.start(validKaInterval); + callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS); + } // Sanity check before testing started keepalive. - ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv4, dstIPv4, executor, callback); - ka.start(validKaInterval); - callback.expectError(SocketKeepalive.ERROR_HARDWARE_UNSUPPORTED); + try (SocketKeepalive ka = mCm.createSocketKeepalive( + myNet, testSocket, myIPv4, dstIPv4, executor, callback)) { + ka.start(validKaInterval); + callback.expectError(SocketKeepalive.ERROR_UNSUPPORTED); + } // Check that a started keepalive can be stopped. mWiFiNetworkAgent.setStartKeepaliveError(SocketKeepalive.SUCCESS); - ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv4, dstIPv4, executor, callback); - ka.start(validKaInterval); - callback.expectStarted(); - mWiFiNetworkAgent.setStopKeepaliveError(SocketKeepalive.SUCCESS); - ka.stop(); - callback.expectStopped(); - - // Check that keepalive could be restarted. - ka.start(validKaInterval); - callback.expectStarted(); - ka.stop(); - callback.expectStopped(); - - // Check that keepalive can be restarted without waiting for callback. - ka.start(validKaInterval); - callback.expectStarted(); - ka.stop(); - ka.start(validKaInterval); - callback.expectStopped(); - callback.expectStarted(); - ka.stop(); - callback.expectStopped(); + try (SocketKeepalive ka = mCm.createSocketKeepalive( + myNet, testSocket, myIPv4, dstIPv4, executor, callback)) { + ka.start(validKaInterval); + callback.expectStarted(); + mWiFiNetworkAgent.setStopKeepaliveError(SocketKeepalive.SUCCESS); + ka.stop(); + callback.expectStopped(); + + // Check that keepalive could be restarted. + ka.start(validKaInterval); + callback.expectStarted(); + ka.stop(); + callback.expectStopped(); + + // Check that keepalive can be restarted without waiting for callback. + ka.start(validKaInterval); + callback.expectStarted(); + ka.stop(); + ka.start(validKaInterval); + callback.expectStopped(); + callback.expectStarted(); + ka.stop(); + callback.expectStopped(); + } // Check that deleting the IP address stops the keepalive. LinkProperties bogusLp = new LinkProperties(lp); - ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv4, dstIPv4, executor, callback); - ka.start(validKaInterval); - callback.expectStarted(); - bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25)); - bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25)); - mWiFiNetworkAgent.sendLinkProperties(bogusLp); - callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS); - mWiFiNetworkAgent.sendLinkProperties(lp); + try (SocketKeepalive ka = mCm.createSocketKeepalive( + myNet, testSocket, myIPv4, dstIPv4, executor, callback)) { + ka.start(validKaInterval); + callback.expectStarted(); + bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25)); + bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25)); + mWiFiNetworkAgent.sendLinkProperties(bogusLp); + callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS); + mWiFiNetworkAgent.sendLinkProperties(lp); + } // Check that a started keepalive is stopped correctly when the network disconnects. - ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv4, dstIPv4, executor, callback); - ka.start(validKaInterval); - callback.expectStarted(); - mWiFiNetworkAgent.disconnect(); - waitFor(mWiFiNetworkAgent.getDisconnectedCV()); - callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK); + try (SocketKeepalive ka = mCm.createSocketKeepalive( + myNet, testSocket, myIPv4, dstIPv4, executor, callback)) { + ka.start(validKaInterval); + callback.expectStarted(); + mWiFiNetworkAgent.disconnect(); + waitFor(mWiFiNetworkAgent.getDisconnectedCV()); + callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK); - // ... and that stopping it after that has no adverse effects. - waitForIdle(); - final Network myNetAlias = myNet; - assertNull(mCm.getNetworkCapabilities(myNetAlias)); - ka.stop(); - callback.assertNoCallback(); + // ... and that stopping it after that has no adverse effects. + waitForIdle(); + final Network myNetAlias = myNet; + assertNull(mCm.getNetworkCapabilities(myNetAlias)); + ka.stop(); + callback.assertNoCallback(); + } // Reconnect. myNet = connectKeepaliveNetwork(lp); @@ -4155,27 +4201,36 @@ public class ConnectivityServiceTest { // Check that keepalive slots start from 1 and increment. The first one gets slot 1. mWiFiNetworkAgent.setExpectedKeepaliveSlot(1); - ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv4, dstIPv4, executor, callback); - ka.start(validKaInterval); - callback.expectStarted(); - - // The second one gets slot 2. - mWiFiNetworkAgent.setExpectedKeepaliveSlot(2); - final UdpEncapsulationSocket testSocket2 = mIpSec.openUdpEncapsulationSocket(6789); - TestSocketKeepaliveCallback callback2 = new TestSocketKeepaliveCallback(executor); - SocketKeepalive ka2 = - mCm.createSocketKeepalive(myNet, testSocket2, myIPv4, dstIPv4, executor, callback2); - ka2.start(validKaInterval); - callback2.expectStarted(); - - ka.stop(); - callback.expectStopped(); - - ka2.stop(); - callback2.expectStopped(); + int srcPort2 = 0; + try (SocketKeepalive ka = mCm.createSocketKeepalive( + myNet, testSocket, myIPv4, dstIPv4, executor, callback)) { + ka.start(validKaInterval); + callback.expectStarted(); + + // The second one gets slot 2. + mWiFiNetworkAgent.setExpectedKeepaliveSlot(2); + final UdpEncapsulationSocket testSocket2 = mIpSec.openUdpEncapsulationSocket(); + srcPort2 = testSocket2.getPort(); + TestSocketKeepaliveCallback callback2 = new TestSocketKeepaliveCallback(executor); + try (SocketKeepalive ka2 = mCm.createSocketKeepalive( + myNet, testSocket2, myIPv4, dstIPv4, executor, callback2)) { + ka2.start(validKaInterval); + callback2.expectStarted(); + + ka.stop(); + callback.expectStopped(); + + ka2.stop(); + callback2.expectStopped(); + + testSocket.close(); + testSocket2.close(); + } + } - testSocket.close(); - testSocket2.close(); + // Check that there is no port leaked after all keepalives and sockets are closed. + assertFalse(isUdpPortInUse(srcPort)); + assertFalse(isUdpPortInUse(srcPort2)); mWiFiNetworkAgent.disconnect(); waitFor(mWiFiNetworkAgent.getDisconnectedCV()); @@ -4183,14 +4238,8 @@ public class ConnectivityServiceTest { } @Test - public void testTcpSocketKeepalives() { - runTestWithSerialExecutors(executor -> { - try { - doTestTcpSocketKeepalivesWithExecutor(executor); - } catch (Exception e) { - fail(e.getMessage()); - } - }); + public void testTcpSocketKeepalives() throws Exception { + runTestWithSerialExecutors(executor -> doTestTcpSocketKeepalivesWithExecutor(executor)); } private void doTestTcpSocketKeepalivesWithExecutor(Executor executor) throws Exception { @@ -4200,7 +4249,6 @@ public class ConnectivityServiceTest { final InetAddress myIPv6 = InetAddress.getByName("::1"); final int validKaInterval = 15; - final int invalidKaInterval = 9; final LinkProperties lp = new LinkProperties(); lp.setInterfaceName("wlan12"); @@ -4216,37 +4264,46 @@ public class ConnectivityServiceTest { final Socket testSocketV6 = new Socket(); TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor); - SocketKeepalive ka; // Attempt to start Tcp keepalives with invalid parameters and check for errors. // Invalid network. - ka = mCm.createSocketKeepalive(notMyNet, testSocketV4, executor, callback); - ka.start(validKaInterval); - callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK); + try (SocketKeepalive ka = mCm.createSocketKeepalive( + notMyNet, testSocketV4, executor, callback)) { + ka.start(validKaInterval); + callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK); + } // Invalid Socket (socket is not bound with IPv4 address). - ka = mCm.createSocketKeepalive(myNet, testSocketV4, executor, callback); - ka.start(validKaInterval); - callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET); + try (SocketKeepalive ka = mCm.createSocketKeepalive( + myNet, testSocketV4, executor, callback)) { + ka.start(validKaInterval); + callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET); + } // Invalid Socket (socket is not bound with IPv6 address). - ka = mCm.createSocketKeepalive(myNet, testSocketV6, executor, callback); - ka.start(validKaInterval); - callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET); + try (SocketKeepalive ka = mCm.createSocketKeepalive( + myNet, testSocketV6, executor, callback)) { + ka.start(validKaInterval); + callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET); + } // Bind the socket address testSocketV4.bind(new InetSocketAddress(myIPv4, srcPortV4)); testSocketV6.bind(new InetSocketAddress(myIPv6, srcPortV6)); // Invalid Socket (socket is bound with IPv4 address). - ka = mCm.createSocketKeepalive(myNet, testSocketV4, executor, callback); - ka.start(validKaInterval); - callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET); + try (SocketKeepalive ka = mCm.createSocketKeepalive( + myNet, testSocketV4, executor, callback)) { + ka.start(validKaInterval); + callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET); + } // Invalid Socket (socket is bound with IPv6 address). - ka = mCm.createSocketKeepalive(myNet, testSocketV6, executor, callback); - ka.start(validKaInterval); - callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET); + try (SocketKeepalive ka = mCm.createSocketKeepalive( + myNet, testSocketV6, executor, callback)) { + ka.start(validKaInterval); + callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET); + } testSocketV4.close(); testSocketV6.close(); @@ -4256,6 +4313,66 @@ public class ConnectivityServiceTest { mWiFiNetworkAgent = null; } + private void doTestNattSocketKeepalivesFdWithExecutor(Executor executor) throws Exception { + final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129"); + final InetAddress anyIPv4 = InetAddress.getByName("0.0.0.0"); + final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8"); + final int validKaInterval = 15; + + // Prepare the target network. + LinkProperties lp = new LinkProperties(); + lp.setInterfaceName("wlan12"); + lp.addLinkAddress(new LinkAddress(myIPv4, 25)); + lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254"))); + Network myNet = connectKeepaliveNetwork(lp); + mWiFiNetworkAgent.setStartKeepaliveError(SocketKeepalive.SUCCESS); + mWiFiNetworkAgent.setStopKeepaliveError(SocketKeepalive.SUCCESS); + + TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor); + + // Prepare the target file descriptor, keep only one instance. + final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE); + final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket(); + final int srcPort = testSocket.getPort(); + final ParcelFileDescriptor testPfd = + ParcelFileDescriptor.dup(testSocket.getFileDescriptor()); + testSocket.close(); + assertTrue(isUdpPortInUse(srcPort)); + + // Start keepalive and explicit make the variable goes out of scope with try-with-resources + // block. + try (SocketKeepalive ka = mCm.createNattKeepalive( + myNet, testPfd, myIPv4, dstIPv4, executor, callback)) { + ka.start(validKaInterval); + callback.expectStarted(); + ka.stop(); + callback.expectStopped(); + } + + // Check that the ParcelFileDescriptor is still valid after keepalive stopped, + // ErrnoException with EBADF will be thrown if the socket is closed when checking local + // address. + assertTrue(isUdpPortInUse(srcPort)); + final InetSocketAddress sa = + (InetSocketAddress) Os.getsockname(testPfd.getFileDescriptor()); + assertEquals(anyIPv4, sa.getAddress()); + + testPfd.close(); + assertFalse(isUdpPortInUse(srcPort)); + + mWiFiNetworkAgent.disconnect(); + waitFor(mWiFiNetworkAgent.getDisconnectedCV()); + mWiFiNetworkAgent = null; + } + + private static boolean isUdpPortInUse(int port) { + try (DatagramSocket ignored = new DatagramSocket(port)) { + return false; + } catch (IOException ignored) { + return true; + } + } + @Test public void testGetCaptivePortalServerUrl() throws Exception { String url = mCm.getCaptivePortalServerUrl(); @@ -4664,14 +4781,14 @@ public class ConnectivityServiceTest { ArgumentCaptor<String[]> tlsServers = ArgumentCaptor.forClass(String[].class); // Clear any interactions that occur as a result of CS starting up. - reset(mNetworkManagementService); + reset(mMockDnsResolver); - final String[] EMPTY_STRING_ARRAY = new String[0]; mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); waitForIdle(); - verify(mNetworkManagementService, never()).setDnsConfigurationForNetwork( - anyInt(), eq(EMPTY_STRING_ARRAY), any(), any(), eq(""), eq(EMPTY_STRING_ARRAY)); - verifyNoMoreInteractions(mNetworkManagementService); + verify(mMockDnsResolver, never()).setResolverConfiguration( + anyInt(), eq(EMPTY_STRING_ARRAY), any(), any(), eq(""), + eq(EMPTY_STRING_ARRAY), eq(EMPTY_STRING_ARRAY)); + verifyNoMoreInteractions(mMockDnsResolver); final LinkProperties cellLp = new LinkProperties(); cellLp.setInterfaceName(MOBILE_IFNAME); @@ -4688,28 +4805,29 @@ public class ConnectivityServiceTest { mCellNetworkAgent.connect(false); waitForIdle(); // CS tells netd about the empty DNS config for this network. - verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork( - anyInt(), eq(EMPTY_STRING_ARRAY), any(), any(), eq(""), eq(EMPTY_STRING_ARRAY)); - reset(mNetworkManagementService); + verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration( + anyInt(), eq(EMPTY_STRING_ARRAY), any(), any(), eq(""), + eq(EMPTY_STRING_ARRAY), eq(EMPTY_STRING_ARRAY)); + reset(mMockDnsResolver); cellLp.addDnsServer(InetAddress.getByName("2001:db8::1")); mCellNetworkAgent.sendLinkProperties(cellLp); waitForIdle(); - verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork( + verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration( anyInt(), mStringArrayCaptor.capture(), any(), any(), - eq(""), tlsServers.capture()); + eq(""), tlsServers.capture(), eq(EMPTY_STRING_ARRAY)); assertEquals(1, mStringArrayCaptor.getValue().length); assertTrue(ArrayUtils.contains(mStringArrayCaptor.getValue(), "2001:db8::1")); // Opportunistic mode. assertTrue(ArrayUtils.contains(tlsServers.getValue(), "2001:db8::1")); - reset(mNetworkManagementService); + reset(mMockDnsResolver); cellLp.addDnsServer(InetAddress.getByName("192.0.2.1")); mCellNetworkAgent.sendLinkProperties(cellLp); waitForIdle(); - verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork( + verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration( anyInt(), mStringArrayCaptor.capture(), any(), any(), - eq(""), tlsServers.capture()); + eq(""), tlsServers.capture(), eq(EMPTY_STRING_ARRAY)); assertEquals(2, mStringArrayCaptor.getValue().length); assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(), new String[]{"2001:db8::1", "192.0.2.1"})); @@ -4717,7 +4835,7 @@ public class ConnectivityServiceTest { assertEquals(2, tlsServers.getValue().length); assertTrue(ArrayUtils.containsAll(tlsServers.getValue(), new String[]{"2001:db8::1", "192.0.2.1"})); - reset(mNetworkManagementService); + reset(mMockDnsResolver); final String TLS_SPECIFIER = "tls.example.com"; final String TLS_SERVER6 = "2001:db8:53::53"; @@ -4727,22 +4845,21 @@ public class ConnectivityServiceTest { new PrivateDnsConfig(TLS_SPECIFIER, TLS_IPS).toParcel()); waitForIdle(); - verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork( + verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration( anyInt(), mStringArrayCaptor.capture(), any(), any(), - eq(TLS_SPECIFIER), eq(TLS_SERVERS)); + eq(TLS_SPECIFIER), eq(TLS_SERVERS), eq(EMPTY_STRING_ARRAY)); assertEquals(2, mStringArrayCaptor.getValue().length); assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(), new String[]{"2001:db8::1", "192.0.2.1"})); - reset(mNetworkManagementService); + reset(mMockDnsResolver); } @Test public void testPrivateDnsSettingsChange() throws Exception { - final String[] EMPTY_STRING_ARRAY = new String[0]; ArgumentCaptor<String[]> tlsServers = ArgumentCaptor.forClass(String[].class); // Clear any interactions that occur as a result of CS starting up. - reset(mNetworkManagementService); + reset(mMockDnsResolver); // The default on Android is opportunistic mode ("Automatic"). setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com"); @@ -4755,9 +4872,10 @@ public class ConnectivityServiceTest { mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); waitForIdle(); // CS tells netd about the empty DNS config for this network. - verify(mNetworkManagementService, never()).setDnsConfigurationForNetwork( - anyInt(), eq(EMPTY_STRING_ARRAY), any(), any(), eq(""), eq(EMPTY_STRING_ARRAY)); - verifyNoMoreInteractions(mNetworkManagementService); + verify(mMockDnsResolver, never()).setResolverConfiguration( + anyInt(), eq(EMPTY_STRING_ARRAY), any(), any(), eq(""), + eq(EMPTY_STRING_ARRAY), eq(EMPTY_STRING_ARRAY)); + verifyNoMoreInteractions(mMockDnsResolver); final LinkProperties cellLp = new LinkProperties(); cellLp.setInterfaceName(MOBILE_IFNAME); @@ -4776,9 +4894,9 @@ public class ConnectivityServiceTest { mCellNetworkAgent.sendLinkProperties(cellLp); mCellNetworkAgent.connect(false); waitForIdle(); - verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork( + verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration( anyInt(), mStringArrayCaptor.capture(), any(), any(), - eq(""), tlsServers.capture()); + eq(""), tlsServers.capture(), eq(EMPTY_STRING_ARRAY)); assertEquals(2, mStringArrayCaptor.getValue().length); assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(), new String[]{"2001:db8::1", "192.0.2.1"})); @@ -4786,7 +4904,7 @@ public class ConnectivityServiceTest { assertEquals(2, tlsServers.getValue().length); assertTrue(ArrayUtils.containsAll(tlsServers.getValue(), new String[]{"2001:db8::1", "192.0.2.1"})); - reset(mNetworkManagementService); + reset(mMockDnsResolver); cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent); cellNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, mCellNetworkAgent); @@ -4798,26 +4916,26 @@ public class ConnectivityServiceTest { assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName()); setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com"); - verify(mNetworkManagementService, times(1)).setDnsConfigurationForNetwork( + verify(mMockDnsResolver, times(1)).setResolverConfiguration( anyInt(), mStringArrayCaptor.capture(), any(), any(), - eq(""), eq(EMPTY_STRING_ARRAY)); + eq(""), eq(EMPTY_STRING_ARRAY), eq(EMPTY_STRING_ARRAY)); assertEquals(2, mStringArrayCaptor.getValue().length); assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(), new String[]{"2001:db8::1", "192.0.2.1"})); - reset(mNetworkManagementService); + reset(mMockDnsResolver); cellNetworkCallback.assertNoCallback(); setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com"); - verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork( + verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration( anyInt(), mStringArrayCaptor.capture(), any(), any(), - eq(""), tlsServers.capture()); + eq(""), tlsServers.capture(), eq(EMPTY_STRING_ARRAY)); assertEquals(2, mStringArrayCaptor.getValue().length); assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(), new String[]{"2001:db8::1", "192.0.2.1"})); assertEquals(2, tlsServers.getValue().length); assertTrue(ArrayUtils.containsAll(tlsServers.getValue(), new String[]{"2001:db8::1", "192.0.2.1"})); - reset(mNetworkManagementService); + reset(mMockDnsResolver); cellNetworkCallback.assertNoCallback(); setPrivateDnsSettings(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, "strict.example.com"); @@ -5648,6 +5766,7 @@ public class ConnectivityServiceTest { cellLp.addRoute(new RouteInfo((IpPrefix) null, myIpv6.getAddress(), MOBILE_IFNAME)); cellLp.addRoute(new RouteInfo(myIpv6, null, MOBILE_IFNAME)); reset(mNetworkManagementService); + reset(mMockDnsResolver); when(mNetworkManagementService.getInterfaceConfig(CLAT_PREFIX + MOBILE_IFNAME)) .thenReturn(getClatInterfaceConfig(myIpv4)); @@ -5655,7 +5774,7 @@ public class ConnectivityServiceTest { mCellNetworkAgent.sendLinkProperties(cellLp); mCellNetworkAgent.connect(true); networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - verify(mMockNetd, times(1)).resolverStartPrefix64Discovery(cellNetId); + verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId); // Switching default network updates TCP buffer sizes. verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES); @@ -5665,17 +5784,22 @@ public class ConnectivityServiceTest { cellLp.addLinkAddress(myIpv4); mCellNetworkAgent.sendLinkProperties(cellLp); networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent); - verify(mMockNetd, times(1)).resolverStopPrefix64Discovery(cellNetId); + verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId); + verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration( + eq(cellNetId), eq(EMPTY_STRING_ARRAY), any(), any(), + eq(""), eq(EMPTY_STRING_ARRAY), eq(EMPTY_STRING_ARRAY)); verifyNoMoreInteractions(mMockNetd); + verifyNoMoreInteractions(mMockDnsResolver); reset(mMockNetd); + reset(mMockDnsResolver); // Remove IPv4 address. Expect prefix discovery to be started again. cellLp.removeLinkAddress(myIpv4); cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME)); mCellNetworkAgent.sendLinkProperties(cellLp); networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent); - verify(mMockNetd, times(1)).resolverStartPrefix64Discovery(cellNetId); + verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId); // When NAT64 prefix discovery succeeds, LinkProperties are updated and clatd is started. Nat464Xlat clat = mService.getNat464Xlat(mCellNetworkAgent); @@ -5705,6 +5829,12 @@ public class ConnectivityServiceTest { assertNotEquals(stackedLpsAfterChange, Collections.EMPTY_LIST); assertEquals(makeClatLinkProperties(myIpv4), stackedLpsAfterChange.get(0)); + verify(mMockDnsResolver, times(1)).setResolverConfiguration( + eq(cellNetId), mStringArrayCaptor.capture(), any(), any(), + eq(""), eq(EMPTY_STRING_ARRAY), eq(EMPTY_STRING_ARRAY)); + assertEquals(1, mStringArrayCaptor.getValue().length); + assertTrue(ArrayUtils.contains(mStringArrayCaptor.getValue(), "8.8.8.8")); + // Add ipv4 address, expect that clatd and prefix discovery are stopped and stacked // linkproperties are cleaned up. cellLp.addLinkAddress(myIpv4); @@ -5712,7 +5842,7 @@ public class ConnectivityServiceTest { mCellNetworkAgent.sendLinkProperties(cellLp); networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent); verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME); - verify(mMockNetd, times(1)).resolverStopPrefix64Discovery(cellNetId); + verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId); // As soon as stop is called, the linkproperties lose the stacked interface. networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent); @@ -5727,7 +5857,9 @@ public class ConnectivityServiceTest { networkCallback.assertNoCallback(); verifyNoMoreInteractions(mMockNetd); + verifyNoMoreInteractions(mMockDnsResolver); reset(mMockNetd); + reset(mMockDnsResolver); // Stopping prefix discovery causes netd to tell us that the NAT64 prefix is gone. mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */, @@ -5741,7 +5873,7 @@ public class ConnectivityServiceTest { cellLp.removeDnsServer(InetAddress.getByName("8.8.8.8")); mCellNetworkAgent.sendLinkProperties(cellLp); networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent); - verify(mMockNetd, times(1)).resolverStartPrefix64Discovery(cellNetId); + verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId); mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */, kNat64PrefixString, 96); networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent); @@ -5824,6 +5956,7 @@ public class ConnectivityServiceTest { // Disconnect cell reset(mNetworkManagementService); + reset(mMockNetd); mCellNetworkAgent.disconnect(); networkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent); // LOST callback is triggered earlier than removing idle timer. Broadcast should also be @@ -5831,8 +5964,9 @@ public class ConnectivityServiceTest { // unexpectedly before network being removed. waitForIdle(); verify(mNetworkManagementService, times(0)).removeIdleTimer(eq(MOBILE_IFNAME)); - verify(mNetworkManagementService, times(1)).removeNetwork( - eq(mCellNetworkAgent.getNetwork().netId)); + verify(mMockNetd, times(1)).networkDestroy(eq(mCellNetworkAgent.getNetwork().netId)); + verify(mMockDnsResolver, times(1)) + .clearResolverConfiguration(eq(mCellNetworkAgent.getNetwork().netId)); // Disconnect wifi ConditionVariable cv = waitForConnectivityBroadcasts(1); diff --git a/tests/net/java/com/android/server/connectivity/DnsManagerTest.java b/tests/net/java/com/android/server/connectivity/DnsManagerTest.java index 15ba43df832f..8fa0ab979a54 100644 --- a/tests/net/java/com/android/server/connectivity/DnsManagerTest.java +++ b/tests/net/java/com/android/server/connectivity/DnsManagerTest.java @@ -29,13 +29,13 @@ import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.when; import android.content.Context; +import android.net.IDnsResolver; import android.net.IpPrefix; import android.net.LinkAddress; import android.net.LinkProperties; import android.net.Network; import android.net.RouteInfo; import android.net.shared.PrivateDnsConfig; -import android.os.INetworkManagementService; import android.provider.Settings; import android.test.mock.MockContentResolver; @@ -73,7 +73,7 @@ public class DnsManagerTest { MockContentResolver mContentResolver; @Mock Context mCtx; - @Mock INetworkManagementService mNMService; + @Mock IDnsResolver mMockDnsResolver; @Mock MockableSystemProperties mSystemProperties; @Before @@ -83,7 +83,7 @@ public class DnsManagerTest { mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider()); when(mCtx.getContentResolver()).thenReturn(mContentResolver); - mDnsManager = new DnsManager(mCtx, mNMService, mSystemProperties); + mDnsManager = new DnsManager(mCtx, mMockDnsResolver, mSystemProperties); // Clear the private DNS settings Settings.Global.putString(mContentResolver, PRIVATE_DNS_DEFAULT_MODE, ""); diff --git a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java index 6de4aa1be1ea..142769f61335 100644 --- a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java +++ b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java @@ -32,6 +32,7 @@ import android.app.PendingIntent; import android.content.Context; import android.content.res.Resources; import android.net.ConnectivityManager; +import android.net.IDnsResolver; import android.net.INetd; import android.net.Network; import android.net.NetworkCapabilities; @@ -69,6 +70,7 @@ public class LingerMonitorTest { LingerMonitor mMonitor; @Mock ConnectivityService mConnService; + @Mock IDnsResolver mDnsResolver; @Mock INetd mNetd; @Mock INetworkManagementService mNMS; @Mock Context mCtx; @@ -353,7 +355,7 @@ public class LingerMonitorTest { caps.addCapability(0); caps.addTransportType(transport); NetworkAgentInfo nai = new NetworkAgentInfo(null, null, new Network(netId), info, null, - caps, 50, mCtx, null, mMisc, mConnService, mNetd, mNMS, + caps, 50, mCtx, null, mMisc, mConnService, mNetd, mDnsResolver, mNMS, NetworkFactory.SerialNumber.NONE); nai.everValidated = true; return nai; diff --git a/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java b/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java index cc09fb7ba66f..b709af1a02f1 100644 --- a/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java +++ b/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java @@ -27,6 +27,7 @@ import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; import android.net.ConnectivityManager; +import android.net.IDnsResolver; import android.net.INetd; import android.net.InterfaceConfiguration; import android.net.IpPrefix; @@ -63,6 +64,7 @@ public class Nat464XlatTest { @Mock ConnectivityService mConnectivity; @Mock NetworkMisc mMisc; + @Mock IDnsResolver mDnsResolver; @Mock INetd mNetd; @Mock INetworkManagementService mNms; @Mock InterfaceConfiguration mConfig; @@ -72,7 +74,7 @@ public class Nat464XlatTest { Handler mHandler; Nat464Xlat makeNat464Xlat() { - return new Nat464Xlat(mNai, mNetd, mNms) { + return new Nat464Xlat(mNai, mNetd, mDnsResolver, mNms) { @Override protected int getNetId() { return NETID; } @@ -205,7 +207,7 @@ public class Nat464XlatTest { verify(mNms).unregisterObserver(eq(nat)); assertTrue(c.getValue().getStackedLinks().isEmpty()); assertFalse(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE)); - verify(mNetd).resolverStopPrefix64Discovery(eq(NETID)); + verify(mDnsResolver).stopPrefix64Discovery(eq(NETID)); assertIdle(nat); // Stacked interface removed notification arrives and is ignored. @@ -331,7 +333,7 @@ public class Nat464XlatTest { verify(mNetd).clatdStop(eq(BASE_IFACE)); verify(mConnectivity, times(2)).handleUpdateLinkProperties(eq(mNai), c.capture()); verify(mNms).unregisterObserver(eq(nat)); - verify(mNetd).resolverStopPrefix64Discovery(eq(NETID)); + verify(mDnsResolver).stopPrefix64Discovery(eq(NETID)); assertTrue(c.getValue().getStackedLinks().isEmpty()); assertFalse(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE)); assertIdle(nat); @@ -358,7 +360,7 @@ public class Nat464XlatTest { verify(mNetd).clatdStop(eq(BASE_IFACE)); verify(mNms).unregisterObserver(eq(nat)); - verify(mNetd).resolverStopPrefix64Discovery(eq(NETID)); + verify(mDnsResolver).stopPrefix64Discovery(eq(NETID)); assertIdle(nat); // In-flight interface up notification arrives: no-op @@ -390,7 +392,7 @@ public class Nat464XlatTest { verify(mNetd).clatdStop(eq(BASE_IFACE)); verify(mNms).unregisterObserver(eq(nat)); - verify(mNetd).resolverStopPrefix64Discovery(eq(NETID)); + verify(mDnsResolver).stopPrefix64Discovery(eq(NETID)); assertIdle(nat); verifyNoMoreInteractions(mNetd, mNms, mConnectivity); diff --git a/tests/net/java/com/android/server/connectivity/tethering/EntitlementManagerTest.java b/tests/net/java/com/android/server/connectivity/tethering/EntitlementManagerTest.java index 3944fad2ac9e..d28ab708f051 100644 --- a/tests/net/java/com/android/server/connectivity/tethering/EntitlementManagerTest.java +++ b/tests/net/java/com/android/server/connectivity/tethering/EntitlementManagerTest.java @@ -16,6 +16,7 @@ package com.android.server.connectivity.tethering; +import static android.net.ConnectivityManager.TETHERING_BLUETOOTH; import static android.net.ConnectivityManager.TETHERING_USB; import static android.net.ConnectivityManager.TETHERING_WIFI; import static android.net.ConnectivityManager.TETHER_ERROR_ENTITLEMENT_UNKONWN; @@ -30,6 +31,8 @@ import static org.junit.Assert.fail; import static org.mockito.Matchers.anyBoolean; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.ContentResolver; @@ -72,12 +75,14 @@ public final class EntitlementManagerTest { private static final int EVENT_EM_UPDATE = 1; private static final String[] PROVISIONING_APP_NAME = {"some", "app"}; + private static final String PROVISIONING_NO_UI_APP_NAME = "no_ui_app"; @Mock private CarrierConfigManager mCarrierConfigManager; @Mock private Context mContext; @Mock private MockableSystemProperties mSystemProperties; @Mock private Resources mResources; @Mock private SharedLog mLog; + @Mock private EntitlementManager.OnUiEntitlementFailedListener mEntitlementFailedListener; // Like so many Android system APIs, these cannot be mocked because it is marked final. // We have to use the real versions. @@ -107,18 +112,31 @@ public final class EntitlementManagerTest { public class WrappedEntitlementManager extends EntitlementManager { public int fakeEntitlementResult = TETHER_ERROR_ENTITLEMENT_UNKONWN; - public boolean everRunUiEntitlement = false; + public int uiProvisionCount = 0; + public int silentProvisionCount = 0; public WrappedEntitlementManager(Context ctx, StateMachine target, - SharedLog log, MockableSystemProperties systemProperties) { - super(ctx, target, log, systemProperties); + SharedLog log, int what, MockableSystemProperties systemProperties) { + super(ctx, target, log, what, systemProperties); + } + + public void reset() { + fakeEntitlementResult = TETHER_ERROR_ENTITLEMENT_UNKONWN; + uiProvisionCount = 0; + silentProvisionCount = 0; } @Override protected void runUiTetherProvisioning(int type, ResultReceiver receiver) { - everRunUiEntitlement = true; + uiProvisionCount++; receiver.send(fakeEntitlementResult, null); } + + @Override + protected void runSilentTetherProvisioning(int type) { + silentProvisionCount++; + addDownstreamMapping(type, fakeEntitlementResult); + } } @Before @@ -141,7 +159,9 @@ public final class EntitlementManagerTest { mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider()); mMockContext = new MockContext(mContext); mSM = new TestStateMachine(); - mEnMgr = new WrappedEntitlementManager(mMockContext, mSM, mLog, mSystemProperties); + mEnMgr = new WrappedEntitlementManager(mMockContext, mSM, mLog, EVENT_EM_UPDATE, + mSystemProperties); + mEnMgr.setOnUiEntitlementFailedListener(mEntitlementFailedListener); mEnMgr.updateConfiguration( new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID)); } @@ -158,7 +178,9 @@ public final class EntitlementManagerTest { // Produce some acceptable looking provision app setting if requested. when(mResources.getStringArray(R.array.config_mobile_hotspot_provision_app)) .thenReturn(PROVISIONING_APP_NAME); - // Don't disable tethering provisioning unless requested. + when(mResources.getString(R.string.config_mobile_hotspot_provision_app_no_ui)) + .thenReturn(PROVISIONING_NO_UI_APP_NAME); + // Don't disable tethering provisioning unless requested. when(mSystemProperties.getBoolean(eq(EntitlementManager.DISABLE_PROVISIONING_SYSPROP_KEY), anyBoolean())).thenReturn(false); // Act like the CarrierConfigManager is present and ready unless told otherwise. @@ -166,6 +188,7 @@ public final class EntitlementManagerTest { .thenReturn(mCarrierConfigManager); when(mCarrierConfigManager.getConfig()).thenReturn(mCarrierConfig); mCarrierConfig.putBoolean(CarrierConfigManager.KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL, true); + mCarrierConfig.putBoolean(CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL, true); } @Test @@ -199,6 +222,16 @@ public final class EntitlementManagerTest { } @Test + public void toleratesCarrierConfigNotLoaded() { + setupForRequiredProvisioning(); + mCarrierConfig.putBoolean(CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL, false); + mEnMgr.updateConfiguration( + new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID)); + // We still have a provisioning app configured, so still require provisioning. + assertTrue(mEnMgr.isTetherProvisioningRequired()); + } + + @Test public void provisioningNotRequiredWhenAppNotFound() { setupForRequiredProvisioning(); when(mResources.getStringArray(R.array.config_mobile_hotspot_provision_app)) @@ -218,7 +251,6 @@ public final class EntitlementManagerTest { final CountDownLatch mCallbacklatch = new CountDownLatch(1); // 1. Entitlement check is not required. mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR; - mEnMgr.everRunUiEntitlement = false; ResultReceiver receiver = new ResultReceiver(null) { @Override protected void onReceiveResult(int resultCode, Bundle resultData) { @@ -227,14 +259,15 @@ public final class EntitlementManagerTest { } }; mEnMgr.getLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, true); + mLooper.dispatchAll(); callbackTimeoutHelper(mCallbacklatch); - assertFalse(mEnMgr.everRunUiEntitlement); + assertEquals(0, mEnMgr.uiProvisionCount); + mEnMgr.reset(); setupForRequiredProvisioning(); mEnMgr.updateConfiguration(new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID)); // 2. No cache value and don't need to run entitlement check. - mEnMgr.everRunUiEntitlement = false; receiver = new ResultReceiver(null) { @Override protected void onReceiveResult(int resultCode, Bundle resultData) { @@ -243,11 +276,12 @@ public final class EntitlementManagerTest { } }; mEnMgr.getLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, false); + mLooper.dispatchAll(); callbackTimeoutHelper(mCallbacklatch); - assertFalse(mEnMgr.everRunUiEntitlement); + assertEquals(0, mEnMgr.uiProvisionCount); + mEnMgr.reset(); // 3. No cache value and ui entitlement check is needed. mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISION_FAILED; - mEnMgr.everRunUiEntitlement = false; receiver = new ResultReceiver(null) { @Override protected void onReceiveResult(int resultCode, Bundle resultData) { @@ -258,10 +292,10 @@ public final class EntitlementManagerTest { mEnMgr.getLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, true); mLooper.dispatchAll(); callbackTimeoutHelper(mCallbacklatch); - assertTrue(mEnMgr.everRunUiEntitlement); + assertEquals(1, mEnMgr.uiProvisionCount); + mEnMgr.reset(); // 4. Cache value is TETHER_ERROR_PROVISION_FAILED and don't need to run entitlement check. mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR; - mEnMgr.everRunUiEntitlement = false; receiver = new ResultReceiver(null) { @Override protected void onReceiveResult(int resultCode, Bundle resultData) { @@ -270,11 +304,12 @@ public final class EntitlementManagerTest { } }; mEnMgr.getLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, false); + mLooper.dispatchAll(); callbackTimeoutHelper(mCallbacklatch); - assertFalse(mEnMgr.everRunUiEntitlement); + assertEquals(0, mEnMgr.uiProvisionCount); + mEnMgr.reset(); // 5. Cache value is TETHER_ERROR_PROVISION_FAILED and ui entitlement check is needed. mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR; - mEnMgr.everRunUiEntitlement = false; receiver = new ResultReceiver(null) { @Override protected void onReceiveResult(int resultCode, Bundle resultData) { @@ -285,10 +320,10 @@ public final class EntitlementManagerTest { mEnMgr.getLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, true); mLooper.dispatchAll(); callbackTimeoutHelper(mCallbacklatch); - assertTrue(mEnMgr.everRunUiEntitlement); + assertEquals(1, mEnMgr.uiProvisionCount); + mEnMgr.reset(); // 6. Cache value is TETHER_ERROR_NO_ERROR. mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR; - mEnMgr.everRunUiEntitlement = false; receiver = new ResultReceiver(null) { @Override protected void onReceiveResult(int resultCode, Bundle resultData) { @@ -297,10 +332,11 @@ public final class EntitlementManagerTest { } }; mEnMgr.getLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, true); + mLooper.dispatchAll(); callbackTimeoutHelper(mCallbacklatch); - assertFalse(mEnMgr.everRunUiEntitlement); + assertEquals(0, mEnMgr.uiProvisionCount); + mEnMgr.reset(); // 7. Test get value for other downstream type. - mEnMgr.everRunUiEntitlement = false; receiver = new ResultReceiver(null) { @Override protected void onReceiveResult(int resultCode, Bundle resultData) { @@ -309,19 +345,152 @@ public final class EntitlementManagerTest { } }; mEnMgr.getLatestTetheringEntitlementResult(TETHERING_USB, receiver, false); + mLooper.dispatchAll(); callbackTimeoutHelper(mCallbacklatch); - assertFalse(mEnMgr.everRunUiEntitlement); + assertEquals(0, mEnMgr.uiProvisionCount); + mEnMgr.reset(); } void callbackTimeoutHelper(final CountDownLatch latch) throws Exception { if (!latch.await(1, TimeUnit.SECONDS)) { - fail("Timout, fail to recieve callback"); + fail("Timout, fail to receive callback"); } } + + @Test + public void verifyPermissionResult() { + setupForRequiredProvisioning(); + mEnMgr.notifyUpstream(true); + mEnMgr.updateConfiguration(new TetheringConfiguration(mMockContext, mLog, + INVALID_SUBSCRIPTION_ID)); + mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISION_FAILED; + mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, true); + mLooper.dispatchAll(); + assertFalse(mEnMgr.isCellularUpstreamPermitted()); + mEnMgr.stopProvisioningIfNeeded(TETHERING_WIFI); + mLooper.dispatchAll(); + mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR; + mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, true); + mLooper.dispatchAll(); + assertTrue(mEnMgr.isCellularUpstreamPermitted()); + } + + @Test + public void verifyPermissionIfAllNotApproved() { + setupForRequiredProvisioning(); + mEnMgr.notifyUpstream(true); + mEnMgr.updateConfiguration(new TetheringConfiguration(mMockContext, mLog, + INVALID_SUBSCRIPTION_ID)); + mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISION_FAILED; + mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, true); + mLooper.dispatchAll(); + assertFalse(mEnMgr.isCellularUpstreamPermitted()); + mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISION_FAILED; + mEnMgr.startProvisioningIfNeeded(TETHERING_USB, true); + mLooper.dispatchAll(); + assertFalse(mEnMgr.isCellularUpstreamPermitted()); + mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISION_FAILED; + mEnMgr.startProvisioningIfNeeded(TETHERING_BLUETOOTH, true); + mLooper.dispatchAll(); + assertFalse(mEnMgr.isCellularUpstreamPermitted()); + } + + @Test + public void verifyPermissionIfAnyApproved() { + setupForRequiredProvisioning(); + mEnMgr.notifyUpstream(true); + mEnMgr.updateConfiguration(new TetheringConfiguration(mMockContext, mLog, + INVALID_SUBSCRIPTION_ID)); + mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR; + mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, true); + mLooper.dispatchAll(); + assertTrue(mEnMgr.isCellularUpstreamPermitted()); + mLooper.dispatchAll(); + mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISION_FAILED; + mEnMgr.startProvisioningIfNeeded(TETHERING_USB, true); + mLooper.dispatchAll(); + assertTrue(mEnMgr.isCellularUpstreamPermitted()); + mEnMgr.stopProvisioningIfNeeded(TETHERING_WIFI); + mLooper.dispatchAll(); + assertFalse(mEnMgr.isCellularUpstreamPermitted()); + + } + + @Test + public void testRunTetherProvisioning() { + setupForRequiredProvisioning(); + mEnMgr.updateConfiguration(new TetheringConfiguration(mMockContext, mLog, + INVALID_SUBSCRIPTION_ID)); + // 1. start ui provisioning, upstream is mobile + mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR; + mEnMgr.notifyUpstream(true); + mLooper.dispatchAll(); + mEnMgr.startProvisioningIfNeeded(TETHERING_USB, true); + mLooper.dispatchAll(); + assertEquals(1, mEnMgr.uiProvisionCount); + assertEquals(0, mEnMgr.silentProvisionCount); + assertTrue(mEnMgr.isCellularUpstreamPermitted()); + mEnMgr.reset(); + // 2. start no-ui provisioning + mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR; + mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, false); + mLooper.dispatchAll(); + assertEquals(0, mEnMgr.uiProvisionCount); + assertEquals(1, mEnMgr.silentProvisionCount); + assertTrue(mEnMgr.isCellularUpstreamPermitted()); + mEnMgr.reset(); + // 3. tear down mobile, then start ui provisioning + mEnMgr.notifyUpstream(false); + mLooper.dispatchAll(); + mEnMgr.startProvisioningIfNeeded(TETHERING_BLUETOOTH, true); + mLooper.dispatchAll(); + assertEquals(0, mEnMgr.uiProvisionCount); + assertEquals(0, mEnMgr.silentProvisionCount); + mEnMgr.reset(); + // 4. switch upstream back to mobile + mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR; + mEnMgr.notifyUpstream(true); + mLooper.dispatchAll(); + assertEquals(1, mEnMgr.uiProvisionCount); + assertEquals(0, mEnMgr.silentProvisionCount); + assertTrue(mEnMgr.isCellularUpstreamPermitted()); + mEnMgr.reset(); + // 5. tear down mobile, then switch SIM + mEnMgr.notifyUpstream(false); + mLooper.dispatchAll(); + mEnMgr.reevaluateSimCardProvisioning(); + assertEquals(0, mEnMgr.uiProvisionCount); + assertEquals(0, mEnMgr.silentProvisionCount); + mEnMgr.reset(); + // 6. switch upstream back to mobile again + mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISION_FAILED; + mEnMgr.notifyUpstream(true); + mLooper.dispatchAll(); + assertEquals(0, mEnMgr.uiProvisionCount); + assertEquals(3, mEnMgr.silentProvisionCount); + mEnMgr.reset(); + } + + @Test + public void testCallStopTetheringWhenUiProvisioningFail() { + setupForRequiredProvisioning(); + mEnMgr.updateConfiguration(new TetheringConfiguration(mMockContext, mLog, + INVALID_SUBSCRIPTION_ID)); + verify(mEntitlementFailedListener, times(0)).onUiEntitlementFailed(TETHERING_WIFI); + mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISION_FAILED; + mEnMgr.notifyUpstream(true); + mLooper.dispatchAll(); + mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, true); + mLooper.dispatchAll(); + assertEquals(1, mEnMgr.uiProvisionCount); + verify(mEntitlementFailedListener, times(1)).onUiEntitlementFailed(TETHERING_WIFI); + } + + public class TestStateMachine extends StateMachine { public final ArrayList<Message> messages = new ArrayList<>(); - private final State mLoggingState = - new EntitlementManagerTest.TestStateMachine.LoggingState(); + private final State + mLoggingState = new EntitlementManagerTest.TestStateMachine.LoggingState(); class LoggingState extends State { @Override public void enter() { diff --git a/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java b/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java index 5a1f853e75a9..0d276cbd1b85 100644 --- a/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java +++ b/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java @@ -90,6 +90,7 @@ public class UpstreamNetworkMonitorTest { private static final NetworkRequest mDefaultRequest = new NetworkRequest.Builder().build(); @Mock private Context mContext; + @Mock private EntitlementManager mEntitleMgr; @Mock private IConnectivityManager mCS; @Mock private SharedLog mLog; @@ -103,6 +104,7 @@ public class UpstreamNetworkMonitorTest { reset(mCS); reset(mLog); when(mLog.forSubComponent(anyString())).thenReturn(mLog); + when(mEntitleMgr.isCellularUpstreamPermitted()).thenReturn(true); mCM = spy(new TestConnectivityManager(mContext, mCS)); mSM = new TestStateMachine(); @@ -138,7 +140,7 @@ public class UpstreamNetworkMonitorTest { @Test public void testDefaultNetworkIsTracked() throws Exception { assertTrue(mCM.hasNoCallbacks()); - mUNM.startTrackDefaultNetwork(mDefaultRequest); + mUNM.startTrackDefaultNetwork(mDefaultRequest, mEntitleMgr); mUNM.startObserveAllNetworks(); assertEquals(1, mCM.trackingDefault.size()); @@ -151,7 +153,7 @@ public class UpstreamNetworkMonitorTest { public void testListensForAllNetworks() throws Exception { assertTrue(mCM.listening.isEmpty()); - mUNM.startTrackDefaultNetwork(mDefaultRequest); + mUNM.startTrackDefaultNetwork(mDefaultRequest, mEntitleMgr); mUNM.startObserveAllNetworks(); assertFalse(mCM.listening.isEmpty()); assertTrue(mCM.isListeningForAll()); @@ -162,7 +164,7 @@ public class UpstreamNetworkMonitorTest { @Test public void testCallbacksRegistered() { - mUNM.startTrackDefaultNetwork(mDefaultRequest); + mUNM.startTrackDefaultNetwork(mDefaultRequest, mEntitleMgr); verify(mCM, times(1)).requestNetwork( eq(mDefaultRequest), any(NetworkCallback.class), any(Handler.class)); mUNM.startObserveAllNetworks(); @@ -285,7 +287,7 @@ public class UpstreamNetworkMonitorTest { final Collection<Integer> preferredTypes = new ArrayList<>(); preferredTypes.add(TYPE_WIFI); - mUNM.startTrackDefaultNetwork(mDefaultRequest); + mUNM.startTrackDefaultNetwork(mDefaultRequest, mEntitleMgr); mUNM.startObserveAllNetworks(); // There are no networks, so there is nothing to select. assertSatisfiesLegacyType(TYPE_NONE, mUNM.selectPreferredUpstreamType(preferredTypes)); @@ -319,6 +321,14 @@ public class UpstreamNetworkMonitorTest { NetworkRequest netReq = (NetworkRequest) mCM.requested.values().toArray()[0]; assertTrue(netReq.networkCapabilities.hasTransport(TRANSPORT_CELLULAR)); assertFalse(netReq.networkCapabilities.hasCapability(NET_CAPABILITY_DUN)); + // mobile is not permitted, we should not use HIPRI. + when(mEntitleMgr.isCellularUpstreamPermitted()).thenReturn(false); + assertSatisfiesLegacyType(TYPE_NONE, mUNM.selectPreferredUpstreamType(preferredTypes)); + assertEquals(0, mCM.requested.size()); + // mobile change back to permitted, HIRPI should come back + when(mEntitleMgr.isCellularUpstreamPermitted()).thenReturn(true); + assertSatisfiesLegacyType(TYPE_MOBILE_HIPRI, + mUNM.selectPreferredUpstreamType(preferredTypes)); wifiAgent.fakeConnect(); // WiFi is up, and we should prefer it over cell. @@ -347,11 +357,19 @@ public class UpstreamNetworkMonitorTest { netReq = (NetworkRequest) mCM.requested.values().toArray()[0]; assertTrue(netReq.networkCapabilities.hasTransport(TRANSPORT_CELLULAR)); assertTrue(netReq.networkCapabilities.hasCapability(NET_CAPABILITY_DUN)); + // mobile is not permitted, we should not use DUN. + when(mEntitleMgr.isCellularUpstreamPermitted()).thenReturn(false); + assertSatisfiesLegacyType(TYPE_NONE, mUNM.selectPreferredUpstreamType(preferredTypes)); + assertEquals(0, mCM.requested.size()); + // mobile change back to permitted, DUN should come back + when(mEntitleMgr.isCellularUpstreamPermitted()).thenReturn(true); + assertSatisfiesLegacyType(TYPE_MOBILE_DUN, + mUNM.selectPreferredUpstreamType(preferredTypes)); } @Test public void testGetCurrentPreferredUpstream() throws Exception { - mUNM.startTrackDefaultNetwork(mDefaultRequest); + mUNM.startTrackDefaultNetwork(mDefaultRequest, mEntitleMgr); mUNM.startObserveAllNetworks(); mUNM.updateMobileRequiresDun(false); @@ -361,37 +379,46 @@ public class UpstreamNetworkMonitorTest { mCM.makeDefaultNetwork(cellAgent); assertEquals(cellAgent.networkId, mUNM.getCurrentPreferredUpstream().network); - // [1] WiFi connects but not validated/promoted to default -> mobile selected. + // [1] Mobile connects but not permitted -> null selected + when(mEntitleMgr.isCellularUpstreamPermitted()).thenReturn(false); + assertEquals(null, mUNM.getCurrentPreferredUpstream()); + when(mEntitleMgr.isCellularUpstreamPermitted()).thenReturn(true); + + // [2] WiFi connects but not validated/promoted to default -> mobile selected. final TestNetworkAgent wifiAgent = new TestNetworkAgent(mCM, TRANSPORT_WIFI); wifiAgent.fakeConnect(); assertEquals(cellAgent.networkId, mUNM.getCurrentPreferredUpstream().network); - // [2] WiFi validates and is promoted to the default network -> WiFi selected. + // [3] WiFi validates and is promoted to the default network -> WiFi selected. mCM.makeDefaultNetwork(wifiAgent); assertEquals(wifiAgent.networkId, mUNM.getCurrentPreferredUpstream().network); - // [3] DUN required, no other changes -> WiFi still selected + // [4] DUN required, no other changes -> WiFi still selected mUNM.updateMobileRequiresDun(true); assertEquals(wifiAgent.networkId, mUNM.getCurrentPreferredUpstream().network); - // [4] WiFi no longer validated, mobile becomes default, DUN required -> null selected. + // [5] WiFi no longer validated, mobile becomes default, DUN required -> null selected. mCM.makeDefaultNetwork(cellAgent); assertEquals(null, mUNM.getCurrentPreferredUpstream()); // TODO: make sure that a DUN request has been filed. This is currently // triggered by code over in Tethering, but once that has been moved // into UNM we should test for this here. - // [5] DUN network arrives -> DUN selected + // [6] DUN network arrives -> DUN selected final TestNetworkAgent dunAgent = new TestNetworkAgent(mCM, TRANSPORT_CELLULAR); dunAgent.networkCapabilities.addCapability(NET_CAPABILITY_DUN); dunAgent.networkCapabilities.removeCapability(NET_CAPABILITY_INTERNET); dunAgent.fakeConnect(); assertEquals(dunAgent.networkId, mUNM.getCurrentPreferredUpstream().network); + + // [7] Mobile is not permitted -> null selected + when(mEntitleMgr.isCellularUpstreamPermitted()).thenReturn(false); + assertEquals(null, mUNM.getCurrentPreferredUpstream()); } @Test public void testLocalPrefixes() throws Exception { - mUNM.startTrackDefaultNetwork(mDefaultRequest); + mUNM.startTrackDefaultNetwork(mDefaultRequest, mEntitleMgr); mUNM.startObserveAllNetworks(); // [0] Test minimum set of local prefixes. @@ -492,6 +519,26 @@ public class UpstreamNetworkMonitorTest { assertTrue(local.isEmpty()); } + @Test + public void testSelectMobileWhenMobileIsNotDefault() { + final Collection<Integer> preferredTypes = new ArrayList<>(); + // Mobile has higher pirority than wifi. + preferredTypes.add(TYPE_MOBILE_HIPRI); + preferredTypes.add(TYPE_WIFI); + mUNM.startTrackDefaultNetwork(mDefaultRequest, mEntitleMgr); + mUNM.startObserveAllNetworks(); + // Setup wifi and make wifi as default network. + final TestNetworkAgent wifiAgent = new TestNetworkAgent(mCM, TRANSPORT_WIFI); + wifiAgent.fakeConnect(); + mCM.makeDefaultNetwork(wifiAgent); + // Setup mobile network. + final TestNetworkAgent cellAgent = new TestNetworkAgent(mCM, TRANSPORT_CELLULAR); + cellAgent.fakeConnect(); + + assertSatisfiesLegacyType(TYPE_MOBILE_HIPRI, + mUNM.selectPreferredUpstreamType(preferredTypes)); + verify(mEntitleMgr, times(1)).maybeRunProvisioning(); + } private void assertSatisfiesLegacyType(int legacyType, NetworkState ns) { if (legacyType == TYPE_NONE) { assertTrue(ns == null); diff --git a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java index bce526d3ae29..e35c34affd1a 100644 --- a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java +++ b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java @@ -57,6 +57,7 @@ import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_PO import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; @@ -216,11 +217,16 @@ public class NetworkStatsServiceTest { expectNetworkStatsUidDetail(buildEmptyStats()); expectSystemReady(); + assertNull(mService.getTunAdjustedStats()); mService.systemReady(); + // Verify that system ready fetches realtime stats and initializes tun adjusted stats. + verify(mNetManager).getNetworkStatsUidDetail(UID_ALL, INTERFACES_ALL); + assertNotNull("failed to initialize TUN adjusted stats", mService.getTunAdjustedStats()); + assertEquals(0, mService.getTunAdjustedStats().size()); + mSession = mService.openSession(); assertNotNull("openSession() failed", mSession); - // catch INetworkManagementEventObserver during systemReady() ArgumentCaptor<INetworkManagementEventObserver> networkObserver = ArgumentCaptor.forClass(INetworkManagementEventObserver.class); @@ -733,11 +739,13 @@ public class NetworkStatsServiceTest { NetworkStats stats = mService.getDetailedUidStats(ifaceFilter); - verify(mNetManager, times(1)).getNetworkStatsUidDetail(eq(UID_ALL), argThat(ifaces -> - ifaces != null && ifaces.length == 2 - && ArrayUtils.contains(ifaces, TEST_IFACE) - && ArrayUtils.contains(ifaces, stackedIface))); - + // mNetManager#getNetworkStatsUidDetail(UID_ALL, INTERFACES_ALL) has following invocations: + // 1) NetworkStatsService#systemReady from #setUp. + // 2) mService#forceUpdateIfaces in the test above. + // 3) Finally, mService#getDetailedUidStats. + verify(mNetManager, times(3)).getNetworkStatsUidDetail(UID_ALL, INTERFACES_ALL); + assertTrue(ArrayUtils.contains(stats.getUniqueIfaces(), TEST_IFACE)); + assertTrue(ArrayUtils.contains(stats.getUniqueIfaces(), stackedIface)); assertEquals(2, stats.size()); assertEquals(uidStats, stats.getValues(0, null)); assertEquals(tetheredStats1, stats.getValues(1, null)); @@ -927,7 +935,7 @@ public class NetworkStatsServiceTest { // WiFi network is connected and VPN is using WiFi (which has TEST_IFACE). expectDefaultSettings(); NetworkState[] networkStates = new NetworkState[] {buildWifiState(), buildVpnState()}; - VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(TEST_IFACE)}; + VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE})}; expectNetworkStatsUidDetail(buildEmptyStats()); expectBandwidthControlCheck(); @@ -947,8 +955,10 @@ public class NetworkStatsServiceTest { expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 3) .addValues(TUN_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1000L, 100L, 1000L, 100L, 1L) .addValues(TUN_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 500L, 50L, 500L, 50L, 1L) - .addValues( - TEST_IFACE, UID_VPN, SET_DEFAULT, TAG_NONE, 1650L, 150L, 1650L, 150L, 2L)); + // VPN received 1650 bytes over WiFi in background (SET_DEFAULT). + .addValues(TEST_IFACE, UID_VPN, SET_DEFAULT, TAG_NONE, 1650L, 150L, 0L, 0L, 1L) + // VPN sent 1650 bytes over WiFi in foreground (SET_FOREGROUND). + .addValues(TEST_IFACE, UID_VPN, SET_FOREGROUND, TAG_NONE, 0L, 0L, 1650L, 150L, 1L)); forcePollAndWaitForIdle(); @@ -962,7 +972,7 @@ public class NetworkStatsServiceTest { // WiFi network is connected and VPN is using WiFi (which has TEST_IFACE). expectDefaultSettings(); NetworkState[] networkStates = new NetworkState[] {buildWifiState(), buildVpnState()}; - VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(TEST_IFACE)}; + VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE})}; expectNetworkStatsUidDetail(buildEmptyStats()); expectBandwidthControlCheck(); @@ -993,6 +1003,132 @@ public class NetworkStatsServiceTest { } @Test + public void vpnWithTwoUnderlyingIfaces_packetDuplication() throws Exception { + // WiFi and Cell networks are connected and VPN is using WiFi (which has TEST_IFACE) and + // Cell (which has TEST_IFACE2) and has declared both of them in its underlying network set. + // Additionally, VPN is duplicating traffic across both WiFi and Cell. + expectDefaultSettings(); + NetworkState[] networkStates = + new NetworkState[] { + buildWifiState(), buildMobile4gState(TEST_IFACE2), buildVpnState() + }; + VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE, TEST_IFACE2})}; + expectNetworkStatsUidDetail(buildEmptyStats()); + expectBandwidthControlCheck(); + + mService.forceUpdateIfaces( + new Network[] {WIFI_NETWORK, VPN_NETWORK}, + vpnInfos, + networkStates, + getActiveIface(networkStates)); + // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption + // overhead per packet): + // 1000 bytes (100 packets) were sent/received by UID_RED and UID_BLUE over VPN. + // VPN sent/received 4400 bytes (400 packets) over both WiFi and Cell (8800 bytes in total). + // Of 8800 bytes over WiFi/Cell, expect: + // - 500 bytes rx/tx each over WiFi/Cell attributed to both UID_RED and UID_BLUE. + // - 1200 bytes rx/tx each over WiFi/Cell for VPN_UID. + incrementCurrentTime(HOUR_IN_MILLIS); + expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 4) + .addValues(TUN_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1000L, 100L, 1000L, 100L, 2L) + .addValues(TUN_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 1000L, 100L, 1000L, 100L, 2L) + .addValues(TEST_IFACE, UID_VPN, SET_DEFAULT, TAG_NONE, 2200L, 200L, 2200L, 200L, 2L) + .addValues( + TEST_IFACE2, UID_VPN, SET_DEFAULT, TAG_NONE, 2200L, 200L, 2200L, 200L, 2L)); + + forcePollAndWaitForIdle(); + + assertUidTotal(sTemplateWifi, UID_RED, 500L, 50L, 500L, 50L, 1); + assertUidTotal(sTemplateWifi, UID_BLUE, 500L, 50L, 500L, 50L, 1); + assertUidTotal(sTemplateWifi, UID_VPN, 1200L, 100L, 1200L, 100L, 2); + + assertUidTotal(buildTemplateMobileWildcard(), UID_RED, 500L, 50L, 500L, 50L, 1); + assertUidTotal(buildTemplateMobileWildcard(), UID_BLUE, 500L, 50L, 500L, 50L, 1); + assertUidTotal(buildTemplateMobileWildcard(), UID_VPN, 1200L, 100L, 1200L, 100L, 2); + } + + @Test + public void vpnWithTwoUnderlyingIfaces_splitTraffic() throws Exception { + // WiFi and Cell networks are connected and VPN is using WiFi (which has TEST_IFACE) and + // Cell (which has TEST_IFACE2) and has declared both of them in its underlying network set. + // Additionally, VPN is arbitrarily splitting traffic across WiFi and Cell. + expectDefaultSettings(); + NetworkState[] networkStates = + new NetworkState[] { + buildWifiState(), buildMobile4gState(TEST_IFACE2), buildVpnState() + }; + VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE, TEST_IFACE2})}; + expectNetworkStatsUidDetail(buildEmptyStats()); + expectBandwidthControlCheck(); + + mService.forceUpdateIfaces( + new Network[] {WIFI_NETWORK, VPN_NETWORK}, + vpnInfos, + networkStates, + getActiveIface(networkStates)); + // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption + // overhead per packet): + // 1000 bytes (100 packets) were sent/received by UID_RED over VPN. + // VPN sent/received 660 bytes (60 packets) over WiFi and 440 bytes (40 packets) over Cell. + // For UID_RED, expect 600 bytes attributed over WiFi and 400 bytes over Cell for both + // rx/tx. + // For UID_VPN, expect 60 bytes attributed over WiFi and 40 bytes over Cell for both rx/tx. + incrementCurrentTime(HOUR_IN_MILLIS); + expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 3) + .addValues(TUN_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1000L, 100L, 1000L, 100L, 2L) + .addValues(TEST_IFACE, UID_VPN, SET_DEFAULT, TAG_NONE, 660L, 60L, 660L, 60L, 1L) + .addValues(TEST_IFACE2, UID_VPN, SET_DEFAULT, TAG_NONE, 440L, 40L, 440L, 40L, 1L)); + + forcePollAndWaitForIdle(); + + assertUidTotal(sTemplateWifi, UID_RED, 600L, 60L, 600L, 60L, 1); + assertUidTotal(sTemplateWifi, UID_VPN, 60L, 0L, 60L, 0L, 1); + + assertUidTotal(buildTemplateMobileWildcard(), UID_RED, 400L, 40L, 400L, 40L, 1); + assertUidTotal(buildTemplateMobileWildcard(), UID_VPN, 40L, 0L, 40L, 0L, 1); + } + + @Test + public void vpnWithTwoUnderlyingIfaces_splitTrafficWithCompression() throws Exception { + // WiFi and Cell networks are connected and VPN is using WiFi (which has TEST_IFACE) and + // Cell (which has TEST_IFACE2) and has declared both of them in its underlying network set. + // Additionally, VPN is arbitrarily splitting compressed traffic across WiFi and Cell. + expectDefaultSettings(); + NetworkState[] networkStates = + new NetworkState[] { + buildWifiState(), buildMobile4gState(TEST_IFACE2), buildVpnState() + }; + VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE, TEST_IFACE2})}; + expectNetworkStatsUidDetail(buildEmptyStats()); + expectBandwidthControlCheck(); + + mService.forceUpdateIfaces( + new Network[] {WIFI_NETWORK, VPN_NETWORK}, + vpnInfos, + networkStates, + getActiveIface(networkStates)); + // create some traffic (assume 10 bytes of MTU for VPN interface: + // 1000 bytes (100 packets) were sent/received by UID_RED over VPN. + // VPN sent/received 600 bytes (60 packets) over WiFi and 200 bytes (20 packets) over Cell. + // For UID_RED, expect 600 bytes attributed over WiFi and 200 bytes over Cell for both + // rx/tx. + // UID_VPN gets nothing attributed to it (avoiding negative stats). + incrementCurrentTime(HOUR_IN_MILLIS); + expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 4) + .addValues(TUN_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1000L, 100L, 1000L, 100L, 1L) + .addValues(TEST_IFACE, UID_VPN, SET_DEFAULT, TAG_NONE, 600L, 60L, 600L, 60L, 0L) + .addValues(TEST_IFACE2, UID_VPN, SET_DEFAULT, TAG_NONE, 200L, 20L, 200L, 20L, 0L)); + + forcePollAndWaitForIdle(); + + assertUidTotal(sTemplateWifi, UID_RED, 600L, 60L, 600L, 60L, 0); + assertUidTotal(sTemplateWifi, UID_VPN, 0L, 0L, 0L, 0L, 0); + + assertUidTotal(buildTemplateMobileWildcard(), UID_RED, 200L, 20L, 200L, 20L, 0); + assertUidTotal(buildTemplateMobileWildcard(), UID_VPN, 0L, 0L, 0L, 0L, 0); + } + + @Test public void vpnWithIncorrectUnderlyingIface() throws Exception { // WiFi and Cell networks are connected and VPN is using Cell (which has TEST_IFACE2), // but has declared only WiFi (TEST_IFACE) in its underlying network set. @@ -1001,7 +1137,7 @@ public class NetworkStatsServiceTest { new NetworkState[] { buildWifiState(), buildMobile4gState(TEST_IFACE2), buildVpnState() }; - VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(TEST_IFACE)}; + VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE})}; expectNetworkStatsUidDetail(buildEmptyStats()); expectBandwidthControlCheck(); @@ -1030,6 +1166,134 @@ public class NetworkStatsServiceTest { } @Test + public void recordSnapshot_migratesTunTrafficAndUpdatesTunAdjustedStats() throws Exception { + assertEquals(0, mService.getTunAdjustedStats().size()); + // VPN using WiFi (TEST_IFACE). + VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE})}; + expectBandwidthControlCheck(); + // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption + // overhead per packet): + // 1000 bytes (100 packets) were downloaded by UID_RED over VPN. + // VPN received 1100 bytes (100 packets) over WiFi. + incrementCurrentTime(HOUR_IN_MILLIS); + expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 2) + .addValues(TUN_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1000L, 100L, 0L, 0L, 0L) + .addValues(TEST_IFACE, UID_VPN, SET_DEFAULT, TAG_NONE, 1100L, 100L, 0L, 0L, 0L)); + + // this should lead to NSS#recordSnapshotLocked + mService.forceUpdateIfaces( + new Network[0], vpnInfos, new NetworkState[0], null /* activeIface */); + + // Verify TUN adjusted stats have traffic migrated correctly. + // Of 1100 bytes VPN received over WiFi, expect 1000 bytes attributed to UID_RED and 100 + // bytes attributed to UID_VPN. + NetworkStats tunAdjStats = mService.getTunAdjustedStats(); + assertValues( + tunAdjStats, TEST_IFACE, UID_RED, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL, + DEFAULT_NETWORK_ALL, 1000L, 100L, 0L, 0L, 0); + assertValues( + tunAdjStats, TEST_IFACE, UID_VPN, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL, + DEFAULT_NETWORK_ALL, 100L, 0L, 0L, 0L, 0); + } + + @Test + public void getDetailedUidStats_migratesTunTrafficAndUpdatesTunAdjustedStats() + throws Exception { + assertEquals(0, mService.getTunAdjustedStats().size()); + // VPN using WiFi (TEST_IFACE). + VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE})}; + expectBandwidthControlCheck(); + mService.forceUpdateIfaces( + new Network[0], vpnInfos, new NetworkState[0], null /* activeIface */); + // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption + // overhead per packet): + // 1000 bytes (100 packets) were downloaded by UID_RED over VPN. + // VPN received 1100 bytes (100 packets) over WiFi. + incrementCurrentTime(HOUR_IN_MILLIS); + expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 2) + .addValues(TUN_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1000L, 100L, 0L, 0L, 0L) + .addValues(TEST_IFACE, UID_VPN, SET_DEFAULT, TAG_NONE, 1100L, 100L, 0L, 0L, 0L)); + + mService.getDetailedUidStats(INTERFACES_ALL); + + // Verify internally maintained TUN adjusted stats + NetworkStats tunAdjStats = mService.getTunAdjustedStats(); + // Verify stats for TEST_IFACE (WiFi): + // Of 1100 bytes VPN received over WiFi, expect 1000 bytes attributed to UID_RED and 100 + // bytes attributed to UID_VPN. + assertValues( + tunAdjStats, TEST_IFACE, UID_RED, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL, + DEFAULT_NETWORK_ALL, 1000L, 100L, 0L, 0L, 0); + assertValues( + tunAdjStats, TEST_IFACE, UID_VPN, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL, + DEFAULT_NETWORK_ALL, 100L, 0L, 0L, 0L, 0); + // Verify stats for TUN_IFACE; only UID_RED should have usage on it. + assertValues( + tunAdjStats, TUN_IFACE, UID_RED, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL, + DEFAULT_NETWORK_ALL, 1000L, 100L, 0L, 0L, 0); + assertValues( + tunAdjStats, TUN_IFACE, UID_VPN, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL, + DEFAULT_NETWORK_ALL, 0L, 0L, 0L, 0L, 0); + + // lets assume that since last time, VPN received another 1100 bytes (same assumptions as + // before i.e. UID_RED downloaded another 1000 bytes). + incrementCurrentTime(HOUR_IN_MILLIS); + // Note - NetworkStatsFactory returns counters that are monotonically increasing. + expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 2) + .addValues(TUN_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 2000L, 200L, 0L, 0L, 0L) + .addValues(TEST_IFACE, UID_VPN, SET_DEFAULT, TAG_NONE, 2200L, 200L, 0L, 0L, 0L)); + + mService.getDetailedUidStats(INTERFACES_ALL); + + tunAdjStats = mService.getTunAdjustedStats(); + // verify TEST_IFACE stats: + assertValues( + tunAdjStats, TEST_IFACE, UID_RED, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL, + DEFAULT_NETWORK_ALL, 2000L, 200L, 0L, 0L, 0); + assertValues( + tunAdjStats, TEST_IFACE, UID_VPN, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL, + DEFAULT_NETWORK_ALL, 200L, 0L, 0L, 0L, 0); + // verify TUN_IFACE stats: + assertValues( + tunAdjStats, TUN_IFACE, UID_RED, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL, + DEFAULT_NETWORK_ALL, 2000L, 200L, 0L, 0L, 0); + assertValues( + tunAdjStats, TUN_IFACE, UID_VPN, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL, + DEFAULT_NETWORK_ALL, 0L, 0L, 0L, 0L, 0); + } + + @Test + public void getDetailedUidStats_returnsCorrectStatsWithVpnRunning() throws Exception { + // VPN using WiFi (TEST_IFACE). + VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE})}; + expectBandwidthControlCheck(); + mService.forceUpdateIfaces( + new Network[0], vpnInfos, new NetworkState[0], null /* activeIface */); + // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption + // overhead per packet): + // 1000 bytes (100 packets) were downloaded by UID_RED over VPN. + // VPN received 1100 bytes (100 packets) over WiFi. + incrementCurrentTime(HOUR_IN_MILLIS); + expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 2) + .addValues(TUN_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1000L, 100L, 0L, 0L, 0L) + .addValues(TEST_IFACE, UID_VPN, SET_DEFAULT, TAG_NONE, 1100L, 100L, 0L, 0L, 0L)); + + // Query realtime stats for TEST_IFACE. + NetworkStats queriedStats = + mService.getDetailedUidStats(new String[] {TEST_IFACE}); + + assertEquals(HOUR_IN_MILLIS, queriedStats.getElapsedRealtime()); + // verify that returned stats are only for TEST_IFACE and VPN traffic is migrated correctly. + assertEquals(new String[] {TEST_IFACE}, queriedStats.getUniqueIfaces()); + assertValues( + queriedStats, TEST_IFACE, UID_RED, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL, + DEFAULT_NETWORK_ALL, 1000L, 100L, 0L, 0L, 0); + assertValues( + queriedStats, TEST_IFACE, UID_VPN, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL, + DEFAULT_NETWORK_ALL, 100L, 0L, 0L, 0L, 0); + } + + @Test public void testRegisterUsageCallback() throws Exception { // pretend that wifi network comes online; service should ask about full // network state, and poll any existing interfaces before updating. @@ -1382,11 +1646,11 @@ public class NetworkStatsServiceTest { return new NetworkState(info, prop, new NetworkCapabilities(), VPN_NETWORK, null, null); } - private static VpnInfo createVpnInfo(String underlyingIface) { + private static VpnInfo createVpnInfo(String[] underlyingIfaces) { VpnInfo info = new VpnInfo(); info.ownerUid = UID_VPN; info.vpnIface = TUN_IFACE; - info.primaryUnderlyingIface = underlyingIface; + info.underlyingIfaces = underlyingIfaces; return info; } diff --git a/tests/utils/testutils/Android.bp b/tests/utils/testutils/Android.bp index 0a9e964d8d8d..f71be7b0b7d3 100644 --- a/tests/utils/testutils/Android.bp +++ b/tests/utils/testutils/Android.bp @@ -19,7 +19,10 @@ java_library { srcs: ["java/**/*.java"], - static_libs: ["junit"], + static_libs: [ + "junit", + "hamcrest-library", + ], libs: [ "android.test.runner", diff --git a/tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java b/tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java new file mode 100644 index 000000000000..2ce1fc68e1ce --- /dev/null +++ b/tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java @@ -0,0 +1,66 @@ +/* + * 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.test.filters; + +import android.os.Bundle; + +import com.android.test.filters.SelectTest; + +/** + * JUnit test filter that select Window Manager Service related tests from FrameworksCoreTests. + * + * <p>Use this filter when running FrameworksCoreTests as + * <pre> + * adb shell am instrument -w \ + * -e filter com.android.server.wm.test.filters.FrameworksTestsFilter \ + * -e selectTest_verbose true \ + * com.android.frameworks.coretests/androidx.test.runner.AndroidJUnitRunner + * </pre> + */ +public final class FrameworksTestsFilter extends SelectTest { + + private static final String[] SELECTED_TESTS = { + // Test specifications for FrameworksCoreTests. + "android.app.servertransaction.", // all tests under the package. + "android.view.DisplayCutoutTest", + // Test specifications for FrameworksServicesTests. + "com.android.server.policy.", // all tests under the package. + "com.android.server.am.ActivityLaunchParamsModifierTests", + "com.android.server.am.ActivityRecordTests", + "com.android.server.am.ActivityStackSupervisorTests", + "com.android.server.am.ActivityStackTests", + "com.android.server.am.ActivityStartControllerTests", + "com.android.server.am.ActivityStarterTests", + "com.android.server.am.ActivityStartInterceptorTest", + "com.android.server.am.AssistDataRequesterTest", + "com.android.server.am.ClientLifecycleManagerTests", + "com.android.server.am.LaunchParamsControllerTests", + "com.android.server.am.PendingRemoteAnimationRegistryTest", + "com.android.server.am.RecentsAnimationTest", + "com.android.server.am.RecentTasksTest", + "com.android.server.am.RunningTasksTest", + "com.android.server.am.SafeActivityOptionsTest", + "com.android.server.am.TaskLaunchParamsModifierTests", + "com.android.server.am.TaskPersisterTest", + "com.android.server.am.TaskRecordTests", + "com.android.server.am.TaskStackChangedListenerTest", + }; + + public FrameworksTestsFilter(Bundle testArgs) { + super(addSelectTest(testArgs, SELECTED_TESTS)); + } +} diff --git a/tests/utils/testutils/java/com/android/test/filters/SelectTest.java b/tests/utils/testutils/java/com/android/test/filters/SelectTest.java index d0350aff5ef5..d5b14c58512e 100644 --- a/tests/utils/testutils/java/com/android/test/filters/SelectTest.java +++ b/tests/utils/testutils/java/com/android/test/filters/SelectTest.java @@ -26,10 +26,12 @@ import com.android.internal.annotations.VisibleForTesting; import org.junit.runner.Description; import org.junit.runner.manipulation.Filter; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.LinkedHashMap; import java.util.LinkedHashSet; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.StringJoiner; @@ -131,7 +133,8 @@ public class SelectTest extends Filter { * * @param testArgs instrumentation test arguments. * @param selectTests array of class name to be selected to run. - * @return modified instrumentation test arguments. + * @return modified instrumentation test arguments. if {@link #OPTION_SELECT_TEST} argument + * already exists in {@code testArgs}, those are prepended before {@code selectTests}. */ @NonNull protected static Bundle addSelectTest( @@ -139,7 +142,13 @@ public class SelectTest extends Filter { if (selectTests.length == 0) { return testArgs; } - testArgs.putString(OPTION_SELECT_TEST, join(Arrays.asList(selectTests))); + final List<String> selectedTestList = new ArrayList<>(); + final String selectTestArgs = testArgs.getString(OPTION_SELECT_TEST); + if (selectTestArgs != null) { + selectedTestList.addAll(Arrays.asList(selectTestArgs.split(ARGUMENT_ITEM_SEPARATOR))); + } + selectedTestList.addAll(Arrays.asList(selectTests)); + testArgs.putString(OPTION_SELECT_TEST, join(selectedTestList)); return testArgs; } diff --git a/tests/utils/testutils/java/com/android/test/filters/SelectTestTests.java b/tests/utils/testutils/java/com/android/test/filters/SelectTestTests.java index 163b00abafcd..df18985f77bf 100644 --- a/tests/utils/testutils/java/com/android/test/filters/SelectTestTests.java +++ b/tests/utils/testutils/java/com/android/test/filters/SelectTestTests.java @@ -19,7 +19,11 @@ package com.android.test.filters; import static com.android.test.filters.SelectTest.OPTION_SELECT_TEST; import static com.android.test.filters.SelectTest.OPTION_SELECT_TEST_VERBOSE; +import static org.hamcrest.collection.IsArrayContaining.hasItemInArray; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import android.os.Bundle; @@ -146,6 +150,45 @@ public class SelectTestTests { } @Test + public void testAddSelectTest() { + final Bundle testArgs = new Bundle(); + + final Bundle modifiedTestArgs = + SelectTest.addSelectTest(testArgs, PACKAGE_A, CLASS_B3, METHOD_C5X); + assertSame(testArgs, modifiedTestArgs); + + final String selectTestArgs = modifiedTestArgs.getString(OPTION_SELECT_TEST); + assertNotNull(selectTestArgs); + final String[] selectedTests = selectTestArgs.split(","); + assertThat(selectedTests, hasItemInArray(PACKAGE_A)); + assertThat(selectedTests, hasItemInArray(CLASS_B3)); + assertThat(selectedTests, hasItemInArray(METHOD_C5X)); + } + + @Test + public void testAddSelectTest_prependExistingTestArg() { + final Bundle testArgs = new Bundle(); + testArgs.putString(OPTION_SELECT_TEST, new StringJoiner(",") + .add(PACKAGE_A) + .add(CLASS_B3) + .add(METHOD_C5X) + .toString()); + + final Bundle modifiedTestArgs = + SelectTest.addSelectTest(testArgs, PACKAGE_B, CLASS_B4, METHOD_C6Y); + + final String selectTestArgs = modifiedTestArgs.getString(OPTION_SELECT_TEST); + assertNotNull(selectTestArgs); + final String[] selectedTests = selectTestArgs.split(","); + assertThat(selectedTests, hasItemInArray(PACKAGE_A)); + assertThat(selectedTests, hasItemInArray(CLASS_B3)); + assertThat(selectedTests, hasItemInArray(METHOD_C5X)); + assertThat(selectedTests, hasItemInArray(PACKAGE_B)); + assertThat(selectedTests, hasItemInArray(CLASS_B4)); + assertThat(selectedTests, hasItemInArray(METHOD_C6Y)); + } + + @Test public void testFilterDisabled() { final Filter filter = mBuilder.build(); acceptTests(filter, TEST_ALL); |