diff options
107 files changed, 2853 insertions, 809 deletions
diff --git a/Android.bp b/Android.bp index a211d2675ec2..9a0d542277f3 100644 --- a/Android.bp +++ b/Android.bp @@ -526,7 +526,6 @@ java_library { host_supported: true, srcs: [ "core/java/android/annotation/IntDef.java", - "core/java/android/annotation/UnsupportedAppUsage.java", ], static_libs: [ "art.module.api.annotations", @@ -591,7 +590,6 @@ filegroup { "core/java/android/annotation/IntDef.java", "core/java/android/annotation/IntRange.java", "core/java/android/annotation/SystemApi.java", - "core/java/android/annotation/UnsupportedAppUsage.java", "core/java/com/android/internal/annotations/GuardedBy.java", "core/java/com/android/internal/annotations/VisibleForTesting.java", ], @@ -927,7 +925,6 @@ java_library { "core/java/android/annotation/Nullable.java", "core/java/android/annotation/SystemApi.java", "core/java/android/annotation/TestApi.java", - "core/java/android/annotation/UnsupportedAppUsage.java", "core/java/android/os/HidlMemory.java", "core/java/android/os/HwBinder.java", "core/java/android/os/HwBlob.java", @@ -994,7 +991,6 @@ filegroup { "core/java/android/annotation/StringDef.java", "core/java/android/annotation/SystemApi.java", "core/java/android/annotation/TestApi.java", - "core/java/android/annotation/UnsupportedAppUsage.java", "core/java/com/android/internal/annotations/GuardedBy.java", ], } diff --git a/apex/sdkextensions/OWNERS b/apex/sdkextensions/OWNERS index feb274262bef..a6e55228596b 100644 --- a/apex/sdkextensions/OWNERS +++ b/apex/sdkextensions/OWNERS @@ -1 +1,2 @@ +dariofreni@google.com hansson@google.com diff --git a/api/current.txt b/api/current.txt index 22f014e8d948..ce28b957aaae 100644 --- a/api/current.txt +++ b/api/current.txt @@ -29984,7 +29984,9 @@ package android.net.ssl { package android.net.wifi { public class ScanResult implements android.os.Parcelable { + ctor public ScanResult(@NonNull android.net.wifi.ScanResult); method public int describeContents(); + method @NonNull public java.util.List<android.net.wifi.ScanResult.InformationElement> getInformationElements(); method public boolean is80211mcResponder(); method public boolean isPasspointNetwork(); method public void writeToParcel(android.os.Parcel, int); @@ -29994,6 +29996,7 @@ package android.net.wifi { field public static final int CHANNEL_WIDTH_40MHZ = 1; // 0x1 field public static final int CHANNEL_WIDTH_80MHZ = 2; // 0x2 field public static final int CHANNEL_WIDTH_80MHZ_PLUS_MHZ = 4; // 0x4 + field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.ScanResult> CREATOR; field public String SSID; field public String capabilities; field public int centerFreq0; @@ -30006,6 +30009,12 @@ package android.net.wifi { field public CharSequence venueName; } + public static class ScanResult.InformationElement { + ctor public ScanResult.InformationElement(@NonNull android.net.wifi.ScanResult.InformationElement); + method @NonNull public java.nio.ByteBuffer getBytes(); + method public int getId(); + } + public enum SupplicantState implements android.os.Parcelable { method public int describeContents(); method public static boolean isValidState(android.net.wifi.SupplicantState); @@ -35400,7 +35409,7 @@ package android.os { method public boolean isSustainedPerformanceModeSupported(); method public boolean isWakeLockLevelSupported(int); method public android.os.PowerManager.WakeLock newWakeLock(int, String); - method public void reboot(@Nullable String); + method @RequiresPermission(android.Manifest.permission.REBOOT) public void reboot(@Nullable String); method public void removeThermalStatusListener(@NonNull android.os.PowerManager.OnThermalStatusChangedListener); field public static final int ACQUIRE_CAUSES_WAKEUP = 268435456; // 0x10000000 field public static final String ACTION_DEVICE_IDLE_MODE_CHANGED = "android.os.action.DEVICE_IDLE_MODE_CHANGED"; @@ -37310,6 +37319,7 @@ package android.provider { field public static final int FEATURES_PULLED_EXTERNALLY = 2; // 0x2 field public static final int FEATURES_RTT = 32; // 0x20 field public static final int FEATURES_VIDEO = 1; // 0x1 + field public static final int FEATURES_VOLTE = 64; // 0x40 field public static final int FEATURES_WIFI = 8; // 0x8 field public static final String GEOCODED_LOCATION = "geocoded_location"; field public static final int INCOMING_TYPE = 1; // 0x1 @@ -44653,6 +44663,12 @@ package android.telephony { field public static final int BAND_7 = 7; // 0x7 field public static final int BAND_8 = 8; // 0x8 field public static final int BAND_9 = 9; // 0x9 + field public static final int BAND_A = 101; // 0x65 + field public static final int BAND_B = 102; // 0x66 + field public static final int BAND_C = 103; // 0x67 + field public static final int BAND_D = 104; // 0x68 + field public static final int BAND_E = 105; // 0x69 + field public static final int BAND_F = 106; // 0x6a } public final class AvailableNetworkInfo implements android.os.Parcelable { @@ -44686,6 +44702,7 @@ package android.telephony { field public static final String KEY_5G_NR_SSRSRP_THRESHOLDS_INT_ARRAY = "5g_nr_ssrsrp_thresholds_int_array"; field public static final String KEY_5G_NR_SSRSRQ_THRESHOLDS_INT_ARRAY = "5g_nr_ssrsrq_thresholds_int_array"; field public static final String KEY_5G_NR_SSSINR_THRESHOLDS_INT_ARRAY = "5g_nr_sssinr_thresholds_int_array"; + field public static final String KEY_5G_WATCHDOG_TIME_MS_LONG = "5g_watchdog_time_long"; field public static final String KEY_ADDITIONAL_CALL_SETTING_BOOL = "additional_call_setting_bool"; field public static final String KEY_ALLOW_ADDING_APNS_BOOL = "allow_adding_apns_bool"; field public static final String KEY_ALLOW_ADD_CALL_DURING_VIDEO_CALL_BOOL = "allow_add_call_during_video_call"; @@ -44769,6 +44786,7 @@ package android.telephony { field public static final String KEY_DATA_LIMIT_NOTIFICATION_BOOL = "data_limit_notification_bool"; field public static final String KEY_DATA_LIMIT_THRESHOLD_BYTES_LONG = "data_limit_threshold_bytes_long"; field public static final String KEY_DATA_RAPID_NOTIFICATION_BOOL = "data_rapid_notification_bool"; + field public static final String KEY_DATA_SWITCH_VALIDATION_TIMEOUT_LONG = "data_switch_validation_timeout_long"; field public static final String KEY_DATA_WARNING_NOTIFICATION_BOOL = "data_warning_notification_bool"; field public static final String KEY_DATA_WARNING_THRESHOLD_BYTES_LONG = "data_warning_threshold_bytes_long"; field public static final String KEY_DEFAULT_SIM_CALL_MANAGER_STRING = "default_sim_call_manager_string"; @@ -44851,6 +44869,8 @@ package android.telephony { field public static final String KEY_ONLY_AUTO_SELECT_IN_HOME_NETWORK_BOOL = "only_auto_select_in_home_network"; field public static final String KEY_ONLY_SINGLE_DC_ALLOWED_INT_ARRAY = "only_single_dc_allowed_int_array"; field public static final String KEY_OPERATOR_SELECTION_EXPAND_BOOL = "operator_selection_expand_bool"; + field public static final String KEY_OPPORTUNISTIC_NETWORK_BACKOFF_TIME_LONG = "opportunistic_network_backoff_time_long"; + field public static final String KEY_OPPORTUNISTIC_NETWORK_DATA_SWITCH_EXIT_HYSTERESIS_TIME_LONG = "opportunistic_network_data_switch_exit_hysteresis_time_long"; field public static final String KEY_OPPORTUNISTIC_NETWORK_DATA_SWITCH_HYSTERESIS_TIME_LONG = "opportunistic_network_data_switch_hysteresis_time_long"; field public static final String KEY_OPPORTUNISTIC_NETWORK_ENTRY_OR_EXIT_HYSTERESIS_TIME_LONG = "opportunistic_network_entry_or_exit_hysteresis_time_long"; field public static final String KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_BANDWIDTH_INT = "opportunistic_network_entry_threshold_bandwidth_int"; @@ -44858,6 +44878,9 @@ package android.telephony { field public static final String KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_RSSNR_INT = "opportunistic_network_entry_threshold_rssnr_int"; field public static final String KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_RSRP_INT = "opportunistic_network_exit_threshold_rsrp_int"; field public static final String KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_RSSNR_INT = "opportunistic_network_exit_threshold_rssnr_int"; + field public static final String KEY_OPPORTUNISTIC_NETWORK_MAX_BACKOFF_TIME_LONG = "opportunistic_network_max_backoff_time_long"; + field public static final String KEY_OPPORTUNISTIC_NETWORK_PING_PONG_TIME_LONG = "opportunistic_network_ping_pong_time_long"; + field public static final String KEY_PING_TEST_BEFORE_DATA_SWITCH_BOOL = "ping_test_before_data_switch_bool"; field public static final String KEY_PREFER_2G_BOOL = "prefer_2g_bool"; field public static final String KEY_PREVENT_CLIR_ACTIVATION_AND_DEACTIVATION_CODE_BOOL = "prevent_clir_activation_and_deactivation_code_bool"; field public static final String KEY_RADIO_RESTART_FAILURE_CAUSES_INT_ARRAY = "radio_restart_failure_causes_int_array"; @@ -44894,6 +44917,7 @@ package android.telephony { field public static final String KEY_SUPPORT_SWAP_AFTER_MERGE_BOOL = "support_swap_after_merge_bool"; field public static final String KEY_SUPPORT_TDSCDMA_BOOL = "support_tdscdma_bool"; field public static final String KEY_SUPPORT_TDSCDMA_ROAMING_NETWORKS_STRING_ARRAY = "support_tdscdma_roaming_networks_string_array"; + field public static final String KEY_SWITCH_DATA_TO_PRIMARY_IF_PRIMARY_IS_OOS_BOOL = "switch_data_to_primary_if_primary_is_oos_bool"; field public static final String KEY_TREAT_DOWNGRADED_VIDEO_CALLS_AS_VIDEO_CALLS_BOOL = "treat_downgraded_video_calls_as_video_calls_bool"; field public static final String KEY_TTY_SUPPORTED_BOOL = "tty_supported_bool"; field public static final String KEY_UNLOGGABLE_NUMBERS_STRING_ARRAY = "unloggable_numbers_string_array"; @@ -44947,6 +44971,7 @@ package android.telephony { } public final class CellIdentityGsm extends android.telephony.CellIdentity { + method @NonNull public java.util.List<java.lang.String> getAdditionalPlmns(); method public int getArfcn(); method public int getBsic(); method public int getCid(); @@ -44962,8 +44987,11 @@ package android.telephony { } public final class CellIdentityLte extends android.telephony.CellIdentity { + method @NonNull public java.util.List<java.lang.String> getAdditionalPlmns(); + method @NonNull public java.util.List<java.lang.Integer> getBands(); method public int getBandwidth(); method public int getCi(); + method @Nullable public android.telephony.ClosedSubscriberGroupInfo getClosedSubscriberGroupInfo(); method public int getEarfcn(); method @Deprecated public int getMcc(); method @Nullable public String getMccString(); @@ -44977,6 +45005,8 @@ package android.telephony { } public final class CellIdentityNr extends android.telephony.CellIdentity { + method @NonNull public java.util.List<java.lang.String> getAdditionalPlmns(); + method @NonNull public java.util.List<java.lang.Integer> getBands(); method @Nullable public String getMccString(); method @Nullable public String getMncString(); method public long getNci(); @@ -44988,7 +45018,9 @@ package android.telephony { } public final class CellIdentityTdscdma extends android.telephony.CellIdentity { + method @NonNull public java.util.List<java.lang.String> getAdditionalPlmns(); method public int getCid(); + method @Nullable public android.telephony.ClosedSubscriberGroupInfo getClosedSubscriberGroupInfo(); method public int getCpid(); method public int getLac(); method @Nullable public String getMccString(); @@ -45000,7 +45032,9 @@ package android.telephony { } public final class CellIdentityWcdma extends android.telephony.CellIdentity { + method @NonNull public java.util.List<java.lang.String> getAdditionalPlmns(); method public int getCid(); + method @Nullable public android.telephony.ClosedSubscriberGroupInfo getClosedSubscriberGroupInfo(); method public int getLac(); method @Deprecated public int getMcc(); method @Nullable public String getMccString(); @@ -45170,6 +45204,15 @@ package android.telephony { field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CellSignalStrengthWcdma> CREATOR; } + public final class ClosedSubscriberGroupInfo implements android.os.Parcelable { + method public int describeContents(); + method @IntRange(from=0, to=134217727) public int getCsgIdentity(); + method public boolean getCsgIndicator(); + method @NonNull public String getHomeNodebName(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ClosedSubscriberGroupInfo> CREATOR; + } + public class IccOpenLogicalChannelResponse implements android.os.Parcelable { method public int describeContents(); method public int getChannel(); @@ -45313,8 +45356,32 @@ package android.telephony { public final class PhoneCapability implements android.os.Parcelable { method public int describeContents(); + method @NonNull public java.util.List<java.lang.Integer> getBands(int); + method @NonNull public java.util.List<java.util.List<java.lang.Long>> getConcurrentFeaturesSupport(); + method @NonNull public java.util.List<java.lang.String> getLogicalModemUuids(); + method public int getMaxActiveDedicatedBearers(); + method public int getMaxActiveInternetData(); + method public int getMaxActivePsVoice(); + method public long getPsDataConnectionLingerTimeMillis(); + method @NonNull public java.util.List<android.telephony.SimSlotCapability> getSimSlotCapabilities(); + method public long getSupportedRats(); + method public int getUeCategory(boolean, int); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.telephony.PhoneCapability> CREATOR; + field public static final long MODEM_FEATURE_3GPP2_REG = 1L; // 0x1L + field public static final long MODEM_FEATURE_3GPP_REG = 2L; // 0x2L + field public static final long MODEM_FEATURE_CDMA2000_EHRPD_REG = 4L; // 0x4L + field public static final long MODEM_FEATURE_CSIM = 8192L; // 0x2000L + field public static final long MODEM_FEATURE_CS_VOICE_SESSION = 512L; // 0x200L + field public static final long MODEM_FEATURE_DEDICATED_BEARER = 2048L; // 0x800L + field public static final long MODEM_FEATURE_EUTRAN_REG = 32L; // 0x20L + field public static final long MODEM_FEATURE_EUTRA_NR_DUAL_CONNECTIVITY_REG = 128L; // 0x80L + field public static final long MODEM_FEATURE_GERAN_REG = 8L; // 0x8L + field public static final long MODEM_FEATURE_INTERACTIVE_DATA_SESSION = 1024L; // 0x400L + field public static final long MODEM_FEATURE_NETWORK_SCAN = 4096L; // 0x1000L + field public static final long MODEM_FEATURE_NGRAN_REG = 64L; // 0x40L + field public static final long MODEM_FEATURE_PS_VOICE_REG = 256L; // 0x100L + field public static final long MODEM_FEATURE_UTRAN_REG = 16L; // 0x10L } public class PhoneNumberFormattingTextWatcher implements android.text.TextWatcher { @@ -45499,6 +45566,18 @@ package android.telephony { field public static final int INVALID = 2147483647; // 0x7fffffff } + public final class SimSlotCapability implements android.os.Parcelable { + method public int describeContents(); + method public int getPhysicalSlotIndex(); + method public int getSlotType(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.SimSlotCapability> CREATOR; + field public static final int SLOT_TYPE_EUICC = 3; // 0x3 + field public static final int SLOT_TYPE_IUICC = 2; // 0x2 + field public static final int SLOT_TYPE_SOFT_SIM = 4; // 0x4 + field public static final int SLOT_TYPE_UICC = 1; // 0x1 + } + public final class SmsManager { method public String createAppSpecificSmsToken(android.app.PendingIntent); method @Nullable public String createAppSpecificSmsTokenWithPackageInfo(@Nullable String, @NonNull android.app.PendingIntent); @@ -45845,6 +45924,7 @@ package android.telephony { method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public int getNetworkSelectionMode(); method public String getNetworkSpecifier(); method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public int getNetworkType(); + method @Nullable @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public android.telephony.PhoneCapability getPhoneCapability(); method @Deprecated public int getPhoneCount(); method public int getPhoneType(); method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PHONE_STATE}) public int getPreferredOpportunisticDataSubscription(); diff --git a/api/module-lib-current.txt b/api/module-lib-current.txt index c657e0049670..eeef074c5b16 100644 --- a/api/module-lib-current.txt +++ b/api/module-lib-current.txt @@ -19,7 +19,7 @@ package android.app.timedetector { method @NonNull public android.app.timedetector.PhoneTimeSuggestion.Builder setUtcTime(@Nullable android.os.TimestampedValue<java.lang.Long>); } - public class TimeDetector { + public interface TimeDetector { method @RequiresPermission("android.permission.SUGGEST_PHONE_TIME_AND_ZONE") public void suggestPhoneTime(@NonNull android.app.timedetector.PhoneTimeSuggestion); } @@ -59,7 +59,7 @@ package android.app.timezonedetector { method @NonNull public android.app.timezonedetector.PhoneTimeZoneSuggestion.Builder setZoneId(@Nullable String); } - public class TimeZoneDetector { + public interface TimeZoneDetector { method @RequiresPermission("android.permission.SUGGEST_PHONE_TIME_AND_ZONE") public void suggestPhoneTimeZone(@NonNull android.app.timezonedetector.PhoneTimeZoneSuggestion); } @@ -102,18 +102,18 @@ package android.timezone { method @NonNull public String getTimeZoneId(); } - public class TelephonyLookup { + public final class TelephonyLookup { method @NonNull public static android.timezone.TelephonyLookup getInstance(); method @Nullable public android.timezone.TelephonyNetworkFinder getTelephonyNetworkFinder(); } - public class TelephonyNetwork { + public final class TelephonyNetwork { method @NonNull public String getCountryIsoCode(); method @NonNull public String getMcc(); method @NonNull public String getMnc(); } - public class TelephonyNetworkFinder { + public final class TelephonyNetworkFinder { method @Nullable public android.timezone.TelephonyNetwork findNetworkByMccMnc(@NonNull String, @NonNull String); } @@ -134,7 +134,7 @@ package android.timezone { method @NonNull public static android.timezone.TzDataSetVersion read() throws java.io.IOException, android.timezone.TzDataSetVersion.TzDataSetException; } - public static class TzDataSetVersion.TzDataSetException extends java.lang.Exception { + public static final class TzDataSetVersion.TzDataSetException extends java.lang.Exception { ctor public TzDataSetVersion.TzDataSetException(String); ctor public TzDataSetVersion.TzDataSetException(String, Throwable); } diff --git a/api/system-current.txt b/api/system-current.txt index 9b62fcc03313..fe904109580e 100755 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -226,6 +226,7 @@ package android { public static final class R.array { field public static final int config_keySystemUuidMapping = 17235973; // 0x1070005 + field public static final int simColors = 17235974; // 0x1070006 } public static final class R.attr { @@ -1577,6 +1578,7 @@ package android.content { field public static final String BUGREPORT_SERVICE = "bugreport"; field public static final String CONTENT_SUGGESTIONS_SERVICE = "content_suggestions"; field public static final String CONTEXTHUB_SERVICE = "contexthub"; + field public static final String ETHERNET_SERVICE = "ethernet"; field public static final String EUICC_CARD_SERVICE = "euicc_card"; field public static final String HDMI_CONTROL_SERVICE = "hdmi_control"; field public static final String NETD_SERVICE = "netd"; @@ -3285,10 +3287,12 @@ package android.hardware.usb { method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public void setCurrentFunctions(long); field @RequiresPermission(android.Manifest.permission.MANAGE_USB) public static final String ACTION_USB_PORT_CHANGED = "android.hardware.usb.action.USB_PORT_CHANGED"; field public static final String ACTION_USB_STATE = "android.hardware.usb.action.USB_STATE"; + field public static final long FUNCTION_NCM = 1024L; // 0x400L field public static final long FUNCTION_NONE = 0L; // 0x0L field public static final long FUNCTION_RNDIS = 32L; // 0x20L field public static final String USB_CONFIGURED = "configured"; field public static final String USB_CONNECTED = "connected"; + field public static final String USB_FUNCTION_NCM = "ncm"; field public static final String USB_FUNCTION_RNDIS = "rndis"; } @@ -4380,6 +4384,19 @@ package android.net { method @Deprecated public void onUpstreamChanged(@Nullable android.net.Network); } + public class EthernetManager { + method @NonNull public android.net.EthernetManager.TetheredInterfaceRequest requestTetheredInterface(@NonNull android.net.EthernetManager.TetheredInterfaceCallback); + } + + public static interface EthernetManager.TetheredInterfaceCallback { + method public void onAvailable(@NonNull String); + method public void onUnavailable(); + } + + public static class EthernetManager.TetheredInterfaceRequest { + method public void release(); + } + public class InvalidPacketException extends java.lang.Exception { ctor public InvalidPacketException(int); field public static final int ERROR_INVALID_IP_ADDRESS = -21; // 0xffffffeb @@ -4652,6 +4669,8 @@ package android.net { public final class RouteInfo implements android.os.Parcelable { ctor public RouteInfo(@Nullable android.net.IpPrefix, @Nullable java.net.InetAddress, @Nullable String, int); + ctor public RouteInfo(@Nullable android.net.IpPrefix, @Nullable java.net.InetAddress, @Nullable String, int, int); + method public int getMtu(); method public int getType(); field public static final int RTN_THROW = 9; // 0x9 field public static final int RTN_UNICAST = 1; // 0x1 @@ -4753,7 +4772,9 @@ package android.net { field public static final String EXTRA_AVAILABLE_TETHER = "availableArray"; field public static final String EXTRA_ERRORED_TETHER = "erroredArray"; field public static final int TETHERING_BLUETOOTH = 2; // 0x2 + field public static final int TETHERING_ETHERNET = 5; // 0x5 field public static final int TETHERING_INVALID = -1; // 0xffffffff + field public static final int TETHERING_NCM = 4; // 0x4 field public static final int TETHERING_USB = 1; // 0x1 field public static final int TETHERING_WIFI = 0; // 0x0 field public static final int TETHERING_WIFI_P2P = 3; // 0x3 @@ -8373,6 +8394,13 @@ package android.telephony { field public static final int TRANSPORT_TYPE_INVALID = -1; // 0xffffffff } + public static final class AccessNetworkConstants.NgranBands { + method public static int getFrequencyRangeGroup(int); + field public static final int FREQUENCY_RANGE_GROUP_1 = 1; // 0x1 + field public static final int FREQUENCY_RANGE_GROUP_2 = 2; // 0x2 + field public static final int FREQUENCY_RANGE_GROUP_UNKNOWN = 0; // 0x0 + } + public final class CallAttributes implements android.os.Parcelable { ctor public CallAttributes(@NonNull android.telephony.PreciseCallState, int, @NonNull android.telephony.CallQuality); method public int describeContents(); @@ -8470,7 +8498,7 @@ package android.telephony { } public class CellBroadcastIntents { - method public static void sendOrderedBroadcastForBackgroundReceivers(@NonNull android.content.Context, @Nullable android.os.UserHandle, @NonNull android.content.Intent, @Nullable String, @Nullable String, @Nullable android.content.BroadcastReceiver, @Nullable android.os.Handler, int, @Nullable String, @Nullable android.os.Bundle); + method public static void sendSmsCbReceivedBroadcast(@NonNull android.content.Context, @Nullable android.os.UserHandle, @NonNull android.telephony.SmsCbMessage, @Nullable android.content.BroadcastReceiver, @Nullable android.os.Handler, int, int); } public abstract class CellBroadcastService extends android.app.Service { @@ -8987,6 +9015,7 @@ package android.telephony { method public int getSleepTimeMillis(); method public long getTimestamp(); method @NonNull public java.util.List<android.telephony.ModemActivityInfo.TransmitPower> getTransmitPowerInfo(); + method public boolean isValid(); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ModemActivityInfo> CREATOR; field public static final int TX_POWER_LEVELS = 5; // 0x5 @@ -9089,9 +9118,9 @@ package android.telephony { field @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int LISTEN_OUTGOING_EMERGENCY_CALL = 268435456; // 0x10000000 field @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int LISTEN_OUTGOING_EMERGENCY_SMS = 536870912; // 0x20000000 field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_PRECISE_CALL_STATE = 2048; // 0x800 - field public static final int LISTEN_RADIO_POWER_STATE_CHANGED = 8388608; // 0x800000 + field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int LISTEN_RADIO_POWER_STATE_CHANGED = 8388608; // 0x800000 field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int LISTEN_SRVCC_STATE_CHANGED = 16384; // 0x4000 - field public static final int LISTEN_VOICE_ACTIVATION_STATE = 131072; // 0x20000 + field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int LISTEN_VOICE_ACTIVATION_STATE = 131072; // 0x20000 } public final class PreciseCallState implements android.os.Parcelable { @@ -9528,6 +9557,7 @@ package android.telephony { method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean rebootRadio(); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void reportDefaultNetworkStatus(boolean); method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.MODIFY_PHONE_STATE}) public void requestCellInfoUpdate(@NonNull android.os.WorkSource, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CellInfoCallback); + method public void requestModemActivityInfo(@NonNull android.os.ResultReceiver); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void requestNumberVerification(@NonNull android.telephony.PhoneNumberRange, long, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.NumberVerificationCallback); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void resetAllCarrierActions(); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void resetCarrierKeysForImsiEncryption(); @@ -9543,6 +9573,7 @@ package android.telephony { method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataEnabled(int, boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataRoamingEnabled(boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setMultiSimCarrierRestriction(boolean); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setNetworkSelectionModeManual(@NonNull String, int, boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setOpportunisticNetworkState(boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setPreferredNetworkTypeBitmask(long); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setRadio(boolean); @@ -9706,7 +9737,9 @@ package android.telephony.data { method public int getId(); method @NonNull public String getInterfaceName(); method public int getLinkStatus(); - method public int getMtu(); + method @Deprecated public int getMtu(); + method public int getMtuV4(); + method public int getMtuV6(); method @NonNull public java.util.List<java.net.InetAddress> getPcscfAddresses(); method public int getProtocolType(); method public int getSuggestedRetryTime(); @@ -9728,7 +9761,9 @@ package android.telephony.data { method @NonNull public android.telephony.data.DataCallResponse.Builder setId(int); method @NonNull public android.telephony.data.DataCallResponse.Builder setInterfaceName(@NonNull String); method @NonNull public android.telephony.data.DataCallResponse.Builder setLinkStatus(int); - method @NonNull public android.telephony.data.DataCallResponse.Builder setMtu(int); + method @Deprecated @NonNull public android.telephony.data.DataCallResponse.Builder setMtu(int); + method @NonNull public android.telephony.data.DataCallResponse.Builder setMtuV4(int); + method @NonNull public android.telephony.data.DataCallResponse.Builder setMtuV6(int); method @NonNull public android.telephony.data.DataCallResponse.Builder setPcscfAddresses(@NonNull java.util.List<java.net.InetAddress>); method @NonNull public android.telephony.data.DataCallResponse.Builder setProtocolType(int); method @NonNull public android.telephony.data.DataCallResponse.Builder setSuggestedRetryTime(int); @@ -9739,7 +9774,9 @@ package android.telephony.data { method @NonNull public String getApn(); method public int getAuthType(); method public int getBearerBitmask(); - method public int getMtu(); + method @Deprecated public int getMtu(); + method public int getMtuV4(); + method public int getMtuV6(); method @Nullable public String getPassword(); method public int getProfileId(); method public int getProtocolType(); @@ -9764,7 +9801,9 @@ package android.telephony.data { method @NonNull public android.telephony.data.DataProfile.Builder setApn(@NonNull String); method @NonNull public android.telephony.data.DataProfile.Builder setAuthType(int); method @NonNull public android.telephony.data.DataProfile.Builder setBearerBitmask(int); - method @NonNull public android.telephony.data.DataProfile.Builder setMtu(int); + method @Deprecated @NonNull public android.telephony.data.DataProfile.Builder setMtu(int); + method @NonNull public android.telephony.data.DataProfile.Builder setMtuV4(int); + method @NonNull public android.telephony.data.DataProfile.Builder setMtuV6(int); method @NonNull public android.telephony.data.DataProfile.Builder setPassword(@NonNull String); method @NonNull public android.telephony.data.DataProfile.Builder setPersistent(boolean); method @NonNull public android.telephony.data.DataProfile.Builder setPreferred(boolean); diff --git a/api/test-current.txt b/api/test-current.txt index 827ec3486122..9a331a2f8521 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -653,6 +653,7 @@ package android.content { method public void setContentCaptureOptions(@Nullable android.content.ContentCaptureOptions); field public static final String BUGREPORT_SERVICE = "bugreport"; field public static final String CONTENT_CAPTURE_MANAGER_SERVICE = "content_capture"; + field public static final String ETHERNET_SERVICE = "ethernet"; field public static final String NETWORK_STACK_SERVICE = "network_stack"; field public static final String PERMISSION_SERVICE = "permission"; field public static final String ROLLBACK_SERVICE = "rollback"; @@ -1392,6 +1393,19 @@ package android.net { field public static final String EXTRA_CAPTIVE_PORTAL_USER_AGENT = "android.net.extra.CAPTIVE_PORTAL_USER_AGENT"; } + public class EthernetManager { + method @NonNull public android.net.EthernetManager.TetheredInterfaceRequest requestTetheredInterface(@NonNull android.net.EthernetManager.TetheredInterfaceCallback); + } + + public static interface EthernetManager.TetheredInterfaceCallback { + method public void onAvailable(@NonNull String); + method public void onUnavailable(); + } + + public static class EthernetManager.TetheredInterfaceRequest { + method public void release(); + } + public final class IpPrefix implements android.os.Parcelable { ctor public IpPrefix(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int); ctor public IpPrefix(@NonNull String); @@ -1540,7 +1554,9 @@ package android.net { field public static final String EXTRA_AVAILABLE_TETHER = "availableArray"; field public static final String EXTRA_ERRORED_TETHER = "erroredArray"; field public static final int TETHERING_BLUETOOTH = 2; // 0x2 + field public static final int TETHERING_ETHERNET = 5; // 0x5 field public static final int TETHERING_INVALID = -1; // 0xffffffff + field public static final int TETHERING_NCM = 4; // 0x4 field public static final int TETHERING_USB = 1; // 0x1 field public static final int TETHERING_WIFI = 0; // 0x0 field public static final int TETHERING_WIFI_P2P = 3; // 0x3 @@ -3020,6 +3036,13 @@ package android.telephony { field public static final int TRANSPORT_TYPE_INVALID = -1; // 0xffffffff } + public static final class AccessNetworkConstants.NgranBands { + method public static int getFrequencyRangeGroup(int); + field public static final int FREQUENCY_RANGE_GROUP_1 = 1; // 0x1 + field public static final int FREQUENCY_RANGE_GROUP_2 = 2; // 0x2 + field public static final int FREQUENCY_RANGE_GROUP_UNKNOWN = 0; // 0x0 + } + public final class CallQuality implements android.os.Parcelable { ctor public CallQuality(int, int, int, int, int, int, int, int, int, int, int); method public int describeContents(); diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index db384baff4d7..85db4b9f0f8f 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -17,6 +17,8 @@ #define LOG_NDEBUG 0 #define LOG_TAG "BootAnimation" +#include <vector> + #include <stdint.h> #include <inttypes.h> #include <sys/inotify.h> @@ -80,6 +82,10 @@ static const char OEM_SHUTDOWNANIMATION_FILE[] = "/oem/media/shutdownanimation.z static const char PRODUCT_SHUTDOWNANIMATION_FILE[] = "/product/media/shutdownanimation.zip"; static const char SYSTEM_SHUTDOWNANIMATION_FILE[] = "/system/media/shutdownanimation.zip"; +static constexpr const char* PRODUCT_USERSPACE_REBOOT_ANIMATION_FILE = "/product/media/userspace-reboot.zip"; +static constexpr const char* OEM_USERSPACE_REBOOT_ANIMATION_FILE = "/oem/media/userspace-reboot.zip"; +static constexpr const char* SYSTEM_USERSPACE_REBOOT_ANIMATION_FILE = "/system/media/userspace-reboot.zip"; + static const char SYSTEM_DATA_DIR_PATH[] = "/data/system"; static const char SYSTEM_TIME_DIR_NAME[] = "time"; static const char SYSTEM_TIME_DIR_PATH[] = "/data/system/time"; @@ -341,6 +347,16 @@ bool BootAnimation::preloadAnimation() { return false; } +bool BootAnimation::findBootAnimationFileInternal(const std::vector<std::string> &files) { + for (const std::string& f : files) { + if (access(f.c_str(), R_OK) == 0) { + mZipFileName = f.c_str(); + return true; + } + } + return false; +} + void BootAnimation::findBootAnimationFile() { // If the device has encryption turned on or is in process // of being encrypted we show the encrypted boot animation. @@ -351,28 +367,33 @@ void BootAnimation::findBootAnimationFile() { !strcmp("trigger_restart_min_framework", decrypt); if (!mShuttingDown && encryptedAnimation) { - static const char* encryptedBootFiles[] = - {PRODUCT_ENCRYPTED_BOOTANIMATION_FILE, SYSTEM_ENCRYPTED_BOOTANIMATION_FILE}; - for (const char* f : encryptedBootFiles) { - if (access(f, R_OK) == 0) { - mZipFileName = f; - return; - } + static const std::vector<std::string> encryptedBootFiles = { + PRODUCT_ENCRYPTED_BOOTANIMATION_FILE, SYSTEM_ENCRYPTED_BOOTANIMATION_FILE, + }; + if (findBootAnimationFileInternal(encryptedBootFiles)) { + return; } } const bool playDarkAnim = android::base::GetIntProperty("ro.boot.theme", 0) == 1; - static const char* bootFiles[] = - {APEX_BOOTANIMATION_FILE, playDarkAnim ? PRODUCT_BOOTANIMATION_DARK_FILE : PRODUCT_BOOTANIMATION_FILE, - OEM_BOOTANIMATION_FILE, SYSTEM_BOOTANIMATION_FILE}; - static const char* shutdownFiles[] = - {PRODUCT_SHUTDOWNANIMATION_FILE, OEM_SHUTDOWNANIMATION_FILE, SYSTEM_SHUTDOWNANIMATION_FILE, ""}; - - for (const char* f : (!mShuttingDown ? bootFiles : shutdownFiles)) { - if (access(f, R_OK) == 0) { - mZipFileName = f; - return; - } + static const std::vector<std::string> bootFiles = { + APEX_BOOTANIMATION_FILE, playDarkAnim ? PRODUCT_BOOTANIMATION_DARK_FILE : PRODUCT_BOOTANIMATION_FILE, + OEM_BOOTANIMATION_FILE, SYSTEM_BOOTANIMATION_FILE + }; + static const std::vector<std::string> shutdownFiles = { + PRODUCT_SHUTDOWNANIMATION_FILE, OEM_SHUTDOWNANIMATION_FILE, SYSTEM_SHUTDOWNANIMATION_FILE, "" + }; + static const std::vector<std::string> userspaceRebootFiles = { + PRODUCT_USERSPACE_REBOOT_ANIMATION_FILE, OEM_USERSPACE_REBOOT_ANIMATION_FILE, + SYSTEM_USERSPACE_REBOOT_ANIMATION_FILE, + }; + + if (android::base::GetBoolProperty("sys.init.userspace_reboot.in_progress", false)) { + findBootAnimationFileInternal(userspaceRebootFiles); + } else if (mShuttingDown) { + findBootAnimationFileInternal(shutdownFiles); + } else { + findBootAnimationFileInternal(bootFiles); } } diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h index dc19fb09ef1d..574d65e425cf 100644 --- a/cmds/bootanimation/BootAnimation.h +++ b/cmds/bootanimation/BootAnimation.h @@ -17,6 +17,8 @@ #ifndef ANDROID_BOOTANIMATION_H #define ANDROID_BOOTANIMATION_H +#include <vector> + #include <stdint.h> #include <sys/types.h> @@ -157,6 +159,7 @@ private: bool parseAnimationDesc(Animation&); bool preloadZip(Animation &animation); void findBootAnimationFile(); + bool findBootAnimationFileInternal(const std::vector<std::string>& files); bool preloadAnimation(); void checkExit(); diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto index d9083886f817..c72e89b481ee 100644 --- a/cmds/statsd/src/atoms.proto +++ b/cmds/statsd/src/atoms.proto @@ -6237,7 +6237,8 @@ message DeviceIdentifierAccessDenied { optional bool is_preinstalled = 3; // True if the package is privileged. - optional bool is_priv_app = 4; + // Starting from Android 11, this boolean is not set and will always be false. + optional bool is_priv_app = 4 [deprecated = true]; } /** diff --git a/core/java/android/annotation/SystemApi.java b/core/java/android/annotation/SystemApi.java index 1a8b78ff08cf..ecbfed96cefd 100644 --- a/core/java/android/annotation/SystemApi.java +++ b/core/java/android/annotation/SystemApi.java @@ -23,6 +23,7 @@ import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.PACKAGE; import static java.lang.annotation.ElementType.TYPE; +import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @@ -40,6 +41,7 @@ import java.lang.annotation.Target; */ @Target({TYPE, FIELD, METHOD, CONSTRUCTOR, ANNOTATION_TYPE, PACKAGE}) @Retention(RetentionPolicy.RUNTIME) +@Repeatable(SystemApi.Container.class) // TODO(b/146727827): make this non-repeatable public @interface SystemApi { enum Client { /** @@ -95,4 +97,14 @@ public @interface SystemApi { */ @Deprecated Process process() default android.annotation.SystemApi.Process.ALL; + + + /** + * Container for {@link SystemApi} that allows it to be applied repeatedly to types. + */ + @Retention(RetentionPolicy.RUNTIME) + @Target(TYPE) + @interface Container { + SystemApi[] value(); + } } diff --git a/core/java/android/annotation/UnsupportedAppUsage.java b/core/java/android/annotation/UnsupportedAppUsage.java deleted file mode 100644 index 1af48cb63079..000000000000 --- a/core/java/android/annotation/UnsupportedAppUsage.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.annotation; - -import static java.lang.annotation.ElementType.CONSTRUCTOR; -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.CLASS; - -import java.lang.annotation.Repeatable; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -/** - * Indicates that this non-SDK interface is used by apps. A non-SDK interface is a - * class member (field or method) that is not part of the public SDK. Since the - * member is not part of the SDK, usage by apps is not supported. - * - * <h2>If you are an Android App developer</h2> - * - * This annotation indicates that you may be able to access the member, but that - * this access is discouraged and not supported by Android. If there is a value - * for {@link #maxTargetSdk()} on the annotation, access will be restricted based - * on the {@code targetSdkVersion} value set in your manifest. - * - * <p>Fields and methods annotated with this are likely to be restricted, changed - * or removed in future Android releases. If you rely on these members for - * functionality that is not otherwise supported by Android, consider filing a - * <a href="http://g.co/dev/appcompat">feature request</a>. - * - * <h2>If you are an Android OS developer</h2> - * - * This annotation acts as a heads up that changing a given method or field - * may affect apps, potentially breaking them when the next Android version is - * released. In some cases, for members that are heavily used, this annotation - * may imply restrictions on changes to the member. - * - * <p>This annotation also results in access to the member being permitted by the - * runtime, with a warning being generated in debug builds. Which apps can access - * the member is determined by the value of {@link #maxTargetSdk()}. - * - * <p>For more details, see go/UnsupportedAppUsage. - * - * {@hide} - */ -@Retention(CLASS) -@Target({CONSTRUCTOR, METHOD, FIELD, TYPE}) -@Repeatable(UnsupportedAppUsage.Container.class) -public @interface UnsupportedAppUsage { - - /** - * Associates a bug tracking the work to add a public alternative to this API. Optional. - * - * @return ID of the associated tracking bug - */ - long trackingBug() default 0; - - /** - * Indicates that usage of this API is limited to apps based on their target SDK version. - * - * <p>Access to the API is allowed if the targetSdkVersion in the apps manifest is no greater - * than this value. Access checks are performed at runtime. - * - * <p>This is used to give app developers a grace period to migrate off a non-SDK interface. - * When making Android version N, existing APIs can have a maxTargetSdk of N-1 added to them. - * Developers must then migrate off the API when their app is updated in future, but it will - * continue working in the meantime. - * - * <p>Possible values are: - * <ul> - * <li> - * An API level like {@link android.os.Build.VERSION_CODES#O} - in which case the API is - * available up to and including the specified release. Or, in other words, the API is - * blacklisted (unavailable) from the next API level from the one specified. - * </li> - * <li> - * absent (default value) - All apps can access this API, but doing so may result in - * warnings in the log, UI warnings (on developer builds) and/or strictmode violations. - * The API is likely to be further restricted in future. - * </li> - * - * </ul> - * - * @return The maximum value for an apps targetSdkVersion in order to access this API. - */ - int maxTargetSdk() default Integer.MAX_VALUE; - - /** - * For debug use only. The expected dex signature to be generated for this API, used to verify - * parts of the build process. - * - * @return A dex API signature. - */ - String expectedSignature() default ""; - - /** - * The signature of an implicit (not present in the source) member that forms part of the - * hiddenapi. - * - * <p>Allows access to non-SDK API elements that are not represented in the input source to be - * managed. - * - * <p>This must only be used when applying the annotation to a type, using it in any other - * situation is an error. - * - * @return A dex API signature. - */ - String implicitMember() default ""; - - /** - * Public API alternatives to this API. - * - * <p>If non-empty, the string must be a description of the public API alternative(s) to this - * API. The explanation must contain at least one Javadoc link tag to public API methods or - * fields. e.g.: - * {@literal @UnsupportedAppUsage(publicAlternatives="Use {@link foo.bar.Baz#bat()} instead.")} - * - * <p>Any elements that can be deduced can be omitted, e.g.: - * <ul> - * <li> - * the class, if it's the same as for the annotated element. - * </li> - * <li> - * the package name, if it's the same as for the annotated element. - * </li> - * <li> - * the method parameters, if there is only one method with that name in the given - * package and class. - * </li> - * </ul> - * @return A Javadoc-formatted string. - */ - @SuppressWarnings("JavadocReference") - String publicAlternatives() default ""; - - /** - * Override the default source position when generating an index of the annotations. - * - * <p>This is intended for use by tools that generate java source code, to point to the - * original source position of the annotation, rather than the position within the generated - * code. It should never be set manually. - * - * <p>The format of the value is "path/to/file:startline:startcol:endline:endcol" indicating - * the position of the annotation itself. - */ - String overrideSourcePosition() default ""; - - /** - * Container for {@link UnsupportedAppUsage} that allows it to be applied repeatedly to types. - */ - @Retention(CLASS) - @Target(TYPE) - @interface Container { - UnsupportedAppUsage[] value(); - } -} diff --git a/core/java/android/app/AlarmManager.java b/core/java/android/app/AlarmManager.java index a0040ffd13fa..b669d775b3c1 100644 --- a/core/java/android/app/AlarmManager.java +++ b/core/java/android/app/AlarmManager.java @@ -35,7 +35,7 @@ import android.util.ArrayMap; import android.util.Log; import android.util.proto.ProtoOutputStream; -import libcore.timezone.ZoneInfoDB; +import libcore.timezone.ZoneInfoDb; import java.io.IOException; import java.lang.annotation.Retention; @@ -1000,7 +1000,7 @@ public class AlarmManager { if (mTargetSdkVersion >= Build.VERSION_CODES.M) { boolean hasTimeZone = false; try { - hasTimeZone = ZoneInfoDB.getInstance().hasTimeZone(timeZone); + hasTimeZone = ZoneInfoDb.getInstance().hasTimeZone(timeZone); } catch (IOException ignored) { } diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index 81f6d28db9fe..2e144461c444 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -30,8 +30,10 @@ import android.app.role.RoleControllerManager; import android.app.role.RoleManager; import android.app.slice.SliceManager; import android.app.timedetector.TimeDetector; +import android.app.timedetector.TimeDetectorImpl; import android.app.timezone.RulesManager; import android.app.timezonedetector.TimeZoneDetector; +import android.app.timezonedetector.TimeZoneDetectorImpl; import android.app.trust.TrustManager; import android.app.usage.IStorageStatsManager; import android.app.usage.IUsageStatsManager; @@ -1277,7 +1279,7 @@ final class SystemServiceRegistry { @Override public TimeDetector createService(ContextImpl ctx) throws ServiceNotFoundException { - return new TimeDetector(); + return new TimeDetectorImpl(); }}); registerService(Context.TIME_ZONE_DETECTOR_SERVICE, TimeZoneDetector.class, @@ -1285,7 +1287,7 @@ final class SystemServiceRegistry { @Override public TimeZoneDetector createService(ContextImpl ctx) throws ServiceNotFoundException { - return new TimeZoneDetector(); + return new TimeZoneDetectorImpl(); }}); registerService(Context.TELEPHONY_IMS_SERVICE, android.telephony.ims.ImsManager.class, diff --git a/core/java/android/app/timedetector/TimeDetector.java b/core/java/android/app/timedetector/TimeDetector.java index 7c29f017c02b..2412fb3994ed 100644 --- a/core/java/android/app/timedetector/TimeDetector.java +++ b/core/java/android/app/timedetector/TimeDetector.java @@ -21,31 +21,29 @@ import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.SystemService; import android.content.Context; -import android.os.RemoteException; -import android.os.ServiceManager; -import android.os.ServiceManager.ServiceNotFoundException; import android.os.SystemClock; import android.os.TimestampedValue; -import android.util.Log; /** * The interface through which system components can send signals to the TimeDetectorService. * - * <p>This class is marked non-final for mockito. * @hide */ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) @SystemService(Context.TIME_DETECTOR_SERVICE) -public class TimeDetector { - private static final String TAG = "timedetector.TimeDetector"; - private static final boolean DEBUG = false; +public interface TimeDetector { - private final ITimeDetectorService mITimeDetectorService; - - /** @hide */ - public TimeDetector() throws ServiceNotFoundException { - mITimeDetectorService = ITimeDetectorService.Stub.asInterface( - ServiceManager.getServiceOrThrow(Context.TIME_DETECTOR_SERVICE)); + /** + * A shared utility method to create a {@link ManualTimeSuggestion}. + * + * @hide + */ + static ManualTimeSuggestion createManualTimeSuggestion(long when, String why) { + TimestampedValue<Long> utcTime = + new TimestampedValue<>(SystemClock.elapsedRealtime(), when); + ManualTimeSuggestion manualTimeSuggestion = new ManualTimeSuggestion(utcTime); + manualTimeSuggestion.addDebugInfo(why); + return manualTimeSuggestion; } /** @@ -54,16 +52,7 @@ public class TimeDetector { * were determined more recently. */ @RequiresPermission(android.Manifest.permission.SUGGEST_PHONE_TIME_AND_ZONE) - public void suggestPhoneTime(@NonNull PhoneTimeSuggestion timeSuggestion) { - if (DEBUG) { - Log.d(TAG, "suggestPhoneTime called: " + timeSuggestion); - } - try { - mITimeDetectorService.suggestPhoneTime(timeSuggestion); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } + void suggestPhoneTime(@NonNull PhoneTimeSuggestion timeSuggestion); /** * Suggests the user's manually entered current time to the detector. @@ -71,29 +60,7 @@ public class TimeDetector { * @hide */ @RequiresPermission(android.Manifest.permission.SUGGEST_MANUAL_TIME_AND_ZONE) - public void suggestManualTime(@NonNull ManualTimeSuggestion timeSuggestion) { - if (DEBUG) { - Log.d(TAG, "suggestManualTime called: " + timeSuggestion); - } - try { - mITimeDetectorService.suggestManualTime(timeSuggestion); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * A shared utility method to create a {@link ManualTimeSuggestion}. - * - * @hide - */ - public static ManualTimeSuggestion createManualTimeSuggestion(long when, String why) { - TimestampedValue<Long> utcTime = - new TimestampedValue<>(SystemClock.elapsedRealtime(), when); - ManualTimeSuggestion manualTimeSuggestion = new ManualTimeSuggestion(utcTime); - manualTimeSuggestion.addDebugInfo(why); - return manualTimeSuggestion; - } + void suggestManualTime(@NonNull ManualTimeSuggestion timeSuggestion); /** * Suggests the time according to a network time source like NTP. @@ -101,14 +68,5 @@ public class TimeDetector { * @hide */ @RequiresPermission(android.Manifest.permission.SET_TIME) - public void suggestNetworkTime(NetworkTimeSuggestion timeSuggestion) { - if (DEBUG) { - Log.d(TAG, "suggestNetworkTime called: " + timeSuggestion); - } - try { - mITimeDetectorService.suggestNetworkTime(timeSuggestion); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } + void suggestNetworkTime(NetworkTimeSuggestion timeSuggestion); } diff --git a/core/java/android/app/timedetector/TimeDetectorImpl.java b/core/java/android/app/timedetector/TimeDetectorImpl.java new file mode 100644 index 000000000000..1683817740c3 --- /dev/null +++ b/core/java/android/app/timedetector/TimeDetectorImpl.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.app.timedetector; + +import android.annotation.NonNull; +import android.content.Context; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.os.ServiceManager.ServiceNotFoundException; +import android.util.Log; + +/** + * The real implementation of {@link TimeDetector}. + * + * @hide + */ +public final class TimeDetectorImpl implements TimeDetector { + private static final String TAG = "timedetector.TimeDetector"; + private static final boolean DEBUG = false; + + private final ITimeDetectorService mITimeDetectorService; + + public TimeDetectorImpl() throws ServiceNotFoundException { + mITimeDetectorService = ITimeDetectorService.Stub.asInterface( + ServiceManager.getServiceOrThrow(Context.TIME_DETECTOR_SERVICE)); + } + + @Override + public void suggestPhoneTime(@NonNull PhoneTimeSuggestion timeSuggestion) { + if (DEBUG) { + Log.d(TAG, "suggestPhoneTime called: " + timeSuggestion); + } + try { + mITimeDetectorService.suggestPhoneTime(timeSuggestion); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + @Override + public void suggestManualTime(@NonNull ManualTimeSuggestion timeSuggestion) { + if (DEBUG) { + Log.d(TAG, "suggestManualTime called: " + timeSuggestion); + } + try { + mITimeDetectorService.suggestManualTime(timeSuggestion); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + @Override + public void suggestNetworkTime(NetworkTimeSuggestion timeSuggestion) { + if (DEBUG) { + Log.d(TAG, "suggestNetworkTime called: " + timeSuggestion); + } + try { + mITimeDetectorService.suggestNetworkTime(timeSuggestion); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } +} diff --git a/core/java/android/app/timezonedetector/TimeZoneDetector.java b/core/java/android/app/timezonedetector/TimeZoneDetector.java index 5b5f311264e3..b4f608787d4a 100644 --- a/core/java/android/app/timezonedetector/TimeZoneDetector.java +++ b/core/java/android/app/timezonedetector/TimeZoneDetector.java @@ -21,29 +21,25 @@ import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.SystemService; import android.content.Context; -import android.os.RemoteException; -import android.os.ServiceManager; -import android.os.ServiceManager.ServiceNotFoundException; -import android.util.Log; /** * The interface through which system components can send signals to the TimeZoneDetectorService. * - * <p>This class is non-final for mockito. * @hide */ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) @SystemService(Context.TIME_ZONE_DETECTOR_SERVICE) -public class TimeZoneDetector { - private static final String TAG = "timezonedetector.TimeZoneDetector"; - private static final boolean DEBUG = false; +public interface TimeZoneDetector { - private final ITimeZoneDetectorService mITimeZoneDetectorService; - - /** @hide */ - public TimeZoneDetector() throws ServiceNotFoundException { - mITimeZoneDetectorService = ITimeZoneDetectorService.Stub.asInterface( - ServiceManager.getServiceOrThrow(Context.TIME_ZONE_DETECTOR_SERVICE)); + /** + * A shared utility method to create a {@link ManualTimeZoneSuggestion}. + * + * @hide + */ + static ManualTimeZoneSuggestion createManualTimeZoneSuggestion(String tzId, String debugInfo) { + ManualTimeZoneSuggestion suggestion = new ManualTimeZoneSuggestion(tzId); + suggestion.addDebugInfo(debugInfo); + return suggestion; } /** @@ -55,16 +51,7 @@ public class TimeZoneDetector { */ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) @RequiresPermission(android.Manifest.permission.SUGGEST_PHONE_TIME_AND_ZONE) - public void suggestPhoneTimeZone(@NonNull PhoneTimeZoneSuggestion timeZoneSuggestion) { - if (DEBUG) { - Log.d(TAG, "suggestPhoneTimeZone called: " + timeZoneSuggestion); - } - try { - mITimeZoneDetectorService.suggestPhoneTimeZone(timeZoneSuggestion); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } + void suggestPhoneTimeZone(@NonNull PhoneTimeZoneSuggestion timeZoneSuggestion); /** * Suggests the current time zone, determined for the user's manually information, to the @@ -73,25 +60,5 @@ public class TimeZoneDetector { * @hide */ @RequiresPermission(android.Manifest.permission.SUGGEST_MANUAL_TIME_AND_ZONE) - public void suggestManualTimeZone(@NonNull ManualTimeZoneSuggestion timeZoneSuggestion) { - if (DEBUG) { - Log.d(TAG, "suggestManualTimeZone called: " + timeZoneSuggestion); - } - try { - mITimeZoneDetectorService.suggestManualTimeZone(timeZoneSuggestion); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * A shared utility method to create a {@link ManualTimeZoneSuggestion}. - * - * @hide - */ - public static ManualTimeZoneSuggestion createManualTimeZoneSuggestion(String tzId, String why) { - ManualTimeZoneSuggestion suggestion = new ManualTimeZoneSuggestion(tzId); - suggestion.addDebugInfo(why); - return suggestion; - } + void suggestManualTimeZone(@NonNull ManualTimeZoneSuggestion timeZoneSuggestion); } diff --git a/core/java/android/app/timezonedetector/TimeZoneDetectorImpl.java b/core/java/android/app/timezonedetector/TimeZoneDetectorImpl.java new file mode 100644 index 000000000000..27b8374db172 --- /dev/null +++ b/core/java/android/app/timezonedetector/TimeZoneDetectorImpl.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.app.timezonedetector; + +import android.annotation.NonNull; +import android.content.Context; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.os.ServiceManager.ServiceNotFoundException; +import android.util.Log; + +/** + * The real implementation of {@link TimeZoneDetector}. + * + * @hide + */ +public final class TimeZoneDetectorImpl implements TimeZoneDetector { + private static final String TAG = "timezonedetector.TimeZoneDetector"; + private static final boolean DEBUG = false; + + private final ITimeZoneDetectorService mITimeZoneDetectorService; + + public TimeZoneDetectorImpl() throws ServiceNotFoundException { + mITimeZoneDetectorService = ITimeZoneDetectorService.Stub.asInterface( + ServiceManager.getServiceOrThrow(Context.TIME_ZONE_DETECTOR_SERVICE)); + } + + @Override + public void suggestPhoneTimeZone(@NonNull PhoneTimeZoneSuggestion timeZoneSuggestion) { + if (DEBUG) { + Log.d(TAG, "suggestPhoneTimeZone called: " + timeZoneSuggestion); + } + try { + mITimeZoneDetectorService.suggestPhoneTimeZone(timeZoneSuggestion); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + @Override + public void suggestManualTimeZone(@NonNull ManualTimeZoneSuggestion timeZoneSuggestion) { + if (DEBUG) { + Log.d(TAG, "suggestManualTimeZone called: " + timeZoneSuggestion); + } + try { + mITimeZoneDetectorService.suggestManualTimeZone(timeZoneSuggestion); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } +} diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 8fa00abb3bcf..c3c7f972066b 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -4022,16 +4022,16 @@ public abstract class Context { public static final String LOWPAN_SERVICE = "lowpan"; /** - * Use with {@link #getSystemService(String)} to retrieve a {@link - * android.net.EthernetManager} for handling management of - * Ethernet access. + * Use with {@link #getSystemService(String)} to retrieve a {@link android.net.EthernetManager} + * for handling management of Ethernet access. * * @see #getSystemService(String) * @see android.net.EthernetManager * * @hide */ - @UnsupportedAppUsage + @SystemApi + @TestApi public static final String ETHERNET_SERVICE = "ethernet"; /** diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java index 67fdda37ed3b..b0d0b4c16873 100644 --- a/core/java/android/hardware/usb/UsbManager.java +++ b/core/java/android/hardware/usb/UsbManager.java @@ -262,6 +262,15 @@ public class UsbManager { public static final String USB_FUNCTION_ACCESSORY = "accessory"; /** + * Name of the NCM USB function. + * Used in extras for the {@link #ACTION_USB_STATE} broadcast + * + * {@hide} + */ + @SystemApi + public static final String USB_FUNCTION_NCM = "ncm"; + + /** * Name of extra for {@link #ACTION_USB_PORT_CHANGED} * containing the {@link UsbPort} object for the port. * @@ -367,8 +376,15 @@ public class UsbManager { */ public static final long FUNCTION_ADB = GadgetFunction.ADB; + /** + * Code for the ncm source usb function. + * {@hide} + */ + @SystemApi + public static final long FUNCTION_NCM = 1 << 10; + private static final long SETTABLE_FUNCTIONS = FUNCTION_MTP | FUNCTION_PTP | FUNCTION_RNDIS - | FUNCTION_MIDI; + | FUNCTION_MIDI | FUNCTION_NCM; private static final Map<String, Long> FUNCTION_NAME_TO_CODE = new HashMap<>(); @@ -380,6 +396,7 @@ public class UsbManager { FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_ACCESSORY, FUNCTION_ACCESSORY); FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_AUDIO_SOURCE, FUNCTION_AUDIO_SOURCE); FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_ADB, FUNCTION_ADB); + FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_NCM, FUNCTION_NCM); } private final Context mContext; @@ -935,6 +952,9 @@ public class UsbManager { if ((functions & FUNCTION_AUDIO_SOURCE) != 0) { joiner.add(UsbManager.USB_FUNCTION_AUDIO_SOURCE); } + if ((functions & FUNCTION_NCM) != 0) { + joiner.add(UsbManager.USB_FUNCTION_NCM); + } if ((functions & FUNCTION_ADB) != 0) { joiner.add(UsbManager.USB_FUNCTION_ADB); } diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java index fd015b4fe52c..a3899b705c1b 100644 --- a/core/java/android/net/EthernetManager.java +++ b/core/java/android/net/EthernetManager.java @@ -16,7 +16,10 @@ package android.net; +import android.annotation.NonNull; +import android.annotation.SystemApi; import android.annotation.SystemService; +import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.os.Handler; @@ -24,12 +27,15 @@ import android.os.Message; import android.os.RemoteException; import java.util.ArrayList; +import java.util.Objects; /** * A class representing the IP configuration of the Ethernet network. * * @hide */ +@SystemApi +@TestApi @SystemService(Context.ETHERNET_SERVICE) public class EthernetManager { private static final String TAG = "EthernetManager"; @@ -37,7 +43,7 @@ public class EthernetManager { private final Context mContext; private final IEthernetManager mService; - private final Handler mHandler = new Handler() { + private final Handler mHandler = new Handler(ConnectivityThread.getInstanceLooper()) { @Override public void handleMessage(Message msg) { if (msg.what == MSG_AVAILABILITY_CHANGED) { @@ -60,12 +66,14 @@ public class EthernetManager { /** * A listener interface to receive notification on changes in Ethernet. + * @hide */ public interface Listener { /** * Called when Ethernet port's availability is changed. * @param iface Ethernet interface name * @param isAvailable {@code true} if Ethernet port exists. + * @hide */ @UnsupportedAppUsage void onAvailabilityChanged(String iface, boolean isAvailable); @@ -76,6 +84,7 @@ public class EthernetManager { * Applications will almost always want to use * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve * the standard {@link android.content.Context#ETHERNET_SERVICE Context.ETHERNET_SERVICE}. + * @hide */ public EthernetManager(Context context, IEthernetManager service) { mContext = context; @@ -85,6 +94,7 @@ public class EthernetManager { /** * Get Ethernet configuration. * @return the Ethernet Configuration, contained in {@link IpConfiguration}. + * @hide */ @UnsupportedAppUsage public IpConfiguration getConfiguration(String iface) { @@ -97,6 +107,7 @@ public class EthernetManager { /** * Set Ethernet configuration. + * @hide */ @UnsupportedAppUsage public void setConfiguration(String iface, IpConfiguration config) { @@ -109,6 +120,7 @@ public class EthernetManager { /** * Indicates whether the system currently has one or more Ethernet interfaces. + * @hide */ @UnsupportedAppUsage public boolean isAvailable() { @@ -119,6 +131,7 @@ public class EthernetManager { * Indicates whether the system has given interface. * * @param iface Ethernet interface name + * @hide */ @UnsupportedAppUsage public boolean isAvailable(String iface) { @@ -133,6 +146,7 @@ public class EthernetManager { * Adds a listener. * @param listener A {@link Listener} to add. * @throws IllegalArgumentException If the listener is null. + * @hide */ @UnsupportedAppUsage public void addListener(Listener listener) { @@ -151,6 +165,7 @@ public class EthernetManager { /** * Returns an array of available Ethernet interface names. + * @hide */ @UnsupportedAppUsage public String[] getAvailableInterfaces() { @@ -165,6 +180,7 @@ public class EthernetManager { * Removes a listener. * @param listener A {@link Listener} to remove. * @throws IllegalArgumentException If the listener is null. + * @hide */ @UnsupportedAppUsage public void removeListener(Listener listener) { @@ -180,4 +196,78 @@ public class EthernetManager { } } } + + /** + * A request for a tethered interface. + */ + public static class TetheredInterfaceRequest { + private final IEthernetManager mService; + private final ITetheredInterfaceCallback mCb; + + private TetheredInterfaceRequest(@NonNull IEthernetManager service, + @NonNull ITetheredInterfaceCallback cb) { + this.mService = service; + this.mCb = cb; + } + + /** + * Release the request, causing the interface to revert back from tethering mode if there + * is no other requestor. + */ + public void release() { + try { + mService.releaseTetheredInterface(mCb); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + } + + /** + * Callback for {@link #requestTetheredInterface(TetheredInterfaceCallback)}. + */ + public interface TetheredInterfaceCallback { + /** + * Called when the tethered interface is available. + * @param iface The name of the interface. + */ + void onAvailable(@NonNull String iface); + + /** + * Called when the tethered interface is now unavailable. + */ + void onUnavailable(); + } + + /** + * Request a tethered interface in tethering mode. + * + * <p>When this method is called and there is at least one ethernet interface available, the + * system will designate one to act as a tethered interface. If there is already a tethered + * interface, the existing interface will be used. + * @param callback A callback to be called once the request has been fulfilled. + */ + @NonNull + public TetheredInterfaceRequest requestTetheredInterface( + @NonNull TetheredInterfaceCallback callback) { + Objects.requireNonNull(callback, "Callback must be non-null"); + final ITetheredInterfaceCallback cbInternal = new ITetheredInterfaceCallback.Stub() { + @Override + public void onAvailable(String iface) { + callback.onAvailable(iface); + } + + @Override + public void onUnavailable() { + callback.onUnavailable(); + } + }; + + try { + mService.requestTetheredInterface(cbInternal); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + return new TetheredInterfaceRequest(mService, cbInternal); + } } diff --git a/core/java/android/net/IEthernetManager.aidl b/core/java/android/net/IEthernetManager.aidl index 94960b51d329..ccc6e352098f 100644 --- a/core/java/android/net/IEthernetManager.aidl +++ b/core/java/android/net/IEthernetManager.aidl @@ -18,6 +18,7 @@ package android.net; import android.net.IpConfiguration; import android.net.IEthernetServiceListener; +import android.net.ITetheredInterfaceCallback; /** * Interface that answers queries about, and allows changing @@ -32,4 +33,6 @@ interface IEthernetManager boolean isAvailable(String iface); void addListener(in IEthernetServiceListener listener); void removeListener(in IEthernetServiceListener listener); + void requestTetheredInterface(in ITetheredInterfaceCallback callback); + void releaseTetheredInterface(in ITetheredInterfaceCallback callback); } diff --git a/core/java/android/net/ITetheredInterfaceCallback.aidl b/core/java/android/net/ITetheredInterfaceCallback.aidl new file mode 100644 index 000000000000..e3d075988c8a --- /dev/null +++ b/core/java/android/net/ITetheredInterfaceCallback.aidl @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +/** @hide */ +interface ITetheredInterfaceCallback { + void onAvailable(in String iface); + void onUnavailable(); +}
\ No newline at end of file diff --git a/core/java/android/net/RouteInfo.java b/core/java/android/net/RouteInfo.java index ea6002ca29e6..67bad532cd0d 100644 --- a/core/java/android/net/RouteInfo.java +++ b/core/java/android/net/RouteInfo.java @@ -104,6 +104,11 @@ public final class RouteInfo implements Parcelable { */ private final int mType; + /** + * The maximum transmission unit size for this route. + */ + private final int mMtu; + // Derived data members. // TODO: remove these. @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) @@ -132,6 +137,31 @@ public final class RouteInfo implements Parcelable { @TestApi public RouteInfo(@Nullable IpPrefix destination, @Nullable InetAddress gateway, @Nullable String iface, @RouteType int type) { + this(destination, gateway, iface, type, 0); + } + + /** + * Constructs a RouteInfo object. + * + * If destination is null, then gateway must be specified and the + * constructed route is either the IPv4 default route <code>0.0.0.0</code> + * if the gateway is an instance of {@link Inet4Address}, or the IPv6 default + * route <code>::/0</code> if gateway is an instance of + * {@link Inet6Address}. + * <p> + * destination and gateway may not both be null. + * + * @param destination the destination prefix + * @param gateway the IP address to route packets through + * @param iface the interface name to send packets on + * @param type the type of this route + * @param mtu the maximum transmission unit size for this route + * + * @hide + */ + @SystemApi + public RouteInfo(@Nullable IpPrefix destination, @Nullable InetAddress gateway, + @Nullable String iface, @RouteType int type, int mtu) { switch (type) { case RTN_UNICAST: case RTN_UNREACHABLE: @@ -161,7 +191,7 @@ public final class RouteInfo implements Parcelable { } else { // no destination, no gateway. invalid. throw new IllegalArgumentException("Invalid arguments passed in: " + gateway + "," + - destination); + destination); } } // TODO: set mGateway to null if there is no gateway. This is more correct, saves space, and @@ -176,10 +206,10 @@ public final class RouteInfo implements Parcelable { } mHasGateway = (!gateway.isAnyLocalAddress()); - if ((destination.getAddress() instanceof Inet4Address && - (gateway instanceof Inet4Address == false)) || - (destination.getAddress() instanceof Inet6Address && - (gateway instanceof Inet6Address == false))) { + if ((destination.getAddress() instanceof Inet4Address + && !(gateway instanceof Inet4Address)) + || (destination.getAddress() instanceof Inet6Address + && !(gateway instanceof Inet6Address))) { throw new IllegalArgumentException("address family mismatch in RouteInfo constructor"); } mDestination = destination; // IpPrefix objects are immutable. @@ -187,6 +217,7 @@ public final class RouteInfo implements Parcelable { mInterface = iface; // Strings are immutable. mType = type; mIsHost = isHost(); + mMtu = mtu; } /** @@ -373,6 +404,17 @@ public final class RouteInfo implements Parcelable { } /** + * Retrieves the MTU size for this route. + * + * @return The MTU size, or 0 if it has not been set. + * @hide + */ + @SystemApi + public int getMtu() { + return mMtu; + } + + /** * Indicates if this route is a default route (ie, has no destination specified). * * @return {@code true} if the destination has a prefix length of 0. @@ -476,6 +518,7 @@ public final class RouteInfo implements Parcelable { val += " unknown type " + mType; } } + val += " mtu " + mMtu; return val; } @@ -493,7 +536,7 @@ public final class RouteInfo implements Parcelable { return Objects.equals(mDestination, target.getDestination()) && Objects.equals(mGateway, target.getGateway()) && Objects.equals(mInterface, target.getInterface()) && - mType == target.getType(); + mType == target.getType() && mMtu == target.getMtu(); } /** @@ -503,7 +546,7 @@ public final class RouteInfo implements Parcelable { return (mDestination.hashCode() * 41) + (mGateway == null ? 0 :mGateway.hashCode() * 47) + (mInterface == null ? 0 :mInterface.hashCode() * 67) - + (mType * 71); + + (mType * 71) + (mMtu * 89); } /** @@ -522,6 +565,7 @@ public final class RouteInfo implements Parcelable { dest.writeByteArray(gatewayBytes); dest.writeString(mInterface); dest.writeInt(mType); + dest.writeInt(mMtu); } /** @@ -540,8 +584,9 @@ public final class RouteInfo implements Parcelable { String iface = in.readString(); int type = in.readInt(); + int mtu = in.readInt(); - return new RouteInfo(dest, gateway, iface, type); + return new RouteInfo(dest, gateway, iface, type, mtu); } public RouteInfo[] newArray(int size) { diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java index febc36cbe47b..68c2764a78d7 100644 --- a/core/java/android/os/PowerManager.java +++ b/core/java/android/os/PowerManager.java @@ -1409,6 +1409,7 @@ public final class PowerManager { * @throws UnsupportedOperationException if userspace reboot was requested on a device that * doesn't support it. */ + @RequiresPermission(permission.REBOOT) public void reboot(@Nullable String reason) { if (REBOOT_USERSPACE.equals(reason) && !isRebootingUserspaceSupported()) { throw new UnsupportedOperationException( @@ -1428,6 +1429,7 @@ public final class PowerManager { * </p> * @hide */ + @RequiresPermission(permission.REBOOT) public void rebootSafeMode() { try { mService.rebootSafeMode(false, true); diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java index 9ffeff99e153..a0e92b398c4e 100644 --- a/core/java/android/provider/CallLog.java +++ b/core/java/android/provider/CallLog.java @@ -232,6 +232,9 @@ public class CallLog { /** Call was on RTT at some point */ public static final int FEATURES_RTT = 1 << 5; + /** Call was VoLTE */ + public static final int FEATURES_VOLTE = 1 << 6; + /** * The phone number as the user entered it. * <P>Type: TEXT</P> diff --git a/core/java/android/telephony/CellBroadcastIntents.java b/core/java/android/telephony/CellBroadcastIntents.java index 8446253c6302..2e0810835a52 100644 --- a/core/java/android/telephony/CellBroadcastIntents.java +++ b/core/java/android/telephony/CellBroadcastIntents.java @@ -16,22 +16,23 @@ package android.telephony; +import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; +import android.app.AppOpsManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; -import android.content.pm.PackageManager; -import android.os.Bundle; import android.os.Handler; import android.os.UserHandle; +import android.provider.Telephony; /** * A static helper class used to send Intents with prepopulated flags. * <p> - * This is intended to be used by the CellBroadcastService and will throw a security exception if - * used from a UID besides the network stack UID. + * This is intended to be used by the CellBroadcastService and does nothing if the caller does not + * have permission to broadcast {@link Telephony.Sms.Intents.SMS_CB_RECEIVED_ACTION}. * * @hide */ @@ -39,6 +40,8 @@ import android.os.UserHandle; public class CellBroadcastIntents { private static final String LOG_TAG = "CellBroadcastIntents"; + private static final String EXTRA_MESSAGE = "message"; + /** * @hide */ @@ -46,50 +49,71 @@ public class CellBroadcastIntents { } /** - * Returns an intent which can be received by background BroadcastReceivers. This is only - * intended to be used by the CellBroadcastService and will throw a security exception if called - * from another UID. + * Broadcasts an SMS_CB_RECEIVED_ACTION intent which can be received by background + * BroadcastReceivers. This is only intended to be used by the CellBroadcastService and will + * do nothing if the caller does not have permission to broadcast + * {@link Telephony.Sms.Intents.SMS_CB_RECEIVED_ACTION}. * * @param context The context from which to send the broadcast * @param user The user from which to send the broadcast - * @param intent The Intent to broadcast; all receivers matching this Intent will - * receive the broadcast. - * @param receiverPermission String naming a permissions that a receiver must hold in order to - * receive your broadcast. If null, no permission is required. - * @param receiverAppOp The app op associated with the broadcast. If null, no appOp is - * required. If both receiverAppOp and receiverPermission are - * non-null, a receiver must have both of them to receive the - * broadcast + * @param smsCbMessage The SmsCbMessage to include with the intent * @param resultReceiver Your own BroadcastReceiver to treat as the final receiver of the * broadcast. * @param scheduler A custom Handler with which to schedule the resultReceiver * callback; if null it will be scheduled in the Context's main * thread. * @param initialCode An initial value for the result code. Often Activity.RESULT_OK. - * @param initialData An initial value for the result data. Often null. - * @param initialExtras An initial value for the result extras. Often null. + * @param slotIndex The slot index to include in the intent */ - public static void sendOrderedBroadcastForBackgroundReceivers(@NonNull Context context, - @Nullable UserHandle user, @NonNull Intent intent, @Nullable String receiverPermission, - @Nullable String receiverAppOp, @Nullable BroadcastReceiver resultReceiver, - @Nullable Handler scheduler, int initialCode, @Nullable String initialData, - @Nullable Bundle initialExtras) { - int status = context.checkCallingOrSelfPermission( - "android.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS"); - if (status == PackageManager.PERMISSION_DENIED) { - throw new SecurityException( - "Caller does not have permission to send broadcast for background receivers"); - } - Intent backgroundIntent = new Intent(intent); + public static void sendSmsCbReceivedBroadcast(@NonNull Context context, + @Nullable UserHandle user, @NonNull SmsCbMessage smsCbMessage, + @Nullable BroadcastReceiver resultReceiver, @Nullable Handler scheduler, + int initialCode, int slotIndex) { + Intent backgroundIntent = new Intent(Telephony.Sms.Intents.SMS_CB_RECEIVED_ACTION); + backgroundIntent.putExtra(EXTRA_MESSAGE, smsCbMessage); backgroundIntent.setFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); + putPhoneIdAndSubIdExtra(context, backgroundIntent, slotIndex); + + String receiverPermission = Manifest.permission.RECEIVE_SMS; + String receiverAppOp = AppOpsManager.OPSTR_RECEIVE_SMS; if (user != null) { context.createContextAsUser(user, 0).sendOrderedBroadcast(backgroundIntent, receiverPermission, receiverAppOp, resultReceiver, scheduler, initialCode, - initialData, initialExtras); + null, null); } else { context.sendOrderedBroadcast(backgroundIntent, receiverPermission, - receiverAppOp, resultReceiver, scheduler, initialCode, initialData, - initialExtras); + receiverAppOp, resultReceiver, scheduler, initialCode, null, null); + } + } + + /** + * Put the phone ID and sub ID into an intent as extras. + */ + private static void putPhoneIdAndSubIdExtra(Context context, Intent intent, int phoneId) { + int subId = getSubIdForPhone(context, phoneId); + if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { + intent.putExtra("subscription", subId); + intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId); + } + intent.putExtra("phone", phoneId); + intent.putExtra(SubscriptionManager.EXTRA_SLOT_INDEX, phoneId); + } + + /** + * Get the subscription ID for a phone ID, or INVALID_SUBSCRIPTION_ID if the phone does not + * have an active sub + * @param phoneId the phoneId to use + * @return the associated sub id + */ + private static int getSubIdForPhone(Context context, int phoneId) { + SubscriptionManager subMan = + (SubscriptionManager) context.getSystemService( + Context.TELEPHONY_SUBSCRIPTION_SERVICE); + int[] subIds = subMan.getSubscriptionIds(phoneId); + if (subIds != null) { + return subIds[0]; + } else { + return SubscriptionManager.INVALID_SUBSCRIPTION_ID; } } } diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java index 03e7361159e1..1d0b4a0ca20a 100644 --- a/core/java/android/telephony/PhoneStateListener.java +++ b/core/java/android/telephony/PhoneStateListener.java @@ -225,6 +225,9 @@ public class PhoneStateListener { /** * Listen for changes to the SRVCC state of the active call. + * + * <p>Requires permission {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE} + * * @see #onServiceStateChanged(ServiceState) * @hide */ @@ -253,6 +256,9 @@ public class PhoneStateListener { /** * Listen for changes to the sim voice activation state + * + * <p>Requires permission {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE} + * * @see TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATING * @see TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATED * @see TelephonyManager#SIM_ACTIVATION_STATE_DEACTIVATED @@ -266,6 +272,7 @@ public class PhoneStateListener { * @hide */ @SystemApi + @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int LISTEN_VOICE_ACTIVATION_STATE = 0x00020000; /** @@ -312,10 +319,13 @@ public class PhoneStateListener { /** * Listen for changes to the radio power state. * + * <p>Requires permission {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE} + * * @see #onRadioPowerStateChanged * @hide */ @SystemApi + @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int LISTEN_RADIO_POWER_STATE_CHANGED = 0x00800000; /** @@ -893,7 +903,6 @@ public class PhoneStateListener { * Callback invoked when phone capability changes. * Note, this callback triggers regardless of registered subscription. * - * Requires the READ_PRIVILEGED_PHONE_STATE permission. * @param capability the new phone capability * @hide */ @@ -923,7 +932,7 @@ public class PhoneStateListener { * subId. Otherwise, this callback applies to * {@link SubscriptionManager#getDefaultSubscriptionId()}. * - * Requires the READ_PRIVILEGED_PHONE_STATE permission. + * Requires the READ_PRECISE_PHONE_STATE permission. * @param callAttributes the call attributes * @hide */ diff --git a/core/java/android/text/format/Time.java b/core/java/android/text/format/Time.java index bab4bc362c0d..248e321df467 100644 --- a/core/java/android/text/format/Time.java +++ b/core/java/android/text/format/Time.java @@ -18,7 +18,7 @@ package android.text.format; import android.util.TimeFormatException; -import libcore.timezone.ZoneInfoDB; +import libcore.timezone.ZoneInfoDb; import libcore.util.ZoneInfo; import java.io.IOException; @@ -1107,9 +1107,9 @@ public class Time { private static ZoneInfo lookupZoneInfo(String timezoneId) { try { - ZoneInfo zoneInfo = ZoneInfoDB.getInstance().makeTimeZone(timezoneId); + ZoneInfo zoneInfo = ZoneInfoDb.getInstance().makeTimeZone(timezoneId); if (zoneInfo == null) { - zoneInfo = ZoneInfoDB.getInstance().makeTimeZone("GMT"); + zoneInfo = ZoneInfoDb.getInstance().makeTimeZone("GMT"); } if (zoneInfo == null) { throw new AssertionError("GMT not found: \"" + timezoneId + "\""); diff --git a/core/java/android/timezone/TelephonyLookup.java b/core/java/android/timezone/TelephonyLookup.java index eebccf4aa577..8a5864e92db1 100644 --- a/core/java/android/timezone/TelephonyLookup.java +++ b/core/java/android/timezone/TelephonyLookup.java @@ -30,9 +30,9 @@ import java.util.Objects; * @hide */ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) -public class TelephonyLookup { +public final class TelephonyLookup { - private static Object sLock = new Object(); + private static final Object sLock = new Object(); @GuardedBy("sLock") private static TelephonyLookup sInstance; diff --git a/core/java/android/timezone/TelephonyNetwork.java b/core/java/android/timezone/TelephonyNetwork.java index ae39fbddfa1c..487b3f2f143b 100644 --- a/core/java/android/timezone/TelephonyNetwork.java +++ b/core/java/android/timezone/TelephonyNetwork.java @@ -27,7 +27,7 @@ import java.util.Objects; * @hide */ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) -public class TelephonyNetwork { +public final class TelephonyNetwork { @NonNull private final libcore.timezone.TelephonyNetwork mDelegate; diff --git a/core/java/android/timezone/TelephonyNetworkFinder.java b/core/java/android/timezone/TelephonyNetworkFinder.java index 079d0882f191..2ddd3d998d8e 100644 --- a/core/java/android/timezone/TelephonyNetworkFinder.java +++ b/core/java/android/timezone/TelephonyNetworkFinder.java @@ -28,7 +28,7 @@ import java.util.Objects; * @hide */ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) -public class TelephonyNetworkFinder { +public final class TelephonyNetworkFinder { @NonNull private final libcore.timezone.TelephonyNetworkFinder mDelegate; diff --git a/core/java/android/timezone/TimeZoneFinder.java b/core/java/android/timezone/TimeZoneFinder.java index 9327b001a9c8..c76bb1d1fd28 100644 --- a/core/java/android/timezone/TimeZoneFinder.java +++ b/core/java/android/timezone/TimeZoneFinder.java @@ -32,7 +32,7 @@ import java.util.Objects; @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) public final class TimeZoneFinder { - private static Object sLock = new Object(); + private static final Object sLock = new Object(); @GuardedBy("sLock") private static TimeZoneFinder sInstance; diff --git a/core/java/android/timezone/TzDataSetVersion.java b/core/java/android/timezone/TzDataSetVersion.java index aba7c4c15903..605155e76c2c 100644 --- a/core/java/android/timezone/TzDataSetVersion.java +++ b/core/java/android/timezone/TzDataSetVersion.java @@ -89,7 +89,7 @@ public final class TzDataSetVersion { * @hide */ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) - public static class TzDataSetException extends Exception { + public static final class TzDataSetException extends Exception { /** Creates an instance with a message. */ public TzDataSetException(String message) { diff --git a/core/java/android/timezone/ZoneInfoDb.java b/core/java/android/timezone/ZoneInfoDb.java index eb191e8e3272..4612a56df117 100644 --- a/core/java/android/timezone/ZoneInfoDb.java +++ b/core/java/android/timezone/ZoneInfoDb.java @@ -32,7 +32,7 @@ import java.util.Objects; @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) public final class ZoneInfoDb { - private static Object sLock = new Object(); + private static final Object sLock = new Object(); @GuardedBy("sLock") private static ZoneInfoDb sInstance; @@ -43,16 +43,16 @@ public final class ZoneInfoDb { public static ZoneInfoDb getInstance() { synchronized (sLock) { if (sInstance == null) { - sInstance = new ZoneInfoDb(libcore.timezone.ZoneInfoDB.getInstance()); + sInstance = new ZoneInfoDb(libcore.timezone.ZoneInfoDb.getInstance()); } } return sInstance; } @NonNull - private final libcore.timezone.ZoneInfoDB mDelegate; + private final libcore.timezone.ZoneInfoDb mDelegate; - private ZoneInfoDb(libcore.timezone.ZoneInfoDB delegate) { + private ZoneInfoDb(libcore.timezone.ZoneInfoDb delegate) { mDelegate = Objects.requireNonNull(delegate); } diff --git a/core/java/android/util/CloseGuard.java b/core/java/android/util/CloseGuard.java index 6ac769623bff..ba504a3b4167 100644 --- a/core/java/android/util/CloseGuard.java +++ b/core/java/android/util/CloseGuard.java @@ -26,7 +26,7 @@ import android.annotation.NonNull; * A simple example: <pre> {@code * class Foo { * - * private final CloseGuard guard = CloseGuard.get(); + * private final CloseGuard guard = new CloseGuard(); * * ... * @@ -64,7 +64,7 @@ import android.annotation.NonNull; * be deferred. For example: <pre> {@code * class Bar { * - * private final CloseGuard guard = CloseGuard.get(); + * private final CloseGuard guard = new CloseGuard(); * * ... * diff --git a/core/java/android/util/TimeUtils.java b/core/java/android/util/TimeUtils.java index dbd3f69e214e..a8a579cea6a3 100644 --- a/core/java/android/util/TimeUtils.java +++ b/core/java/android/util/TimeUtils.java @@ -26,7 +26,7 @@ import android.os.SystemClock; import libcore.timezone.CountryTimeZones; import libcore.timezone.CountryTimeZones.TimeZoneMapping; import libcore.timezone.TimeZoneFinder; -import libcore.timezone.ZoneInfoDB; +import libcore.timezone.ZoneInfoDb; import java.io.PrintWriter; import java.text.SimpleDateFormat; @@ -133,7 +133,7 @@ public class TimeUtils { * during the lifetime of an activity. */ public static String getTimeZoneDatabaseVersion() { - return ZoneInfoDB.getInstance().getVersion(); + return ZoneInfoDb.getInstance().getVersion(); } /** @hide Field length that can hold 999 days of time */ diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 0c0493ba65aa..6960aefd09cf 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -4700,6 +4700,19 @@ <permission android:name="android.permission.ACCESS_SHARED_LIBRARIES" android:protectionLevel="signature|installer" /> + <!-- Allows an app to log compat change usage. + @hide <p>Not for use by third-party applications.</p> --> + <permission android:name="android.permission.LOG_COMPAT_CHANGE" + android:protectionLevel="signature" /> + <!-- Allows an app to read compat change config. + @hide <p>Not for use by third-party applications.</p> --> + <permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG" + android:protectionLevel="signature" /> + <!-- Allows an app to override compat change config. + @hide <p>Not for use by third-party applications.</p> --> + <permission android:name="android.permission.OVERRIDE_COMPAT_CHANGE_CONFIG" + android:protectionLevel="signature" /> + <!-- Allows input events to be monitored. Very dangerous! @hide --> <permission android:name="android.permission.MONITOR_INPUT" android:protectionLevel="signature" /> diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml index f05898561b8a..567581e0ab71 100644 --- a/core/res/res/values/arrays.xml +++ b/core/res/res/values/arrays.xml @@ -165,7 +165,7 @@ <item>中文 (繁體)</item> </string-array> - <array name="sim_colors"> + <array name="simColors"> <item>@color/Teal_700</item> <item>@color/Blue_700</item> <item>@color/Indigo_700</item> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index fb54566fc959..8a7b515ee436 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -3021,6 +3021,10 @@ <public-group type="color" first-id="0x0106001d"> </public-group> + <public-group type="array" first-id="0x01070006"> + <!-- @hide @SystemApi --> + <public name="simColors" /> + </public-group> <!-- =============================================================== DO NOT ADD UN-GROUPED ITEMS HERE diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index cd43e9fca526..001d7c0118cb 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1303,7 +1303,7 @@ <java-symbol type="array" name="preloaded_color_state_lists" /> <java-symbol type="array" name="preloaded_drawables" /> <java-symbol type="array" name="preloaded_freeform_multi_window_drawables" /> - <java-symbol type="array" name="sim_colors" /> + <java-symbol type="array" name="simColors" /> <java-symbol type="array" name="special_locale_codes" /> <java-symbol type="array" name="special_locale_names" /> <java-symbol type="array" name="supported_locales" /> diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml index eec2072c6d5d..7f9a4ecb0171 100644 --- a/data/etc/privapp-permissions-platform.xml +++ b/data/etc/privapp-permissions-platform.xml @@ -343,6 +343,9 @@ applications that come with the platform <permission name="android.permission.CONTROL_INCALL_EXPERIENCE"/> <!-- Permission required for Tethering CTS tests. --> <permission name="android.permission.TETHER_PRIVILEGED"/> + <!-- Permissions required to test ambient display. --> + <permission name="android.permission.READ_DREAM_STATE" /> + <permission name="android.permission.WRITE_DREAM_STATE" /> </privapp-permissions> <privapp-permissions package="com.android.statementservice"> diff --git a/media/java/android/media/audiopolicy/AudioVolumeGroupChangeHandler.java b/media/java/android/media/audiopolicy/AudioVolumeGroupChangeHandler.java index 074188e01000..adf4d3dcfa09 100644 --- a/media/java/android/media/audiopolicy/AudioVolumeGroupChangeHandler.java +++ b/media/java/android/media/audiopolicy/AudioVolumeGroupChangeHandler.java @@ -157,9 +157,7 @@ public class AudioVolumeGroupChangeHandler { Handler handler = eventHandler.handler(); if (handler != null) { Message m = handler.obtainMessage(what, arg1, arg2, obj); - if (what != AUDIOVOLUMEGROUP_EVENT_NEW_LISTENER) { - handler.removeMessages(what); - } + // Do not remove previous messages, as we would lose notification of group changes handler.sendMessage(m); } } diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index af2569dcb1f2..5a5a7576484e 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -108,6 +108,7 @@ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_MEDIA_STORAGE" /> + <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" /> <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" /> <uses-permission android:name="android.permission.CREATE_USERS" /> @@ -219,6 +220,10 @@ <!-- Permission required for CTS test - TetheringManagerTest --> <uses-permission android:name="android.permission.TETHER_PRIVILEGED"/> + <!-- Permissions required to test ambient display. --> + <uses-permission android:name="android.permission.READ_DREAM_STATE"/> + <uses-permission android:name="android.permission.WRITE_DREAM_STATE"/> + <application android:label="@string/app_label" android:theme="@android:style/Theme.DeviceDefault.DayNight" android:defaultToDeviceProtectedStorage="true" diff --git a/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java b/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java index 8dacecc4ff2a..37ce1d57da36 100644 --- a/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java +++ b/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java @@ -130,6 +130,18 @@ public class TetheringManager { */ public static final int TETHERING_WIFI_P2P = 3; + /** + * Ncm local tethering type. + * @see #startTethering(TetheringRequest, Executor, StartTetheringCallback) + */ + public static final int TETHERING_NCM = 4; + + /** + * Ethernet tethering type. + * @see #startTethering(TetheringRequest, Executor, StartTetheringCallback) + */ + public static final int TETHERING_ETHERNET = 5; + public static final int TETHER_ERROR_NO_ERROR = 0; public static final int TETHER_ERROR_UNKNOWN_IFACE = 1; public static final int TETHER_ERROR_SERVICE_UNAVAIL = 2; diff --git a/packages/Tethering/res/values/config.xml b/packages/Tethering/res/values/config.xml index 6fa1f77bdd38..379cd180d483 100644 --- a/packages/Tethering/res/values/config.xml +++ b/packages/Tethering/res/values/config.xml @@ -29,6 +29,12 @@ </string-array> <!-- List of regexpressions describing the interface (if any) that represent tetherable + NCM interfaces. If the device doesn't want to support tethering over NCM this should + be empty. --> + <string-array translatable="false" name="config_tether_ncm_regexs"> + </string-array> + + <!-- List of regexpressions describing the interface (if any) that represent tetherable Wifi interfaces. If the device doesn't want to support tethering over Wifi this should be empty. An example would be "softap.*" --> <string-array translatable="false" name="config_tether_wifi_regexs"> diff --git a/packages/Tethering/res/values/overlayable.xml b/packages/Tethering/res/values/overlayable.xml index e089d9d19950..fe025c7ac993 100644 --- a/packages/Tethering/res/values/overlayable.xml +++ b/packages/Tethering/res/values/overlayable.xml @@ -17,6 +17,7 @@ <overlayable name="TetheringConfig"> <policy type="product|system|vendor"> <item type="array" name="config_tether_usb_regexs"/> + <item type="array" name="config_tether_ncm_regexs" /> <item type="array" name="config_tether_wifi_regexs"/> <item type="array" name="config_tether_wifi_p2p_regexs"/> <item type="array" name="config_tether_bluetooth_regexs"/> diff --git a/packages/Tethering/src/android/net/dhcp/DhcpServerCallbacks.java b/packages/Tethering/src/android/net/dhcp/DhcpServerCallbacks.java index 7c41377985d3..9fda1257b4c9 100644 --- a/packages/Tethering/src/android/net/dhcp/DhcpServerCallbacks.java +++ b/packages/Tethering/src/android/net/dhcp/DhcpServerCallbacks.java @@ -28,4 +28,9 @@ public abstract class DhcpServerCallbacks extends IDhcpServerCallbacks.Stub { public int getInterfaceVersion() { return IDhcpServerCallbacks.VERSION; } + + @Override + public String getInterfaceHash() { + return IDhcpServerCallbacks.HASH; + } } diff --git a/packages/Tethering/src/android/net/ip/IpServer.java b/packages/Tethering/src/android/net/ip/IpServer.java index 0491ad7c3413..f39e7af43ee6 100644 --- a/packages/Tethering/src/android/net/ip/IpServer.java +++ b/packages/Tethering/src/android/net/ip/IpServer.java @@ -93,6 +93,8 @@ public class IpServer extends StateMachine { private static final int WIFI_HOST_IFACE_PREFIX_LENGTH = 24; private static final String WIFI_P2P_IFACE_ADDR = "192.168.49.1"; private static final int WIFI_P2P_IFACE_PREFIX_LENGTH = 24; + private static final String ETHERNET_IFACE_ADDR = "192.168.50.1"; + private static final int ETHERNET_IFACE_PREFIX_LENGTH = 24; // TODO: have PanService use some visible version of this constant private static final String BLUETOOTH_IFACE_ADDR = "192.168.44.1"; @@ -299,6 +301,11 @@ public class IpServer extends StateMachine { public int getInterfaceVersion() { return this.VERSION; } + + @Override + public String getInterfaceHash() { + return this.HASH; + } } private class DhcpServerCallbacksImpl extends DhcpServerCallbacks { @@ -416,7 +423,8 @@ public class IpServer extends StateMachine { final Inet4Address srvAddr; int prefixLen = 0; try { - if (mInterfaceType == TetheringManager.TETHERING_USB) { + if (mInterfaceType == TetheringManager.TETHERING_USB + || mInterfaceType == TetheringManager.TETHERING_NCM) { srvAddr = (Inet4Address) parseNumericAddress(USB_NEAR_IFACE_ADDR); prefixLen = USB_PREFIX_LENGTH; } else if (mInterfaceType == TetheringManager.TETHERING_WIFI) { @@ -425,6 +433,10 @@ public class IpServer extends StateMachine { } else if (mInterfaceType == TetheringManager.TETHERING_WIFI_P2P) { srvAddr = (Inet4Address) parseNumericAddress(WIFI_P2P_IFACE_ADDR); prefixLen = WIFI_P2P_IFACE_PREFIX_LENGTH; + } else if (mInterfaceType == TetheringManager.TETHERING_ETHERNET) { + // TODO: randomize address for tethering too, similarly to wifi + srvAddr = (Inet4Address) parseNumericAddress(ETHERNET_IFACE_ADDR); + prefixLen = ETHERNET_IFACE_PREFIX_LENGTH; } else { // BT configures the interface elsewhere: only start DHCP. // TODO: make all tethering types behave the same way, and delete the bluetooth diff --git a/packages/Tethering/src/android/net/util/BaseNetdUnsolicitedEventListener.java b/packages/Tethering/src/android/net/util/BaseNetdUnsolicitedEventListener.java index 3218c0b387bb..b1ffdb01f5f3 100644 --- a/packages/Tethering/src/android/net/util/BaseNetdUnsolicitedEventListener.java +++ b/packages/Tethering/src/android/net/util/BaseNetdUnsolicitedEventListener.java @@ -67,4 +67,9 @@ public class BaseNetdUnsolicitedEventListener extends INetdUnsolicitedEventListe public int getInterfaceVersion() { return INetdUnsolicitedEventListener.VERSION; } + + @Override + public String getInterfaceHash() { + return INetdUnsolicitedEventListener.HASH; + } } diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java b/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java index ce6a43f8f4b5..5b35bb6e713d 100644 --- a/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java +++ b/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java @@ -19,6 +19,7 @@ package com.android.server.connectivity.tethering; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.hardware.usb.UsbManager.USB_CONFIGURED; import static android.hardware.usb.UsbManager.USB_CONNECTED; +import static android.hardware.usb.UsbManager.USB_FUNCTION_NCM; import static android.hardware.usb.UsbManager.USB_FUNCTION_RNDIS; import static android.net.ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED; import static android.net.ConnectivityManager.CONNECTIVITY_ACTION; @@ -29,7 +30,9 @@ import static android.net.TetheringManager.EXTRA_ACTIVE_TETHER; import static android.net.TetheringManager.EXTRA_AVAILABLE_TETHER; import static android.net.TetheringManager.EXTRA_ERRORED_TETHER; import static android.net.TetheringManager.TETHERING_BLUETOOTH; +import static android.net.TetheringManager.TETHERING_ETHERNET; import static android.net.TetheringManager.TETHERING_INVALID; +import static android.net.TetheringManager.TETHERING_NCM; import static android.net.TetheringManager.TETHERING_USB; import static android.net.TetheringManager.TETHERING_WIFI; import static android.net.TetheringManager.TETHERING_WIFI_P2P; @@ -66,6 +69,7 @@ import android.content.IntentFilter; import android.content.res.Resources; import android.hardware.usb.UsbManager; import android.net.ConnectivityManager; +import android.net.EthernetManager; import android.net.IIntResultListener; import android.net.INetd; import android.net.ITetheringEventCallback; @@ -110,6 +114,7 @@ import android.util.SparseArray; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.MessageUtils; @@ -212,6 +217,13 @@ public class Tethering { private boolean mDataSaverEnabled = false; private String mWifiP2pTetherInterface = null; + @GuardedBy("mPublicSync") + private EthernetManager.TetheredInterfaceRequest mEthernetIfaceRequest; + @GuardedBy("mPublicSync") + private String mConfiguredEthernetIface; + @GuardedBy("mPublicSync") + private EthernetCallback mEthernetCallback; + public Tethering(TetheringDependencies deps) { mLog.mark("Tethering.constructed"); mDeps = deps; @@ -408,6 +420,8 @@ public class Tethering { return TETHERING_USB; } else if (cfg.isBluetooth(iface)) { return TETHERING_BLUETOOTH; + } else if (cfg.isNcm(iface)) { + return TETHERING_NCM; } return TETHERING_INVALID; } @@ -456,6 +470,14 @@ public class Tethering { case TETHERING_BLUETOOTH: setBluetoothTethering(enable, listener); break; + case TETHERING_NCM: + result = setNcmTethering(enable); + sendTetherResult(listener, result); + break; + case TETHERING_ETHERNET: + result = setEthernetTethering(enable); + sendTetherResult(listener, result); + break; default: Log.w(TAG, "Invalid tether type."); sendTetherResult(listener, TETHER_ERROR_UNKNOWN_IFACE); @@ -532,6 +554,57 @@ public class Tethering { }, BluetoothProfile.PAN); } + private int setEthernetTethering(final boolean enable) { + final EthernetManager em = (EthernetManager) mContext.getSystemService( + Context.ETHERNET_SERVICE); + synchronized (mPublicSync) { + if (enable) { + mEthernetCallback = new EthernetCallback(); + mEthernetIfaceRequest = em.requestTetheredInterface(mEthernetCallback); + } else { + if (mConfiguredEthernetIface != null) { + stopEthernetTetheringLocked(); + mEthernetIfaceRequest.release(); + } + mEthernetCallback = null; + } + } + return TETHER_ERROR_NO_ERROR; + } + + private void stopEthernetTetheringLocked() { + if (mConfiguredEthernetIface == null) return; + changeInterfaceState(mConfiguredEthernetIface, IpServer.STATE_AVAILABLE); + stopTrackingInterfaceLocked(mConfiguredEthernetIface); + mConfiguredEthernetIface = null; + } + + private class EthernetCallback implements EthernetManager.TetheredInterfaceCallback { + @Override + public void onAvailable(String iface) { + synchronized (mPublicSync) { + if (this != mEthernetCallback) { + // Ethernet callback arrived after Ethernet tethering stopped. Ignore. + return; + } + maybeTrackNewInterfaceLocked(iface, TETHERING_ETHERNET); + changeInterfaceState(iface, IpServer.STATE_TETHERED); + mConfiguredEthernetIface = iface; + } + } + + @Override + public void onUnavailable() { + synchronized (mPublicSync) { + if (this != mEthernetCallback) { + // onAvailable called after stopping Ethernet tethering. + return; + } + stopEthernetTetheringLocked(); + } + } + } + int tether(String iface) { return tether(iface, IpServer.STATE_TETHERED); } @@ -582,6 +655,7 @@ public class Tethering { stopTethering(TETHERING_WIFI_P2P); stopTethering(TETHERING_USB); stopTethering(TETHERING_BLUETOOTH); + stopTethering(TETHERING_ETHERNET); } int getLastTetherError(String iface) { @@ -805,6 +879,7 @@ public class Tethering { final boolean usbConnected = intent.getBooleanExtra(USB_CONNECTED, false); final boolean usbConfigured = intent.getBooleanExtra(USB_CONFIGURED, false); final boolean rndisEnabled = intent.getBooleanExtra(USB_FUNCTION_RNDIS, false); + final boolean ncmEnabled = intent.getBooleanExtra(USB_FUNCTION_NCM, false); mLog.log(String.format("USB bcast connected:%s configured:%s rndis:%s", usbConnected, usbConfigured, rndisEnabled)); @@ -832,6 +907,8 @@ public class Tethering { } else if (usbConfigured && rndisEnabled) { // Tether if rndis is enabled and usb is configured. tetherMatchingInterfaces(IpServer.STATE_TETHERED, TETHERING_USB); + } else if (usbConnected && ncmEnabled) { + tetherMatchingInterfaces(IpServer.STATE_LOCAL_ONLY, TETHERING_NCM); } mRndisEnabled = usbConfigured && rndisEnabled; } @@ -1133,6 +1210,16 @@ public class Tethering { return TETHER_ERROR_NO_ERROR; } + private int setNcmTethering(boolean enable) { + if (VDBG) Log.d(TAG, "setNcmTethering(" + enable + ")"); + UsbManager usbManager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE); + synchronized (mPublicSync) { + usbManager.setCurrentFunctions(enable ? UsbManager.FUNCTION_NCM + : UsbManager.FUNCTION_NONE); + } + return TETHER_ERROR_NO_ERROR; + } + // TODO review API - figure out how to delete these entirely. String[] getTetheredIfaces() { ArrayList<String> list = new ArrayList<String>(); diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringConfiguration.java b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringConfiguration.java index 068c346fbfc1..7e9e26f5af40 100644 --- a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringConfiguration.java +++ b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringConfiguration.java @@ -83,6 +83,7 @@ public class TetheringConfiguration { public final String[] tetherableWifiRegexs; public final String[] tetherableWifiP2pRegexs; public final String[] tetherableBluetoothRegexs; + public final String[] tetherableNcmRegexs; public final boolean isDunRequired; public final boolean chooseUpstreamAutomatically; public final Collection<Integer> preferredUpstreamIfaceTypes; @@ -103,6 +104,7 @@ public class TetheringConfiguration { Resources res = getResources(ctx, activeDataSubId); tetherableUsbRegexs = getResourceStringArray(res, R.array.config_tether_usb_regexs); + tetherableNcmRegexs = getResourceStringArray(res, R.array.config_tether_ncm_regexs); // TODO: Evaluate deleting this altogether now that Wi-Fi always passes // us an interface name. Careful consideration needs to be given to // implications for Settings and for provisioning checks. @@ -156,6 +158,11 @@ public class TetheringConfiguration { return matchesDownstreamRegexs(iface, tetherableBluetoothRegexs); } + /** Check if interface is ncm */ + public boolean isNcm(String iface) { + return matchesDownstreamRegexs(iface, tetherableNcmRegexs); + } + /** Check whether no ui entitlement application is available.*/ public boolean hasMobileHotspotProvisionApp() { return !TextUtils.isEmpty(provisioningAppNoUi); @@ -170,6 +177,7 @@ public class TetheringConfiguration { dumpStringArray(pw, "tetherableWifiRegexs", tetherableWifiRegexs); dumpStringArray(pw, "tetherableWifiP2pRegexs", tetherableWifiP2pRegexs); dumpStringArray(pw, "tetherableBluetoothRegexs", tetherableBluetoothRegexs); + dumpStringArray(pw, "tetherableNcmRegexs", tetherableNcmRegexs); pw.print("isDunRequired: "); pw.println(isDunRequired); diff --git a/packages/Tethering/tests/unit/Android.bp b/packages/Tethering/tests/unit/Android.bp index 53782fed1c50..13174c5bb57a 100644 --- a/packages/Tethering/tests/unit/Android.bp +++ b/packages/Tethering/tests/unit/Android.bp @@ -19,6 +19,7 @@ android_test { certificate: "platform", srcs: [ "src/**/*.java", + "src/**/*.kt", ], test_suites: [ "device-tests", diff --git a/packages/Tethering/tests/unit/AndroidManifest.xml b/packages/Tethering/tests/unit/AndroidManifest.xml index 0a1cdd35b10c..530bc0788a78 100644 --- a/packages/Tethering/tests/unit/AndroidManifest.xml +++ b/packages/Tethering/tests/unit/AndroidManifest.xml @@ -16,6 +16,8 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.networkstack.tethering.tests.unit"> + <uses-permission android:name="android.permission.TETHER_PRIVILEGED"/> + <application android:debuggable="true"> <uses-library android:name="android.test.runner" /> </application> diff --git a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java index e6a552166472..e7c3e5567049 100644 --- a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java +++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java @@ -18,6 +18,7 @@ package com.android.server.connectivity.tethering; import static android.hardware.usb.UsbManager.USB_CONFIGURED; import static android.hardware.usb.UsbManager.USB_CONNECTED; +import static android.hardware.usb.UsbManager.USB_FUNCTION_NCM; import static android.hardware.usb.UsbManager.USB_FUNCTION_RNDIS; import static android.net.ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED; import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_DISABLED; @@ -27,6 +28,7 @@ import static android.net.TetheringManager.ACTION_TETHER_STATE_CHANGED; import static android.net.TetheringManager.EXTRA_ACTIVE_LOCAL_ONLY; import static android.net.TetheringManager.EXTRA_ACTIVE_TETHER; import static android.net.TetheringManager.EXTRA_AVAILABLE_TETHER; +import static android.net.TetheringManager.TETHERING_NCM; import static android.net.TetheringManager.TETHERING_USB; import static android.net.TetheringManager.TETHERING_WIFI; import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR; @@ -151,6 +153,7 @@ public class TetheringTest { private static final String TEST_USB_IFNAME = "test_rndis0"; private static final String TEST_WLAN_IFNAME = "test_wlan0"; private static final String TEST_P2P_IFNAME = "test_p2p-p2p0-0"; + private static final String TEST_NCM_IFNAME = "test_ncm0"; private static final String TETHERING_NAME = "Tethering"; private static final int DHCPSERVER_START_TIMEOUT_MS = 1000; @@ -252,9 +255,11 @@ public class TetheringTest { ifName.equals(TEST_USB_IFNAME) || ifName.equals(TEST_WLAN_IFNAME) || ifName.equals(TEST_MOBILE_IFNAME) - || ifName.equals(TEST_P2P_IFNAME)); + || ifName.equals(TEST_P2P_IFNAME) + || ifName.equals(TEST_NCM_IFNAME)); final String[] ifaces = new String[] { - TEST_USB_IFNAME, TEST_WLAN_IFNAME, TEST_MOBILE_IFNAME, TEST_P2P_IFNAME}; + TEST_USB_IFNAME, TEST_WLAN_IFNAME, TEST_MOBILE_IFNAME, TEST_P2P_IFNAME, + TEST_NCM_IFNAME}; return new InterfaceParams(ifName, ArrayUtils.indexOf(ifaces, ifName) + IFINDEX_OFFSET, MacAddress.ALL_ZEROS_ADDRESS); } @@ -428,13 +433,16 @@ public class TetheringTest { .thenReturn(new String[]{ "test_p2p-p2p\\d-.*" }); when(mResources.getStringArray(R.array.config_tether_bluetooth_regexs)) .thenReturn(new String[0]); + when(mResources.getStringArray(R.array.config_tether_ncm_regexs)) + .thenReturn(new String[] { "test_ncm\\d" }); when(mResources.getIntArray(R.array.config_tether_upstream_types)).thenReturn(new int[0]); when(mResources.getBoolean(R.bool.config_tether_upstream_automatic)).thenReturn(false); when(mResources.getBoolean(R.bool.config_tether_enable_legacy_dhcp_server)).thenReturn( false); when(mNetd.interfaceGetList()) .thenReturn(new String[] { - TEST_MOBILE_IFNAME, TEST_WLAN_IFNAME, TEST_USB_IFNAME, TEST_P2P_IFNAME}); + TEST_MOBILE_IFNAME, TEST_WLAN_IFNAME, TEST_USB_IFNAME, TEST_P2P_IFNAME, + TEST_NCM_IFNAME}); when(mResources.getString(R.string.config_wifi_tether_enable)).thenReturn(""); mInterfaceConfiguration = new InterfaceConfigurationParcel(); mInterfaceConfiguration.flags = new String[0]; @@ -524,11 +532,16 @@ public class TetheringTest { P2P_RECEIVER_PERMISSIONS_FOR_BROADCAST); } - private void sendUsbBroadcast(boolean connected, boolean configured, boolean rndisFunction) { + private void sendUsbBroadcast(boolean connected, boolean configured, boolean function, + int type) { final Intent intent = new Intent(UsbManager.ACTION_USB_STATE); intent.putExtra(USB_CONNECTED, connected); intent.putExtra(USB_CONFIGURED, configured); - intent.putExtra(USB_FUNCTION_RNDIS, rndisFunction); + if (type == TETHERING_USB) { + intent.putExtra(USB_FUNCTION_RNDIS, function); + } else { + intent.putExtra(USB_FUNCTION_NCM, function); + } mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); } @@ -578,6 +591,15 @@ public class TetheringTest { verifyNoMoreInteractions(mWifiManager); } + private void prepareNcmTethering() { + // Emulate startTethering(TETHERING_NCM) called + mTethering.startTethering(createTetheringRquestParcel(TETHERING_NCM), null); + mLooper.dispatchAll(); + verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_NCM); + + mTethering.interfaceStatusChanged(TEST_NCM_IFNAME, true); + } + private void prepareUsbTethering(UpstreamNetworkState upstreamState) { when(mUpstreamNetworkMonitor.getCurrentPreferredUpstream()).thenReturn(upstreamState); when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any())) @@ -600,7 +622,7 @@ public class TetheringTest { verifyNoMoreInteractions(mNetd); // Pretend we then receive USB configured broadcast. - sendUsbBroadcast(true, true, true); + sendUsbBroadcast(true, true, true, TETHERING_USB); mLooper.dispatchAll(); // Now we should see the start of tethering mechanics (in this case: // tetherMatchingInterfaces() which starts by fetching all interfaces). @@ -691,7 +713,7 @@ public class TetheringTest { private void runUsbTethering(UpstreamNetworkState upstreamState) { prepareUsbTethering(upstreamState); - sendUsbBroadcast(true, true, true); + sendUsbBroadcast(true, true, true, TETHERING_USB); mLooper.dispatchAll(); } @@ -814,6 +836,29 @@ public class TetheringTest { verify(mUpstreamNetworkMonitor, times(1)).setCurrentUpstream(upstreamState.network); } + private void runNcmTethering() { + prepareNcmTethering(); + sendUsbBroadcast(true, true, true, TETHERING_NCM); + mLooper.dispatchAll(); + } + + @Test + public void workingNcmTethering() throws Exception { + runNcmTethering(); + + verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).start(any()); + } + + @Test + public void workingNcmTethering_LegacyDhcp() { + when(mResources.getBoolean(R.bool.config_tether_enable_legacy_dhcp_server)).thenReturn( + true); + sendConfigurationChanged(); + runNcmTethering(); + + verify(mIpServerDependencies, never()).makeDhcpServer(any(), any(), any()); + } + @Test public void workingLocalOnlyHotspotEnrichedApBroadcastWithIfaceChanged() throws Exception { workingLocalOnlyHotspotEnrichedApBroadcast(true); diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 478b87c01025..e98c370149a9 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -2955,6 +2955,11 @@ public class ConnectivityService extends IConnectivityManager.Stub public int getInterfaceVersion() { return this.VERSION; } + + @Override + public String getInterfaceHash() { + return this.HASH; + } } private boolean networkRequiresPrivateDnsValidation(NetworkAgentInfo nai) { diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java index 1daed1b54683..33a82d873df9 100644 --- a/services/core/java/com/android/server/NetworkManagementService.java +++ b/services/core/java/com/android/server/NetworkManagementService.java @@ -734,6 +734,11 @@ public class NetworkManagementService extends INetworkManagementService.Stub { public int getInterfaceVersion() { return INetdUnsolicitedEventListener.VERSION; } + + @Override + public String getInterfaceHash() { + return INetdUnsolicitedEventListener.HASH; + } } // diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java index 5eacb28c76a9..a10d57a25f98 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -296,6 +296,12 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { PhoneStateListener.LISTEN_OUTGOING_EMERGENCY_CALL | PhoneStateListener.LISTEN_OUTGOING_EMERGENCY_SMS; + static final int READ_PRIVILEGED_PHONE_STATE_PERMISSION_MASK = + PhoneStateListener.LISTEN_OEM_HOOK_RAW_EVENT + | PhoneStateListener.LISTEN_SRVCC_STATE_CHANGED + | PhoneStateListener.LISTEN_RADIO_POWER_STATE_CHANGED + | PhoneStateListener.LISTEN_VOICE_ACTIVATION_STATE; + private static final int MSG_USER_SWITCHED = 1; private static final int MSG_UPDATE_DEFAULT_SUB = 2; @@ -2448,27 +2454,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION, null); } - if ((events & PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH) != 0) { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH, null); - } - - if ((events & PhoneStateListener.LISTEN_OEM_HOOK_RAW_EVENT) != 0) { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, null); - } - - if ((events & PhoneStateListener.LISTEN_SRVCC_STATE_CHANGED) != 0) { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, null); - } - - if ((events & PhoneStateListener.LISTEN_RADIO_POWER_STATE_CHANGED) != 0) { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, null); - } - - if ((events & PhoneStateListener.LISTEN_VOICE_ACTIVATION_STATE) != 0) { + if ((events & READ_PRIVILEGED_PHONE_STATE_PERMISSION_MASK) != 0) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, null); } diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index f021008cef7d..5833d165f380 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -272,6 +272,7 @@ public final class ActiveServices { static final int MSG_BG_START_TIMEOUT = 1; static final int MSG_UPDATE_FOREGROUND_APPS = 2; + static final int MSG_ENSURE_NOT_START_BG = 3; ServiceMap(Looper looper, int userId) { super(looper); @@ -289,6 +290,11 @@ public final class ActiveServices { case MSG_UPDATE_FOREGROUND_APPS: { updateForegroundApps(this); } break; + case MSG_ENSURE_NOT_START_BG: { + synchronized (mAm) { + rescheduleDelayedStartsLocked(); + } + } break; } } @@ -296,7 +302,9 @@ public final class ActiveServices { if (mStartingBackground.remove(r)) { if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "No longer background starting: " + r); - rescheduleDelayedStartsLocked(); + removeMessages(MSG_ENSURE_NOT_START_BG); + Message msg = obtainMessage(MSG_ENSURE_NOT_START_BG); + sendMessage(msg); } if (mDelayedStartList.remove(r)) { if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "No longer delaying start: " + r); diff --git a/services/core/java/com/android/server/compat/PlatformCompat.java b/services/core/java/com/android/server/compat/PlatformCompat.java index 029b7bc32ef3..e48169fc37c9 100644 --- a/services/core/java/com/android/server/compat/PlatformCompat.java +++ b/services/core/java/com/android/server/compat/PlatformCompat.java @@ -16,6 +16,11 @@ package com.android.server.compat; +import static android.Manifest.permission.LOG_COMPAT_CHANGE; +import static android.Manifest.permission.OVERRIDE_COMPAT_CHANGE_CONFIG; +import static android.Manifest.permission.READ_COMPAT_CHANGE_CONFIG; +import static android.content.pm.PackageManager.PERMISSION_GRANTED; + import android.app.ActivityManager; import android.app.IActivityManager; import android.content.Context; @@ -67,12 +72,14 @@ public class PlatformCompat extends IPlatformCompat.Stub { @Override public void reportChange(long changeId, ApplicationInfo appInfo) { + checkCompatChangeLogPermission(); reportChange(changeId, appInfo.uid, StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__LOGGED); } @Override public void reportChangeByPackageName(long changeId, String packageName, int userId) { + checkCompatChangeLogPermission(); ApplicationInfo appInfo = getApplicationInfo(packageName, userId); if (appInfo == null) { return; @@ -82,11 +89,13 @@ public class PlatformCompat extends IPlatformCompat.Stub { @Override public void reportChangeByUid(long changeId, int uid) { + checkCompatChangeLogPermission(); reportChange(changeId, uid, StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__LOGGED); } @Override public boolean isChangeEnabled(long changeId, ApplicationInfo appInfo) { + checkCompatChangeReadPermission(); if (mCompatConfig.isChangeEnabled(changeId, appInfo)) { reportChange(changeId, appInfo.uid, StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__ENABLED); @@ -99,6 +108,7 @@ public class PlatformCompat extends IPlatformCompat.Stub { @Override public boolean isChangeEnabledByPackageName(long changeId, String packageName, int userId) { + checkCompatChangeReadPermission(); ApplicationInfo appInfo = getApplicationInfo(packageName, userId); if (appInfo == null) { return true; @@ -108,6 +118,7 @@ public class PlatformCompat extends IPlatformCompat.Stub { @Override public boolean isChangeEnabledByUid(long changeId, int uid) { + checkCompatChangeReadPermission(); String[] packages = mContext.getPackageManager().getPackagesForUid(uid); if (packages == null || packages.length == 0) { return true; @@ -140,6 +151,7 @@ public class PlatformCompat extends IPlatformCompat.Stub { @Override public void setOverrides(CompatibilityChangeConfig overrides, String packageName) throws RemoteException, SecurityException { + checkCompatChangeOverridePermission(); mCompatConfig.addOverrides(overrides, packageName); killPackage(packageName); } @@ -147,11 +159,13 @@ public class PlatformCompat extends IPlatformCompat.Stub { @Override public void setOverridesForTest(CompatibilityChangeConfig overrides, String packageName) throws RemoteException, SecurityException { + checkCompatChangeOverridePermission(); mCompatConfig.addOverrides(overrides, packageName); } @Override public void clearOverrides(String packageName) throws RemoteException, SecurityException { + checkCompatChangeOverridePermission(); mCompatConfig.removePackageOverrides(packageName); killPackage(packageName); } @@ -159,12 +173,14 @@ public class PlatformCompat extends IPlatformCompat.Stub { @Override public void clearOverridesForTest(String packageName) throws RemoteException, SecurityException { + checkCompatChangeOverridePermission(); mCompatConfig.removePackageOverrides(packageName); } @Override public boolean clearOverride(long changeId, String packageName) throws RemoteException, SecurityException { + checkCompatChangeOverridePermission(); boolean existed = mCompatConfig.removeOverride(changeId, packageName); killPackage(packageName); return existed; @@ -172,11 +188,13 @@ public class PlatformCompat extends IPlatformCompat.Stub { @Override public CompatibilityChangeConfig getAppConfig(ApplicationInfo appInfo) { + checkCompatChangeReadPermission(); return mCompatConfig.getAppConfig(appInfo); } @Override public CompatibilityChangeInfo[] listAllChanges() { + checkCompatChangeReadPermission(); return mCompatConfig.dumpChanges(); } @@ -215,6 +233,7 @@ public class PlatformCompat extends IPlatformCompat.Stub { @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + checkCompatChangeReadPermission(); if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, "platform_compat", pw)) return; mCompatConfig.dumpConfig(pw); } @@ -276,4 +295,25 @@ public class PlatformCompat extends IPlatformCompat.Stub { Binder.restoreCallingIdentity(identity); } } + + private void checkCompatChangeLogPermission() throws SecurityException { + if (mContext.checkCallingOrSelfPermission(LOG_COMPAT_CHANGE) + != PERMISSION_GRANTED) { + throw new SecurityException("Cannot log compat change usage"); + } + } + + private void checkCompatChangeReadPermission() throws SecurityException { + if (mContext.checkCallingOrSelfPermission(READ_COMPAT_CHANGE_CONFIG) + != PERMISSION_GRANTED) { + throw new SecurityException("Cannot read compat change"); + } + } + + private void checkCompatChangeOverridePermission() throws SecurityException { + if (mContext.checkCallingOrSelfPermission(OVERRIDE_COMPAT_CHANGE_CONFIG) + != PERMISSION_GRANTED) { + throw new SecurityException("Cannot override compat change"); + } + } } diff --git a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java index dbc339b01c89..d15ebe092a08 100644 --- a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java +++ b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java @@ -310,6 +310,11 @@ public class NetdEventListenerService extends INetdEventListener.Stub { return this.VERSION; } + @Override + public String getInterfaceHash() { + return this.HASH; + } + private void addWakeupEvent(WakeupEvent event) { String iface = event.iface; mWakeupEvents.append(event); diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 7e7822cd978e..d8f5dfbbaf48 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -21009,7 +21009,7 @@ public class PackageManagerService extends IPackageManager.Stub // Disable any carrier apps. We do this very early in boot to prevent the apps from being // disabled after already being started. CarrierAppUtils.disableCarrierAppsUntilPrivileged(mContext.getOpPackageName(), this, - mContext.getContentResolver(), UserHandle.USER_SYSTEM); + UserHandle.USER_SYSTEM, mContext); disableSkuSpecificApps(); diff --git a/services/core/java/com/android/server/timezone/RulesManagerService.java b/services/core/java/com/android/server/timezone/RulesManagerService.java index 9347d2194b68..cdf8ea3460c4 100644 --- a/services/core/java/com/android/server/timezone/RulesManagerService.java +++ b/services/core/java/com/android/server/timezone/RulesManagerService.java @@ -49,7 +49,7 @@ import com.android.timezone.distro.installer.TimeZoneDistroInstaller; import libcore.timezone.TimeZoneDataFiles; import libcore.timezone.TimeZoneFinder; import libcore.timezone.TzDataSetVersion; -import libcore.timezone.ZoneInfoDB; +import libcore.timezone.ZoneInfoDb; import java.io.File; import java.io.FileDescriptor; @@ -518,9 +518,9 @@ public final class RulesManagerService extends IRulesManager.Stub { case 'a': { // Report the active rules version (i.e. the rules in use by the current // process). - pw.println("Active rules version (ICU, ZoneInfoDB, TimeZoneFinder): " + pw.println("Active rules version (ICU, ZoneInfoDb, TimeZoneFinder): " + TimeZone.getTZDataVersion() + "," - + ZoneInfoDB.getInstance().getVersion() + "," + + ZoneInfoDb.getInstance().getVersion() + "," + TimeZoneFinder.getInstance().getIanaVersion()); break; } @@ -536,7 +536,7 @@ public final class RulesManagerService extends IRulesManager.Stub { pw.println("RulesManagerService state: " + toString()); pw.println("Active rules version (ICU, ZoneInfoDB, TimeZoneFinder): " + TimeZone.getTZDataVersion() + "," - + ZoneInfoDB.getInstance().getVersion() + "," + + ZoneInfoDb.getInstance().getVersion() + "," + TimeZoneFinder.getInstance().getIanaVersion()); pw.println("Distro state: " + rulesState.toString()); mPackageTracker.dump(pw); diff --git a/services/net/java/android/net/IpMemoryStore.java b/services/net/java/android/net/IpMemoryStore.java index 6f91e006c853..dcefb537d0a0 100644 --- a/services/net/java/android/net/IpMemoryStore.java +++ b/services/net/java/android/net/IpMemoryStore.java @@ -52,6 +52,11 @@ public class IpMemoryStore extends IpMemoryStoreClient { public int getInterfaceVersion() { return this.VERSION; } + + @Override + public String getInterfaceHash() { + return this.HASH; + } }); } diff --git a/services/net/java/android/net/ip/IpClientUtil.java b/services/net/java/android/net/ip/IpClientUtil.java index 7f723b1c232b..a3618b47171a 100644 --- a/services/net/java/android/net/ip/IpClientUtil.java +++ b/services/net/java/android/net/ip/IpClientUtil.java @@ -189,6 +189,11 @@ public class IpClientUtil { public int getInterfaceVersion() { return this.VERSION; } + + @Override + public String getInterfaceHash() { + return this.HASH; + } } /** diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml index 61fe01f1ca6f..1e623e0eea87 100644 --- a/services/tests/servicestests/AndroidManifest.xml +++ b/services/tests/servicestests/AndroidManifest.xml @@ -65,6 +65,8 @@ <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/> <uses-permission android:name="android.permission.SUSPEND_APPS"/> <uses-permission android:name="android.permission.CONTROL_KEYGUARD"/> + <uses-permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG"/> + <uses-permission android:name="android.permission.LOG_COMPAT_CHANGE"/> <uses-permission android:name="android.permission.MANAGE_BIND_INSTANT_SERVICE"/> <uses-permission android:name="android.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS" /> <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" /> diff --git a/telephony/common/com/android/internal/telephony/CarrierAppUtils.java b/telephony/common/com/android/internal/telephony/CarrierAppUtils.java index 3f5aa0f86b75..3c1e707ab1dd 100644 --- a/telephony/common/com/android/internal/telephony/CarrierAppUtils.java +++ b/telephony/common/com/android/internal/telephony/CarrierAppUtils.java @@ -18,16 +18,18 @@ package com.android.internal.telephony; import android.annotation.Nullable; import android.content.ContentResolver; +import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; import android.content.res.Resources; import android.os.RemoteException; +import android.os.UserHandle; import android.provider.Settings; -import android.util.Log; import android.telephony.TelephonyManager; import android.util.ArrayMap; import android.util.ArraySet; +import android.util.Log; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; @@ -75,7 +77,7 @@ public final class CarrierAppUtils { */ public static synchronized void disableCarrierAppsUntilPrivileged(String callingPackage, IPackageManager packageManager, TelephonyManager telephonyManager, - ContentResolver contentResolver, int userId) { + int userId, Context context) { if (DEBUG) { Log.d(TAG, "disableCarrierAppsUntilPrivileged"); } @@ -84,6 +86,7 @@ public final class CarrierAppUtils { config.getDisabledUntilUsedPreinstalledCarrierApps(); ArrayMap<String, List<String>> systemCarrierAssociatedAppsDisabledUntilUsed = config.getDisabledUntilUsedPreinstalledCarrierAssociatedApps(); + ContentResolver contentResolver = getContentResolverForUser(context, userId); disableCarrierAppsUntilPrivileged(callingPackage, packageManager, telephonyManager, contentResolver, userId, systemCarrierAppsDisabledUntilUsed, systemCarrierAssociatedAppsDisabledUntilUsed); @@ -101,7 +104,7 @@ public final class CarrierAppUtils { * Manager can kill it, and this can lead to crashes as the app is in an unexpected state. */ public static synchronized void disableCarrierAppsUntilPrivileged(String callingPackage, - IPackageManager packageManager, ContentResolver contentResolver, int userId) { + IPackageManager packageManager, int userId, Context context) { if (DEBUG) { Log.d(TAG, "disableCarrierAppsUntilPrivileged"); } @@ -112,23 +115,31 @@ public final class CarrierAppUtils { ArrayMap<String, List<String>> systemCarrierAssociatedAppsDisabledUntilUsed = config.getDisabledUntilUsedPreinstalledCarrierAssociatedApps(); + ContentResolver contentResolver = getContentResolverForUser(context, userId); disableCarrierAppsUntilPrivileged(callingPackage, packageManager, null /* telephonyManager */, contentResolver, userId, systemCarrierAppsDisabledUntilUsed, systemCarrierAssociatedAppsDisabledUntilUsed); } + private static ContentResolver getContentResolverForUser(Context context, int userId) { + Context userContext = context.createContextAsUser(UserHandle.getUserHandleForUid(userId), + 0); + return userContext.getContentResolver(); + } + /** * Disable carrier apps until they are privileged * Must be public b/c framework unit tests can't access package-private methods. */ + // Must be public b/c framework unit tests can't access package-private methods. @VisibleForTesting public static void disableCarrierAppsUntilPrivileged(String callingPackage, IPackageManager packageManager, @Nullable TelephonyManager telephonyManager, ContentResolver contentResolver, int userId, ArraySet<String> systemCarrierAppsDisabledUntilUsed, ArrayMap<String, List<String>> systemCarrierAssociatedAppsDisabledUntilUsed) { - List<ApplicationInfo> candidates = getDefaultCarrierAppCandidatesHelper(packageManager, - userId, systemCarrierAppsDisabledUntilUsed); + List<ApplicationInfo> candidates = getDefaultNotUpdatedCarrierAppCandidatesHelper( + packageManager, userId, systemCarrierAppsDisabledUntilUsed); if (candidates == null || candidates.isEmpty()) { return; } @@ -139,9 +150,8 @@ public final class CarrierAppUtils { systemCarrierAssociatedAppsDisabledUntilUsed); List<String> enabledCarrierPackages = new ArrayList<>(); - - boolean hasRunOnce = Settings.Secure.getIntForUser( - contentResolver, Settings.Secure.CARRIER_APPS_HANDLED, 0, userId) == 1; + boolean hasRunOnce = Settings.Secure.getInt(contentResolver, + Settings.Secure.CARRIER_APPS_HANDLED, 0) == 1; try { for (ApplicationInfo ai : candidates) { @@ -165,15 +175,16 @@ public final class CarrierAppUtils { } } + int enabledSetting = packageManager.getApplicationEnabledSetting(packageName, + userId); if (hasPrivileges) { // Only update enabled state for the app on /system. Once it has been // updated we shouldn't touch it. - if (!ai.isUpdatedSystemApp() - && (ai.enabledSetting + if (enabledSetting == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT - || ai.enabledSetting + || enabledSetting == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED - || (ai.flags & ApplicationInfo.FLAG_INSTALLED) == 0)) { + || (ai.flags & ApplicationInfo.FLAG_INSTALLED) == 0) { Log.i(TAG, "Update state(" + packageName + "): ENABLED for user " + userId); packageManager.setSystemAppInstallState( @@ -191,9 +202,12 @@ public final class CarrierAppUtils { // Also enable any associated apps for this carrier app. if (associatedAppList != null) { for (ApplicationInfo associatedApp : associatedAppList) { - if (associatedApp.enabledSetting + int associatedAppEnabledSetting = + packageManager.getApplicationEnabledSetting( + associatedApp.packageName, userId); + if (associatedAppEnabledSetting == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT - || associatedApp.enabledSetting + || associatedAppEnabledSetting == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED || (associatedApp.flags & ApplicationInfo.FLAG_INSTALLED) == 0) { @@ -218,8 +232,7 @@ public final class CarrierAppUtils { } else { // No carrier privileges // Only update enabled state for the app on /system. Once it has been // updated we shouldn't touch it. - if (!ai.isUpdatedSystemApp() - && ai.enabledSetting + if (enabledSetting == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT && (ai.flags & ApplicationInfo.FLAG_INSTALLED) != 0) { Log.i(TAG, "Update state(" + packageName @@ -236,7 +249,10 @@ public final class CarrierAppUtils { if (!hasRunOnce) { if (associatedAppList != null) { for (ApplicationInfo associatedApp : associatedAppList) { - if (associatedApp.enabledSetting + int associatedAppEnabledSetting = + packageManager.getApplicationEnabledSetting( + associatedApp.packageName, userId); + if (associatedAppEnabledSetting == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT && (associatedApp.flags & ApplicationInfo.FLAG_INSTALLED) != 0) { @@ -256,8 +272,7 @@ public final class CarrierAppUtils { // Mark the execution so we do not disable apps again. if (!hasRunOnce) { - Settings.Secure.putIntForUser( - contentResolver, Settings.Secure.CARRIER_APPS_HANDLED, 1, userId); + Settings.Secure.putInt(contentResolver, Settings.Secure.CARRIER_APPS_HANDLED, 1); } if (!enabledCarrierPackages.isEmpty()) { @@ -348,6 +363,31 @@ public final class CarrierAppUtils { return apps; } + private static List<ApplicationInfo> getDefaultNotUpdatedCarrierAppCandidatesHelper( + IPackageManager packageManager, + int userId, + ArraySet<String> systemCarrierAppsDisabledUntilUsed) { + if (systemCarrierAppsDisabledUntilUsed == null) { + return null; + } + + int size = systemCarrierAppsDisabledUntilUsed.size(); + if (size == 0) { + return null; + } + + List<ApplicationInfo> apps = new ArrayList<>(size); + for (int i = 0; i < size; i++) { + String packageName = systemCarrierAppsDisabledUntilUsed.valueAt(i); + ApplicationInfo ai = + getApplicationInfoIfNotUpdatedSystemApp(packageManager, userId, packageName); + if (ai != null) { + apps.add(ai); + } + } + return apps; + } + private static Map<String, List<ApplicationInfo>> getDefaultCarrierAssociatedAppsHelper( IPackageManager packageManager, int userId, @@ -360,11 +400,11 @@ public final class CarrierAppUtils { systemCarrierAssociatedAppsDisabledUntilUsed.valueAt(i); for (int j = 0; j < associatedAppPackages.size(); j++) { ApplicationInfo ai = - getApplicationInfoIfSystemApp( + getApplicationInfoIfNotUpdatedSystemApp( packageManager, userId, associatedAppPackages.get(j)); // Only update enabled state for the app on /system. Once it has been updated we // shouldn't touch it. - if (ai != null && !ai.isUpdatedSystemApp()) { + if (ai != null) { List<ApplicationInfo> appList = associatedApps.get(carrierAppPackage); if (appList == null) { appList = new ArrayList<>(); @@ -378,6 +418,26 @@ public final class CarrierAppUtils { } @Nullable + private static ApplicationInfo getApplicationInfoIfNotUpdatedSystemApp( + IPackageManager packageManager, + int userId, + String packageName) { + try { + ApplicationInfo ai = packageManager.getApplicationInfo(packageName, + PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS + | PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS + | PackageManager.MATCH_SYSTEM_ONLY + | PackageManager.MATCH_FACTORY_ONLY, userId); + if (ai != null) { + return ai; + } + } catch (RemoteException e) { + Log.w(TAG, "Could not reach PackageManager", e); + } + return null; + } + + @Nullable private static ApplicationInfo getApplicationInfoIfSystemApp( IPackageManager packageManager, int userId, @@ -385,8 +445,9 @@ public final class CarrierAppUtils { try { ApplicationInfo ai = packageManager.getApplicationInfo(packageName, PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS - | PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS, userId); - if (ai != null && ai.isSystemApp()) { + | PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS + | PackageManager.MATCH_SYSTEM_ONLY, userId); + if (ai != null) { return ai; } } catch (RemoteException e) { diff --git a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java index 5beb06d8595a..2077800cd808 100644 --- a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java +++ b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java @@ -365,7 +365,6 @@ public final class TelephonyPermissions { private static boolean reportAccessDeniedToReadIdentifiers(Context context, int subId, int pid, int uid, String callingPackage, String message) { boolean isPreinstalled = false; - boolean isPrivApp = false; ApplicationInfo callingPackageInfo = null; try { callingPackageInfo = context.getPackageManager().getApplicationInfoAsUser( @@ -373,9 +372,6 @@ public final class TelephonyPermissions { if (callingPackageInfo != null) { if (callingPackageInfo.isSystemApp()) { isPreinstalled = true; - if (callingPackageInfo.isPrivilegedApp()) { - isPrivApp = true; - } } } } catch (PackageManager.NameNotFoundException e) { @@ -398,10 +394,10 @@ public final class TelephonyPermissions { } invokedMethods.add(message); StatsLog.write(StatsLog.DEVICE_IDENTIFIER_ACCESS_DENIED, callingPackage, message, - isPreinstalled, isPrivApp); + isPreinstalled, false); } Log.w(LOG_TAG, "reportAccessDeniedToReadIdentifiers:" + callingPackage + ":" + message - + ":isPreinstalled=" + isPreinstalled + ":isPrivApp=" + isPrivApp); + + ":isPreinstalled=" + isPreinstalled); // if the target SDK is pre-Q then check if the calling package would have previously // had access to device identifiers. if (callingPackageInfo != null && ( diff --git a/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java b/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java index 0498d7c31406..2abcc76fdccc 100644 --- a/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java +++ b/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java @@ -28,6 +28,7 @@ import android.os.RemoteException; import android.os.SystemProperties; import java.io.PrintWriter; +import java.util.function.Supplier; /** * This class provides various util functions @@ -75,6 +76,42 @@ public final class TelephonyUtils { } /** + * Convenience method for running the provided action enclosed in + * {@link Binder#clearCallingIdentity}/{@link Binder#restoreCallingIdentity} + * + * Any exception thrown by the given action will need to be handled by caller. + * + */ + public static void runWithCleanCallingIdentity( + @NonNull Runnable action) { + long callingIdentity = Binder.clearCallingIdentity(); + try { + action.run(); + } finally { + Binder.restoreCallingIdentity(callingIdentity); + } + } + + + /** + * Convenience method for running the provided action enclosed in + * {@link Binder#clearCallingIdentity}/{@link Binder#restoreCallingIdentity} and return + * the result. + * + * Any exception thrown by the given action will need to be handled by caller. + * + */ + public static <T> T runWithCleanCallingIdentity( + @NonNull Supplier<T> action) { + long callingIdentity = Binder.clearCallingIdentity(); + try { + return action.get(); + } finally { + Binder.restoreCallingIdentity(callingIdentity); + } + } + + /** * Filter values in bundle to only basic types. */ public static Bundle filterValues(Bundle bundle) { diff --git a/telephony/java/android/telephony/AccessNetworkConstants.java b/telephony/java/android/telephony/AccessNetworkConstants.java index d325cd84855c..610eef80c571 100644 --- a/telephony/java/android/telephony/AccessNetworkConstants.java +++ b/telephony/java/android/telephony/AccessNetworkConstants.java @@ -67,6 +67,22 @@ public final class AccessNetworkConstants { } } + /** + * Access network type + * @hide + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = {"RADIO_ACCESS_NETWORK_TYPE_"}, + value = { + AccessNetworkType.UNKNOWN, + AccessNetworkType.GERAN, + AccessNetworkType.UTRAN, + AccessNetworkType.EUTRAN, + AccessNetworkType.CDMA2000, + AccessNetworkType.IWLAN, + AccessNetworkType.NGRAN}) + public @interface RadioAccessNetworkType {} + public static final class AccessNetworkType { public static final int UNKNOWN = 0; public static final int GERAN = 1; @@ -115,11 +131,11 @@ public final class AccessNetworkConstants { public static final int BAND_ER900 = 14; /** @hide */ - private GeranBand() {}; + private GeranBand() {} } /** - * Frenquency bands for UTRAN. + * Frequency bands for UTRAN. * http://www.etsi.org/deliver/etsi_ts/125100_125199/125104/13.03.00_60/ts_125104v130p.pdf */ public static final class UtranBand { @@ -146,12 +162,19 @@ public final class AccessNetworkConstants { public static final int BAND_25 = 25; public static final int BAND_26 = 26; + /** Frequency bands for TD-SCDMA. Defined in 3GPP TS 25.102, Table 5.2. */ + public static final int BAND_A = 101; + public static final int BAND_B = 102; + public static final int BAND_C = 103; + public static final int BAND_D = 104; + public static final int BAND_E = 105; + public static final int BAND_F = 106; /** @hide */ - private UtranBand() {}; + private UtranBand() {} } /** - * Frenquency bands for EUTRAN. + * Frequency bands for EUTRAN. * http://www.etsi.org/deliver/etsi_ts/136100_136199/136101/14.03.00_60/ts_136101v140p.pdf */ public static final class EutranBand { @@ -209,7 +232,7 @@ public final class AccessNetworkConstants { } /** - * Frenquency bands for CDMA2000. + * Frequency bands for CDMA2000. * http://www.3gpp2.org/Public_html/Specs/C.S0057-E_v1.0_Bandclass_Specification.pdf * @hide * @@ -240,7 +263,7 @@ public final class AccessNetworkConstants { public static final int BAND_21 = 22; /** @hide */ - private CdmaBands() {}; + private CdmaBands() {} } /** @@ -294,8 +317,161 @@ public final class AccessNetworkConstants { public static final int BAND_260 = 260; public static final int BAND_261 = 261; + /** + * NR Bands + * + * @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = {"BAND_"}, + value = {BAND_1, + BAND_2, + BAND_3, + BAND_5, + BAND_7, + BAND_8, + BAND_12, + BAND_14, + BAND_18, + BAND_20, + BAND_25, + BAND_28, + BAND_29, + BAND_30, + BAND_34, + BAND_38, + BAND_39, + BAND_40, + BAND_41, + BAND_48, + BAND_50, + BAND_51, + BAND_65, + BAND_66, + BAND_70, + BAND_71, + BAND_74, + BAND_75, + BAND_76, + BAND_77, + BAND_78, + BAND_79, + BAND_80, + BAND_81, + BAND_82, + BAND_83, + BAND_84, + BAND_86, + BAND_90, + BAND_257, + BAND_258, + BAND_260, + BAND_261}) + public @interface NgranBand {} + + /** + * Unknown NR frequency. + * + * @hide + */ + @SystemApi + @TestApi + public static final int FREQUENCY_RANGE_GROUP_UNKNOWN = 0; + + /** + * NR frequency group 1 defined in 3GPP TS 38.101-1 table 5.2-1 + * + * @hide + */ + @SystemApi + @TestApi + public static final int FREQUENCY_RANGE_GROUP_1 = 1; + + /** + * NR frequency group 2 defined in 3GPP TS 38.101-2 table 5.2-1 + * + * @hide + */ + @SystemApi + @TestApi + public static final int FREQUENCY_RANGE_GROUP_2 = 2; + + /** + * Radio frequency range group + * + * @hide + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = {"FREQUENCY_RANGE_GROUP_"}, + value = { + FREQUENCY_RANGE_GROUP_UNKNOWN, + FREQUENCY_RANGE_GROUP_1, + FREQUENCY_RANGE_GROUP_2}) + public @interface FrequencyRangeGroup {} + + /** + * Get frequency range group + * + * @param band NR band + * @return The frequency range group + * + * @hide + */ + @SystemApi + @TestApi + public static @FrequencyRangeGroup int getFrequencyRangeGroup(@NgranBand int band) { + switch (band) { + case BAND_1: + case BAND_2: + case BAND_3: + case BAND_5: + case BAND_7: + case BAND_8: + case BAND_12: + case BAND_14: + case BAND_18: + case BAND_20: + case BAND_25: + case BAND_28: + case BAND_29: + case BAND_30: + case BAND_34: + case BAND_38: + case BAND_39: + case BAND_40: + case BAND_41: + case BAND_48: + case BAND_50: + case BAND_51: + case BAND_65: + case BAND_66: + case BAND_70: + case BAND_71: + case BAND_74: + case BAND_75: + case BAND_76: + case BAND_77: + case BAND_78: + case BAND_79: + case BAND_80: + case BAND_81: + case BAND_82: + case BAND_83: + case BAND_84: + case BAND_86: + case BAND_90: + return FREQUENCY_RANGE_GROUP_1; + case BAND_257: + case BAND_258: + case BAND_260: + case BAND_261: + return FREQUENCY_RANGE_GROUP_2; + default: + return FREQUENCY_RANGE_GROUP_UNKNOWN; + } + }; + /** @hide */ - private NgranBands() {}; + private NgranBands() {} } /** @hide */ diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index 71411d5461a2..1eed0e02f9bd 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -2973,7 +2973,6 @@ public class CarrierConfigManager { /** * Controls hysteresis time in milli seconds for which OpportunisticNetworkService * will wait before switching data from opportunistic network to primary network. - * @hide */ public static final String KEY_OPPORTUNISTIC_NETWORK_DATA_SWITCH_EXIT_HYSTERESIS_TIME_LONG = "opportunistic_network_data_switch_exit_hysteresis_time_long"; @@ -2981,17 +2980,58 @@ public class CarrierConfigManager { /** * Controls whether to do ping test before switching data to opportunistic network. * This carrier config is used to disable this feature. - * @hide */ public static final String KEY_PING_TEST_BEFORE_DATA_SWITCH_BOOL = "ping_test_before_data_switch_bool"; /** * Controls time in milliseconds until DcTracker reevaluates 5G connection state. - * @hide */ public static final String KEY_5G_WATCHDOG_TIME_MS_LONG = "5g_watchdog_time_long"; + /** + * Controls whether to switch data to primary from opportunistic subscription + * if primary is out of service. This control only affects system or 1st party app + * initiated data switch, but will not override data switch initiated by privileged carrier apps + * This carrier config is used to disable this feature. + */ + public static final String KEY_SWITCH_DATA_TO_PRIMARY_IF_PRIMARY_IS_OOS_BOOL = + "switch_data_to_primary_if_primary_is_oos_bool"; + + /** + * Controls the ping pong determination of opportunistic network. + * If opportunistic network is determined as out of service or below + * #KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_RSRP_INT or + * #KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_RSSNR_INT within + * #KEY_OPPORTUNISTIC_NETWORK_PING_PONG_TIME_LONG of switching to opportunistic network, + * it will be determined as ping pong situation by system app or 1st party app. + */ + public static final String KEY_OPPORTUNISTIC_NETWORK_PING_PONG_TIME_LONG = + "opportunistic_network_ping_pong_time_long"; + /** + * Controls back off time in milli seconds for switching back to + * opportunistic subscription. This time will be added to + * {@link CarrierConfigManager#KEY_OPPORTUNISTIC_NETWORK_DATA_SWITCH_HYSTERESIS_TIME_LONG} to + * determine hysteresis time if there is ping pong situation + * (determined by system app or 1st party app) between primary and opportunistic + * subscription. Ping ping situation is defined in + * #KEY_OPPORTUNISTIC_NETWORK_PING_PONG_TIME_LONG. + * If ping pong situation continuous #KEY_OPPORTUNISTIC_NETWORK_BACKOFF_TIME_LONG + * will be added to previously determined hysteresis time. + */ + public static final String KEY_OPPORTUNISTIC_NETWORK_BACKOFF_TIME_LONG = + "opportunistic_network_backoff_time_long"; + + /** + * Controls the max back off time in milli seconds for switching back to + * opportunistic subscription. + * This time will be the max hysteresis that can be determined irrespective of there is + * continuous ping pong situation or not as described in + * #KEY_OPPORTUNISTIC_NETWORK_PING_PONG_TIME_LONG and + * #KEY_OPPORTUNISTIC_NETWORK_BACKOFF_TIME_LONG. + */ + public static final String KEY_OPPORTUNISTIC_NETWORK_MAX_BACKOFF_TIME_LONG = + "opportunistic_network_max_backoff_time_long"; /** * Indicates zero or more emergency number prefix(es), because some carrier requires @@ -3035,7 +3075,6 @@ public class CarrierConfigManager { * validation result, this value defines customized value of how long we wait for validation * success before we fail and revoke the switch. * Time out is in milliseconds. - * @hide */ public static final String KEY_DATA_SWITCH_VALIDATION_TIMEOUT_LONG = "data_switch_validation_timeout_long"; @@ -3816,6 +3855,13 @@ public class CarrierConfigManager { sDefaults.putBoolean(KEY_PING_TEST_BEFORE_DATA_SWITCH_BOOL, true); /* Default value is 1 hour. */ sDefaults.putLong(KEY_5G_WATCHDOG_TIME_MS_LONG, 3600000); + sDefaults.putBoolean(KEY_SWITCH_DATA_TO_PRIMARY_IF_PRIMARY_IS_OOS_BOOL, true); + /* Default value is 60 seconds. */ + sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_PING_PONG_TIME_LONG, 60000); + /* Default value is 10 seconds. */ + sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_BACKOFF_TIME_LONG, 10000); + /* Default value is 60 seconds. */ + sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_MAX_BACKOFF_TIME_LONG, 60000); sDefaults.putAll(Gps.getDefaults()); sDefaults.putIntArray(KEY_CDMA_ENHANCED_ROAMING_INDICATOR_FOR_HOME_NETWORK_INT_ARRAY, new int[] { diff --git a/telephony/java/android/telephony/CellIdentityGsm.java b/telephony/java/android/telephony/CellIdentityGsm.java index 49f425acead6..dc73cbf735b0 100644 --- a/telephony/java/android/telephony/CellIdentityGsm.java +++ b/telephony/java/android/telephony/CellIdentityGsm.java @@ -23,6 +23,8 @@ import android.os.Parcel; import android.telephony.gsm.GsmCellLocation; import android.text.TextUtils; +import java.util.Collections; +import java.util.List; import java.util.Objects; /** @@ -46,6 +48,9 @@ public final class CellIdentityGsm extends CellIdentity { // 6-bit Base Station Identity Code private final int mBsic; + // a list of additional PLMN-IDs reported for this cell + private final List<String> mAdditionalPlmns; + /** * @hide */ @@ -56,6 +61,7 @@ public final class CellIdentityGsm extends CellIdentity { mCid = CellInfo.UNAVAILABLE; mArfcn = CellInfo.UNAVAILABLE; mBsic = CellInfo.UNAVAILABLE; + mAdditionalPlmns = Collections.emptyList(); } /** @@ -68,35 +74,48 @@ public final class CellIdentityGsm extends CellIdentity { * @param mncStr 2 or 3-digit Mobile Network Code in string format * @param alphal long alpha Operator Name String or Enhanced Operator Name String * @param alphas short alpha Operator Name String or Enhanced Operator Name String + * @param additionalPlmns a list of additional PLMN IDs broadcast by the cell * * @hide */ public CellIdentityGsm(int lac, int cid, int arfcn, int bsic, String mccStr, - String mncStr, String alphal, String alphas) { + String mncStr, String alphal, String alphas, + List<String> additionalPlmns) { super(TAG, CellInfo.TYPE_GSM, mccStr, mncStr, alphal, alphas); mLac = inRangeOrUnavailable(lac, 0, MAX_LAC); mCid = inRangeOrUnavailable(cid, 0, MAX_CID); mArfcn = inRangeOrUnavailable(arfcn, 0, MAX_ARFCN); mBsic = inRangeOrUnavailable(bsic, 0, MAX_BSIC); + mAdditionalPlmns = additionalPlmns; } /** @hide */ public CellIdentityGsm(android.hardware.radio.V1_0.CellIdentityGsm cid) { this(cid.lac, cid.cid, cid.arfcn, cid.bsic == (byte) 0xFF ? CellInfo.UNAVAILABLE : cid.bsic, - cid.mcc, cid.mnc, "", ""); + cid.mcc, cid.mnc, "", "", Collections.emptyList()); } /** @hide */ public CellIdentityGsm(android.hardware.radio.V1_2.CellIdentityGsm cid) { this(cid.base.lac, cid.base.cid, cid.base.arfcn, cid.base.bsic == (byte) 0xFF ? CellInfo.UNAVAILABLE : cid.base.bsic, cid.base.mcc, - cid.base.mnc, cid.operatorNames.alphaLong, cid.operatorNames.alphaShort); + cid.base.mnc, cid.operatorNames.alphaLong, cid.operatorNames.alphaShort, + Collections.emptyList()); + } + + /** @hide */ + public CellIdentityGsm(android.hardware.radio.V1_5.CellIdentityGsm cid) { + this(cid.base.base.lac, cid.base.base.cid, cid.base.base.arfcn, + cid.base.base.bsic == (byte) 0xFF ? CellInfo.UNAVAILABLE + : cid.base.base.bsic, cid.base.base.mcc, + cid.base.base.mnc, cid.base.operatorNames.alphaLong, + cid.base.operatorNames.alphaShort, cid.additionalPlmns); } private CellIdentityGsm(CellIdentityGsm cid) { this(cid.mLac, cid.mCid, cid.mArfcn, cid.mBsic, cid.mMccStr, - cid.mMncStr, cid.mAlphaLong, cid.mAlphaShort); + cid.mMncStr, cid.mAlphaLong, cid.mAlphaShort, cid.mAdditionalPlmns); } CellIdentityGsm copy() { @@ -107,7 +126,7 @@ public final class CellIdentityGsm extends CellIdentity { @Override public @NonNull CellIdentityGsm sanitizeLocationInfo() { return new CellIdentityGsm(CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE, - CellInfo.UNAVAILABLE, mMccStr, mMncStr, mAlphaLong, mAlphaShort); + CellInfo.UNAVAILABLE, mMccStr, mMncStr, mAlphaLong, mAlphaShort, mAdditionalPlmns); } /** @@ -193,6 +212,14 @@ public final class CellIdentityGsm extends CellIdentity { } /** + * @return a list of additional PLMN IDs supported by this cell. + */ + @NonNull + public List<String> getAdditionalPlmns() { + return mAdditionalPlmns; + } + + /** * @deprecated Primary Scrambling Code is not applicable to GSM. * @return {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} - undefined for GSM */ @@ -215,7 +242,7 @@ public final class CellIdentityGsm extends CellIdentity { @Override public int hashCode() { - return Objects.hash(mLac, mCid, super.hashCode()); + return Objects.hash(mLac, mCid, mAdditionalPlmns.hashCode(), super.hashCode()); } @Override @@ -235,6 +262,7 @@ public final class CellIdentityGsm extends CellIdentity { && mBsic == o.mBsic && TextUtils.equals(mMccStr, o.mMccStr) && TextUtils.equals(mMncStr, o.mMncStr) + && mAdditionalPlmns.equals(o.mAdditionalPlmns) && super.equals(other); } @@ -249,6 +277,7 @@ public final class CellIdentityGsm extends CellIdentity { .append(" mMnc=").append(mMncStr) .append(" mAlphaLong=").append(mAlphaLong) .append(" mAlphaShort=").append(mAlphaShort) + .append(" mAdditionalPlmns=").append(mAdditionalPlmns) .append("}").toString(); } @@ -261,6 +290,7 @@ public final class CellIdentityGsm extends CellIdentity { dest.writeInt(mCid); dest.writeInt(mArfcn); dest.writeInt(mBsic); + dest.writeList(mAdditionalPlmns); } /** Construct from Parcel, type has already been processed */ @@ -270,6 +300,7 @@ public final class CellIdentityGsm extends CellIdentity { mCid = in.readInt(); mArfcn = in.readInt(); mBsic = in.readInt(); + mAdditionalPlmns = in.readArrayList(null); if (DBG) log(toString()); } diff --git a/telephony/java/android/telephony/CellIdentityLte.java b/telephony/java/android/telephony/CellIdentityLte.java index bc4655069dba..cf8fe6a3c345 100644 --- a/telephony/java/android/telephony/CellIdentityLte.java +++ b/telephony/java/android/telephony/CellIdentityLte.java @@ -24,6 +24,8 @@ import android.os.Parcel; import android.telephony.gsm.GsmCellLocation; import android.text.TextUtils; +import java.util.Collections; +import java.util.List; import java.util.Objects; /** @@ -50,6 +52,11 @@ public final class CellIdentityLte extends CellIdentity { // cell bandwidth, in kHz private final int mBandwidth; + // a list of additional PLMN-IDs reported for this cell + private final List<String> mAdditionalPlmns; + + private ClosedSubscriberGroupInfo mCsgInfo; + /** * @hide */ @@ -61,6 +68,8 @@ public final class CellIdentityLte extends CellIdentity { mTac = CellInfo.UNAVAILABLE; mEarfcn = CellInfo.UNAVAILABLE; mBandwidth = CellInfo.UNAVAILABLE; + mAdditionalPlmns = Collections.emptyList(); + mCsgInfo = null; } /** @@ -76,7 +85,7 @@ public final class CellIdentityLte extends CellIdentity { @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) public CellIdentityLte(int mcc, int mnc, int ci, int pci, int tac) { this(ci, pci, tac, CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE, String.valueOf(mcc), - String.valueOf(mnc), null, null); + String.valueOf(mnc), null, null, Collections.emptyList(), null); } /** @@ -90,34 +99,49 @@ public final class CellIdentityLte extends CellIdentity { * @param mncStr 2 or 3-digit Mobile Network Code in string format * @param alphal long alpha Operator Name String or Enhanced Operator Name String * @param alphas short alpha Operator Name String or Enhanced Operator Name String + * @param additionalPlmns a list of additional PLMN IDs broadcast by the cell + * @param csgInfo info about the closed subscriber group broadcast by the cell * * @hide */ public CellIdentityLte(int ci, int pci, int tac, int earfcn, int bandwidth, String mccStr, - String mncStr, String alphal, String alphas) { + String mncStr, String alphal, String alphas, List<String> additionalPlmns, + ClosedSubscriberGroupInfo csgInfo) { super(TAG, CellInfo.TYPE_LTE, mccStr, mncStr, alphal, alphas); mCi = inRangeOrUnavailable(ci, 0, MAX_CI); mPci = inRangeOrUnavailable(pci, 0, MAX_PCI); mTac = inRangeOrUnavailable(tac, 0, MAX_TAC); mEarfcn = inRangeOrUnavailable(earfcn, 0, MAX_EARFCN); mBandwidth = inRangeOrUnavailable(bandwidth, 0, MAX_BANDWIDTH); + mAdditionalPlmns = additionalPlmns; + mCsgInfo = csgInfo; } /** @hide */ public CellIdentityLte(android.hardware.radio.V1_0.CellIdentityLte cid) { - this(cid.ci, cid.pci, cid.tac, cid.earfcn, CellInfo.UNAVAILABLE, cid.mcc, cid.mnc, "", ""); + this(cid.ci, cid.pci, cid.tac, cid.earfcn, + CellInfo.UNAVAILABLE, cid.mcc, cid.mnc, "", "", Collections.emptyList(), null); } /** @hide */ public CellIdentityLte(android.hardware.radio.V1_2.CellIdentityLte cid) { this(cid.base.ci, cid.base.pci, cid.base.tac, cid.base.earfcn, cid.bandwidth, cid.base.mcc, cid.base.mnc, cid.operatorNames.alphaLong, - cid.operatorNames.alphaShort); + cid.operatorNames.alphaShort, Collections.emptyList(), null); + } + + /** @hide */ + public CellIdentityLte(android.hardware.radio.V1_5.CellIdentityLte cid) { + this(cid.base.base.ci, cid.base.base.pci, cid.base.base.tac, cid.base.base.earfcn, + cid.base.bandwidth, cid.base.base.mcc, cid.base.base.mnc, + cid.base.operatorNames.alphaLong, cid.base.operatorNames.alphaShort, + cid.additionalPlmns, cid.optionalCsgInfo.csgInfo() != null + ? new ClosedSubscriberGroupInfo(cid.optionalCsgInfo.csgInfo()) : null); } private CellIdentityLte(CellIdentityLte cid) { this(cid.mCi, cid.mPci, cid.mTac, cid.mEarfcn, cid.mBandwidth, cid.mMccStr, - cid.mMncStr, cid.mAlphaLong, cid.mAlphaShort); + cid.mMncStr, cid.mAlphaLong, cid.mAlphaShort, cid.mAdditionalPlmns, cid.mCsgInfo); } /** @hide */ @@ -125,7 +149,7 @@ public final class CellIdentityLte extends CellIdentity { public @NonNull CellIdentityLte sanitizeLocationInfo() { return new CellIdentityLte(CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE, - mMccStr, mMncStr, mAlphaLong, mAlphaShort); + mMccStr, mMncStr, mAlphaLong, mAlphaShort, mAdditionalPlmns, null); } CellIdentityLte copy() { @@ -185,6 +209,19 @@ public final class CellIdentityLte extends CellIdentity { } /** + * Get bands of the cell + * + * Reference: 3GPP TS 36.101 section 5.5 + * + * @return List of band number or empty list if not available. + */ + @NonNull + public List<Integer> getBands() { + // Todo: Add actual support + return Collections.emptyList(); + } + + /** * @return Cell bandwidth in kHz, * {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable. */ @@ -223,6 +260,22 @@ public final class CellIdentityLte extends CellIdentity { } /** + * @return a list of additional PLMN IDs supported by this cell. + */ + @NonNull + public List<String> getAdditionalPlmns() { + return mAdditionalPlmns; + } + + /** + * @return closed subscriber group information about the cell if available, otherwise null. + */ + @Nullable + public ClosedSubscriberGroupInfo getClosedSubscriberGroupInfo() { + return mCsgInfo; + } + + /** * A hack to allow tunneling of LTE information via GsmCellLocation * so that older Network Location Providers can return some information * on LTE only networks, see bug 9228974. @@ -247,7 +300,8 @@ public final class CellIdentityLte extends CellIdentity { @Override public int hashCode() { - return Objects.hash(mCi, mPci, mTac, super.hashCode()); + return Objects.hash(mCi, mPci, mTac, + mAdditionalPlmns.hashCode(), mCsgInfo, super.hashCode()); } @Override @@ -268,6 +322,8 @@ public final class CellIdentityLte extends CellIdentity { && mBandwidth == o.mBandwidth && TextUtils.equals(mMccStr, o.mMccStr) && TextUtils.equals(mMncStr, o.mMncStr) + && mAdditionalPlmns.equals(o.mAdditionalPlmns) + && Objects.equals(mCsgInfo, o.mCsgInfo) && super.equals(other); } @@ -283,6 +339,8 @@ public final class CellIdentityLte extends CellIdentity { .append(" mMnc=").append(mMncStr) .append(" mAlphaLong=").append(mAlphaLong) .append(" mAlphaShort=").append(mAlphaShort) + .append(" mAdditionalPlmns=").append(mAdditionalPlmns) + .append(" mCsgInfo=").append(mCsgInfo) .append("}").toString(); } @@ -296,6 +354,8 @@ public final class CellIdentityLte extends CellIdentity { dest.writeInt(mTac); dest.writeInt(mEarfcn); dest.writeInt(mBandwidth); + dest.writeList(mAdditionalPlmns); + dest.writeParcelable(mCsgInfo, flags); } /** Construct from Parcel, type has already been processed */ @@ -306,7 +366,8 @@ public final class CellIdentityLte extends CellIdentity { mTac = in.readInt(); mEarfcn = in.readInt(); mBandwidth = in.readInt(); - + mAdditionalPlmns = in.readArrayList(null); + mCsgInfo = in.readParcelable(null); if (DBG) log(toString()); } diff --git a/telephony/java/android/telephony/CellIdentityNr.java b/telephony/java/android/telephony/CellIdentityNr.java index f08a5807c2b6..d4f181fc735a 100644 --- a/telephony/java/android/telephony/CellIdentityNr.java +++ b/telephony/java/android/telephony/CellIdentityNr.java @@ -20,8 +20,12 @@ import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.Parcel; +import android.telephony.AccessNetworkConstants.NgranBands.NgranBand; import android.telephony.gsm.GsmCellLocation; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import java.util.Objects; /** @@ -39,40 +43,58 @@ public final class CellIdentityNr extends CellIdentity { private final int mPci; private final int mTac; private final long mNci; + private final List<Integer> mBands; + + // a list of additional PLMN-IDs reported for this cell + private final List<String> mAdditionalPlmns; /** * * @param pci Physical Cell Id in range [0, 1007]. * @param tac 16-bit Tracking Area Code. * @param nrArfcn NR Absolute Radio Frequency Channel Number, in range [0, 3279165]. + * @param bands Bands used by the cell. Band number defined in 3GPP TS 38.101-1 and TS 38.101-2. * @param mccStr 3-digit Mobile Country Code in string format. * @param mncStr 2 or 3-digit Mobile Network Code in string format. * @param nci The 36-bit NR Cell Identity in range [0, 68719476735]. * @param alphal long alpha Operator Name String or Enhanced Operator Name String. * @param alphas short alpha Operator Name String or Enhanced Operator Name String. + * @param additionalPlmns a list of additional PLMN IDs broadcast by the cell * * @hide */ - public CellIdentityNr(int pci, int tac, int nrArfcn, String mccStr, String mncStr, - long nci, String alphal, String alphas) { + public CellIdentityNr(int pci, int tac, int nrArfcn, @NgranBand List<Integer> bands, + String mccStr, String mncStr, long nci, String alphal, String alphas, + List<String> additionalPlmns) { super(TAG, CellInfo.TYPE_NR, mccStr, mncStr, alphal, alphas); mPci = inRangeOrUnavailable(pci, 0, MAX_PCI); mTac = inRangeOrUnavailable(tac, 0, MAX_TAC); mNrArfcn = inRangeOrUnavailable(nrArfcn, 0, MAX_NRARFCN); + mBands = new ArrayList<>(bands); mNci = inRangeOrUnavailable(nci, 0, MAX_NCI); + mAdditionalPlmns = new ArrayList<>(additionalPlmns); } /** @hide */ public CellIdentityNr(android.hardware.radio.V1_4.CellIdentityNr cid) { - this(cid.pci, cid.tac, cid.nrarfcn, cid.mcc, cid.mnc, cid.nci, cid.operatorNames.alphaLong, - cid.operatorNames.alphaShort); + this(cid.pci, cid.tac, cid.nrarfcn, Collections.emptyList(), cid.mcc, cid.mnc, cid.nci, + cid.operatorNames.alphaLong, cid.operatorNames.alphaShort, + Collections.emptyList()); + } + + /** @hide */ + public CellIdentityNr(android.hardware.radio.V1_5.CellIdentityNr cid) { + this(cid.base.pci, cid.base.tac, cid.base.nrarfcn, cid.bands, cid.base.mcc, cid.base.mnc, + cid.base.nci, cid.base.operatorNames.alphaLong, + cid.base.operatorNames.alphaShort, cid.additionalPlmns); } /** @hide */ @Override public @NonNull CellIdentityNr sanitizeLocationInfo() { - return new CellIdentityNr(CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE, - mMccStr, mMncStr, CellInfo.UNAVAILABLE, mAlphaLong, mAlphaShort); + return new CellIdentityNr(CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE, mNrArfcn, + mBands, mMccStr, mMncStr, CellInfo.UNAVAILABLE, mAlphaLong, mAlphaShort, + mAdditionalPlmns); } /** @@ -87,7 +109,8 @@ public final class CellIdentityNr extends CellIdentity { @Override public int hashCode() { - return Objects.hash(super.hashCode(), mPci, mTac, mNrArfcn, mNci); + return Objects.hash(super.hashCode(), mPci, mTac, + mNrArfcn, mBands.hashCode(), mNci, mAdditionalPlmns.hashCode()); } @Override @@ -98,7 +121,8 @@ public final class CellIdentityNr extends CellIdentity { CellIdentityNr o = (CellIdentityNr) other; return super.equals(o) && mPci == o.mPci && mTac == o.mTac && mNrArfcn == o.mNrArfcn - && mNci == o.mNci; + && mBands.equals(o.mBands) && mNci == o.mNci + && mAdditionalPlmns.equals(o.mAdditionalPlmns); } /** @@ -125,6 +149,20 @@ public final class CellIdentityNr extends CellIdentity { } /** + * Get bands of the cell + * + * Reference: TS 38.101-1 table 5.2-1 + * Reference: TS 38.101-2 table 5.2-1 + * + * @return List of band number or empty list if not available. + */ + @NgranBand + @NonNull + public List<Integer> getBands() { + return Collections.unmodifiableList(mBands); + } + + /** * Get the physical cell id. * @return Integer value in range [0, 1007] or {@link CellInfo#UNAVAILABLE} if unknown. */ @@ -158,17 +196,33 @@ public final class CellIdentityNr extends CellIdentity { return mMncStr; } + /** @hide */ + @Override + public int getChannelNumber() { + return mNrArfcn; + } + + /** + * @return a list of additional PLMN IDs supported by this cell. + */ + @NonNull + public List<String> getAdditionalPlmns() { + return Collections.unmodifiableList(mAdditionalPlmns); + } + @Override public String toString() { return new StringBuilder(TAG + ":{") .append(" mPci = ").append(mPci) .append(" mTac = ").append(mTac) .append(" mNrArfcn = ").append(mNrArfcn) + .append(" mBands = ").append(mBands) .append(" mMcc = ").append(mMccStr) .append(" mMnc = ").append(mMncStr) .append(" mNci = ").append(mNci) .append(" mAlphaLong = ").append(mAlphaLong) .append(" mAlphaShort = ").append(mAlphaShort) + .append(" mAdditionalPlmns = ").append(mAdditionalPlmns) .append(" }") .toString(); } @@ -179,7 +233,9 @@ public final class CellIdentityNr extends CellIdentity { dest.writeInt(mPci); dest.writeInt(mTac); dest.writeInt(mNrArfcn); + dest.writeList(mBands); dest.writeLong(mNci); + dest.writeList(mAdditionalPlmns); } /** Construct from Parcel, type has already been processed */ @@ -188,7 +244,9 @@ public final class CellIdentityNr extends CellIdentity { mPci = in.readInt(); mTac = in.readInt(); mNrArfcn = in.readInt(); + mBands = in.readArrayList(null); mNci = in.readLong(); + mAdditionalPlmns = in.readArrayList(null); } /** Implement the Parcelable interface */ diff --git a/telephony/java/android/telephony/CellIdentityTdscdma.java b/telephony/java/android/telephony/CellIdentityTdscdma.java index 4bb3a95a9f1d..2ff351c17e9a 100644 --- a/telephony/java/android/telephony/CellIdentityTdscdma.java +++ b/telephony/java/android/telephony/CellIdentityTdscdma.java @@ -21,6 +21,8 @@ import android.annotation.Nullable; import android.os.Parcel; import android.telephony.gsm.GsmCellLocation; +import java.util.Collections; +import java.util.List; import java.util.Objects; /** @@ -46,6 +48,11 @@ public final class CellIdentityTdscdma extends CellIdentity { // 16-bit UMTS Absolute RF Channel Number described in TS 25.101 sec. 5.4.3 private final int mUarfcn; + // a list of additional PLMN-IDs reported for this cell + private final List<String> mAdditionalPlmns; + + private ClosedSubscriberGroupInfo mCsgInfo; + /** * @hide */ @@ -55,6 +62,8 @@ public final class CellIdentityTdscdma extends CellIdentity { mCid = CellInfo.UNAVAILABLE; mCpid = CellInfo.UNAVAILABLE; mUarfcn = CellInfo.UNAVAILABLE; + mAdditionalPlmns = Collections.emptyList(); + mCsgInfo = null; } /** @@ -68,39 +77,57 @@ public final class CellIdentityTdscdma extends CellIdentity { * @param uarfcn 16-bit UMTS Absolute RF Channel Number described in TS 25.101 sec. 5.4.3 * @param alphal long alpha Operator Name String or Enhanced Operator Name String * @param alphas short alpha Operator Name String or Enhanced Operator Name String + * @param additionalPlmns a list of additional PLMN IDs broadcast by the cell + * @param csgInfo info about the closed subscriber group broadcast by the cell * * @hide */ public CellIdentityTdscdma(String mcc, String mnc, int lac, int cid, int cpid, int uarfcn, - String alphal, String alphas) { + String alphal, String alphas, @NonNull List<String> additionalPlmns, + ClosedSubscriberGroupInfo csgInfo) { super(TAG, CellInfo.TYPE_TDSCDMA, mcc, mnc, alphal, alphas); mLac = inRangeOrUnavailable(lac, 0, MAX_LAC); mCid = inRangeOrUnavailable(cid, 0, MAX_CID); mCpid = inRangeOrUnavailable(cpid, 0, MAX_CPID); mUarfcn = inRangeOrUnavailable(uarfcn, 0, MAX_UARFCN); + mAdditionalPlmns = additionalPlmns; + mCsgInfo = csgInfo; } private CellIdentityTdscdma(CellIdentityTdscdma cid) { this(cid.mMccStr, cid.mMncStr, cid.mLac, cid.mCid, - cid.mCpid, cid.mUarfcn, cid.mAlphaLong, cid.mAlphaShort); + cid.mCpid, cid.mUarfcn, cid.mAlphaLong, + cid.mAlphaShort, cid.mAdditionalPlmns, cid.mCsgInfo); } /** @hide */ public CellIdentityTdscdma(android.hardware.radio.V1_0.CellIdentityTdscdma cid) { - this(cid.mcc, cid.mnc, cid.lac, cid.cid, cid.cpid, CellInfo.UNAVAILABLE, "", ""); + this(cid.mcc, cid.mnc, cid.lac, cid.cid, cid.cpid, CellInfo.UNAVAILABLE, "", "", + Collections.emptyList(), null); } /** @hide */ public CellIdentityTdscdma(android.hardware.radio.V1_2.CellIdentityTdscdma cid) { this(cid.base.mcc, cid.base.mnc, cid.base.lac, cid.base.cid, cid.base.cpid, - cid.uarfcn, cid.operatorNames.alphaLong, cid.operatorNames.alphaShort); + cid.uarfcn, cid.operatorNames.alphaLong, cid.operatorNames.alphaShort, + Collections.emptyList(), null); + } + + /** @hide */ + public CellIdentityTdscdma(android.hardware.radio.V1_5.CellIdentityTdscdma cid) { + this(cid.base.base.mcc, cid.base.base.mnc, cid.base.base.lac, cid.base.base.cid, + cid.base.base.cpid, cid.base.uarfcn, cid.base.operatorNames.alphaLong, + cid.base.operatorNames.alphaShort, + cid.additionalPlmns, cid.optionalCsgInfo.csgInfo() != null + ? new ClosedSubscriberGroupInfo(cid.optionalCsgInfo.csgInfo()) : null); } /** @hide */ @Override public @NonNull CellIdentityTdscdma sanitizeLocationInfo() { return new CellIdentityTdscdma(mMccStr, mMncStr, CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE, - CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE, mAlphaLong, mAlphaShort); + CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE, mAlphaLong, mAlphaShort, + mAdditionalPlmns, null); } CellIdentityTdscdma copy() { @@ -171,6 +198,22 @@ public final class CellIdentityTdscdma extends CellIdentity { return mUarfcn; } + /** + * @return a list of additional PLMN IDs supported by this cell. + */ + @NonNull + public List<String> getAdditionalPlmns() { + return mAdditionalPlmns; + } + + /** + * @return closed subscriber group information about the cell if available, otherwise null. + */ + @Nullable + public ClosedSubscriberGroupInfo getClosedSubscriberGroupInfo() { + return mCsgInfo; + } + /** @hide */ @NonNull @Override @@ -198,12 +241,15 @@ public final class CellIdentityTdscdma extends CellIdentity { && mCid == o.mCid && mCpid == o.mCpid && mUarfcn == o.mUarfcn + && mAdditionalPlmns.equals(o.mAdditionalPlmns) + && Objects.equals(mCsgInfo, o.mCsgInfo) && super.equals(other); } @Override public int hashCode() { - return Objects.hash(mLac, mCid, mCpid, mUarfcn, super.hashCode()); + return Objects.hash(mLac, mCid, mCpid, mUarfcn, + mAdditionalPlmns.hashCode(), mCsgInfo, super.hashCode()); } @Override @@ -217,6 +263,8 @@ public final class CellIdentityTdscdma extends CellIdentity { .append(" mCid=").append(mCid) .append(" mCpid=").append(mCpid) .append(" mUarfcn=").append(mUarfcn) + .append(" mAdditionalPlmns=").append(mAdditionalPlmns) + .append(" mCsgInfo=").append(mCsgInfo) .append("}").toString(); } @@ -235,6 +283,8 @@ public final class CellIdentityTdscdma extends CellIdentity { dest.writeInt(mCid); dest.writeInt(mCpid); dest.writeInt(mUarfcn); + dest.writeList(mAdditionalPlmns); + dest.writeParcelable(mCsgInfo, flags); } /** Construct from Parcel, type has already been processed */ @@ -244,6 +294,8 @@ public final class CellIdentityTdscdma extends CellIdentity { mCid = in.readInt(); mCpid = in.readInt(); mUarfcn = in.readInt(); + mAdditionalPlmns = in.readArrayList(null); + mCsgInfo = in.readParcelable(null); if (DBG) log(toString()); } diff --git a/telephony/java/android/telephony/CellIdentityWcdma.java b/telephony/java/android/telephony/CellIdentityWcdma.java index 4ecd134c4ba9..9be42a17677b 100644 --- a/telephony/java/android/telephony/CellIdentityWcdma.java +++ b/telephony/java/android/telephony/CellIdentityWcdma.java @@ -23,6 +23,8 @@ import android.os.Parcel; import android.telephony.gsm.GsmCellLocation; import android.text.TextUtils; +import java.util.Collections; +import java.util.List; import java.util.Objects; /** @@ -47,6 +49,12 @@ public final class CellIdentityWcdma extends CellIdentity { @UnsupportedAppUsage private final int mUarfcn; + // a list of additional PLMN-IDs reported for this cell + private final List<String> mAdditionalPlmns; + + @Nullable + private final ClosedSubscriberGroupInfo mCsgInfo; + /** * @hide */ @@ -56,6 +64,8 @@ public final class CellIdentityWcdma extends CellIdentity { mCid = CellInfo.UNAVAILABLE; mPsc = CellInfo.UNAVAILABLE; mUarfcn = CellInfo.UNAVAILABLE; + mAdditionalPlmns = Collections.emptyList(); + mCsgInfo = null; } /** @@ -68,33 +78,49 @@ public final class CellIdentityWcdma extends CellIdentity { * @param mncStr 2 or 3-digit Mobile Network Code in string format * @param alphal long alpha Operator Name String or Enhanced Operator Name String * @param alphas short alpha Operator Name String or Enhanced Operator Name String + * @param additionalPlmns a list of additional PLMN IDs broadcast by the cell + * @param csgInfo info about the closed subscriber group broadcast by the cell * * @hide */ public CellIdentityWcdma (int lac, int cid, int psc, int uarfcn, - String mccStr, String mncStr, String alphal, String alphas) { + String mccStr, String mncStr, String alphal, String alphas, + @NonNull List<String> additionalPlmns, + @Nullable ClosedSubscriberGroupInfo csgInfo) { super(TAG, CellInfo.TYPE_WCDMA, mccStr, mncStr, alphal, alphas); mLac = inRangeOrUnavailable(lac, 0, MAX_LAC); mCid = inRangeOrUnavailable(cid, 0, MAX_CID); mPsc = inRangeOrUnavailable(psc, 0, MAX_PSC); mUarfcn = inRangeOrUnavailable(uarfcn, 0, MAX_UARFCN); + mAdditionalPlmns = additionalPlmns; + mCsgInfo = csgInfo; } /** @hide */ public CellIdentityWcdma(android.hardware.radio.V1_0.CellIdentityWcdma cid) { - this(cid.lac, cid.cid, cid.psc, cid.uarfcn, cid.mcc, cid.mnc, "", ""); + this(cid.lac, cid.cid, cid.psc, cid.uarfcn, cid.mcc, cid.mnc, "", "", + Collections.emptyList(), null); } /** @hide */ public CellIdentityWcdma(android.hardware.radio.V1_2.CellIdentityWcdma cid) { this(cid.base.lac, cid.base.cid, cid.base.psc, cid.base.uarfcn, cid.base.mcc, cid.base.mnc, cid.operatorNames.alphaLong, - cid.operatorNames.alphaShort); + cid.operatorNames.alphaShort, Collections.emptyList(), null); + } + + /** @hide */ + public CellIdentityWcdma(android.hardware.radio.V1_5.CellIdentityWcdma cid) { + this(cid.base.base.lac, cid.base.base.cid, cid.base.base.psc, cid.base.base.uarfcn, + cid.base.base.mcc, cid.base.base.mnc, cid.base.operatorNames.alphaLong, + cid.base.operatorNames.alphaShort, cid.additionalPlmns, + cid.optionalCsgInfo.csgInfo() != null + ? new ClosedSubscriberGroupInfo(cid.optionalCsgInfo.csgInfo()) : null); } private CellIdentityWcdma(CellIdentityWcdma cid) { this(cid.mLac, cid.mCid, cid.mPsc, cid.mUarfcn, cid.mMccStr, - cid.mMncStr, cid.mAlphaLong, cid.mAlphaShort); + cid.mMncStr, cid.mAlphaLong, cid.mAlphaShort, cid.mAdditionalPlmns, cid.mCsgInfo); } /** @hide */ @@ -102,7 +128,7 @@ public final class CellIdentityWcdma extends CellIdentity { public @NonNull CellIdentityWcdma sanitizeLocationInfo() { return new CellIdentityWcdma(CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE, mMccStr, mMncStr, - mAlphaLong, mAlphaShort); + mAlphaLong, mAlphaShort, mAdditionalPlmns, null); } CellIdentityWcdma copy() { @@ -180,7 +206,7 @@ public final class CellIdentityWcdma extends CellIdentity { @Override public int hashCode() { - return Objects.hash(mLac, mCid, mPsc, super.hashCode()); + return Objects.hash(mLac, mCid, mPsc, mAdditionalPlmns.hashCode(), super.hashCode()); } /** @@ -197,6 +223,22 @@ public final class CellIdentityWcdma extends CellIdentity { return mUarfcn; } + /** + * @return a list of additional PLMN IDs supported by this cell. + */ + @NonNull + public List<String> getAdditionalPlmns() { + return mAdditionalPlmns; + } + + /** + * @return closed subscriber group information about the cell if available, otherwise null. + */ + @Nullable + public ClosedSubscriberGroupInfo getClosedSubscriberGroupInfo() { + return mCsgInfo; + } + /** @hide */ @NonNull @Override @@ -228,6 +270,8 @@ public final class CellIdentityWcdma extends CellIdentity { && mUarfcn == o.mUarfcn && TextUtils.equals(mMccStr, o.mMccStr) && TextUtils.equals(mMncStr, o.mMncStr) + && mAdditionalPlmns.equals(o.mAdditionalPlmns) + && Objects.equals(mCsgInfo, o.mCsgInfo) && super.equals(other); } @@ -242,6 +286,8 @@ public final class CellIdentityWcdma extends CellIdentity { .append(" mMnc=").append(mMncStr) .append(" mAlphaLong=").append(mAlphaLong) .append(" mAlphaShort=").append(mAlphaShort) + .append(" mAdditionalPlmns=").append(mAdditionalPlmns) + .append(" mCsgInfo=").append(mCsgInfo) .append("}").toString(); } @@ -254,6 +300,8 @@ public final class CellIdentityWcdma extends CellIdentity { dest.writeInt(mCid); dest.writeInt(mPsc); dest.writeInt(mUarfcn); + dest.writeList(mAdditionalPlmns); + dest.writeParcelable(mCsgInfo, flags); } /** Construct from Parcel, type has already been processed */ @@ -263,6 +311,8 @@ public final class CellIdentityWcdma extends CellIdentity { mCid = in.readInt(); mPsc = in.readInt(); mUarfcn = in.readInt(); + mAdditionalPlmns = in.readArrayList(null); + mCsgInfo = in.readParcelable(null); if (DBG) log(toString()); } diff --git a/telephony/java/android/telephony/ClosedSubscriberGroupInfo.aidl b/telephony/java/android/telephony/ClosedSubscriberGroupInfo.aidl new file mode 100644 index 000000000000..cbe76381a608 --- /dev/null +++ b/telephony/java/android/telephony/ClosedSubscriberGroupInfo.aidl @@ -0,0 +1,20 @@ +/* +** +** Copyright 2020, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +package android.telephony; + +parcelable ClosedSubscriberGroupInfo; diff --git a/telephony/java/android/telephony/ClosedSubscriberGroupInfo.java b/telephony/java/android/telephony/ClosedSubscriberGroupInfo.java new file mode 100644 index 000000000000..e7dfe634590d --- /dev/null +++ b/telephony/java/android/telephony/ClosedSubscriberGroupInfo.java @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony; + +import android.annotation.IntRange; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.Objects; + +/** + * Information to represent a closed subscriber group. + */ +public final class ClosedSubscriberGroupInfo implements Parcelable { + private static final String TAG = "ClosedSubscriberGroupInfo"; + + private final boolean mCsgIndicator; + + private final String mHomeNodebName; + + private final int mCsgIdentity; + + /** @hide */ + public ClosedSubscriberGroupInfo(boolean csgIndicator, @Nullable String homeNodebName, + int csgIdentity) { + mCsgIndicator = csgIndicator; + mHomeNodebName = (homeNodebName == null) ? "" : homeNodebName; + mCsgIdentity = csgIdentity; + } + + /** @hide */ + public ClosedSubscriberGroupInfo( + @NonNull android.hardware.radio.V1_5.ClosedSubscriberGroupInfo csgInfo) { + this(csgInfo.csgIndication, csgInfo.homeNodebName, csgInfo.csgIdentity); + } + + /** + * Indicates whether the cell is restricted to only CSG members. + * + * A cell not broadcasting the CSG Indication but reporting CSG information is considered a + * Hybrid Cell. + * Refer to the "csg-Indication" field in 3GPP TS 36.331 section 6.2.2 + * SystemInformationBlockType1. + * Also refer to "CSG Indicator" in 3GPP TS 25.331 section 10.2.48.8.1 and TS 25.304. + * + * @return true if the cell is restricted to group members only. + */ + public boolean getCsgIndicator() { + return mCsgIndicator; + } + + /** + * Returns human-readable name of the closed subscriber group operating this cell (Node-B). + * + * Refer to "hnb-Name" in TS 36.331 section 6.2.2 SystemInformationBlockType9. + * Also refer to "HNB Name" in 3GPP TS25.331 section 10.2.48.8.23 and TS 23.003 section 4.8. + * + * @return the home Node-B name if available. + */ + public @NonNull String getHomeNodebName() { + return mHomeNodebName; + } + + /** + * The identity of the closed subscriber group that the cell belongs to. + * + * Refer to "CSG-Identity" in TS 36.336 section 6.3.4. + * Also refer to "CSG Identity" in 3GPP TS 25.331 section 10.3.2.8 and TS 23.003 section 4.7. + * + * @return the unique 27-bit CSG Identity. + */ + @IntRange(from = 0, to = 0x7FFFFFF) + public int getCsgIdentity() { + return mCsgIdentity; + } + + @Override + public int hashCode() { + return Objects.hash(mCsgIndicator, mHomeNodebName, mCsgIdentity); + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof ClosedSubscriberGroupInfo)) { + return false; + } + + ClosedSubscriberGroupInfo o = (ClosedSubscriberGroupInfo) other; + return mCsgIndicator == o.mCsgIndicator && mHomeNodebName == o.mHomeNodebName + && mCsgIdentity == o.mCsgIdentity; + } + + @Override + public String toString() { + return new StringBuilder(TAG + ":{") + .append(" mCsgIndicator = ").append(mCsgIndicator) + .append(" mHomeNodebName = ").append(mHomeNodebName) + .append(" mCsgIdentity = ").append(mCsgIdentity) + .toString(); + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int type) { + dest.writeBoolean(mCsgIndicator); + dest.writeString(mHomeNodebName); + dest.writeInt(mCsgIdentity); + } + + /** Construct from Parcel, type has already been processed */ + private ClosedSubscriberGroupInfo(Parcel in) { + this(in.readBoolean(), in.readString(), in.readInt()); + } + + /** + * Implement the Parcelable interface + */ + @Override + public int describeContents() { + return 0; + } + + /** Implement the Parcelable interface */ + public static final @android.annotation.NonNull Creator<ClosedSubscriberGroupInfo> CREATOR = + new Creator<ClosedSubscriberGroupInfo>() { + @Override + public ClosedSubscriberGroupInfo createFromParcel(Parcel in) { + return createFromParcelBody(in); + } + + @Override + public ClosedSubscriberGroupInfo[] newArray(int size) { + return new ClosedSubscriberGroupInfo[size]; + } + }; + + /** @hide */ + protected static ClosedSubscriberGroupInfo createFromParcelBody(Parcel in) { + return new ClosedSubscriberGroupInfo(in); + } +} diff --git a/telephony/java/android/telephony/ModemActivityInfo.java b/telephony/java/android/telephony/ModemActivityInfo.java index aee7cca75252..bd2375f7d297 100644 --- a/telephony/java/android/telephony/ModemActivityInfo.java +++ b/telephony/java/android/telephony/ModemActivityInfo.java @@ -199,10 +199,10 @@ public final class ModemActivityInfo implements Parcelable { } /** + * Indicate if the ModemActivityInfo is invalid due to modem's invalid reporting. + * * @return {@code true} if this {@link ModemActivityInfo} record is valid, * {@code false} otherwise. - * - * @hide */ public boolean isValid() { for (TransmitPower powerInfo : getTransmitPowerInfo()) { diff --git a/telephony/java/android/telephony/ModemInfo.java b/telephony/java/android/telephony/ModemInfo.java deleted file mode 100644 index c0833af954d8..000000000000 --- a/telephony/java/android/telephony/ModemInfo.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.telephony; - -import android.os.Parcel; -import android.os.Parcelable; - -import java.util.Objects; - -/** - * Information of a single logical modem indicating - * its id, supported rats and whether it supports voice or data, etc. - * @hide - */ -public class ModemInfo implements Parcelable { - public final int modemId; - public final int rat; /* bitset */ - public final boolean isVoiceSupported; - public final boolean isDataSupported; - - // TODO b/121394331: Clean up this class after V1_1.PhoneCapability cleanup. - public ModemInfo(int modemId) { - this(modemId, 0, true, true); - } - - public ModemInfo(int modemId, int rat, boolean isVoiceSupported, boolean isDataSupported) { - this.modemId = modemId; - this.rat = rat; - this.isVoiceSupported = isVoiceSupported; - this.isDataSupported = isDataSupported; - } - - public ModemInfo(Parcel in) { - modemId = in.readInt(); - rat = in.readInt(); - isVoiceSupported = in.readBoolean(); - isDataSupported = in.readBoolean(); - } - - @Override - public String toString() { - return "modemId=" + modemId + " rat=" + rat + " isVoiceSupported:" + isVoiceSupported - + " isDataSupported:" + isDataSupported; - } - - @Override - public int hashCode() { - return Objects.hash(modemId, rat, isVoiceSupported, isDataSupported); - } - - @Override - public boolean equals(Object o) { - if (o == null || !(o instanceof ModemInfo) || hashCode() != o.hashCode()) { - return false; - } - - if (this == o) { - return true; - } - - ModemInfo s = (ModemInfo) o; - - return (modemId == s.modemId - && rat == s.rat - && isVoiceSupported == s.isVoiceSupported - && isDataSupported == s.isDataSupported); - } - - /** - * {@link Parcelable#describeContents} - */ - public @ContentsFlags int describeContents() { - return 0; - } - - /** - * {@link Parcelable#writeToParcel} - */ - public void writeToParcel(Parcel dest, @WriteFlags int flags) { - dest.writeInt(modemId); - dest.writeInt(rat); - dest.writeBoolean(isVoiceSupported); - dest.writeBoolean(isDataSupported); - } - - public static final @android.annotation.NonNull Parcelable.Creator<ModemInfo> CREATOR = new Parcelable.Creator() { - public ModemInfo createFromParcel(Parcel in) { - return new ModemInfo(in); - } - - public ModemInfo[] newArray(int size) { - return new ModemInfo[size]; - } - }; -} diff --git a/telephony/java/android/telephony/NetworkScanRequest.java b/telephony/java/android/telephony/NetworkScanRequest.java index 465b6aa79d40..c8b8ffb9846b 100644 --- a/telephony/java/android/telephony/NetworkScanRequest.java +++ b/telephony/java/android/telephony/NetworkScanRequest.java @@ -20,10 +20,10 @@ import android.annotation.IntDef; import android.os.Parcel; import android.os.Parcelable; -import java.util.ArrayList; -import java.util.Arrays; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.ArrayList; +import java.util.Arrays; /** * Defines a request to peform a network scan. @@ -221,9 +221,15 @@ public final class NetworkScanRequest implements Parcelable { private NetworkScanRequest(Parcel in) { mScanType = in.readInt(); - mSpecifiers = (RadioAccessSpecifier[]) in.readParcelableArray( - Object.class.getClassLoader(), - RadioAccessSpecifier.class); + Parcelable[] tempSpecifiers = in.readParcelableArray(Object.class.getClassLoader()); + if (tempSpecifiers != null) { + mSpecifiers = new RadioAccessSpecifier[tempSpecifiers.length]; + for (int i = 0; i < tempSpecifiers.length; i++) { + mSpecifiers[i] = (RadioAccessSpecifier) tempSpecifiers[i]; + } + } else { + mSpecifiers = null; + } mSearchPeriodicity = in.readInt(); mMaxSearchTime = in.readInt(); mIncrementalResults = in.readBoolean(); diff --git a/telephony/java/android/telephony/PhoneCapability.java b/telephony/java/android/telephony/PhoneCapability.java index 8a75831a75b8..90244b3df350 100644 --- a/telephony/java/android/telephony/PhoneCapability.java +++ b/telephony/java/android/telephony/PhoneCapability.java @@ -16,13 +16,20 @@ package android.telephony; +import android.annotation.LongDef; import android.annotation.NonNull; -import android.annotation.SystemApi; +import android.annotation.Nullable; import android.os.Parcel; import android.os.Parcelable; +import android.telephony.AccessNetworkConstants.AccessNetworkType; +import android.telephony.AccessNetworkConstants.RadioAccessNetworkType; +import android.telephony.TelephonyManager.NetworkTypeBitMask; +import com.android.internal.util.CollectionUtils; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.Objects; @@ -31,68 +38,365 @@ import java.util.Objects; * are shared between those modems defined by list of modem IDs. */ public final class PhoneCapability implements Parcelable { - // Hardcoded default DSDS capability. + /** Modem feature indicating 3GPP2 capability. */ + public static final long MODEM_FEATURE_3GPP2_REG = 1 << 0; + /** Modem feature indicating 3GPP capability. */ + public static final long MODEM_FEATURE_3GPP_REG = 1 << 1; + /** Modem feature indicating CDMA 2000 with EHRPD capability. */ + public static final long MODEM_FEATURE_CDMA2000_EHRPD_REG = 1 << 2; + /** Modem feature indicating GSM capability. */ + public static final long MODEM_FEATURE_GERAN_REG = 1 << 3; + /** Modem feature indicating UMTS capability. */ + public static final long MODEM_FEATURE_UTRAN_REG = 1 << 4; + /** Modem feature indicating LTE capability. */ + public static final long MODEM_FEATURE_EUTRAN_REG = 1 << 5; + /** Modem feature indicating 5G capability.*/ + public static final long MODEM_FEATURE_NGRAN_REG = 1 << 6; + /** Modem feature indicating EN-DC capability. */ + public static final long MODEM_FEATURE_EUTRA_NR_DUAL_CONNECTIVITY_REG = 1 << 7; + /** Modem feature indicating VoLTE capability (IMS registered). */ + public static final long MODEM_FEATURE_PS_VOICE_REG = 1 << 8; + /** Modem feature indicating CS voice call capability. */ + public static final long MODEM_FEATURE_CS_VOICE_SESSION = 1 << 9; + /** Modem feature indicating Internet connection capability. */ + public static final long MODEM_FEATURE_INTERACTIVE_DATA_SESSION = 1 << 10; + /** + * Modem feature indicating dedicated bearer capability. + * For services that require a high level QoS (eg. VoLTE), the network can create + * a dedicated bearer with the required QoS on top of an established default bearer. + * This will provide a dedicated tunnel for one or more specific traffic types. + */ + public static final long MODEM_FEATURE_DEDICATED_BEARER = 1 << 11; + /** Modem feature indicating network scan capability. */ + public static final long MODEM_FEATURE_NETWORK_SCAN = 1 << 12; + /** Modem feature indicating corresponding SIM has CDMA capability. */ + public static final long MODEM_FEATURE_CSIM = 1 << 13; + /** @hide */ + @LongDef(flag = true, prefix = {"MODEM_FEATURE_" }, value = { + MODEM_FEATURE_3GPP2_REG, + MODEM_FEATURE_3GPP_REG, + MODEM_FEATURE_CDMA2000_EHRPD_REG, + MODEM_FEATURE_GERAN_REG, + MODEM_FEATURE_UTRAN_REG, + MODEM_FEATURE_EUTRAN_REG, + MODEM_FEATURE_NGRAN_REG, + MODEM_FEATURE_EUTRA_NR_DUAL_CONNECTIVITY_REG, + MODEM_FEATURE_PS_VOICE_REG, + MODEM_FEATURE_CS_VOICE_SESSION, + MODEM_FEATURE_INTERACTIVE_DATA_SESSION, + MODEM_FEATURE_DEDICATED_BEARER, + MODEM_FEATURE_NETWORK_SCAN, + MODEM_FEATURE_CSIM, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface ModemFeature { + } + + /** + * Hardcoded default DSDS capability. + * @hide + */ public static final PhoneCapability DEFAULT_DSDS_CAPABILITY; - // Hardcoded default Single SIM single standby capability. - /** @hide */ + /** + * Hardcoded default Single SIM single standby capability. + * @hide + */ public static final PhoneCapability DEFAULT_SSSS_CAPABILITY; static { - ModemInfo modemInfo1 = new ModemInfo(0, 0, true, true); - ModemInfo modemInfo2 = new ModemInfo(1, 0, true, true); + List<List<Long>> capabilities = new ArrayList<>(); + List<Long> modem1 = new ArrayList<>(); + List<Long> modem2 = new ArrayList<>(); + modem1.add(MODEM_FEATURE_GERAN_REG | MODEM_FEATURE_UTRAN_REG | MODEM_FEATURE_EUTRAN_REG + | MODEM_FEATURE_PS_VOICE_REG | MODEM_FEATURE_CS_VOICE_SESSION + | MODEM_FEATURE_INTERACTIVE_DATA_SESSION | MODEM_FEATURE_DEDICATED_BEARER); + modem2.add(MODEM_FEATURE_GERAN_REG | MODEM_FEATURE_UTRAN_REG | MODEM_FEATURE_EUTRAN_REG + | MODEM_FEATURE_PS_VOICE_REG | MODEM_FEATURE_INTERACTIVE_DATA_SESSION + | MODEM_FEATURE_DEDICATED_BEARER); + capabilities.add(modem1); + capabilities.add(modem2); + List<String> uuids = new ArrayList<>(); + uuids.add("com.xxxx.lm0"); + uuids.add("com.xxxx.lm1"); + long rats = TelephonyManager.NETWORK_TYPE_BITMASK_GSM + | TelephonyManager.NETWORK_TYPE_BITMASK_GPRS + | TelephonyManager.NETWORK_TYPE_BITMASK_EDGE + | TelephonyManager.NETWORK_TYPE_BITMASK_UMTS + | TelephonyManager.NETWORK_TYPE_BITMASK_LTE; + DEFAULT_DSDS_CAPABILITY = new PhoneCapability(0, 0, 0, 0, 0, rats, null, null, null, null, + uuids, null, capabilities); + + capabilities = new ArrayList<>(); + capabilities.add(modem1); + uuids = new ArrayList<>(); + uuids.add("com.xxxx.lm0"); + DEFAULT_SSSS_CAPABILITY = new PhoneCapability(0, 0, 0, 0, 0, rats, null, null, null, null, + uuids, null, capabilities); + } - List<ModemInfo> logicalModemList = new ArrayList<>(); - logicalModemList.add(modemInfo1); - logicalModemList.add(modemInfo2); - DEFAULT_DSDS_CAPABILITY = new PhoneCapability(1, 1, 0, logicalModemList, false); + private final int mUtranUeCategoryDl; + private final int mUtranUeCategoryUl; + private final int mEutranUeCategoryDl; + private final int mEutranUeCategoryUl; + private final long mPsDataConnectionLingerTimeMillis; + private final @NetworkTypeBitMask long mSupportedRats; + private final List<Integer> mGeranBands; + private final List<Integer> mUtranBands; + private final List<Integer> mEutranBands; + private final List<Integer> mNgranBands; + private final List<String> mLogicalModemUuids; + private final List<SimSlotCapability> mSimSlotCapabilities; + private final @ModemFeature List<List<Long>> mConcurrentFeaturesSupport; - logicalModemList = new ArrayList<>(); - logicalModemList.add(modemInfo1); - DEFAULT_SSSS_CAPABILITY = new PhoneCapability(1, 1, 0, logicalModemList, false); + /** + * Default constructor to create a PhoneCapability object. + * @param utranUeCategoryDl 3GPP UE category for UTRAN downlink. + * @param utranUeCategoryUl 3GPP UE category for UTRAN uplink. + * @param eutranUeCategoryDl 3GPP UE category for EUTRAN downlink. + * @param eutranUeCategoryUl 3GPP UE category for EUTRAN uplink. + * @param psDataConnectionLingerTimeMillis length of the grace period to allow a smooth + * "handover" between data connections. + * @param supportedRats all radio access technologies this phone is capable of supporting. + * @param geranBands list of supported {@link AccessNetworkConstants.GeranBand}. + * @param utranBands list of supported {@link AccessNetworkConstants.UtranBand}. + * @param eutranBands list of supported {@link AccessNetworkConstants.EutranBand}. + * @param ngranBands list of supported {@link AccessNetworkConstants.NgranBands}. + * @param logicalModemUuids list of logical modem UUIDs, typically of the form + * "com.xxxx.lmX", where X is the logical modem ID. + * @param simSlotCapabilities list of {@link SimSlotCapability} for the device + * @param concurrentFeaturesSupport list of list of concurrently supportable modem feature sets. + * @hide + */ + public PhoneCapability(int utranUeCategoryDl, int utranUeCategoryUl, int eutranUeCategoryDl, + int eutranUeCategoryUl, long psDataConnectionLingerTimeMillis, + @NetworkTypeBitMask long supportedRats, @Nullable List<Integer> geranBands, + @Nullable List<Integer> utranBands, @Nullable List<Integer> eutranBands, + @Nullable List<Integer> ngranBands, @Nullable List<String> logicalModemUuids, + @Nullable List<SimSlotCapability> simSlotCapabilities, + @Nullable @ModemFeature List<List<Long>> concurrentFeaturesSupport) { + this.mUtranUeCategoryDl = utranUeCategoryDl; + this.mUtranUeCategoryUl = utranUeCategoryUl; + this.mEutranUeCategoryDl = eutranUeCategoryDl; + this.mEutranUeCategoryUl = eutranUeCategoryUl; + this.mPsDataConnectionLingerTimeMillis = psDataConnectionLingerTimeMillis; + this.mSupportedRats = supportedRats; + this.mGeranBands = CollectionUtils.emptyIfNull(geranBands); + this.mUtranBands = CollectionUtils.emptyIfNull(utranBands); + this.mEutranBands = CollectionUtils.emptyIfNull(eutranBands); + this.mNgranBands = CollectionUtils.emptyIfNull(ngranBands); + this.mLogicalModemUuids = CollectionUtils.emptyIfNull(logicalModemUuids); + this.mSimSlotCapabilities = CollectionUtils.emptyIfNull(simSlotCapabilities); + this.mConcurrentFeaturesSupport = CollectionUtils.emptyIfNull(concurrentFeaturesSupport); } - /** @hide */ - public final int maxActiveVoiceCalls; - /** @hide */ - public final int maxActiveData; - /** @hide */ - public final int max5G; - /** @hide */ - public final boolean validationBeforeSwitchSupported; - /** @hide */ - public final List<ModemInfo> logicalModemList; - /** @hide */ - public PhoneCapability(int maxActiveVoiceCalls, int maxActiveData, int max5G, - List<ModemInfo> logicalModemList, boolean validationBeforeSwitchSupported) { - this.maxActiveVoiceCalls = maxActiveVoiceCalls; - this.maxActiveData = maxActiveData; - this.max5G = max5G; - // Make sure it's not null. - this.logicalModemList = logicalModemList == null ? new ArrayList<>() : logicalModemList; - this.validationBeforeSwitchSupported = validationBeforeSwitchSupported; + private PhoneCapability(Parcel in) { + mUtranUeCategoryDl = in.readInt(); + mUtranUeCategoryUl = in.readInt(); + mEutranUeCategoryDl = in.readInt(); + mEutranUeCategoryUl = in.readInt(); + mPsDataConnectionLingerTimeMillis = in.readLong(); + mSupportedRats = in.readLong(); + mGeranBands = new ArrayList<>(); + in.readList(mGeranBands, Integer.class.getClassLoader()); + mUtranBands = new ArrayList<>(); + in.readList(mUtranBands, Integer.class.getClassLoader()); + mEutranBands = new ArrayList<>(); + in.readList(mEutranBands, Integer.class.getClassLoader()); + mNgranBands = new ArrayList<>(); + in.readList(mNgranBands, Integer.class.getClassLoader()); + mLogicalModemUuids = in.createStringArrayList(); + mSimSlotCapabilities = in.createTypedArrayList(SimSlotCapability.CREATOR); + int length = in.readInt(); + mConcurrentFeaturesSupport = new ArrayList<>(); + for (int i = 0; i < length; i++) { + ArrayList<Long> feature = new ArrayList<>(); + in.readList(feature, Long.class.getClassLoader()); + mConcurrentFeaturesSupport.add(feature); + } } - @Override - public String toString() { - return "maxActiveVoiceCalls=" + maxActiveVoiceCalls + " maxActiveData=" + maxActiveData - + " max5G=" + max5G + "logicalModemList:" - + Arrays.toString(logicalModemList.toArray()); + /** + * 3GPP UE category for a given Radio Access Network and direction. + * + * References are: + * TS 25.306 Table 4.1a EUTRAN downlink + * TS 25.306 Table 5.1a-2 EUTRAN uplink + * TS 25.306 Table 5.1a UTRAN downlink + * TS 25.306 Table 5.1g UTRAN uplink + * + * @param uplink true for uplink direction and false for downlink direction. + * @param accessNetworkType accessNetworkType, defined in {@link AccessNetworkType}. + * @return the UE category, or -1 if it is not supported. + */ + public int getUeCategory(boolean uplink, @RadioAccessNetworkType int accessNetworkType) { + if (uplink) { + switch (accessNetworkType) { + case AccessNetworkType.UTRAN: return mUtranUeCategoryUl; + case AccessNetworkType.EUTRAN: return mEutranUeCategoryUl; + default: return -1; + } + } else { + switch (accessNetworkType) { + case AccessNetworkType.UTRAN: return mUtranUeCategoryDl; + case AccessNetworkType.EUTRAN: return mEutranUeCategoryDl; + default: return -1; + } + } } - private PhoneCapability(Parcel in) { - maxActiveVoiceCalls = in.readInt(); - maxActiveData = in.readInt(); - max5G = in.readInt(); - validationBeforeSwitchSupported = in.readBoolean(); - logicalModemList = new ArrayList<>(); - in.readList(logicalModemList, ModemInfo.class.getClassLoader()); + /** + * In cellular devices that support a greater number of logical modems than + * Internet connections, some devices support a grace period to allow a smooth "handover" + * between those connections. If that feature is supported, then this API will provide + * the length of that grace period in milliseconds. If it is not supported, the default value + * for the grace period is 0. + * @return handover linger time in milliseconds, or 0 if it is not supported. + */ + public long getPsDataConnectionLingerTimeMillis() { + return mPsDataConnectionLingerTimeMillis; + } + + /** + * The radio access technologies this device is capable of supporting. + * @return a bitfield of all supported network types, defined in {@link TelephonyManager} + */ + public @NetworkTypeBitMask long getSupportedRats() { + return mSupportedRats; + } + + /** + * List of supported cellular bands for the given accessNetworkType. + * @param accessNetworkType accessNetworkType, defined in {@link AccessNetworkType}. + * @return a list of bands, or an empty list if the access network type is unsupported. + */ + public @NonNull List<Integer> getBands(@RadioAccessNetworkType int accessNetworkType) { + switch (accessNetworkType) { + case AccessNetworkType.GERAN: return mGeranBands; + case AccessNetworkType.UTRAN: return mUtranBands; + case AccessNetworkType.EUTRAN: return mEutranBands; + case AccessNetworkType.NGRAN: return mNgranBands; + default: return new ArrayList<>(); + } + } + + /** + * List of logical modem UUIDs, each typically "com.xxxx.lmX", where X is the logical modem ID. + * @return a list of modem UUIDs, one for every logical modem the device has. + */ + public @NonNull List<String> getLogicalModemUuids() { + return mLogicalModemUuids; + } + + /** + * List of {@link SimSlotCapability} for the device. The order of SIMs corresponds to the + * order of modems in {@link #getLogicalModemUuids}. + * @return a list of SIM slot capabilities, one for every SIM slot the device has. + */ + public @NonNull List<SimSlotCapability> getSimSlotCapabilities() { + return mSimSlotCapabilities; + } + + /** + * A List of Lists of concurrently supportable modem feature sets. + * + * Each entry in the top-level list is an independent configuration across all modems + * that describes the capabilities of the device as a whole. + * + * Each entry in the second-level list is a bitfield of ModemFeatures that describes + * the capabilities for a single modem. In the second-level list, the order of the modems + * corresponds to order of the UUIDs in {@link #getLogicalModemUuids}. + * + * For symmetric capabilities that can only be active on one modem at a time, there will be + * multiple configurations (equal to the number of modems) that shows it active on each modem. + * For asymmetric capabilities that are only available on one of the modems, all configurations + * will have that capability on just that one modem. + * + * The example below shows the concurrentFeaturesSupport for a 3-modem device with + * theoretical capabilities SYMMETRIC (available on all modems, but only one at a time) and + * ASYMMETRIC (only available on the first modem): + * { + * Configuration 1: ASYMMETRIC and SYMMETRIC on modem 1, modem 2 empty, modem 3 empty + * {(ASYMMETRIC | SYMMETRIC), (), ()}, + * + * Configuration 2: ASYMMETRIC on modem 1, SYMMETRIC on modem 2, modem 3 empty + * {(ASYMMETRIC), (SYMMETRIC), ()}, + * + * Configuration 3: ASYMMETRIC on modem 1, modem 2 empty, SYMMETRIC on modem 3 + * {(ASYMMETRIC), (), (SYMMETRIC)} + * } + * + * @return List of all concurrently supportable modem features. + */ + public @NonNull @ModemFeature List<List<Long>> getConcurrentFeaturesSupport() { + return mConcurrentFeaturesSupport; + } + + /** + * How many modems can simultaneously have PS attached. + * @return maximum number of active PS voice connections. + */ + public int getMaxActivePsVoice() { + return countFeature(MODEM_FEATURE_PS_VOICE_REG); + } + + /** + * How many modems can simultaneously support active data connections. + * For DSDS, this will be 1, and for DSDA this will be 2. + * @return maximum number of active Internet data sessions. + */ + public int getMaxActiveInternetData() { + return countFeature(MODEM_FEATURE_INTERACTIVE_DATA_SESSION); + } + + /** + * How many modems can simultaneously have dedicated bearer capability. + * @return maximum number of active dedicated bearers. + */ + public int getMaxActiveDedicatedBearers() { + return countFeature(MODEM_FEATURE_DEDICATED_BEARER); + } + + /** + * Whether the CBRS band 48 is supported or not. + * @return true if any RadioAccessNetwork supports CBRS and false if none do. + * @hide + */ + public boolean isCbrsSupported() { + return mEutranBands.contains(AccessNetworkConstants.EutranBand.BAND_48) + || mNgranBands.contains(AccessNetworkConstants.NgranBands.BAND_48); + } + + private int countFeature(@ModemFeature long feature) { + int count = 0; + for (long featureSet : mConcurrentFeaturesSupport.get(0)) { + if ((featureSet & feature) != 0) { + count++; + } + } + return count; + } + + @Override + public String toString() { + return "utranUeCategoryDl=" + mUtranUeCategoryDl + + " utranUeCategoryUl=" + mUtranUeCategoryUl + + " eutranUeCategoryDl=" + mEutranUeCategoryDl + + " eutranUeCategoryUl=" + mEutranUeCategoryUl + + " psDataConnectionLingerTimeMillis=" + mPsDataConnectionLingerTimeMillis + + " supportedRats=" + mSupportedRats + " geranBands=" + mGeranBands + + " utranBands=" + mUtranBands + " eutranBands=" + mEutranBands + + " ngranBands=" + mNgranBands + " logicalModemUuids=" + mLogicalModemUuids + + " simSlotCapabilities=" + mSimSlotCapabilities + + " concurrentFeaturesSupport=" + mConcurrentFeaturesSupport; } @Override public int hashCode() { - return Objects.hash(maxActiveVoiceCalls, maxActiveData, max5G, logicalModemList, - validationBeforeSwitchSupported); + return Objects.hash(mUtranUeCategoryDl, mUtranUeCategoryUl, mEutranUeCategoryDl, + mEutranUeCategoryUl, mPsDataConnectionLingerTimeMillis, mSupportedRats, mGeranBands, + mUtranBands, mEutranBands, mNgranBands, mLogicalModemUuids, mSimSlotCapabilities, + mConcurrentFeaturesSupport); } @Override @@ -107,11 +411,19 @@ public final class PhoneCapability implements Parcelable { PhoneCapability s = (PhoneCapability) o; - return (maxActiveVoiceCalls == s.maxActiveVoiceCalls - && maxActiveData == s.maxActiveData - && max5G == s.max5G - && validationBeforeSwitchSupported == s.validationBeforeSwitchSupported - && logicalModemList.equals(s.logicalModemList)); + return (mUtranUeCategoryDl == s.mUtranUeCategoryDl + && mUtranUeCategoryUl == s.mUtranUeCategoryUl + && mEutranUeCategoryDl == s.mEutranUeCategoryDl + && mEutranUeCategoryUl == s.mEutranUeCategoryUl + && mPsDataConnectionLingerTimeMillis == s.mPsDataConnectionLingerTimeMillis + && mSupportedRats == s.mSupportedRats + && mGeranBands.equals(s.mGeranBands) + && mUtranBands.equals(s.mUtranBands) + && mEutranBands.equals(s.mEutranBands) + && mNgranBands.equals(s.mNgranBands) + && mLogicalModemUuids.equals(s.mLogicalModemUuids) + && mSimSlotCapabilities.equals(s.mSimSlotCapabilities) + && mConcurrentFeaturesSupport.equals(s.mConcurrentFeaturesSupport)); } /** @@ -125,20 +437,32 @@ public final class PhoneCapability implements Parcelable { * {@link Parcelable#writeToParcel} */ public void writeToParcel(@NonNull Parcel dest, @Parcelable.WriteFlags int flags) { - dest.writeInt(maxActiveVoiceCalls); - dest.writeInt(maxActiveData); - dest.writeInt(max5G); - dest.writeBoolean(validationBeforeSwitchSupported); - dest.writeList(logicalModemList); + dest.writeInt(mUtranUeCategoryDl); + dest.writeInt(mUtranUeCategoryUl); + dest.writeInt(mEutranUeCategoryDl); + dest.writeInt(mEutranUeCategoryUl); + dest.writeLong(mPsDataConnectionLingerTimeMillis); + dest.writeLong(mSupportedRats); + dest.writeList(mGeranBands); + dest.writeList(mUtranBands); + dest.writeList(mEutranBands); + dest.writeList(mNgranBands); + dest.writeStringList(mLogicalModemUuids); + dest.writeTypedList(mSimSlotCapabilities); + dest.writeInt(mConcurrentFeaturesSupport.size()); + for (List<Long> feature : mConcurrentFeaturesSupport) { + dest.writeList(feature); + } } - public static final @android.annotation.NonNull Parcelable.Creator<PhoneCapability> CREATOR = new Parcelable.Creator() { - public PhoneCapability createFromParcel(Parcel in) { - return new PhoneCapability(in); - } + public static final @NonNull Parcelable.Creator<PhoneCapability> CREATOR = + new Parcelable.Creator() { + public PhoneCapability createFromParcel(Parcel in) { + return new PhoneCapability(in); + } - public PhoneCapability[] newArray(int size) { - return new PhoneCapability[size]; - } - }; + public PhoneCapability[] newArray(int size) { + return new PhoneCapability[size]; + } + }; } diff --git a/telephony/java/android/telephony/PhoneNumberRange.java b/telephony/java/android/telephony/PhoneNumberRange.java index e6f107e28c98..2b199d2df141 100644 --- a/telephony/java/android/telephony/PhoneNumberRange.java +++ b/telephony/java/android/telephony/PhoneNumberRange.java @@ -85,18 +85,18 @@ public final class PhoneNumberRange implements Parcelable { } private PhoneNumberRange(Parcel in) { - mCountryCode = in.readStringNoHelper(); - mPrefix = in.readStringNoHelper(); - mLowerBound = in.readStringNoHelper(); - mUpperBound = in.readStringNoHelper(); + mCountryCode = in.readString(); + mPrefix = in.readString(); + mLowerBound = in.readString(); + mUpperBound = in.readString(); } @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeStringNoHelper(mCountryCode); - dest.writeStringNoHelper(mPrefix); - dest.writeStringNoHelper(mLowerBound); - dest.writeStringNoHelper(mUpperBound); + dest.writeString(mCountryCode); + dest.writeString(mPrefix); + dest.writeString(mLowerBound); + dest.writeString(mUpperBound); } @Override diff --git a/telephony/java/android/telephony/SimSlotCapability.java b/telephony/java/android/telephony/SimSlotCapability.java new file mode 100644 index 000000000000..3d38d0429908 --- /dev/null +++ b/telephony/java/android/telephony/SimSlotCapability.java @@ -0,0 +1,130 @@ +/* + * 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.telephony; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.os.Parcel; +import android.os.Parcelable; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.Objects; + +/** + * Capabilities for a SIM Slot. + */ +public final class SimSlotCapability implements Parcelable { + /** Slot type for UICC (removable SIM). */ + public static final int SLOT_TYPE_UICC = 1; + /** Slot type for iUICC/iSIM (integrated SIM). */ + public static final int SLOT_TYPE_IUICC = 2; + /** Slot type for eUICC/eSIM (embedded SIM). */ + public static final int SLOT_TYPE_EUICC = 3; + /** Slot type for soft SIM (no physical SIM). */ + public static final int SLOT_TYPE_SOFT_SIM = 4; + + /** @hide */ + @IntDef(prefix = {"SLOT_TYPE_" }, value = { + SLOT_TYPE_UICC, + SLOT_TYPE_IUICC, + SLOT_TYPE_EUICC, + SLOT_TYPE_SOFT_SIM, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface SlotType { + } + + private final int mPhysicalSlotIndex; + private final int mSlotType; + + /** @hide */ + public SimSlotCapability(int physicalSlotId, int slotType) { + this.mPhysicalSlotIndex = physicalSlotId; + this.mSlotType = slotType; + } + + private SimSlotCapability(Parcel in) { + mPhysicalSlotIndex = in.readInt(); + mSlotType = in.readInt(); + } + + /** + * @return physical SIM slot index + */ + public int getPhysicalSlotIndex() { + return mPhysicalSlotIndex; + } + + /** + * @return type of SIM {@link SlotType} + */ + public @SlotType int getSlotType() { + return mSlotType; + } + + @Override + public String toString() { + return "mPhysicalSlotIndex=" + mPhysicalSlotIndex + " slotType=" + mSlotType; + } + + @Override + public int hashCode() { + return Objects.hash(mPhysicalSlotIndex, mSlotType); + } + + @Override + public boolean equals(Object o) { + if (o == null || !(o instanceof SimSlotCapability) || hashCode() != o.hashCode()) { + return false; + } + + if (this == o) { + return true; + } + + SimSlotCapability s = (SimSlotCapability) o; + + return (mPhysicalSlotIndex == s.mPhysicalSlotIndex && mSlotType == s.mSlotType); + } + + /** + * {@link Parcelable#describeContents} + */ + public @ContentsFlags int describeContents() { + return 0; + } + + /** + * {@link Parcelable#writeToParcel} + */ + public void writeToParcel(@NonNull Parcel dest, @WriteFlags int flags) { + dest.writeInt(mPhysicalSlotIndex); + dest.writeInt(mSlotType); + } + + public static final @NonNull Parcelable.Creator<SimSlotCapability> CREATOR = + new Parcelable.Creator() { + public SimSlotCapability createFromParcel(Parcel in) { + return new SimSlotCapability(in); + } + + public SimSlotCapability[] newArray(int size) { + return new SimSlotCapability[size]; + } + }; +} diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java index 2d8e2376b9d8..832771daa409 100644 --- a/telephony/java/android/telephony/SubscriptionInfo.java +++ b/telephony/java/android/telephony/SubscriptionInfo.java @@ -16,8 +16,6 @@ package android.telephony; -import com.android.telephony.Rlog; - import android.annotation.Nullable; import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; @@ -40,6 +38,7 @@ import android.util.DisplayMetrics; import android.util.Log; import com.android.internal.telephony.util.TelephonyUtils; +import com.android.telephony.Rlog; import java.util.ArrayList; import java.util.Arrays; @@ -685,8 +684,8 @@ public class SubscriptionInfo implements Parcelable { int id = source.readInt(); String iccId = source.readString(); int simSlotIndex = source.readInt(); - CharSequence displayName = source.readCharSequence(); - CharSequence carrierName = source.readCharSequence(); + CharSequence displayName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source); + CharSequence carrierName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source); int nameSource = source.readInt(); int iconTint = source.readInt(); String number = source.readString(); @@ -705,8 +704,8 @@ public class SubscriptionInfo implements Parcelable { int carrierid = source.readInt(); int profileClass = source.readInt(); int subType = source.readInt(); - String[] ehplmns = source.readStringArray(); - String[] hplmns = source.readStringArray(); + String[] ehplmns = source.createStringArray(); + String[] hplmns = source.createStringArray(); String groupOwner = source.readString(); UiccAccessRule[] carrierConfigAccessRules = source.createTypedArray( UiccAccessRule.CREATOR); @@ -732,8 +731,8 @@ public class SubscriptionInfo implements Parcelable { dest.writeInt(mId); dest.writeString(mIccId); dest.writeInt(mSimSlotIndex); - dest.writeCharSequence(mDisplayName); - dest.writeCharSequence(mCarrierName); + TextUtils.writeToParcel(mDisplayName, dest, 0); + TextUtils.writeToParcel(mCarrierName, dest, 0); dest.writeInt(mNameSource); dest.writeInt(mIconTint); dest.writeString(mNumber); diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 3dff079497bf..58b82bfab485 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -1520,6 +1520,24 @@ public class TelephonyManager { // /** + * Returns the {@link PhoneCapability} for the device or null if it is not available. + * <p> + * Requires Permission: READ_PHONE_STATE or that the calling app has + * carrier privileges (see {@link #hasCarrierPrivileges}). + */ + @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) + @Nullable + public PhoneCapability getPhoneCapability() { + try { + ITelephony telephony = getITelephony(); + return telephony == null ? null : + telephony.getPhoneCapability(getSubId(), getOpPackageName(), getFeatureId()); + } catch (RemoteException ex) { + return null; + } + } + + /** * Returns the software version number for the device, for example, * the IMEI/SV for GSM phones. Return null if the software version is * not available. @@ -7637,6 +7655,36 @@ public class TelephonyManager { * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling * app has carrier privileges (see {@link #hasCarrierPrivileges}). * + * @param operatorNumeric the PLMN ID of the network to select. + * @param ran the initial suggested radio access network type. + * If registration fails, the RAN is not available after, the RAN is not within the + * network types specified by {@link #setPreferredNetworkTypeBitmask}, or the value is + * {@link AccessNetworkConstants.AccessNetworkType#UNKNOWN}, modem will select + * the next best RAN for network registration. + * @param persistSelection whether the selection will persist until reboot. + * If true, only allows attaching to the selected PLMN until reboot; otherwise, + * attach to the chosen PLMN and resume normal network selection next time. + * @return {@code true} on success; {@code false} on any failure. + * @hide + */ + @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) + @SystemApi + public boolean setNetworkSelectionModeManual(@NonNull String operatorNumeric, + @AccessNetworkConstants.RadioAccessNetworkType int ran, boolean persistSelection) { + return setNetworkSelectionModeManual(new OperatorInfo("" /* operatorAlphaLong */, + "" /* operatorAlphaShort */, operatorNumeric, ran), persistSelection); + } + + /** + * Ask the radio to connect to the input network and change selection mode to manual. + * + * <p>If this object has been created with {@link #createForSubscriptionId}, applies to the + * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultSubscriptionId()} + * + * <p>Requires Permission: + * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling + * app has carrier privileges (see {@link #hasCarrierPrivileges}). + * * @param operatorInfo included the PLMN id, long name, short name of the operator to attach to. * @param persistSelection whether the selection will persist until reboot. If true, only allows * attaching to the selected PLMN until reboot; otherwise, attach to the chosen PLMN and resume @@ -9817,7 +9865,8 @@ public class TelephonyManager { * {@link android.telephony.ModemActivityInfo} object. * @hide */ - public void requestModemActivityInfo(ResultReceiver result) { + @SystemApi + public void requestModemActivityInfo(@NonNull ResultReceiver result) { try { ITelephony service = getITelephony(); if (service != null) { diff --git a/telephony/java/android/telephony/data/DataCallResponse.java b/telephony/java/android/telephony/data/DataCallResponse.java index 49625bbecf4f..a116c07e2646 100644 --- a/telephony/java/android/telephony/data/DataCallResponse.java +++ b/telephony/java/android/telephony/data/DataCallResponse.java @@ -78,6 +78,9 @@ public final class DataCallResponse implements Parcelable { private final List<InetAddress> mGatewayAddresses; private final List<InetAddress> mPcscfAddresses; private final int mMtu; + private final int mMtuV4; + private final int mMtuV6; + private final int mVersion; /** * @param cause Data call fail cause. {@link DataFailCause#NONE} indicates no error. @@ -97,9 +100,8 @@ public final class DataCallResponse implements Parcelable { * "192.0.1.11 2001:db8::1". When null, the addresses represent point to point connections. * @param pcscfAddresses A list of Proxy Call State Control Function address via PCO (Protocol * Configuration Option) for IMS client. - * @param mtu MTU (maximum transmission unit) in bytes received from network. Zero or negative - * values means network has either not sent a value or sent an invalid value. - * either not sent a value or sent an invalid value. + * @param mtu MTU (maximum transmission unit) in bytes received from network. + * Zero or negative values means network has either not sent a value or sent an invalid value. * * @removed Use the {@link Builder()} instead. */ @@ -125,6 +127,34 @@ public final class DataCallResponse implements Parcelable { mPcscfAddresses = (pcscfAddresses == null) ? new ArrayList<>() : new ArrayList<>(pcscfAddresses); mMtu = mtu; + mMtuV4 = mMtuV6 = 0; + mVersion = 0; + } + + /** @hide */ + private DataCallResponse(@DataFailureCause int cause, int suggestedRetryTime, int id, + @LinkStatus int linkStatus, @ProtocolType int protocolType, + @Nullable String interfaceName, @Nullable List<LinkAddress> addresses, + @Nullable List<InetAddress> dnsAddresses, @Nullable List<InetAddress> gatewayAddresses, + @Nullable List<InetAddress> pcscfAddresses, int mtuV4, int mtuV6, int version) { + mCause = cause; + mSuggestedRetryTime = suggestedRetryTime; + mId = id; + mLinkStatus = linkStatus; + mProtocolType = protocolType; + mInterfaceName = (interfaceName == null) ? "" : interfaceName; + mAddresses = (addresses == null) + ? new ArrayList<>() : new ArrayList<>(addresses); + mDnsAddresses = (dnsAddresses == null) + ? new ArrayList<>() : new ArrayList<>(dnsAddresses); + mGatewayAddresses = (gatewayAddresses == null) + ? new ArrayList<>() : new ArrayList<>(gatewayAddresses); + mPcscfAddresses = (pcscfAddresses == null) + ? new ArrayList<>() : new ArrayList<>(pcscfAddresses); + mMtu = 0; + mMtuV4 = mtuV4; + mMtuV6 = mtuV6; + mVersion = version; } /** @hide */ @@ -145,6 +175,9 @@ public final class DataCallResponse implements Parcelable { mPcscfAddresses = new ArrayList<>(); source.readList(mPcscfAddresses, InetAddress.class.getClassLoader()); mMtu = source.readInt(); + mMtuV4 = source.readInt(); + mMtuV6 = source.readInt(); + mVersion = source.readInt(); } /** @@ -210,8 +243,29 @@ public final class DataCallResponse implements Parcelable { /** * @return MTU (maximum transmission unit) in bytes received from network. Zero or negative * values means network has either not sent a value or sent an invalid value. + * @deprecated For IRadio 1.5 and up, use {@link #getMtuV4} or {@link #getMtuV6} instead. + */ + @Deprecated + public int getMtu() { + return mVersion < 5 ? mMtu : 0; + } + + /** + * This replaces the deprecated method getMtu. + * @return MTU (maximum transmission unit) in bytes received from network, for IPv4. + * Zero or negative values means network has either not sent a value or sent an invalid value. */ - public int getMtu() { return mMtu; } + public int getMtuV4() { + return mVersion < 5 ? 0 : mMtuV4; + } + + /** + * @return MTU (maximum transmission unit) in bytes received from network, for IPv6. + * Zero or negative values means network has either not sent a value or sent an invalid value. + */ + public int getMtuV6() { + return mVersion < 5 ? 0 : mMtuV6; + } @NonNull @Override @@ -229,6 +283,9 @@ public final class DataCallResponse implements Parcelable { .append(" gateways=").append(mGatewayAddresses) .append(" pcscf=").append(mPcscfAddresses) .append(" mtu=").append(mMtu) + .append(" mtuV4=").append(mMtuV4) + .append(" mtuV6=").append(mMtuV6) + .append(" version=").append(mVersion) .append("}"); return sb.toString(); } @@ -256,14 +313,17 @@ public final class DataCallResponse implements Parcelable { && mGatewayAddresses.containsAll(other.mGatewayAddresses) && mPcscfAddresses.size() == other.mPcscfAddresses.size() && mPcscfAddresses.containsAll(other.mPcscfAddresses) - && mMtu == other.mMtu; + && mMtu == other.mMtu + && mMtuV4 == other.mMtuV4 + && mMtuV6 == other.mMtuV6 + && mVersion == other.mVersion; } @Override public int hashCode() { return Objects.hash(mCause, mSuggestedRetryTime, mId, mLinkStatus, mProtocolType, mInterfaceName, mAddresses, mDnsAddresses, mGatewayAddresses, mPcscfAddresses, - mMtu); + mMtu, mMtuV4, mMtuV6, mVersion); } @Override @@ -284,6 +344,9 @@ public final class DataCallResponse implements Parcelable { dest.writeList(mGatewayAddresses); dest.writeList(mPcscfAddresses); dest.writeInt(mMtu); + dest.writeInt(mMtuV4); + dest.writeInt(mMtuV6); + dest.writeInt(mVersion); } public static final @android.annotation.NonNull Parcelable.Creator<DataCallResponse> CREATOR = @@ -336,6 +399,12 @@ public final class DataCallResponse implements Parcelable { private int mMtu; + private int mMtuV4; + + private int mMtuV6; + + private int mVersion; + /** * Default constructor for Builder. */ @@ -460,6 +529,7 @@ public final class DataCallResponse implements Parcelable { * negative values means network has either not sent a value or sent an invalid value. * * @return The same instance of the builder. + * @deprecated For IRadio 1.5 and up, use {@link #setMtuV4} or {@link #setMtuV6} instead. */ public @NonNull Builder setMtu(int mtu) { mMtu = mtu; @@ -467,14 +537,55 @@ public final class DataCallResponse implements Parcelable { } /** + * Set maximum transmission unit of the data connection, for IPv4. + * + * @param mtu MTU (maximum transmission unit) in bytes received from network. Zero or + * negative values means network has either not sent a value or sent an invalid value. + * + * @return The same instance of the builder. + */ + public @NonNull Builder setMtuV4(int mtu) { + mMtuV4 = mtu; + return this; + } + + /** + * Set maximum transmission unit of the data connection, for IPv6. + * + * @param mtu MTU (maximum transmission unit) in bytes received from network. Zero or + * negative values means network has either not sent a value or sent an invalid value. + * + * @return The same instance of the builder. + */ + public @NonNull Builder setMtuV6(int mtu) { + mMtuV6 = mtu; + return this; + } + + /** + * Set the IRadio version for this DataCallResponse + * @hide + */ + public @NonNull Builder setVersion(int version) { + mVersion = version; + return this; + } + + /** * Build the DataCallResponse. * * @return the DataCallResponse object. */ public @NonNull DataCallResponse build() { - return new DataCallResponse(mCause, mSuggestedRetryTime, mId, mLinkStatus, - mProtocolType, mInterfaceName, mAddresses, mDnsAddresses, mGatewayAddresses, - mPcscfAddresses, mMtu); + if (mVersion >= 5) { + return new DataCallResponse(mCause, mSuggestedRetryTime, mId, mLinkStatus, + mProtocolType, mInterfaceName, mAddresses, mDnsAddresses, mGatewayAddresses, + mPcscfAddresses, mMtuV4, mMtuV6, mVersion); + } else { + return new DataCallResponse(mCause, mSuggestedRetryTime, mId, mLinkStatus, + mProtocolType, mInterfaceName, mAddresses, mDnsAddresses, mGatewayAddresses, + mPcscfAddresses, mMtu); + } } } } diff --git a/telephony/java/android/telephony/data/DataProfile.java b/telephony/java/android/telephony/data/DataProfile.java index 96a5a8151065..f2a124901bc4 100644 --- a/telephony/java/android/telephony/data/DataProfile.java +++ b/telephony/java/android/telephony/data/DataProfile.java @@ -96,7 +96,9 @@ public final class DataProfile implements Parcelable { @NetworkTypeBitMask private final int mBearerBitmask; - private final int mMtu; + private final int mMtuV4; + + private final int mMtuV6; private final boolean mPersistent; @@ -104,12 +106,11 @@ public final class DataProfile implements Parcelable { /** @hide */ private DataProfile(int profileId, String apn, @ProtocolType int protocolType, int authType, - String userName, String password, int type, int maxConnectionsTime, - int maxConnections, int waitTime, boolean enabled, - @ApnType int supportedApnTypesBitmask, - @ProtocolType int roamingProtocolType, - @NetworkTypeBitMask int bearerBitmask, int mtu, boolean persistent, - boolean preferred) { + String userName, String password, int type, int maxConnectionsTime, + int maxConnections, int waitTime, boolean enabled, + @ApnType int supportedApnTypesBitmask, @ProtocolType int roamingProtocolType, + @NetworkTypeBitMask int bearerBitmask, int mtuV4, int mtuV6, boolean persistent, + boolean preferred) { this.mProfileId = profileId; this.mApn = apn; this.mProtocolType = protocolType; @@ -128,7 +129,8 @@ public final class DataProfile implements Parcelable { this.mSupportedApnTypesBitmask = supportedApnTypesBitmask; this.mRoamingProtocolType = roamingProtocolType; this.mBearerBitmask = bearerBitmask; - this.mMtu = mtu; + this.mMtuV4 = mtuV4; + this.mMtuV6 = mtuV6; this.mPersistent = persistent; this.mPreferred = preferred; } @@ -148,7 +150,8 @@ public final class DataProfile implements Parcelable { mSupportedApnTypesBitmask = source.readInt(); mRoamingProtocolType = source.readInt(); mBearerBitmask = source.readInt(); - mMtu = source.readInt(); + mMtuV4 = source.readInt(); + mMtuV6 = source.readInt(); mPersistent = source.readBoolean(); mPreferred = source.readBoolean(); } @@ -237,8 +240,21 @@ public final class DataProfile implements Parcelable { /** * @return The maximum transmission unit (MTU) size in bytes. + * @deprecated use {@link #getMtuV4} or {@link #getMtuV6} instead. + */ + @Deprecated + public int getMtu() { return mMtuV4; } + + /** + * This replaces the deprecated method getMtu. + * @return The maximum transmission unit (MTU) size in bytes, for IPv4. + */ + public int getMtuV4() { return mMtuV4; } + + /** + * @return The maximum transmission unit (MTU) size in bytes, for IPv6. */ - public int getMtu() { return mMtu; } + public int getMtuV6() { return mMtuV6; } /** * @return {@code true} if modem must persist this data profile. @@ -265,8 +281,8 @@ public final class DataProfile implements Parcelable { (mApn + "/" + mUserName + "/" + mPassword)) + "/" + mType + "/" + mMaxConnectionsTime + "/" + mMaxConnections + "/" + mWaitTime + "/" + mEnabled + "/" + mSupportedApnTypesBitmask + "/" - + mRoamingProtocolType + "/" + mBearerBitmask + "/" + mMtu + "/" + mPersistent + "/" - + mPreferred; + + mRoamingProtocolType + "/" + mBearerBitmask + "/" + mMtuV4 + "/" + mMtuV6 + "/" + + mPersistent + "/" + mPreferred; } @Override @@ -285,7 +301,8 @@ public final class DataProfile implements Parcelable { dest.writeInt(mSupportedApnTypesBitmask); dest.writeInt(mRoamingProtocolType); dest.writeInt(mBearerBitmask); - dest.writeInt(mMtu); + dest.writeInt(mMtuV4); + dest.writeInt(mMtuV6); dest.writeBoolean(mPersistent); dest.writeBoolean(mPreferred); } @@ -319,7 +336,8 @@ public final class DataProfile implements Parcelable { && mSupportedApnTypesBitmask == that.mSupportedApnTypesBitmask && mRoamingProtocolType == that.mRoamingProtocolType && mBearerBitmask == that.mBearerBitmask - && mMtu == that.mMtu + && mMtuV4 == that.mMtuV4 + && mMtuV6 == that.mMtuV6 && mPersistent == that.mPersistent && mPreferred == that.mPreferred && Objects.equals(mApn, that.mApn) @@ -331,8 +349,8 @@ public final class DataProfile implements Parcelable { public int hashCode() { return Objects.hash(mProfileId, mApn, mProtocolType, mAuthType, mUserName, mPassword, mType, mMaxConnectionsTime, mMaxConnections, mWaitTime, mEnabled, - mSupportedApnTypesBitmask, mRoamingProtocolType, mBearerBitmask, mMtu, mPersistent, - mPreferred); + mSupportedApnTypesBitmask, mRoamingProtocolType, mBearerBitmask, mMtuV4, mMtuV6, + mPersistent, mPreferred); } /** @@ -384,7 +402,9 @@ public final class DataProfile implements Parcelable { @NetworkTypeBitMask private int mBearerBitmask; - private int mMtu; + private int mMtuV4; + + private int mMtuV6; private boolean mPersistent; @@ -567,9 +587,33 @@ public final class DataProfile implements Parcelable { * * @param mtu The maximum transmission unit (MTU) size in bytes. * @return The same instance of the builder. + * @deprecated use {@link #setMtuV4} or {@link #setMtuV6} instead. */ public @NonNull Builder setMtu(int mtu) { - mMtu = mtu; + mMtuV4 = mMtuV6 = mtu; + return this; + } + + /** + * Set the maximum transmission unit (MTU) size in bytes, for IPv4. + * This replaces the deprecated method setMtu. + * + * @param mtu The maximum transmission unit (MTU) size in bytes. + * @return The same instance of the builder. + */ + public @NonNull Builder setMtuV4(int mtu) { + mMtuV4 = mtu; + return this; + } + + /** + * Set the maximum transmission unit (MTU) size in bytes, for IPv6. + * + * @param mtu The maximum transmission unit (MTU) size in bytes. + * @return The same instance of the builder. + */ + public @NonNull Builder setMtuV6(int mtu) { + mMtuV6 = mtu; return this; } @@ -606,7 +650,7 @@ public final class DataProfile implements Parcelable { public @NonNull DataProfile build() { return new DataProfile(mProfileId, mApn, mProtocolType, mAuthType, mUserName, mPassword, mType, mMaxConnectionsTime, mMaxConnections, mWaitTime, mEnabled, - mSupportedApnTypesBitmask, mRoamingProtocolType, mBearerBitmask, mMtu, + mSupportedApnTypesBitmask, mRoamingProtocolType, mBearerBitmask, mMtuV4, mMtuV6, mPersistent, mPreferred); } } diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java index ba8e90ff539b..494009f35dba 100644 --- a/telephony/java/android/telephony/ims/ImsMmTelManager.java +++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java @@ -163,9 +163,13 @@ public class ImsMmTelManager implements RegistrationManager { public void onCapabilitiesStatusChanged(int config) { if (mLocalCallback == null) return; - Binder.withCleanCallingIdentity(() -> - mExecutor.execute(() -> mLocalCallback.onCapabilitiesStatusChanged( - new MmTelFeature.MmTelCapabilities(config)))); + long callingIdentity = Binder.clearCallingIdentity(); + try { + mExecutor.execute(() -> mLocalCallback.onCapabilitiesStatusChanged( + new MmTelFeature.MmTelCapabilities(config))); + } finally { + restoreCallingIdentity(callingIdentity); + } } @Override diff --git a/telephony/java/android/telephony/ims/ImsRcsManager.java b/telephony/java/android/telephony/ims/ImsRcsManager.java index 5aa37bba7efe..917f91fcf232 100644 --- a/telephony/java/android/telephony/ims/ImsRcsManager.java +++ b/telephony/java/android/telephony/ims/ImsRcsManager.java @@ -75,9 +75,13 @@ public class ImsRcsManager implements RegistrationManager { public void onCapabilitiesStatusChanged(int config) { if (mLocalCallback == null) return; - Binder.withCleanCallingIdentity(() -> - mExecutor.execute(() -> mLocalCallback.onAvailabilityChanged( - new RcsFeature.RcsImsCapabilities(config)))); + long callingIdentity = Binder.clearCallingIdentity(); + try { + mExecutor.execute(() -> mLocalCallback.onAvailabilityChanged( + new RcsFeature.RcsImsCapabilities(config))); + } finally { + restoreCallingIdentity(callingIdentity); + } } @Override diff --git a/telephony/java/android/telephony/ims/ProvisioningManager.java b/telephony/java/android/telephony/ims/ProvisioningManager.java index aa4f77d09212..6125001850db 100644 --- a/telephony/java/android/telephony/ims/ProvisioningManager.java +++ b/telephony/java/android/telephony/ims/ProvisioningManager.java @@ -791,17 +791,24 @@ public class ProvisioningManager { @Override public final void onIntConfigChanged(int item, int value) { - Binder.withCleanCallingIdentity(() -> - mExecutor.execute(() -> - mLocalConfigurationCallback.onProvisioningIntChanged(item, value))); + long callingIdentity = Binder.clearCallingIdentity(); + try { + mExecutor.execute(() -> + mLocalConfigurationCallback.onProvisioningIntChanged(item, value)); + } finally { + restoreCallingIdentity(callingIdentity); + } } @Override public final void onStringConfigChanged(int item, String value) { - Binder.withCleanCallingIdentity(() -> - mExecutor.execute(() -> - mLocalConfigurationCallback.onProvisioningStringChanged(item, - value))); + long callingIdentity = Binder.clearCallingIdentity(); + try { + mExecutor.execute(() -> + mLocalConfigurationCallback.onProvisioningStringChanged(item, value)); + } finally { + restoreCallingIdentity(callingIdentity); + } } private void setExecutor(Executor executor) { diff --git a/telephony/java/android/telephony/ims/RcsUceAdapter.java b/telephony/java/android/telephony/ims/RcsUceAdapter.java index d3f393ae11a2..5e3847f1359a 100644 --- a/telephony/java/android/telephony/ims/RcsUceAdapter.java +++ b/telephony/java/android/telephony/ims/RcsUceAdapter.java @@ -251,15 +251,22 @@ public class RcsUceAdapter { IRcsUceControllerCallback internalCallback = new IRcsUceControllerCallback.Stub() { @Override public void onCapabilitiesReceived(List<RcsContactUceCapability> contactCapabilities) { - Binder.withCleanCallingIdentity(() -> - executor.execute(() -> - c.onCapabilitiesReceived(contactCapabilities))); + long callingIdentity = Binder.clearCallingIdentity(); + try { + executor.execute(() -> + c.onCapabilitiesReceived(contactCapabilities)); + } finally { + restoreCallingIdentity(callingIdentity); + } } @Override public void onError(int errorCode) { - Binder.withCleanCallingIdentity(() -> - executor.execute(() -> - c.onError(errorCode))); + long callingIdentity = Binder.clearCallingIdentity(); + try { + executor.execute(() -> c.onError(errorCode)); + } finally { + restoreCallingIdentity(callingIdentity); + } } }; diff --git a/telephony/java/android/telephony/ims/RegistrationManager.java b/telephony/java/android/telephony/ims/RegistrationManager.java index a1f6b78ba7c5..5c86ba732701 100644 --- a/telephony/java/android/telephony/ims/RegistrationManager.java +++ b/telephony/java/android/telephony/ims/RegistrationManager.java @@ -105,41 +105,62 @@ public interface RegistrationManager { public void onRegistered(int imsRadioTech) { if (mLocalCallback == null) return; - Binder.withCleanCallingIdentity(() -> mExecutor.execute(() -> - mLocalCallback.onRegistered(getAccessType(imsRadioTech)))); + long callingIdentity = Binder.clearCallingIdentity(); + try { + mExecutor.execute(() -> + mLocalCallback.onRegistered(getAccessType(imsRadioTech))); + } finally { + restoreCallingIdentity(callingIdentity); + } } @Override public void onRegistering(int imsRadioTech) { if (mLocalCallback == null) return; - Binder.withCleanCallingIdentity(() -> mExecutor.execute(() -> - mLocalCallback.onRegistering(getAccessType(imsRadioTech)))); + long callingIdentity = Binder.clearCallingIdentity(); + try { + mExecutor.execute(() -> + mLocalCallback.onRegistering(getAccessType(imsRadioTech))); + } finally { + restoreCallingIdentity(callingIdentity); + } } @Override public void onDeregistered(ImsReasonInfo info) { if (mLocalCallback == null) return; - Binder.withCleanCallingIdentity(() -> - mExecutor.execute(() -> mLocalCallback.onUnregistered(info))); + long callingIdentity = Binder.clearCallingIdentity(); + try { + mExecutor.execute(() -> mLocalCallback.onUnregistered(info)); + } finally { + restoreCallingIdentity(callingIdentity); + } } @Override public void onTechnologyChangeFailed(int imsRadioTech, ImsReasonInfo info) { if (mLocalCallback == null) return; - Binder.withCleanCallingIdentity(() -> - mExecutor.execute(() -> mLocalCallback.onTechnologyChangeFailed( - getAccessType(imsRadioTech), info))); + long callingIdentity = Binder.clearCallingIdentity(); + try { + mExecutor.execute(() -> mLocalCallback.onTechnologyChangeFailed( + getAccessType(imsRadioTech), info)); + } finally { + restoreCallingIdentity(callingIdentity); + } } public void onSubscriberAssociatedUriChanged(Uri[] uris) { if (mLocalCallback == null) return; - Binder.withCleanCallingIdentity(() -> - mExecutor.execute(() -> - mLocalCallback.onSubscriberAssociatedUriChanged(uris))); + long callingIdentity = Binder.clearCallingIdentity(); + try { + mExecutor.execute(() -> mLocalCallback.onSubscriberAssociatedUriChanged(uris)); + } finally { + restoreCallingIdentity(callingIdentity); + } } private void setExecutor(Executor executor) { diff --git a/telephony/java/android/telephony/ims/feature/ImsFeature.java b/telephony/java/android/telephony/ims/feature/ImsFeature.java index 5d102cb4ac06..e5779b315c93 100644 --- a/telephony/java/android/telephony/ims/feature/ImsFeature.java +++ b/telephony/java/android/telephony/ims/feature/ImsFeature.java @@ -22,7 +22,6 @@ import android.annotation.SystemApi; import android.annotation.TestApi; import android.content.Context; import android.os.IInterface; -import android.os.RemoteCallbackList; import android.os.RemoteException; import android.telephony.SubscriptionManager; import android.telephony.ims.aidl.IImsCapabilityCallback; @@ -31,6 +30,7 @@ import android.util.Log; import com.android.ims.internal.IImsFeatureStatusCallback; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.telephony.util.RemoteCallbackListExt; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -326,12 +326,12 @@ public abstract class ImsFeature { /** @hide */ protected final Object mLock = new Object(); - private final RemoteCallbackList<IImsFeatureStatusCallback> mStatusCallbacks = - new RemoteCallbackList<>(); + private final RemoteCallbackListExt<IImsFeatureStatusCallback> mStatusCallbacks = + new RemoteCallbackListExt<>(); private @ImsState int mState = STATE_UNAVAILABLE; private int mSlotId = SubscriptionManager.INVALID_SIM_SLOT_INDEX; - private final RemoteCallbackList<IImsCapabilityCallback> mCapabilityCallbacks = - new RemoteCallbackList<>(); + private final RemoteCallbackListExt<IImsCapabilityCallback> mCapabilityCallbacks = + new RemoteCallbackListExt<>(); private Capabilities mCapabilityStatus = new Capabilities(); /** @@ -412,7 +412,7 @@ public abstract class ImsFeature { * Internal method called by ImsFeature when setFeatureState has changed. */ private void notifyFeatureState(@ImsState int state) { - mStatusCallbacks.broadcast((c) -> { + mStatusCallbacks.broadcastAction((c) -> { try { c.notifyImsFeatureStatus(state); } catch (RemoteException e) { @@ -491,7 +491,7 @@ public abstract class ImsFeature { synchronized (mLock) { mCapabilityStatus = caps.copy(); } - mCapabilityCallbacks.broadcast((callback) -> { + mCapabilityCallbacks.broadcastAction((callback) -> { try { callback.onCapabilitiesStatusChanged(caps.mCapabilities); } catch (RemoteException e) { diff --git a/telephony/java/android/telephony/ims/feature/RcsFeature.java b/telephony/java/android/telephony/ims/feature/RcsFeature.java index e4efc20437bb..8e67621b2ea3 100644 --- a/telephony/java/android/telephony/ims/feature/RcsFeature.java +++ b/telephony/java/android/telephony/ims/feature/RcsFeature.java @@ -22,7 +22,6 @@ import android.annotation.NonNull; import android.annotation.SystemApi; import android.annotation.TestApi; import android.net.Uri; -import android.os.Binder; import android.os.RemoteException; import android.telephony.ims.RcsContactUceCapability; import android.telephony.ims.aidl.IImsCapabilityCallback; @@ -33,7 +32,7 @@ import android.telephony.ims.stub.RcsPresenceExchangeImplBase; import android.telephony.ims.stub.RcsSipOptionsImplBase; import android.util.Log; -import com.android.internal.util.FunctionalUtils; +import com.android.internal.telephony.util.TelephonyUtils; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -43,6 +42,7 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; +import java.util.function.Supplier; /** * Base implementation of the RcsFeature APIs. Any ImsService wishing to support RCS should extend @@ -150,13 +150,13 @@ public class RcsFeature extends ImsFeature { // Call the methods with a clean calling identity on the executor and wait indefinitely for // the future to return. - private void executeMethodAsync(FunctionalUtils.ThrowingRunnable r, String errorLogName) + private void executeMethodAsync(Runnable r, String errorLogName) throws RemoteException { // call with a clean calling identity on the executor and wait indefinitely for the // future to return. try { CompletableFuture.runAsync( - () -> Binder.withCleanCallingIdentity(r), mExecutor).join(); + () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join(); } catch (CancellationException | CompletionException e) { Log.w(LOG_TAG, "RcsFeatureBinder - " + errorLogName + " exception: " + e.getMessage()); @@ -164,12 +164,12 @@ public class RcsFeature extends ImsFeature { } } - private <T> T executeMethodAsyncForResult(FunctionalUtils.ThrowingSupplier<T> r, + private <T> T executeMethodAsyncForResult(Supplier<T> r, String errorLogName) throws RemoteException { // call with a clean calling identity on the executor and wait indefinitely for the // future to return. CompletableFuture<T> future = CompletableFuture.supplyAsync( - () -> Binder.withCleanCallingIdentity(r), mExecutor); + () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor); try { return future.get(); } catch (ExecutionException | InterruptedException e) { diff --git a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java index e0d576db4f14..6a2638bc7221 100644 --- a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java +++ b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java @@ -22,7 +22,6 @@ import android.annotation.SystemApi; import android.annotation.TestApi; import android.content.Context; import android.os.PersistableBundle; -import android.os.RemoteCallbackList; import android.os.RemoteException; import android.telephony.ims.ProvisioningManager; import android.telephony.ims.aidl.IImsConfig; @@ -31,6 +30,7 @@ import android.util.Log; import com.android.ims.ImsConfig; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.telephony.util.RemoteCallbackListExt; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -257,7 +257,8 @@ public class ImsConfigImplBase { }) public @interface SetConfigResult {} - private final RemoteCallbackList<IImsConfigCallback> mCallbacks = new RemoteCallbackList<>(); + private final RemoteCallbackListExt<IImsConfigCallback> mCallbacks = + new RemoteCallbackListExt<>(); ImsConfigStub mImsConfigStub; /** @@ -298,7 +299,7 @@ public class ImsConfigImplBase { if (mCallbacks == null) { return; } - mCallbacks.broadcast(c -> { + mCallbacks.broadcastAction(c -> { try { c.onIntConfigChanged(item, value); } catch (RemoteException e) { @@ -312,7 +313,7 @@ public class ImsConfigImplBase { if (mCallbacks == null) { return; } - mCallbacks.broadcast(c -> { + mCallbacks.broadcastAction(c -> { try { c.onStringConfigChanged(item, value); } catch (RemoteException e) { diff --git a/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java index c0f16e5f9fbc..14a64d2585ed 100644 --- a/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java +++ b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java @@ -20,7 +20,6 @@ import android.annotation.IntDef; import android.annotation.SystemApi; import android.annotation.TestApi; import android.net.Uri; -import android.os.RemoteCallbackList; import android.os.RemoteException; import android.telephony.ims.ImsReasonInfo; import android.telephony.ims.RegistrationManager; @@ -29,6 +28,7 @@ import android.telephony.ims.aidl.IImsRegistrationCallback; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.telephony.util.RemoteCallbackListExt; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -94,8 +94,8 @@ public class ImsRegistrationImplBase { } }; - private final RemoteCallbackList<IImsRegistrationCallback> mCallbacks - = new RemoteCallbackList<>(); + private final RemoteCallbackListExt<IImsRegistrationCallback> mCallbacks = + new RemoteCallbackListExt<>(); private final Object mLock = new Object(); // Locked on mLock private @ImsRegistrationTech @@ -129,7 +129,7 @@ public class ImsRegistrationImplBase { */ public final void onRegistered(@ImsRegistrationTech int imsRadioTech) { updateToState(imsRadioTech, RegistrationManager.REGISTRATION_STATE_REGISTERED); - mCallbacks.broadcast((c) -> { + mCallbacks.broadcastAction((c) -> { try { c.onRegistered(imsRadioTech); } catch (RemoteException e) { @@ -147,7 +147,7 @@ public class ImsRegistrationImplBase { */ public final void onRegistering(@ImsRegistrationTech int imsRadioTech) { updateToState(imsRadioTech, RegistrationManager.REGISTRATION_STATE_REGISTERING); - mCallbacks.broadcast((c) -> { + mCallbacks.broadcastAction((c) -> { try { c.onRegistering(imsRadioTech); } catch (RemoteException e) { @@ -175,7 +175,7 @@ public class ImsRegistrationImplBase { */ public final void onDeregistered(ImsReasonInfo info) { updateToDisconnectedState(info); - mCallbacks.broadcast((c) -> { + mCallbacks.broadcastAction((c) -> { try { c.onDeregistered(info); } catch (RemoteException e) { @@ -194,7 +194,7 @@ public class ImsRegistrationImplBase { */ public final void onTechnologyChangeFailed(@ImsRegistrationTech int imsRadioTech, ImsReasonInfo info) { - mCallbacks.broadcast((c) -> { + mCallbacks.broadcastAction((c) -> { try { c.onTechnologyChangeFailed(imsRadioTech, info); } catch (RemoteException e) { @@ -210,7 +210,7 @@ public class ImsRegistrationImplBase { * @param uris */ public final void onSubscriberAssociatedUriChanged(Uri[] uris) { - mCallbacks.broadcast((c) -> { + mCallbacks.broadcastAction((c) -> { try { c.onSubscriberAssociatedUriChanged(uris); } catch (RemoteException e) { diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index f3b467b54b86..1d794cde7d9c 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -38,6 +38,7 @@ import android.telephony.ICellInfoCallback; import android.telephony.ModemActivityInfo; import android.telephony.NeighboringCellInfo; import android.telephony.NetworkScanRequest; +import android.telephony.PhoneCapability; import android.telephony.PhoneNumberRange; import android.telephony.RadioAccessFamily; import android.telephony.ServiceState; @@ -1830,12 +1831,17 @@ interface ITelephony { /** * Return the network selection mode on the subscription with id {@code subId}. */ - int getNetworkSelectionMode(int subId); + int getNetworkSelectionMode(int subId); - /** + /** + * Return the PhoneCapability for the device. + */ + PhoneCapability getPhoneCapability(int subId, String callingPackage, String callingFeatureId); + + /** * Return true if the device is in emergency sms mode, false otherwise. */ - boolean isInEmergencySmsMode(); + boolean isInEmergencySmsMode(); /** * Return the modem radio power state for slot index. diff --git a/telephony/java/com/android/internal/telephony/OperatorInfo.java b/telephony/java/com/android/internal/telephony/OperatorInfo.java index 64d786391021..2ca459811e04 100644 --- a/telephony/java/com/android/internal/telephony/OperatorInfo.java +++ b/telephony/java/com/android/internal/telephony/OperatorInfo.java @@ -20,6 +20,7 @@ import android.compat.annotation.UnsupportedAppUsage; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; +import android.telephony.AccessNetworkConstants.AccessNetworkType; /** * @hide @@ -43,6 +44,7 @@ public class OperatorInfo implements Parcelable { @UnsupportedAppUsage private State mState = State.UNKNOWN; + private int mRan = AccessNetworkType.UNKNOWN; @UnsupportedAppUsage @@ -69,6 +71,10 @@ public class OperatorInfo implements Parcelable { return mState; } + public int getRan() { + return mRan; + } + @UnsupportedAppUsage OperatorInfo(String operatorAlphaLong, String operatorAlphaShort, @@ -82,6 +88,14 @@ public class OperatorInfo implements Parcelable { mState = state; } + OperatorInfo(String operatorAlphaLong, + String operatorAlphaShort, + String operatorNumeric, + State state, + int ran) { + this (operatorAlphaLong, operatorAlphaShort, operatorNumeric, state); + mRan = ran; + } @UnsupportedAppUsage public OperatorInfo(String operatorAlphaLong, @@ -92,6 +106,14 @@ public class OperatorInfo implements Parcelable { operatorNumeric, rilStateToState(stateString)); } + public OperatorInfo(String operatorAlphaLong, + String operatorAlphaShort, + String operatorNumeric, + int ran) { + this (operatorAlphaLong, operatorAlphaShort, operatorNumeric); + mRan = ran; + } + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) public OperatorInfo(String operatorAlphaLong, String operatorAlphaShort, @@ -124,7 +146,8 @@ public class OperatorInfo implements Parcelable { return "OperatorInfo " + mOperatorAlphaLong + "/" + mOperatorAlphaShort + "/" + mOperatorNumeric - + "/" + mState; + + "/" + mState + + "/" + mRan; } /** @@ -150,6 +173,7 @@ public class OperatorInfo implements Parcelable { dest.writeString(mOperatorAlphaShort); dest.writeString(mOperatorNumeric); dest.writeSerializable(mState); + dest.writeInt(mRan); } /** @@ -158,20 +182,21 @@ public class OperatorInfo implements Parcelable { */ @UnsupportedAppUsage public static final Creator<OperatorInfo> CREATOR = - new Creator<OperatorInfo>() { - @Override - public OperatorInfo createFromParcel(Parcel in) { - OperatorInfo opInfo = new OperatorInfo( - in.readString(), /*operatorAlphaLong*/ - in.readString(), /*operatorAlphaShort*/ - in.readString(), /*operatorNumeric*/ - (State) in.readSerializable()); /*state*/ - return opInfo; - } - - @Override - public OperatorInfo[] newArray(int size) { - return new OperatorInfo[size]; - } - }; + new Creator<OperatorInfo>() { + @Override + public OperatorInfo createFromParcel(Parcel in) { + OperatorInfo opInfo = new OperatorInfo( + in.readString(), /*operatorAlphaLong*/ + in.readString(), /*operatorAlphaShort*/ + in.readString(), /*operatorNumeric*/ + (State) in.readSerializable(), /*state*/ + in.readInt()); /*ran*/ + return opInfo; + } + + @Override + public OperatorInfo[] newArray(int size) { + return new OperatorInfo[size]; + } + }; } diff --git a/telephony/java/com/android/internal/telephony/util/RemoteCallbackListExt.java b/telephony/java/com/android/internal/telephony/util/RemoteCallbackListExt.java new file mode 100644 index 000000000000..d66bda911729 --- /dev/null +++ b/telephony/java/com/android/internal/telephony/util/RemoteCallbackListExt.java @@ -0,0 +1,46 @@ +/* + * 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.internal.telephony.util; + +import android.os.IInterface; +import android.os.RemoteCallbackList; + +import java.util.function.Consumer; + +/** + * Extension of RemoteCallbackList + * @param <E> defines the type of registered callbacks + */ +public class RemoteCallbackListExt<E extends IInterface> extends RemoteCallbackList<E> { + /** + * Performs {@code action} on each callback, calling + * {@link RemoteCallbackListExt#beginBroadcast()} + * /{@link RemoteCallbackListExt#finishBroadcast()} before/after looping + * @param action to be performed on each callback + * + */ + public void broadcastAction(Consumer<E> action) { + int itemCount = beginBroadcast(); + try { + for (int i = 0; i < itemCount; i++) { + action.accept(getBroadcastItem(i)); + } + } finally { + finishBroadcast(); + } + } +} diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ChangeAppRotationTest.java b/tests/FlickerTests/src/com/android/server/wm/flicker/ChangeAppRotationTest.java index 42cafd43f8bd..5a66e805c575 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/ChangeAppRotationTest.java +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ChangeAppRotationTest.java @@ -66,7 +66,7 @@ public class ChangeAppRotationTest extends FlickerTestBase { @Parameters(name = "{0}-{1}") public static Collection<Object[]> getParams() { int[] supportedRotations = - {Surface.ROTATION_0, Surface.ROTATION_90, Surface.ROTATION_270}; + {Surface.ROTATION_0, Surface.ROTATION_90}; Collection<Object[]> params = new ArrayList<>(); for (int begin : supportedRotations) { for (int end : supportedRotations) { diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/CloseImeWindowToHomeTest.java b/tests/FlickerTests/src/com/android/server/wm/flicker/CloseImeWindowToHomeTest.java index fc6719e2f9d9..f740af9b89bf 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/CloseImeWindowToHomeTest.java +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/CloseImeWindowToHomeTest.java @@ -25,6 +25,7 @@ import com.android.server.wm.flicker.helpers.ImeAppHelper; import org.junit.Before; import org.junit.FixMethodOrder; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; @@ -62,6 +63,7 @@ public class CloseImeWindowToHomeTest extends NonRotationTestBase { .forAllEntries()); } + @Ignore("Flaky") @Test public void checkVisibility_imeLayerBecomesInvisible() { checkResults(result -> LayersTraceSubject.assertThat(result) @@ -71,6 +73,7 @@ public class CloseImeWindowToHomeTest extends NonRotationTestBase { .forAllEntries()); } + @Ignore("Flaky") @Test public void checkVisibility_imeAppLayerBecomesInvisible() { checkResults(result -> LayersTraceSubject.assertThat(result) diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/SeamlessAppRotationTest.java b/tests/FlickerTests/src/com/android/server/wm/flicker/SeamlessAppRotationTest.java index 8559cb9f51f7..37d7c4ca2b46 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/SeamlessAppRotationTest.java +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/SeamlessAppRotationTest.java @@ -69,7 +69,7 @@ public class SeamlessAppRotationTest extends FlickerTestBase { @Parameters(name = "{0}") public static Collection<Object[]> getParams() { int[] supportedRotations = - {Surface.ROTATION_0, Surface.ROTATION_90, Surface.ROTATION_270}; + {Surface.ROTATION_0, Surface.ROTATION_90}; Collection<Object[]> params = new ArrayList<>(); ArrayList<Intent> testIntents = new ArrayList<>(); @@ -112,7 +112,7 @@ public class SeamlessAppRotationTest extends FlickerTestBase { super.runTransition( changeAppRotation(mIntent, intentId, InstrumentationRegistry.getContext(), - mUiDevice, mBeginRotation, mEndRotation).repeat(5).build()); + mUiDevice, mBeginRotation, mEndRotation).build()); } @Test diff --git a/tests/PlatformCompatGating/Android.bp b/tests/PlatformCompatGating/Android.bp index 5e9ef8efc402..609896ea9e95 100644 --- a/tests/PlatformCompatGating/Android.bp +++ b/tests/PlatformCompatGating/Android.bp @@ -18,7 +18,6 @@ android_test { name: "PlatformCompatGating", // Only compile source java files in this apk. srcs: ["src/**/*.java"], - certificate: "platform", libs: [ "android.test.runner", "android.test.base", diff --git a/tests/PlatformCompatGating/test-rules/src/android/compat/testing/PlatformCompatChangeRule.java b/tests/PlatformCompatGating/test-rules/src/android/compat/testing/PlatformCompatChangeRule.java index 932ec643d478..c00aa2ac25b3 100644 --- a/tests/PlatformCompatGating/test-rules/src/android/compat/testing/PlatformCompatChangeRule.java +++ b/tests/PlatformCompatGating/test-rules/src/android/compat/testing/PlatformCompatChangeRule.java @@ -16,7 +16,9 @@ package android.compat.testing; +import android.Manifest; import android.app.Instrumentation; +import android.app.UiAutomation; import android.compat.Compatibility; import android.compat.Compatibility.ChangeConfig; import android.content.Context; @@ -83,12 +85,16 @@ public class PlatformCompatChangeRule extends CoreCompatChangeRule { @Override public void evaluate() throws Throwable { Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); + UiAutomation uiAutomation = instrumentation.getUiAutomation(); String packageName = instrumentation.getTargetContext().getPackageName(); IPlatformCompat platformCompat = IPlatformCompat.Stub .asInterface(ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE)); if (platformCompat == null) { throw new IllegalStateException("Could not get IPlatformCompat service!"); } + uiAutomation.adoptShellPermissionIdentity( + Manifest.permission.READ_COMPAT_CHANGE_CONFIG, + Manifest.permission.OVERRIDE_COMPAT_CHANGE_CONFIG); Compatibility.setOverrides(mConfig); try { platformCompat.setOverridesForTest(new CompatibilityChangeConfig(mConfig), @@ -101,6 +107,7 @@ public class PlatformCompatChangeRule extends CoreCompatChangeRule { } catch (RemoteException e) { throw new RuntimeException("Could not call IPlatformCompat binder method!", e); } finally { + uiAutomation.dropShellPermissionIdentity(); Compatibility.clearOverrides(); } } diff --git a/tests/net/common/java/android/net/RouteInfoTest.java b/tests/net/common/java/android/net/RouteInfoTest.java index 5ce84363082f..fe51b3af4d72 100644 --- a/tests/net/common/java/android/net/RouteInfoTest.java +++ b/tests/net/common/java/android/net/RouteInfoTest.java @@ -258,6 +258,16 @@ public class RouteInfoTest extends TestCase { assertParcelingIsLossless(r); r = new RouteInfo(Prefix("192.0.2.0/24"), null, "wlan0"); - assertParcelSane(r, 6); + assertParcelSane(r, 7); + } + + public void testMtu() { + RouteInfo r; + r = new RouteInfo(Prefix("0.0.0.0/0"), Address("0.0.0.0"), "wlan0", + RouteInfo.RTN_UNICAST, 1500); + assertEquals(1500, r.getMtu()); + + r = new RouteInfo(Prefix("0.0.0.0/0"), Address("0.0.0.0"), "wlan0"); + assertEquals(0, r.getMtu()); } } diff --git a/wifi/java/android/net/wifi/ScanResult.aidl b/wifi/java/android/net/wifi/ScanResult.aidl index bb66722e4a13..b30689ca5d16 100644 --- a/wifi/java/android/net/wifi/ScanResult.aidl +++ b/wifi/java/android/net/wifi/ScanResult.aidl @@ -16,4 +16,4 @@ package android.net.wifi; -parcelable ScanResult; +@JavaOnlyStableParcelable parcelable ScanResult; diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java index 2901bd8cbb48..2d0942d3ffa7 100644 --- a/wifi/java/android/net/wifi/ScanResult.java +++ b/wifi/java/android/net/wifi/ScanResult.java @@ -16,13 +16,16 @@ package android.net.wifi; +import android.annotation.NonNull; import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; +import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Objects; @@ -433,58 +436,100 @@ public class ScanResult implements Parcelable { @UnsupportedAppUsage public List<String> anqpLines; - /** information elements from beacon - * @hide + /** + * information elements from beacon. */ public static class InformationElement { + /** @hide */ @UnsupportedAppUsage public static final int EID_SSID = 0; + /** @hide */ @UnsupportedAppUsage public static final int EID_SUPPORTED_RATES = 1; + /** @hide */ @UnsupportedAppUsage public static final int EID_TIM = 5; + /** @hide */ @UnsupportedAppUsage public static final int EID_BSS_LOAD = 11; + /** @hide */ @UnsupportedAppUsage public static final int EID_ERP = 42; + /** @hide */ public static final int EID_HT_CAPABILITIES = 45; + /** @hide */ @UnsupportedAppUsage public static final int EID_RSN = 48; + /** @hide */ @UnsupportedAppUsage public static final int EID_EXTENDED_SUPPORTED_RATES = 50; + /** @hide */ @UnsupportedAppUsage public static final int EID_HT_OPERATION = 61; + /** @hide */ @UnsupportedAppUsage public static final int EID_INTERWORKING = 107; + /** @hide */ @UnsupportedAppUsage public static final int EID_ROAMING_CONSORTIUM = 111; + /** @hide */ @UnsupportedAppUsage public static final int EID_EXTENDED_CAPS = 127; + /** @hide */ public static final int EID_VHT_CAPABILITIES = 191; + /** @hide */ @UnsupportedAppUsage public static final int EID_VHT_OPERATION = 192; + /** @hide */ @UnsupportedAppUsage public static final int EID_VSA = 221; + /** @hide */ @UnsupportedAppUsage public int id; + /** @hide */ @UnsupportedAppUsage public byte[] bytes; + /** @hide */ public InformationElement() { } - public InformationElement(InformationElement rhs) { + public InformationElement(@NonNull InformationElement rhs) { this.id = rhs.id; this.bytes = rhs.bytes.clone(); } + + /** + * The element ID of the information element. Defined in the IEEE 802.11-2016 spec + * Table 9-77. + */ + public int getId() { + return id; + } + + /** + * Get the specific content of the information element. + */ + @NonNull + public ByteBuffer getBytes() { + return ByteBuffer.wrap(bytes).asReadOnlyBuffer(); + } } - /** information elements found in the beacon + /** + * information elements found in the beacon. * @hide */ @UnsupportedAppUsage public InformationElement[] informationElements; + /** + * Get all information elements found in the beacon. + */ + @NonNull + public List<InformationElement> getInformationElements() { + return Collections.unmodifiableList(Arrays.asList(informationElements)); + } /** ANQP response elements. * @hide @@ -604,8 +649,8 @@ public class ScanResult implements Parcelable { this.wifiSsid = wifiSsid; } - /** copy constructor {@hide} */ - public ScanResult(ScanResult source) { + /** copy constructor */ + public ScanResult(@NonNull ScanResult source) { if (source != null) { wifiSsid = source.wifiSsid; SSID = source.SSID; @@ -759,9 +804,8 @@ public class ScanResult implements Parcelable { } } - /** Implement the Parcelable interface {@hide} */ - @UnsupportedAppUsage - public static final @android.annotation.NonNull Creator<ScanResult> CREATOR = + /** Implement the Parcelable interface */ + public static final @NonNull Creator<ScanResult> CREATOR = new Creator<ScanResult>() { public ScanResult createFromParcel(Parcel in) { WifiSsid wifiSsid = null; |