diff options
130 files changed, 3339 insertions, 1197 deletions
diff --git a/Android.bp b/Android.bp index 8c2d236ec076..c9ae9bad7deb 100644 --- a/Android.bp +++ b/Android.bp @@ -524,42 +524,9 @@ java_library { ], } -java_library { - name: "framework-annotation-proc", - defaults: ["framework-defaults"], - srcs: [":framework-all-sources"], - libs: [ - "app-compat-annotations", - "unsupportedappusage", - ], - installable: false, - plugins: [ - "compat-changeid-annotation-processor", - ], -} - platform_compat_config { - name: "framework-platform-compat-config", - src: ":framework-annotation-proc", -} - -// A library including just UnsupportedAppUsage.java classes. -// -// Provided for target so that libraries can use it without depending on -// the whole of framework or the core platform API. -// -// Built for host so that the annotation processor can also use this annotation. -java_library { - name: "unsupportedappusage-annotation", - host_supported: true, - srcs: [ - "core/java/android/annotation/IntDef.java", - ], - static_libs: [ - "art.module.api.annotations", - ], - - sdk_version: "core_current", + name: "framework-platform-compat-config", + src: ":framework-minus-apex", } // A temporary build target that is conditionally included on the bootclasspath if @@ -646,6 +613,7 @@ filegroup { srcs: [ "core/java/android/annotation/StringDef.java", "core/java/android/net/annotations/PolicyDirection.java", + "core/java/com/android/internal/util/HexDump.java", "core/java/com/android/internal/util/IState.java", "core/java/com/android/internal/util/State.java", "core/java/com/android/internal/util/StateMachine.java", @@ -1021,16 +989,6 @@ aidl_mapping { output: "framework-aidl-mappings.txt", } -genrule { - name: "framework-annotation-proc-index", - srcs: [":framework-annotation-proc"], - cmd: "unzip -qp $(in) unsupportedappusage/unsupportedappusage_index.csv > $(out)", - out: ["unsupportedappusage_index.csv"], - dist: { - targets: ["droidcore"], - }, -} - filegroup { name: "framework-cellbroadcast-shared-srcs", srcs: [ diff --git a/Android.mk b/Android.mk index 09f2c40e7202..aea0c951052f 100644 --- a/Android.mk +++ b/Android.mk @@ -42,6 +42,8 @@ $(call dist-for-goals,sdk,$(INTERNAL_PLATFORM_TEST_API_FILE)) $(call dist-for-goals,sdk,$(INTERNAL_PLATFORM_API_FILE):apistubs/android/public/api/android.txt) $(call dist-for-goals,sdk,$(INTERNAL_PLATFORM_SYSTEM_API_FILE):apistubs/android/system/api/android.txt) $(call dist-for-goals,sdk,$(INTERNAL_PLATFORM_TEST_API_FILE):apistubs/android/test/api/android.txt) +$(call dist-for-goals,sdk,$(INTERNAL_PLATFORM_MODULE_LIB_API_FILE):apistubs/android/module-lib/api/android.txt) +$(call dist-for-goals,sdk,$(INTERNAL_PLATFORM_SYSTEM_SERVER_API_FILE):apistubs/android/system-server/api/android.txt) # sdk.atree needs to copy the whole dir: $(OUT_DOCS)/offline-sdk to the final zip. # So keep offline-sdk-timestamp target here, and unzip offline-sdk-docs.zip to diff --git a/ApiDocs.bp b/ApiDocs.bp index b7e364690d03..7fd116886e7a 100644 --- a/ApiDocs.bp +++ b/ApiDocs.bp @@ -65,8 +65,9 @@ stubs_defaults { "test-base/src/**/*.java", ":opt-telephony-srcs", ":opt-net-voip-srcs", - ":core-current-stubs-source", - ":core_public_api_files", + ":art-module-public-api-stubs-source", + ":conscrypt-module-public-api-stubs-source", + ":android_icu4j_public_api_files", "test-mock/src/**/*.java", "test-runner/src/**/*.java", ], diff --git a/StubLibraries.bp b/StubLibraries.bp index 9a52cf69ef3d..f0810713f39f 100644 --- a/StubLibraries.bp +++ b/StubLibraries.bp @@ -47,8 +47,9 @@ stubs_defaults { "core/java/**/*.logtags", ":opt-telephony-srcs", ":opt-net-voip-srcs", - ":core-current-stubs-source", - ":core_public_api_files", + ":art-module-public-api-stubs-source", + ":conscrypt-module-public-api-stubs-source", + ":android_icu4j_public_api_files", ], libs: ["framework-internal-utils"], installable: false, @@ -187,6 +188,7 @@ droidstubs { droidstubs { name: "module-lib-api", defaults: ["metalava-full-api-stubs-default"], + api_tag_name: "MODULE_LIB", arg_files: ["core/res/AndroidManifest.xml"], args: metalava_framework_docs_args + module_libs, check_api: { @@ -227,16 +229,18 @@ droidstubs { java_defaults { name: "framework-stubs-default", libs: [ "stub-annotations" ], - static_libs: [ "private-stub-annotations-jar" ], + static_libs: [ + "private-stub-annotations-jar", + + // License notices from art module + "art-notices-for-framework-stubs-jar", + ], sdk_version: "core_current", errorprone: { javacflags: [ "-XepDisableAllChecks", ], }, - java_resources: [ - ":notices-for-framework-stubs", - ], system_modules: "none", java_version: "1.8", compile_dex: true, diff --git a/apex/Android.bp b/apex/Android.bp index 19439401a7fb..a6461f39d553 100644 --- a/apex/Android.bp +++ b/apex/Android.bp @@ -66,6 +66,24 @@ stubs_defaults { }, } +java_defaults { + name: "framework-module-stubs-lib-defaults-publicapi", + installable: false, + sdk_version: "module_current", +} + +java_defaults { + name: "framework-module-stubs-lib-defaults-systemapi", + installable: false, + sdk_version: "module_current", +} + +java_defaults { + name: "framework-module-stubs-lib-defaults-module_libs_api", + installable: false, + sdk_version: "module_current", +} + // The defaults for module_libs comes in two parts - defaults for API checks // and defaults for stub generation. This is because we want the API txt // files to *only* include the module_libs_api, but the stubs to include diff --git a/apex/sdkextensions/framework/Android.bp b/apex/sdkextensions/framework/Android.bp index 86f4ab7c1128..707113b9672c 100644 --- a/apex/sdkextensions/framework/Android.bp +++ b/apex/sdkextensions/framework/Android.bp @@ -86,7 +86,7 @@ droidstubs { java_library { name: "framework-sdkextensions-stubs-publicapi", srcs: [":framework-sdkextensions-stubs-srcs-publicapi"], - sdk_version: "current", + defaults: ["framework-module-stubs-lib-defaults-publicapi"], visibility: [ "//frameworks/base", // Framework "//frameworks/base/apex/sdkextensions", // sdkextensions SDK @@ -96,7 +96,7 @@ java_library { java_library { name: "framework-sdkextensions-stubs-systemapi", srcs: [":framework-sdkextensions-stubs-srcs-systemapi"], - sdk_version: "system_current", + defaults: ["framework-module-stubs-lib-defaults-systemapi"], visibility: [ "//frameworks/base", // Framework "//frameworks/base/apex/sdkextensions", // sdkextensions SDK @@ -106,7 +106,7 @@ java_library { java_library { name: "framework-sdkextensions-stubs-module_libs_api", srcs: [":framework-sdkextensions-stubs-srcs-module_libs_api"], - sdk_version: "system_current", + defaults: ["framework-module-stubs-lib-defaults-module_libs_api"], visibility: [ "//frameworks/base", // Framework "//frameworks/base/apex/sdkextensions", // sdkextensions SDK diff --git a/api/current.txt b/api/current.txt index 4b2323ee966d..a5b88b381e79 100644 --- a/api/current.txt +++ b/api/current.txt @@ -11405,7 +11405,8 @@ package android.content.pm { public class PackageInstaller { method public void abandonSession(int); method public int createSession(@NonNull android.content.pm.PackageInstaller.SessionParams) throws java.io.IOException; - method @Nullable public android.content.pm.PackageInstaller.SessionInfo getActiveStagedSession(); + method @Deprecated @Nullable public android.content.pm.PackageInstaller.SessionInfo getActiveStagedSession(); + method @NonNull public java.util.List<android.content.pm.PackageInstaller.SessionInfo> getActiveStagedSessions(); method @NonNull public java.util.List<android.content.pm.PackageInstaller.SessionInfo> getAllSessions(); method @NonNull public java.util.List<android.content.pm.PackageInstaller.SessionInfo> getMySessions(); method @Nullable public android.content.pm.PackageInstaller.SessionInfo getSessionInfo(int); @@ -11490,11 +11491,13 @@ package android.content.pm { method @NonNull public String getStagedSessionErrorMessage(); method public long getUpdatedMillis(); method @NonNull public android.os.UserHandle getUser(); + method public boolean hasParentSessionId(); method public boolean isActive(); method public boolean isCommitted(); method public boolean isMultiPackage(); method public boolean isSealed(); method public boolean isStaged(); + method public boolean isStagedSessionActive(); method public boolean isStagedSessionApplied(); method public boolean isStagedSessionFailed(); method public boolean isStagedSessionReady(); @@ -29143,9 +29146,6 @@ package android.net { public final class NetworkCapabilities implements android.os.Parcelable { ctor public NetworkCapabilities(); ctor public NetworkCapabilities(android.net.NetworkCapabilities); - method @NonNull public android.net.NetworkCapabilities addCapability(int); - method @NonNull public android.net.NetworkCapabilities addTransportType(int); - method public void clearAll(); method public int describeContents(); method public int getLinkDownstreamBandwidthKbps(); method public int getLinkUpstreamBandwidthKbps(); @@ -29155,13 +29155,6 @@ package android.net { method @Nullable public android.net.TransportInfo getTransportInfo(); method public boolean hasCapability(int); method public boolean hasTransport(int); - method @NonNull public android.net.NetworkCapabilities removeCapability(int); - method @NonNull public android.net.NetworkCapabilities setCapability(int, boolean); - method @NonNull public android.net.NetworkCapabilities setLinkDownstreamBandwidthKbps(int); - method @NonNull public android.net.NetworkCapabilities setLinkUpstreamBandwidthKbps(int); - method @NonNull public android.net.NetworkCapabilities setNetworkSpecifier(@NonNull android.net.NetworkSpecifier); - method @NonNull public android.net.NetworkCapabilities setOwnerUid(int); - method @NonNull public android.net.NetworkCapabilities setSignalStrength(int); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkCapabilities> CREATOR; field public static final int NET_CAPABILITY_CAPTIVE_PORTAL = 17; // 0x11 @@ -44724,12 +44717,9 @@ package android.telephony { field public static final String EXTRA_SLOT_INDEX = "android.telephony.extra.SLOT_INDEX"; field public static final String EXTRA_SUBSCRIPTION_INDEX = "android.telephony.extra.SUBSCRIPTION_INDEX"; field public static final String IMSI_KEY_AVAILABILITY_INT = "imsi_key_availability_int"; - field public static final String KEY_5G_ICON_CONFIGURATION_STRING = "5g_icon_configuration_string"; - field public static final String KEY_5G_ICON_DISPLAY_GRACE_PERIOD_SEC_INT = "5g_icon_display_grace_period_sec_int"; 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"; @@ -44922,7 +44912,6 @@ package android.telephony { field public static final String KEY_SHOW_APN_SETTING_CDMA_BOOL = "show_apn_setting_cdma_bool"; field public static final String KEY_SHOW_BLOCKING_PAY_PHONE_OPTION_BOOL = "show_blocking_pay_phone_option_bool"; field public static final String KEY_SHOW_CALL_BLOCKING_DISABLED_NOTIFICATION_ALWAYS_BOOL = "show_call_blocking_disabled_notification_always_bool"; - field public static final String KEY_SHOW_CARRIER_DATA_ICON_PATTERN_STRING = "show_carrier_data_icon_pattern_string"; field public static final String KEY_SHOW_CDMA_CHOICES_BOOL = "show_cdma_choices_bool"; field public static final String KEY_SHOW_ICCID_IN_SIM_STATUS_BOOL = "show_iccid_in_sim_status_bool"; field public static final String KEY_SHOW_IMS_REGISTRATION_STATUS_BOOL = "show_ims_registration_status_bool"; @@ -45014,7 +45003,7 @@ package android.telephony { public final class CellIdentityLte extends android.telephony.CellIdentity { method @NonNull public java.util.Set<java.lang.String> getAdditionalPlmns(); - method @NonNull public java.util.List<java.lang.Integer> getBands(); + method @NonNull public int[] getBands(); method public int getBandwidth(); method public int getCi(); method @Nullable public android.telephony.ClosedSubscriberGroupInfo getClosedSubscriberGroupInfo(); @@ -45032,7 +45021,7 @@ package android.telephony { public final class CellIdentityNr extends android.telephony.CellIdentity { method @NonNull public java.util.Set<java.lang.String> getAdditionalPlmns(); - method @NonNull public java.util.List<java.lang.Integer> getBands(); + method @NonNull public int[] getBands(); method @Nullable public String getMccString(); method @Nullable public String getMncString(); method public long getNci(); @@ -45347,7 +45336,6 @@ package android.telephony { method @NonNull public java.util.List<java.lang.Integer> getAvailableServices(); method @Nullable public android.telephony.CellIdentity getCellIdentity(); method public int getDomain(); - method public int getNrState(); method @Nullable public String getRegisteredPlmn(); method public int getTransportType(); method public boolean isRegistered(); @@ -45874,7 +45862,7 @@ package android.telephony { method public long getDataLimitBytes(); method public long getDataUsageBytes(); method public long getDataUsageTime(); - method @Nullable public int[] getNetworkTypes(); + method @NonNull public int[] getNetworkTypes(); method @Nullable public CharSequence getSummary(); method @Nullable public CharSequence getTitle(); method public void writeToParcel(android.os.Parcel, int); @@ -45894,7 +45882,7 @@ package android.telephony { method public static android.telephony.SubscriptionPlan.Builder createRecurring(java.time.ZonedDateTime, java.time.Period); method public android.telephony.SubscriptionPlan.Builder setDataLimit(long, int); method public android.telephony.SubscriptionPlan.Builder setDataUsage(long, long); - method @NonNull public android.telephony.SubscriptionPlan.Builder setNetworkTypes(@Nullable int[]); + method @NonNull public android.telephony.SubscriptionPlan.Builder setNetworkTypes(@NonNull int[]); method public android.telephony.SubscriptionPlan.Builder setSummary(@Nullable CharSequence); method public android.telephony.SubscriptionPlan.Builder setTitle(@Nullable CharSequence); } @@ -46000,6 +45988,7 @@ package android.telephony { method public boolean setLine1NumberForDisplay(String, String); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setNetworkSelectionModeAutomatic(); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setNetworkSelectionModeManual(String, boolean); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setNetworkSelectionModeManual(@NonNull String, boolean, int); method public boolean setOperatorBrandOverride(String); method public boolean setPreferredNetworkTypeToGlobal(); method public void setPreferredOpportunisticDataSubscription(int, boolean, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>); @@ -46527,6 +46516,7 @@ package android.telephony.ims { public class ImsManager { method @NonNull public android.telephony.ims.ImsMmTelManager getImsMmTelManager(int); + method @NonNull public android.telephony.ims.ImsRcsManager getImsRcsManager(int); field public static final String ACTION_WFC_IMS_REGISTRATION_ERROR = "android.telephony.ims.action.WFC_IMS_REGISTRATION_ERROR"; field public static final String EXTRA_WFC_REGISTRATION_FAILURE_MESSAGE = "android.telephony.ims.extra.WFC_REGISTRATION_FAILURE_MESSAGE"; field public static final String EXTRA_WFC_REGISTRATION_FAILURE_TITLE = "android.telephony.ims.extra.WFC_REGISTRATION_FAILURE_TITLE"; @@ -46555,6 +46545,15 @@ package android.telephony.ims { method public void onCapabilitiesStatusChanged(@NonNull android.telephony.ims.feature.MmTelFeature.MmTelCapabilities); } + public class ImsRcsManager implements android.telephony.ims.RegistrationManager { + method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getRegistrationState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); + method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getRegistrationTransportType(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); + method @NonNull public android.telephony.ims.RcsUceAdapter getUceAdapter(); + method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.RegistrationManager.RegistrationCallback) throws android.telephony.ims.ImsException; + method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.RegistrationManager.RegistrationCallback); + field public static final String ACTION_SHOW_CAPABILITY_DISCOVERY_OPT_IN = "android.telephony.ims.action.SHOW_CAPABILITY_DISCOVERY_OPT_IN"; + } + public final class ImsReasonInfo implements android.os.Parcelable { ctor public ImsReasonInfo(int, int, @Nullable String); method public int describeContents(); @@ -46738,6 +46737,10 @@ package android.telephony.ims { field public static final int EXTRA_CODE_CALL_RETRY_SILENT_REDIAL = 2; // 0x2 } + public class RcsUceAdapter { + method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public boolean isUceSettingEnabled() throws android.telephony.ims.ImsException; + } + public interface RegistrationManager { method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getRegistrationState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getRegistrationTransportType(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); @@ -46752,8 +46755,8 @@ package android.telephony.ims { ctor public RegistrationManager.RegistrationCallback(); method public void onRegistered(int); method public void onRegistering(int); - method public void onTechnologyChangeFailed(int, @Nullable android.telephony.ims.ImsReasonInfo); - method public void onUnregistered(@Nullable android.telephony.ims.ImsReasonInfo); + method public void onTechnologyChangeFailed(int, @NonNull android.telephony.ims.ImsReasonInfo); + method public void onUnregistered(@NonNull android.telephony.ims.ImsReasonInfo); } } diff --git a/api/system-current.txt b/api/system-current.txt index 9144b3d97fd1..6ab5b1ed25e2 100755 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -229,9 +229,6 @@ package android { public static final class R.array { field public static final int config_keySystemUuidMapping = 17235973; // 0x1070005 - field public static final int config_restrictedPreinstalledCarrierApps = 17235975; // 0x1070007 - field public static final int config_sms_enabled_locking_shift_tables = 17235977; // 0x1070009 - field public static final int config_sms_enabled_single_shift_tables = 17235976; // 0x1070008 field public static final int simColors = 17235974; // 0x1070006 } @@ -279,7 +276,6 @@ package android { field public static final int config_helpIntentNameKey = 17039390; // 0x104001e field public static final int config_helpPackageNameKey = 17039387; // 0x104001b field public static final int config_helpPackageNameValue = 17039388; // 0x104001c - field public static final int low_memory = 17039397; // 0x1040025 } public static final class R.style { @@ -324,7 +320,6 @@ package android.app { method @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS) public static void setPersistentVrThread(int); method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean switchUser(@NonNull android.os.UserHandle); method public void unregisterHomeVisibilityObserver(@NonNull android.app.HomeVisibilityObserver); - method @RequiresPermission(android.Manifest.permission.CHANGE_CONFIGURATION) public boolean updateMccMncConfiguration(@NonNull String, @NonNull String); } public static interface ActivityManager.OnUidImportanceListener { @@ -1542,7 +1537,6 @@ package android.content { 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"; - field public static final String NETWORK_POLICY_SERVICE = "netpolicy"; field public static final String NETWORK_SCORE_SERVICE = "network_score"; field public static final String OEM_LOCK_SERVICE = "oem_lock"; field public static final String PERMISSION_SERVICE = "permission"; @@ -4405,10 +4399,10 @@ package android.net { public class InvalidPacketException extends java.lang.Exception { ctor public InvalidPacketException(int); + method public int getError(); field public static final int ERROR_INVALID_IP_ADDRESS = -21; // 0xffffffeb field public static final int ERROR_INVALID_LENGTH = -23; // 0xffffffe9 field public static final int ERROR_INVALID_PORT = -22; // 0xffffffea - field public final int error; } public final class IpConfiguration implements android.os.Parcelable { @@ -4462,12 +4456,12 @@ package android.net { } public class KeepalivePacketData { - ctor protected KeepalivePacketData(@NonNull java.net.InetAddress, int, @NonNull java.net.InetAddress, int, @NonNull byte[]) throws android.net.InvalidPacketException; + ctor protected KeepalivePacketData(@NonNull java.net.InetAddress, @IntRange(from=0, to=65535) int, @NonNull java.net.InetAddress, @IntRange(from=0, to=65535) int, @NonNull byte[]) throws android.net.InvalidPacketException; + method @NonNull public java.net.InetAddress getDstAddress(); + method public int getDstPort(); method @NonNull public byte[] getPacket(); - field @NonNull public final java.net.InetAddress dstAddress; - field public final int dstPort; - field @NonNull public final java.net.InetAddress srcAddress; - field public final int srcPort; + method @NonNull public java.net.InetAddress getSrcAddress(); + method public int getSrcPort(); } public class LinkAddress implements android.os.Parcelable { @@ -4540,8 +4534,8 @@ package android.net { public class Network implements android.os.Parcelable { ctor public Network(@NonNull android.net.Network); + method public int getNetId(); method @NonNull public android.net.Network getPrivateDnsBypassingCopy(); - field public final int netId; } public abstract class NetworkAgent { @@ -4590,18 +4584,33 @@ package android.net { public final class NetworkCapabilities implements android.os.Parcelable { method @NonNull public int[] getAdministratorUids(); - method @Nullable public String getSSID(); + method @Nullable public String getSsid(); method @NonNull public int[] getTransportTypes(); method public boolean satisfiedByNetworkCapabilities(@Nullable android.net.NetworkCapabilities); - method @NonNull public android.net.NetworkCapabilities setAdministratorUids(@NonNull int[]); - method @NonNull public android.net.NetworkCapabilities setRequestorPackageName(@NonNull String); - method @NonNull public android.net.NetworkCapabilities setRequestorUid(int); - method @NonNull public android.net.NetworkCapabilities setSSID(@Nullable String); - method @NonNull public android.net.NetworkCapabilities setTransportInfo(@NonNull android.net.TransportInfo); field public static final int NET_CAPABILITY_OEM_PAID = 22; // 0x16 field public static final int NET_CAPABILITY_PARTIAL_CONNECTIVITY = 24; // 0x18 } + public static class NetworkCapabilities.Builder { + ctor public NetworkCapabilities.Builder(); + ctor public NetworkCapabilities.Builder(@NonNull android.net.NetworkCapabilities); + method @NonNull public android.net.NetworkCapabilities.Builder addCapability(int); + method @NonNull public android.net.NetworkCapabilities.Builder addTransportType(int); + method @NonNull public android.net.NetworkCapabilities build(); + method @NonNull public android.net.NetworkCapabilities.Builder removeCapability(int); + method @NonNull public android.net.NetworkCapabilities.Builder removeTransportType(int); + method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setAdministratorUids(@NonNull int[]); + method @NonNull public android.net.NetworkCapabilities.Builder setLinkDownstreamBandwidthKbps(int); + method @NonNull public android.net.NetworkCapabilities.Builder setLinkUpstreamBandwidthKbps(int); + method @NonNull public android.net.NetworkCapabilities.Builder setNetworkSpecifier(@Nullable android.net.NetworkSpecifier); + method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setOwnerUid(int); + method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setRequestorPackageName(@Nullable String); + method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setRequestorUid(int); + method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP) public android.net.NetworkCapabilities.Builder setSignalStrength(int); + method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setSsid(@Nullable String); + method @NonNull public android.net.NetworkCapabilities.Builder setTransportInfo(@Nullable android.net.TransportInfo); + } + public class NetworkKey implements android.os.Parcelable { ctor public NetworkKey(android.net.WifiKey); method @Nullable public static android.net.NetworkKey createFromScanResult(@Nullable android.net.wifi.ScanResult); @@ -4795,7 +4804,6 @@ package android.net { method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerTetheringEventCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.TetheringEventCallback); method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void requestLatestTetheringEntitlementResult(int, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.OnTetheringEntitlementResultListener); method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void startTethering(@NonNull android.net.TetheringManager.TetheringRequest, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.StartTetheringCallback); - method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void startTethering(int, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.StartTetheringCallback); method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void stopAllTethering(); method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void stopTethering(int); method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.ACCESS_NETWORK_STATE}) public void unregisterTetheringEventCallback(@NonNull android.net.TetheringManager.TetheringEventCallback); @@ -8014,27 +8022,6 @@ package android.telephony { field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CallAttributes> CREATOR; } - public final class CallForwardingInfo implements android.os.Parcelable { - ctor public CallForwardingInfo(int, int, @Nullable String, int); - method public int describeContents(); - method @Nullable public String getNumber(); - method public int getReason(); - method public int getStatus(); - method public int getTimeoutSeconds(); - field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CallForwardingInfo> CREATOR; - field public static final int REASON_ALL = 4; // 0x4 - field public static final int REASON_ALL_CONDITIONAL = 5; // 0x5 - field public static final int REASON_BUSY = 1; // 0x1 - field public static final int REASON_NOT_REACHABLE = 3; // 0x3 - field public static final int REASON_NO_REPLY = 2; // 0x2 - field public static final int REASON_UNCONDITIONAL = 0; // 0x0 - field public static final int STATUS_ACTIVE = 1; // 0x1 - field public static final int STATUS_FDN_CHECK_FAILURE = 2; // 0x2 - field public static final int STATUS_INACTIVE = 0; // 0x0 - field public static final int STATUS_NOT_SUPPORTED = 4; // 0x4 - field public static final int STATUS_UNKNOWN_ERROR = 3; // 0x3 - } - public final class CallQuality implements android.os.Parcelable { ctor public CallQuality(int, int, int, int, int, int, int, int, int, int, int); ctor public CallQuality(int, int, int, int, int, int, int, int, int, int, int, boolean, boolean, boolean); @@ -8522,7 +8509,6 @@ package android.telephony { public final class DataSpecificRegistrationInfo implements android.os.Parcelable { method public int describeContents(); method @NonNull public android.telephony.LteVopsSupportInfo getLteVopsSupportInfo(); - method public boolean isUsingCarrierAggregation(); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.telephony.DataSpecificRegistrationInfo> CREATOR; } @@ -8744,7 +8730,6 @@ package android.telephony { method public void onRadioPowerStateChanged(int); method public void onSrvccStateChanged(int); method public void onVoiceActivationStateChanged(int); - field @RequiresPermission(android.Manifest.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH) public static final int LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH = 512; // 0x200 field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_CALL_ATTRIBUTES_CHANGED = 67108864; // 0x4000000 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 @@ -8775,7 +8760,6 @@ package android.telephony { } public final class PreciseDataConnectionState implements android.os.Parcelable { - ctor public PreciseDataConnectionState(int, int, int, @NonNull String, @Nullable android.net.LinkProperties, int, @Nullable android.telephony.data.ApnSetting); method @Deprecated @NonNull public String getDataConnectionApn(); method @Deprecated public int getDataConnectionApnTypeBitMask(); method @Deprecated public int getDataConnectionFailCause(); @@ -8888,7 +8872,6 @@ package android.telephony { method @Nullable public android.telephony.NetworkRegistrationInfo getNetworkRegistrationInfo(int, int); method @NonNull public java.util.List<android.telephony.NetworkRegistrationInfo> getNetworkRegistrationInfoListForDomain(int); method @NonNull public java.util.List<android.telephony.NetworkRegistrationInfo> getNetworkRegistrationInfoListForTransportType(int); - method public int getNrFrequencyRange(); method @Nullable public String getOperatorAlphaLongRaw(); method @Nullable public String getOperatorAlphaShortRaw(); method @NonNull public static android.telephony.ServiceState newFromBundle(@NonNull android.os.Bundle); @@ -9120,8 +9103,6 @@ package android.telephony { method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getAidForAppType(int); method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<android.service.carrier.CarrierIdentifier> getAllowedCarriers(int); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getAllowedNetworkTypes(); - method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.CallForwardingInfo getCallForwarding(int); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getCallWaitingStatus(); method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int); method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent); method public java.util.List<java.lang.String> getCarrierPackageNamesForIntentAndPhone(android.content.Intent, int); @@ -9204,15 +9185,12 @@ package android.telephony { method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setAllowedNetworkTypes(long); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setAlwaysAllowMmsData(boolean); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setCallForwarding(@NonNull android.telephony.CallForwardingInfo); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setCallWaitingStatus(boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCarrierDataEnabled(boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setCarrierRestrictionRules(@NonNull android.telephony.CarrierRestrictionRules); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataActivationState(int); method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataEnabled(int, boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataRoamingEnabled(boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setMultiSimCarrierRestriction(boolean); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public 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); @@ -9246,10 +9224,6 @@ package android.telephony { field public static final String ACTION_SIM_APPLICATION_STATE_CHANGED = "android.telephony.action.SIM_APPLICATION_STATE_CHANGED"; field public static final String ACTION_SIM_CARD_STATE_CHANGED = "android.telephony.action.SIM_CARD_STATE_CHANGED"; field public static final String ACTION_SIM_SLOT_STATUS_CHANGED = "android.telephony.action.SIM_SLOT_STATUS_CHANGED"; - field public static final int CALL_WAITING_STATUS_ACTIVE = 1; // 0x1 - field public static final int CALL_WAITING_STATUS_INACTIVE = 2; // 0x2 - field public static final int CALL_WAITING_STATUS_NOT_SUPPORTED = 4; // 0x4 - field public static final int CALL_WAITING_STATUS_UNKNOWN_ERROR = 3; // 0x3 field public static final int CARD_POWER_DOWN = 0; // 0x0 field public static final int CARD_POWER_UP = 1; // 0x1 field public static final int CARD_POWER_UP_PASS_THROUGH = 2; // 0x2 @@ -9716,7 +9690,7 @@ package android.telephony.ims { method public int getEmergencyServiceCategories(); method @NonNull public java.util.List<java.lang.String> getEmergencyUrns(); method public android.telephony.ims.ImsStreamMediaProfile getMediaProfile(); - method @Nullable public android.os.Bundle getProprietaryCallExtras(); + method @NonNull public android.os.Bundle getProprietaryCallExtras(); method public int getRestrictCause(); method public int getServiceType(); method public static int getVideoStateFromCallType(int); @@ -9877,7 +9851,6 @@ package android.telephony.ims { } public class ImsManager { - method @NonNull public android.telephony.ims.ImsRcsManager getImsRcsManager(int); field public static final String ACTION_FORBIDDEN_NO_SERVICE_AUTHORIZATION = "com.android.internal.intent.action.ACTION_FORBIDDEN_NO_SERVICE_AUTHORIZATION"; } @@ -9905,10 +9878,6 @@ package android.telephony.ims { ctor @Deprecated public ImsMmTelManager.RegistrationCallback(); } - public class ImsRcsManager implements android.telephony.ims.RegistrationManager { - method @NonNull public android.telephony.ims.RcsUceAdapter getUceAdapter(); - } - public final class ImsReasonInfo implements android.os.Parcelable { field public static final String EXTRA_MSG_SERVICE_NOT_AUTHORIZED = "Forbidden. Not Authorized for Service"; } @@ -10177,8 +10146,8 @@ package android.telephony.ims { field public static final int KEY_RCS_CAPABILITY_DISCOVERY_ENABLED = 17; // 0x11 field public static final int KEY_RCS_CAPABILITY_POLL_LIST_SUB_EXP_SEC = 23; // 0x17 field public static final int KEY_RCS_MAX_NUM_ENTRIES_IN_RCL = 22; // 0x16 + field public static final int KEY_RCS_PUBLISH_OFFLINE_AVAILABILITY_TIMER_SEC = 16; // 0x10 field public static final int KEY_RCS_PUBLISH_SOURCE_THROTTLE_MS = 21; // 0x15 - field public static final int KEY_RCS_PUBLISH_TIMER_EXTENDED_SEC = 16; // 0x10 field public static final int KEY_RCS_PUBLISH_TIMER_SEC = 15; // 0xf field public static final int KEY_REGISTRATION_DOMAIN_NAME = 12; // 0xc field public static final int KEY_REGISTRATION_RETRY_BASE_TIME_SEC = 33; // 0x21 @@ -10285,7 +10254,6 @@ package android.telephony.ims { } public class RcsUceAdapter { - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isUceSettingEnabled() throws android.telephony.ims.ImsException; method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setUceSettingEnabled(boolean) throws android.telephony.ims.ImsException; } diff --git a/api/system-lint-baseline.txt b/api/system-lint-baseline.txt index d2b3a6446346..306b8afaadae 100644 --- a/api/system-lint-baseline.txt +++ b/api/system-lint-baseline.txt @@ -165,12 +165,6 @@ PublicTypedef: android.content.integrity.Formula.Tag: Don't expose @IntDef: @Tag PublicTypedef: android.content.integrity.Rule.Effect: Don't expose @IntDef: @Effect must be hidden. -ResourceValueFieldName: android.R.array#config_sms_enabled_locking_shift_tables: - Expected resource name in `android.R.array` to be in the `fooBarBaz` style, was `config_sms_enabled_locking_shift_tables` -ResourceValueFieldName: android.R.array#config_sms_enabled_single_shift_tables: - Expected resource name in `android.R.array` to be in the `fooBarBaz` style, was `config_sms_enabled_single_shift_tables` - - SamShouldBeLast: android.accounts.AccountManager#addAccount(String, String, String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler): SamShouldBeLast: android.accounts.AccountManager#addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean): diff --git a/api/test-current.txt b/api/test-current.txt index 697b7e8f8a9d..9ed451c2f47e 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -62,7 +62,6 @@ package android.app { method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public void removeOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener); method public static void resumeAppSwitches() throws android.os.RemoteException; method @RequiresPermission(android.Manifest.permission.CHANGE_CONFIGURATION) public void scheduleApplicationInfoChanged(java.util.List<java.lang.String>, int); - method @RequiresPermission(android.Manifest.permission.CHANGE_CONFIGURATION) public boolean updateMccMncConfiguration(@NonNull String, @NonNull String); } public static interface ActivityManager.OnUidImportanceListener { @@ -1507,16 +1506,39 @@ package android.net { public class Network implements android.os.Parcelable { ctor public Network(@NonNull android.net.Network); + method public int getNetId(); method @NonNull public android.net.Network getPrivateDnsBypassingCopy(); } public final class NetworkCapabilities implements android.os.Parcelable { + method @NonNull public int[] getAdministratorUids(); method public int[] getCapabilities(); + method @Nullable public String getSsid(); method @NonNull public int[] getTransportTypes(); method public boolean satisfiedByNetworkCapabilities(@Nullable android.net.NetworkCapabilities); field public static final int TRANSPORT_TEST = 7; // 0x7 } + public static class NetworkCapabilities.Builder { + ctor public NetworkCapabilities.Builder(); + ctor public NetworkCapabilities.Builder(@NonNull android.net.NetworkCapabilities); + method @NonNull public android.net.NetworkCapabilities.Builder addCapability(int); + method @NonNull public android.net.NetworkCapabilities.Builder addTransportType(int); + method @NonNull public android.net.NetworkCapabilities build(); + method @NonNull public android.net.NetworkCapabilities.Builder removeCapability(int); + method @NonNull public android.net.NetworkCapabilities.Builder removeTransportType(int); + method @NonNull @RequiresPermission("android.permission.NETWORK_FACTORY") public android.net.NetworkCapabilities.Builder setAdministratorUids(@NonNull int[]); + method @NonNull public android.net.NetworkCapabilities.Builder setLinkDownstreamBandwidthKbps(int); + method @NonNull public android.net.NetworkCapabilities.Builder setLinkUpstreamBandwidthKbps(int); + method @NonNull public android.net.NetworkCapabilities.Builder setNetworkSpecifier(@Nullable android.net.NetworkSpecifier); + method @NonNull @RequiresPermission("android.permission.NETWORK_FACTORY") public android.net.NetworkCapabilities.Builder setOwnerUid(int); + method @NonNull @RequiresPermission("android.permission.NETWORK_FACTORY") public android.net.NetworkCapabilities.Builder setRequestorPackageName(@Nullable String); + method @NonNull @RequiresPermission("android.permission.NETWORK_FACTORY") public android.net.NetworkCapabilities.Builder setRequestorUid(int); + method @NonNull @RequiresPermission("android.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP") public android.net.NetworkCapabilities.Builder setSignalStrength(int); + method @NonNull @RequiresPermission("android.permission.NETWORK_FACTORY") public android.net.NetworkCapabilities.Builder setSsid(@Nullable String); + method @NonNull public android.net.NetworkCapabilities.Builder setTransportInfo(@Nullable android.net.TransportInfo); + } + public class NetworkStack { method @Nullable public static android.os.IBinder getService(); method public static void setServiceForTest(@Nullable android.os.IBinder); @@ -1593,7 +1615,6 @@ package android.net { method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerTetheringEventCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.TetheringEventCallback); method @RequiresPermission(anyOf={"android.permission.TETHER_PRIVILEGED", android.Manifest.permission.WRITE_SETTINGS}) public void requestLatestTetheringEntitlementResult(int, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.OnTetheringEntitlementResultListener); method @RequiresPermission(anyOf={"android.permission.TETHER_PRIVILEGED", android.Manifest.permission.WRITE_SETTINGS}) public void startTethering(@NonNull android.net.TetheringManager.TetheringRequest, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.StartTetheringCallback); - method @RequiresPermission(anyOf={"android.permission.TETHER_PRIVILEGED", android.Manifest.permission.WRITE_SETTINGS}) public void startTethering(int, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.StartTetheringCallback); method @RequiresPermission(anyOf={"android.permission.TETHER_PRIVILEGED", android.Manifest.permission.WRITE_SETTINGS}) public void stopAllTethering(); method @RequiresPermission(anyOf={"android.permission.TETHER_PRIVILEGED", android.Manifest.permission.WRITE_SETTINGS}) public void stopTethering(int); method @RequiresPermission(anyOf={"android.permission.TETHER_PRIVILEGED", android.Manifest.permission.ACCESS_NETWORK_STATE}) public void unregisterTetheringEventCallback(@NonNull android.net.TetheringManager.TetheringEventCallback); @@ -3328,7 +3349,7 @@ package android.telephony.ims { method public int getEmergencyServiceCategories(); method @NonNull public java.util.List<java.lang.String> getEmergencyUrns(); method public android.telephony.ims.ImsStreamMediaProfile getMediaProfile(); - method @Nullable public android.os.Bundle getProprietaryCallExtras(); + method @NonNull public android.os.Bundle getProprietaryCallExtras(); method public int getRestrictCause(); method public int getServiceType(); method public static int getVideoStateFromCallType(int); @@ -3490,7 +3511,6 @@ package android.telephony.ims { } public class ImsManager { - method @NonNull public android.telephony.ims.ImsRcsManager getImsRcsManager(int); field public static final String ACTION_FORBIDDEN_NO_SERVICE_AUTHORIZATION = "com.android.internal.intent.action.ACTION_FORBIDDEN_NO_SERVICE_AUTHORIZATION"; } @@ -3518,10 +3538,6 @@ package android.telephony.ims { ctor @Deprecated public ImsMmTelManager.RegistrationCallback(); } - public class ImsRcsManager implements android.telephony.ims.RegistrationManager { - method @NonNull public android.telephony.ims.RcsUceAdapter getUceAdapter(); - } - public class ImsService extends android.app.Service { ctor public ImsService(); method public android.telephony.ims.feature.MmTelFeature createMmTelFeature(int); @@ -3786,8 +3802,8 @@ package android.telephony.ims { field public static final int KEY_RCS_CAPABILITY_DISCOVERY_ENABLED = 17; // 0x11 field public static final int KEY_RCS_CAPABILITY_POLL_LIST_SUB_EXP_SEC = 23; // 0x17 field public static final int KEY_RCS_MAX_NUM_ENTRIES_IN_RCL = 22; // 0x16 + field public static final int KEY_RCS_PUBLISH_OFFLINE_AVAILABILITY_TIMER_SEC = 16; // 0x10 field public static final int KEY_RCS_PUBLISH_SOURCE_THROTTLE_MS = 21; // 0x15 - field public static final int KEY_RCS_PUBLISH_TIMER_EXTENDED_SEC = 16; // 0x10 field public static final int KEY_RCS_PUBLISH_TIMER_SEC = 15; // 0xf field public static final int KEY_REGISTRATION_DOMAIN_NAME = 12; // 0xc field public static final int KEY_REGISTRATION_RETRY_BASE_TIME_SEC = 33; // 0x21 @@ -3894,7 +3910,6 @@ package android.telephony.ims { } public class RcsUceAdapter { - method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public boolean isUceSettingEnabled() throws android.telephony.ims.ImsException; method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setUceSettingEnabled(boolean) throws android.telephony.ims.ImsException; } diff --git a/cmds/idmap2/idmap2/Create.cpp b/cmds/idmap2/idmap2/Create.cpp index bb8d92737563..f482191b09a8 100644 --- a/cmds/idmap2/idmap2/Create.cpp +++ b/cmds/idmap2/idmap2/Create.cpp @@ -50,7 +50,7 @@ Result<Unit> Create(const std::vector<std::string>& args) { std::string overlay_apk_path; std::string idmap_path; std::vector<std::string> policies; - bool ignore_overlayable; + bool ignore_overlayable = false; const CommandLineOptions opts = CommandLineOptions("idmap2 create") diff --git a/cmds/idmap2/idmap2/Dump.cpp b/cmds/idmap2/idmap2/Dump.cpp index 8716bf313ed0..47f442aab235 100644 --- a/cmds/idmap2/idmap2/Dump.cpp +++ b/cmds/idmap2/idmap2/Dump.cpp @@ -39,7 +39,7 @@ using android::idmap2::Unit; Result<Unit> Dump(const std::vector<std::string>& args) { SYSTRACE << "Dump " << args; std::string idmap_path; - bool verbose; + bool verbose = false; const CommandLineOptions opts = CommandLineOptions("idmap2 dump") diff --git a/cmds/idmap2/tests/Idmap2BinaryTests.cpp b/cmds/idmap2/tests/Idmap2BinaryTests.cpp index 8a48f4b8e6d5..499eb99af290 100644 --- a/cmds/idmap2/tests/Idmap2BinaryTests.cpp +++ b/cmds/idmap2/tests/Idmap2BinaryTests.cpp @@ -131,7 +131,6 @@ TEST_F(Idmap2BinaryTests, Dump) { ASSERT_NE(result->stdout.find("0x7f02000c -> 0x7f020000 string/str1"), std::string::npos); ASSERT_NE(result->stdout.find("0x7f02000e -> 0x7f020001 string/str3"), std::string::npos); ASSERT_NE(result->stdout.find("0x7f02000f -> 0x7f020002 string/str4"), std::string::npos); - ASSERT_EQ(result->stdout.find("00000210: 007f target package id"), std::string::npos); // clang-format off result = ExecuteBinary({"idmap2", diff --git a/cmds/incidentd/src/Section.cpp b/cmds/incidentd/src/Section.cpp index f476fcf91bd5..1cc761fa359f 100644 --- a/cmds/incidentd/src/Section.cpp +++ b/cmds/incidentd/src/Section.cpp @@ -512,8 +512,8 @@ status_t LogSection::BlockingCall(int pipeWriteFd) const { // Open log buffer and getting logs since last retrieved time if any. unique_ptr<logger_list, void (*)(logger_list*)> loggers( gLastLogsRetrieved.find(mLogID) == gLastLogsRetrieved.end() - ? android_logger_list_alloc(ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 0, 0) - : android_logger_list_alloc_time(ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, + ? android_logger_list_alloc(ANDROID_LOG_NONBLOCK, 0, 0) + : android_logger_list_alloc_time(ANDROID_LOG_NONBLOCK, gLastLogsRetrieved[mLogID], 0), android_logger_list_free); diff --git a/config/preloaded-classes b/config/preloaded-classes index eb3879fdb50e..b05d02c9eb15 100644 --- a/config/preloaded-classes +++ b/config/preloaded-classes @@ -7438,6 +7438,7 @@ sun.nio.fs.LinuxFileSystemProvider sun.nio.fs.NativeBuffer$Deallocator sun.nio.fs.NativeBuffer sun.nio.fs.NativeBuffers +sun.nio.fs.UnixChannelFactory sun.nio.fs.UnixChannelFactory$Flags sun.nio.fs.UnixConstants sun.nio.fs.UnixException diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 1e50077e1dc9..9d63bc2ef85a 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -3880,8 +3880,6 @@ public class ActivityManager { * {@code false} otherwise. * @hide */ - @SystemApi - @TestApi @RequiresPermission(android.Manifest.permission.CHANGE_CONFIGURATION) public boolean updateMccMncConfiguration(@NonNull String mcc, @NonNull String mnc) { if (mcc == null || mnc == null) { diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java index 2a72d43eccad..71b2773cf3ec 100644 --- a/core/java/android/app/LoadedApk.java +++ b/core/java/android/app/LoadedApk.java @@ -797,6 +797,11 @@ public final class LoadedApk { makePaths(mActivityThread, isBundledApp, mApplicationInfo, zipPaths, libPaths); String libraryPermittedPath = mDataDir; + if (mActivityThread == null) { + // In a zygote context where mActivityThread is null we can't access the app data dir + // and including this in libraryPermittedPath would cause SELinux denials. + libraryPermittedPath = ""; + } if (isBundledApp) { // For bundled apps, add the base directory of the app (e.g., diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index e6b90d87a59f..1508a657cf4a 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -916,23 +916,11 @@ public final class BluetoothAdapter { if (!isBleScanAlwaysAvailable()) { return false; } - - int state = getLeState(); - if (state == BluetoothAdapter.STATE_ON || state == BluetoothAdapter.STATE_BLE_ON) { - String packageName = ActivityThread.currentPackageName(); - if (DBG) { - Log.d(TAG, "disableBLE(): de-registering " + packageName); - } - try { - mManagerService.updateBleAppCount(mToken, false, packageName); - } catch (RemoteException e) { - Log.e(TAG, "", e); - } - return true; - } - - if (DBG) { - Log.d(TAG, "disableBLE(): Already disabled"); + String packageName = ActivityThread.currentPackageName(); + try { + return mManagerService.disableBle(packageName, mToken); + } catch (RemoteException e) { + Log.e(TAG, "", e); } return false; } @@ -973,20 +961,9 @@ public final class BluetoothAdapter { if (!isBleScanAlwaysAvailable()) { return false; } - + String packageName = ActivityThread.currentPackageName(); try { - String packageName = ActivityThread.currentPackageName(); - mManagerService.updateBleAppCount(mToken, true, packageName); - if (isLeEnabled()) { - if (DBG) { - Log.d(TAG, "enableBLE(): Bluetooth already enabled"); - } - return true; - } - if (DBG) { - Log.d(TAG, "enableBLE(): Calling enable"); - } - return mManagerService.enable(packageName); + return mManagerService.enableBle(packageName, mToken); } catch (RemoteException e) { Log.e(TAG, "", e); } diff --git a/core/java/android/bluetooth/BluetoothHearingAid.java b/core/java/android/bluetooth/BluetoothHearingAid.java index e0674d75974a..fa62a02499e0 100644 --- a/core/java/android/bluetooth/BluetoothHearingAid.java +++ b/core/java/android/bluetooth/BluetoothHearingAid.java @@ -379,6 +379,7 @@ public final class BluetoothHearingAid implements BluetoothProfile { public boolean setConnectionPolicy(@NonNull BluetoothDevice device, @ConnectionPolicy int connectionPolicy) { if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")"); + verifyDeviceNotNull(device, "setConnectionPolicy"); final IBluetoothHearingAid service = getService(); try { if (service != null && isEnabled() @@ -428,6 +429,7 @@ public final class BluetoothHearingAid implements BluetoothProfile { @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) public @ConnectionPolicy int getConnectionPolicy(@NonNull BluetoothDevice device) { if (VDBG) log("getConnectionPolicy(" + device + ")"); + verifyDeviceNotNull(device, "getConnectionPolicy"); final IBluetoothHearingAid service = getService(); try { if (service != null && isEnabled() @@ -504,6 +506,7 @@ public final class BluetoothHearingAid implements BluetoothProfile { if (VDBG) { log("getHiSyncId(" + device + ")"); } + verifyDeviceNotNull(device, "getConnectionPolicy"); final IBluetoothHearingAid service = getService(); try { if (service == null) { @@ -577,6 +580,13 @@ public final class BluetoothHearingAid implements BluetoothProfile { return false; } + private void verifyDeviceNotNull(BluetoothDevice device, String methodName) { + if (device == null) { + Log.e(TAG, methodName + ": device param is null"); + throw new IllegalArgumentException("Device cannot be null"); + } + } + private boolean isValidDevice(BluetoothDevice device) { if (device == null) return false; diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 2f621c3cd1f6..b79965eb4c21 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -3945,8 +3945,6 @@ public abstract class Context { */ public static final String NETWORK_STATS_SERVICE = "netstats"; /** {@hide} */ - @SystemApi - @SuppressLint("ServiceName") public static final String NETWORK_POLICY_SERVICE = "netpolicy"; /** {@hide} */ public static final String NETWORK_WATCHLIST_SERVICE = "network_watchlist"; diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java index 2217807254e9..2914e4c2c2ff 100644 --- a/core/java/android/content/pm/PackageInstaller.java +++ b/core/java/android/content/pm/PackageInstaller.java @@ -68,6 +68,7 @@ import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.concurrent.Executor; +import java.util.stream.Collectors; /** * Offers the ability to install, upgrade, and remove applications on the @@ -486,35 +487,30 @@ public class PackageInstaller { } /** - * Returns an active staged session, or {@code null} if there is none. + * Returns first active staged session, or {@code null} if there is none. * - * <p>Staged session is active iff: - * <ul> - * <li>It is committed, i.e. {@link SessionInfo#isCommitted()} is {@code true}, and - * <li>it is not applied, i.e. {@link SessionInfo#isStagedSessionApplied()} is {@code - * false}, and - * <li>it is not failed, i.e. {@link SessionInfo#isStagedSessionFailed()} is {@code false}. - * </ul> + * <p>For more information on what sessions are considered active see + * {@link SessionInfo#isStagedSessionActive()}. * - * <p>In case of a multi-apk session, reasoning above is applied to the parent session, since - * that is the one that should been {@link Session#commit committed}. + * @deprecated Use {@link #getActiveStagedSessions} as there can be more than one active staged + * session */ + @Deprecated public @Nullable SessionInfo getActiveStagedSession() { - final List<SessionInfo> stagedSessions = getStagedSessions(); - for (SessionInfo s : stagedSessions) { - if (s.isStagedSessionApplied() || s.isStagedSessionFailed()) { - // Finalized session. - continue; - } - if (s.getParentSessionId() != SessionInfo.INVALID_ID) { - // Child session. - continue; - } - if (s.isCommitted()) { - return s; - } - } - return null; + List<SessionInfo> activeSessions = getActiveStagedSessions(); + return activeSessions.isEmpty() ? null : activeSessions.get(0); + } + + /** + * Returns list of active staged sessions. Returns empty list if there is none. + * + * <p>For more information on what sessions are considered active see + * * {@link SessionInfo#isStagedSessionActive()}. + */ + public @NonNull List<SessionInfo> getActiveStagedSessions() { + return getStagedSessions().stream() + .filter(s -> s.isStagedSessionActive()) + .collect(Collectors.toList()); } /** @@ -2234,13 +2230,36 @@ public class PackageInstaller { } /** - * Returns true if this session is a staged session which will be applied at next reboot. + * Returns true if this session is a staged session. */ public boolean isStaged() { return isStaged; } /** + * Returns {@code true} if this session is an active staged session. + * + * We consider a session active if it has been committed and it is either pending + * verification, or will be applied at next reboot. + * + * <p>Staged session is active iff: + * <ul> + * <li>It is committed, i.e. {@link SessionInfo#isCommitted()} is {@code true}, and + * <li>it is not applied, i.e. {@link SessionInfo#isStagedSessionApplied()} is {@code + * false}, and + * <li>it is not failed, i.e. {@link SessionInfo#isStagedSessionFailed()} is + * {@code false}. + * </ul> + * + * <p>In case of a multi-package session, reasoning above is applied to the parent session, + * since that is the one that should have been {@link Session#commit committed}. + */ + public boolean isStagedSessionActive() { + return isStaged && isCommitted && !isStagedSessionApplied && !isStagedSessionFailed + && !hasParentSessionId(); + } + + /** * Returns the parent multi-package session ID if this session belongs to one, * {@link #INVALID_ID} otherwise. */ @@ -2249,6 +2268,13 @@ public class PackageInstaller { } /** + * Returns true if session has a valid parent session, otherwise false. + */ + public boolean hasParentSessionId() { + return parentSessionId != INVALID_ID; + } + + /** * Returns the set of session IDs that will be committed when this session is commited if * this session is a multi-package session. */ diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 2db661dc2c96..66f9ac0fb53f 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -1424,7 +1424,7 @@ public abstract class PackageManager { /** * Installation failed return code: a new staged session was attempted to be committed while - * there is already one in-progress. + * there is already one in-progress or new session has package that is already staged. * * @hide */ diff --git a/core/java/android/net/InvalidPacketException.java b/core/java/android/net/InvalidPacketException.java index 909998d4562c..b3b0f11a776b 100644 --- a/core/java/android/net/InvalidPacketException.java +++ b/core/java/android/net/InvalidPacketException.java @@ -28,7 +28,7 @@ import java.lang.annotation.RetentionPolicy; */ @SystemApi public class InvalidPacketException extends Exception { - public final int error; + private final int mError; // Must match SocketKeepalive#ERROR_INVALID_IP_ADDRESS. /** Invalid IP address. */ @@ -56,6 +56,11 @@ public class InvalidPacketException extends Exception { * See the error code for details. */ public InvalidPacketException(@ErrorCode final int error) { - this.error = error; + this.mError = error; + } + + /** Get error code. */ + public int getError() { + return mError; } } diff --git a/core/java/android/net/KeepalivePacketData.java b/core/java/android/net/KeepalivePacketData.java index 6c0ba2f63a80..e21cb44f72d8 100644 --- a/core/java/android/net/KeepalivePacketData.java +++ b/core/java/android/net/KeepalivePacketData.java @@ -19,6 +19,7 @@ package android.net; import static android.net.InvalidPacketException.ERROR_INVALID_IP_ADDRESS; import static android.net.InvalidPacketException.ERROR_INVALID_PORT; +import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.SystemApi; import android.net.util.IpUtils; @@ -37,17 +38,17 @@ public class KeepalivePacketData { /** Source IP address */ @NonNull - public final InetAddress srcAddress; + private final InetAddress mSrcAddress; /** Destination IP address */ @NonNull - public final InetAddress dstAddress; + private final InetAddress mDstAddress; /** Source port */ - public final int srcPort; + private final int mSrcPort; /** Destination port */ - public final int dstPort; + private final int mDstPort; /** Packet data. A raw byte string of packet data, not including the link-layer header. */ private final byte[] mPacket; @@ -60,13 +61,14 @@ public class KeepalivePacketData { /** * A holding class for data necessary to build a keepalive packet. */ - protected KeepalivePacketData(@NonNull InetAddress srcAddress, int srcPort, - @NonNull InetAddress dstAddress, int dstPort, - @NonNull byte[] data) throws InvalidPacketException { - this.srcAddress = srcAddress; - this.dstAddress = dstAddress; - this.srcPort = srcPort; - this.dstPort = dstPort; + protected KeepalivePacketData(@NonNull InetAddress srcAddress, + @IntRange(from = 0, to = 65535) int srcPort, @NonNull InetAddress dstAddress, + @IntRange(from = 0, to = 65535) int dstPort, + @NonNull byte[] data) throws InvalidPacketException { + this.mSrcAddress = srcAddress; + this.mDstAddress = dstAddress; + this.mSrcPort = srcPort; + this.mDstPort = dstPort; this.mPacket = data; // Check we have two IP addresses of the same family. @@ -83,6 +85,31 @@ public class KeepalivePacketData { } } + /** Get source IP address. */ + @NonNull + public InetAddress getSrcAddress() { + return mSrcAddress; + } + + /** Get destination IP address. */ + @NonNull + public InetAddress getDstAddress() { + return mDstAddress; + } + + /** Get source port number. */ + public int getSrcPort() { + return mSrcPort; + } + + /** Get destination port number. */ + public int getDstPort() { + return mDstPort; + } + + /** + * Returns a byte array of the given packet data. + */ @NonNull public byte[] getPacket() { return mPacket.clone(); diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java index 2c356e43d9fe..7ff954bdc1d2 100644 --- a/core/java/android/net/LinkProperties.java +++ b/core/java/android/net/LinkProperties.java @@ -690,9 +690,9 @@ public final class LinkProperties implements Parcelable { route.getMtu()); } - private int findRouteIndexByDestination(RouteInfo route) { + private int findRouteIndexByRouteKey(RouteInfo route) { for (int i = 0; i < mRoutes.size(); i++) { - if (mRoutes.get(i).isSameDestinationAs(route)) { + if (mRoutes.get(i).getRouteKey().equals(route.getRouteKey())) { return i; } } @@ -701,11 +701,11 @@ public final class LinkProperties implements Parcelable { /** * Adds a {@link RouteInfo} to this {@code LinkProperties}, if a {@link RouteInfo} - * with the same destination exists with different properties (e.g., different MTU), - * it will be updated. If the {@link RouteInfo} had an interface name set and - * that differs from the interface set for this {@code LinkProperties} an - * {@link IllegalArgumentException} will be thrown. The proper - * course is to add either un-named or properly named {@link RouteInfo}. + * with the same {@link RouteInfo.RouteKey} with different properties + * (e.g., different MTU), it will be updated. If the {@link RouteInfo} had an + * interface name set and that differs from the interface set for this + * {@code LinkProperties} an {@link IllegalArgumentException} will be thrown. + * The proper course is to add either un-named or properly named {@link RouteInfo}. * * @param route A {@link RouteInfo} to add to this object. * @return {@code true} was added or updated, false otherwise. @@ -719,7 +719,7 @@ public final class LinkProperties implements Parcelable { } route = routeWithInterface(route); - int i = findRouteIndexByDestination(route); + int i = findRouteIndexByRouteKey(route); if (i == -1) { // Route was not present. Add it. mRoutes.add(route); diff --git a/core/java/android/net/NattKeepalivePacketData.java b/core/java/android/net/NattKeepalivePacketData.java index 29da4952daa5..22288b6205d7 100644 --- a/core/java/android/net/NattKeepalivePacketData.java +++ b/core/java/android/net/NattKeepalivePacketData.java @@ -94,10 +94,10 @@ public final class NattKeepalivePacketData extends KeepalivePacketData implement /** Write to parcel */ public void writeToParcel(@NonNull Parcel out, int flags) { - out.writeString(srcAddress.getHostAddress()); - out.writeString(dstAddress.getHostAddress()); - out.writeInt(srcPort); - out.writeInt(dstPort); + out.writeString(getSrcAddress().getHostAddress()); + out.writeString(getDstAddress().getHostAddress()); + out.writeInt(getSrcPort()); + out.writeInt(getDstPort()); } /** Parcelable Creator */ @@ -115,7 +115,7 @@ public final class NattKeepalivePacketData extends KeepalivePacketData implement dstAddress, dstPort); } catch (InvalidPacketException e) { throw new IllegalArgumentException( - "Invalid NAT-T keepalive data: " + e.error); + "Invalid NAT-T keepalive data: " + e.getError()); } } @@ -128,14 +128,16 @@ public final class NattKeepalivePacketData extends KeepalivePacketData implement public boolean equals(@Nullable final Object o) { if (!(o instanceof NattKeepalivePacketData)) return false; final NattKeepalivePacketData other = (NattKeepalivePacketData) o; - return this.srcAddress.equals(other.srcAddress) - && this.dstAddress.equals(other.dstAddress) - && this.srcPort == other.srcPort - && this.dstPort == other.dstPort; + final InetAddress srcAddress = getSrcAddress(); + final InetAddress dstAddress = getDstAddress(); + return srcAddress.equals(other.getSrcAddress()) + && dstAddress.equals(other.getDstAddress()) + && getSrcPort() == other.getSrcPort() + && getDstPort() == other.getDstPort(); } @Override public int hashCode() { - return Objects.hash(srcAddress, dstAddress, srcPort, dstPort); + return Objects.hash(getSrcAddress(), getDstAddress(), getSrcPort(), getDstPort()); } } diff --git a/core/java/android/net/Network.java b/core/java/android/net/Network.java index c145b2bc1881..3d641f5a0029 100644 --- a/core/java/android/net/Network.java +++ b/core/java/android/net/Network.java @@ -27,6 +27,7 @@ import android.system.Os; import android.system.OsConstants; import android.util.proto.ProtoOutputStream; +import com.android.internal.annotations.GuardedBy; import com.android.okhttp.internalandroidapi.Dns; import com.android.okhttp.internalandroidapi.HttpURLConnectionFactory; @@ -64,15 +65,15 @@ public class Network implements Parcelable { * The unique id of the network. * @hide */ - @SystemApi + @UnsupportedAppUsage public final int netId; // Objects used to perform per-network operations such as getSocketFactory // and openConnection, and a lock to protect access to them. private volatile NetworkBoundSocketFactory mNetworkBoundSocketFactory = null; - // mLock should be used to control write access to mUrlConnectionFactory. - // maybeInitUrlConnectionFactory() must be called prior to reading this field. - private volatile HttpURLConnectionFactory mUrlConnectionFactory; + // mUrlConnectionFactory is initialized lazily when it is first needed. + @GuardedBy("mLock") + private HttpURLConnectionFactory mUrlConnectionFactory; private final Object mLock = new Object(); // Default connection pool values. These are evaluated at startup, just @@ -170,6 +171,17 @@ public class Network implements Parcelable { } /** + * Get the unique id of the network. + * + * @hide + */ + @TestApi + @SystemApi + public int getNetId() { + return netId; + } + + /** * Returns a netid marked with the Private DNS bypass flag. * * This flag must be kept in sync with the NETID_USE_LOCAL_NAMESERVERS flag @@ -284,36 +296,16 @@ public class Network implements Parcelable { return mNetworkBoundSocketFactory; } - // TODO: This creates a connection pool and host resolver for - // every Network object, instead of one for every NetId. This is - // suboptimal, because an app could potentially have more than one - // Network object for the same NetId, causing increased memory footprint - // and performance penalties due to lack of connection reuse (connection - // setup time, congestion window growth time, etc.). - // - // Instead, investigate only having one connection pool and host resolver - // for every NetId, perhaps by using a static HashMap of NetIds to - // connection pools and host resolvers. The tricky part is deciding when - // to remove a map entry; a WeakHashMap shouldn't be used because whether - // a Network is referenced doesn't correlate with whether a new Network - // will be instantiated in the near future with the same NetID. A good - // solution would involve purging empty (or when all connections are timed - // out) ConnectionPools. - private void maybeInitUrlConnectionFactory() { - synchronized (mLock) { - if (mUrlConnectionFactory == null) { - // Set configuration on the HttpURLConnectionFactory that will be good for all - // connections created by this Network. Configuration that might vary is left - // until openConnection() and passed as arguments. - Dns dnsLookup = hostname -> Arrays.asList(Network.this.getAllByName(hostname)); - HttpURLConnectionFactory urlConnectionFactory = new HttpURLConnectionFactory(); - urlConnectionFactory.setDns(dnsLookup); // Let traffic go via dnsLookup - // A private connection pool just for this Network. - urlConnectionFactory.setNewConnectionPool(httpMaxConnections, - httpKeepAliveDurationMs, TimeUnit.MILLISECONDS); - mUrlConnectionFactory = urlConnectionFactory; - } - } + private static HttpURLConnectionFactory createUrlConnectionFactory(Dns dnsLookup) { + // Set configuration on the HttpURLConnectionFactory that will be good for all + // connections created by this Network. Configuration that might vary is left + // until openConnection() and passed as arguments. + HttpURLConnectionFactory urlConnectionFactory = new HttpURLConnectionFactory(); + urlConnectionFactory.setDns(dnsLookup); // Let traffic go via dnsLookup + // A private connection pool just for this Network. + urlConnectionFactory.setNewConnectionPool(httpMaxConnections, + httpKeepAliveDurationMs, TimeUnit.MILLISECONDS); + return urlConnectionFactory; } /** @@ -354,9 +346,31 @@ public class Network implements Parcelable { */ public URLConnection openConnection(URL url, java.net.Proxy proxy) throws IOException { if (proxy == null) throw new IllegalArgumentException("proxy is null"); - maybeInitUrlConnectionFactory(); + // TODO: This creates a connection pool and host resolver for + // every Network object, instead of one for every NetId. This is + // suboptimal, because an app could potentially have more than one + // Network object for the same NetId, causing increased memory footprint + // and performance penalties due to lack of connection reuse (connection + // setup time, congestion window growth time, etc.). + // + // Instead, investigate only having one connection pool and host resolver + // for every NetId, perhaps by using a static HashMap of NetIds to + // connection pools and host resolvers. The tricky part is deciding when + // to remove a map entry; a WeakHashMap shouldn't be used because whether + // a Network is referenced doesn't correlate with whether a new Network + // will be instantiated in the near future with the same NetID. A good + // solution would involve purging empty (or when all connections are timed + // out) ConnectionPools. + final HttpURLConnectionFactory urlConnectionFactory; + synchronized (mLock) { + if (mUrlConnectionFactory == null) { + Dns dnsLookup = hostname -> Arrays.asList(getAllByName(hostname)); + mUrlConnectionFactory = createUrlConnectionFactory(dnsLookup); + } + urlConnectionFactory = mUrlConnectionFactory; + } SocketFactory socketFactory = getSocketFactory(); - return mUrlConnectionFactory.openConnection(url, socketFactory, proxy); + return urlConnectionFactory.openConnection(url, socketFactory, proxy); } /** diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index ae5c24ecd7ae..ad1e50122748 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/core/java/android/net/NetworkCapabilities.java @@ -19,6 +19,7 @@ package android.net; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; @@ -32,6 +33,7 @@ import android.util.ArraySet; import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.util.ArrayUtils; import com.android.internal.util.BitUtils; import com.android.internal.util.Preconditions; @@ -86,6 +88,7 @@ public final class NetworkCapabilities implements Parcelable { /** * Completely clears the contents of this object, removing even the capabilities that are set * by default when the object is constructed. + * @hide */ public void clearAll() { mNetworkCapabilities = mTransportTypes = mUnwantedNetworkCapabilities = 0; @@ -412,12 +415,27 @@ public final class NetworkCapabilities implements Parcelable { | (1 << NET_CAPABILITY_PARTIAL_CONNECTIVITY); /** + * Capabilities that are allowed for test networks. This list must be set so that it is safe + * for an unprivileged user to create a network with these capabilities via shell. As such, + * it must never contain capabilities that are generally useful to the system, such as + * INTERNET, IMS, SUPL, etc. + */ + private static final long TEST_NETWORKS_ALLOWED_CAPABILITIES = + (1 << NET_CAPABILITY_NOT_METERED) + | (1 << NET_CAPABILITY_NOT_RESTRICTED) + | (1 << NET_CAPABILITY_NOT_VPN) + | (1 << NET_CAPABILITY_NOT_ROAMING) + | (1 << NET_CAPABILITY_NOT_CONGESTED) + | (1 << NET_CAPABILITY_NOT_SUSPENDED); + + /** * Adds the given capability to this {@code NetworkCapability} instance. - * Multiple capabilities may be applied sequentially. Note that when searching - * for a network to satisfy a request, all capabilities requested must be satisfied. + * Note that when searching for a network to satisfy a request, all capabilities + * requested must be satisfied. * * @param capability the capability to be added. * @return This NetworkCapabilities instance, to facilitate chaining. + * @hide */ public @NonNull NetworkCapabilities addCapability(@NetCapability int capability) { // If the given capability was previously added to the list of unwanted capabilities @@ -432,9 +450,9 @@ public final class NetworkCapabilities implements Parcelable { /** * Adds the given capability to the list of unwanted capabilities of this - * {@code NetworkCapability} instance. Multiple unwanted capabilities may be applied - * sequentially. Note that when searching for a network to satisfy a request, the network - * must not contain any capability from unwanted capability list. + * {@code NetworkCapability} instance. Note that when searching for a network to + * satisfy a request, the network must not contain any capability from unwanted capability + * list. * <p> * If the capability was previously added to the list of required capabilities (for * example, it was there by default or added using {@link #addCapability(int)} method), then @@ -454,6 +472,7 @@ public final class NetworkCapabilities implements Parcelable { * * @param capability the capability to be removed. * @return This NetworkCapabilities instance, to facilitate chaining. + * @hide */ public @NonNull NetworkCapabilities removeCapability(@NetCapability int capability) { // Note that this method removes capabilities that were added via addCapability(int), @@ -468,7 +487,7 @@ public final class NetworkCapabilities implements Parcelable { /** * Sets (or clears) the given capability on this {@link NetworkCapabilities} * instance. - * + * @hide */ public @NonNull NetworkCapabilities setCapability(@NetCapability int capability, boolean value) { @@ -641,6 +660,21 @@ public final class NetworkCapabilities implements Parcelable { } /** + * Test networks have strong restrictions on what capabilities they can have. Enforce these + * restrictions. + * @hide + */ + public void restrictCapabilitesForTestNetwork() { + final long originalCapabilities = mNetworkCapabilities; + final NetworkSpecifier originalSpecifier = mNetworkSpecifier; + clearAll(); + // Reset the transports to only contain TRANSPORT_TEST. + mTransportTypes = (1 << TRANSPORT_TEST); + mNetworkCapabilities = originalCapabilities & TEST_NETWORKS_ALLOWED_CAPABILITIES; + mNetworkSpecifier = originalSpecifier; + } + + /** * Representing the transport type. Apps should generally not care about transport. A * request for a fast internet connection could be satisfied by a number of different * transports. If any are specified here it will be satisfied a Network that matches @@ -728,7 +762,7 @@ public final class NetworkCapabilities implements Parcelable { /** * Adds the given transport type to this {@code NetworkCapability} instance. - * Multiple transports may be applied sequentially. Note that when searching + * Multiple transports may be applied. Note that when searching * for a network to satisfy a request, any listed in the request will satisfy the request. * For example {@code TRANSPORT_WIFI} and {@code TRANSPORT_ETHERNET} added to a * {@code NetworkCapabilities} would cause either a Wi-Fi network or an Ethernet network @@ -737,6 +771,7 @@ public final class NetworkCapabilities implements Parcelable { * * @param transportType the transport type to be added. * @return This NetworkCapabilities instance, to facilitate chaining. + * @hide */ public @NonNull NetworkCapabilities addTransportType(@Transport int transportType) { checkValidTransportType(transportType); @@ -849,6 +884,7 @@ public final class NetworkCapabilities implements Parcelable { /** * Set the UID of the owner app. + * @hide */ public @NonNull NetworkCapabilities setOwnerUid(final int uid) { mOwnerUid = uid; @@ -866,6 +902,8 @@ public final class NetworkCapabilities implements Parcelable { * <li>The user's location toggle is on * </ol> * + * Instances of NetworkCapabilities sent to apps without the appropriate permissions will + * have this field cleared out. */ public int getOwnerUid() { return mOwnerUid; @@ -904,7 +942,6 @@ public final class NetworkCapabilities implements Parcelable { * @hide */ @NonNull - @SystemApi public NetworkCapabilities setAdministratorUids(@NonNull final int[] administratorUids) { mAdministratorUids = Arrays.copyOf(administratorUids, administratorUids.length); return this; @@ -918,6 +955,7 @@ public final class NetworkCapabilities implements Parcelable { */ @NonNull @SystemApi + @TestApi public int[] getAdministratorUids() { return Arrays.copyOf(mAdministratorUids, mAdministratorUids.length); } @@ -940,15 +978,10 @@ public final class NetworkCapabilities implements Parcelable { * Sets the upstream bandwidth for this network in Kbps. This always only refers to * the estimated first hop transport bandwidth. * <p> - * Note that when used to request a network, this specifies the minimum acceptable. - * When received as the state of an existing network this specifies the typical - * first hop bandwidth expected. This is never measured, but rather is inferred - * from technology type and other link parameters. It could be used to differentiate - * between very slow 1xRTT cellular links and other faster networks or even between - * 802.11b vs 802.11AC wifi technologies. It should not be used to differentiate between - * fast backhauls and slow backhauls. + * {@see Builder#setLinkUpstreamBandwidthKbps} * * @param upKbps the estimated first hop upstream (device to network) bandwidth. + * @hide */ public @NonNull NetworkCapabilities setLinkUpstreamBandwidthKbps(int upKbps) { mLinkUpBandwidthKbps = upKbps; @@ -969,15 +1002,10 @@ public final class NetworkCapabilities implements Parcelable { * Sets the downstream bandwidth for this network in Kbps. This always only refers to * the estimated first hop transport bandwidth. * <p> - * Note that when used to request a network, this specifies the minimum acceptable. - * When received as the state of an existing network this specifies the typical - * first hop bandwidth expected. This is never measured, but rather is inferred - * from technology type and other link parameters. It could be used to differentiate - * between very slow 1xRTT cellular links and other faster networks or even between - * 802.11b vs 802.11AC wifi technologies. It should not be used to differentiate between - * fast backhauls and slow backhauls. + * {@see Builder#setLinkUpstreamBandwidthKbps} * * @param downKbps the estimated first hop downstream (network to device) bandwidth. + * @hide */ public @NonNull NetworkCapabilities setLinkDownstreamBandwidthKbps(int downKbps) { mLinkDownBandwidthKbps = downKbps; @@ -1036,6 +1064,7 @@ public final class NetworkCapabilities implements Parcelable { * @param networkSpecifier A concrete, parcelable framework class that extends * NetworkSpecifier. * @return This NetworkCapabilities instance, to facilitate chaining. + * @hide */ public @NonNull NetworkCapabilities setNetworkSpecifier( @NonNull NetworkSpecifier networkSpecifier) { @@ -1057,7 +1086,6 @@ public final class NetworkCapabilities implements Parcelable { * @return This NetworkCapabilities instance, to facilitate chaining. * @hide */ - @SystemApi public @NonNull NetworkCapabilities setTransportInfo(@NonNull TransportInfo transportInfo) { mTransportInfo = transportInfo; return this; @@ -1067,7 +1095,7 @@ public final class NetworkCapabilities implements Parcelable { * Gets the optional bearer specific network specifier. May be {@code null} if not set. * * @return The optional {@link NetworkSpecifier} specifying the bearer specific network - * specifier or {@code null}. See {@link #setNetworkSpecifier}. + * specifier or {@code null}. */ public @Nullable NetworkSpecifier getNetworkSpecifier() { return mNetworkSpecifier; @@ -1137,6 +1165,7 @@ public final class NetworkCapabilities implements Parcelable { * effect when requesting a callback. * * @param signalStrength the bearer-specific signal strength. + * @hide */ public @NonNull NetworkCapabilities setSignalStrength(int signalStrength) { mSignalStrength = signalStrength; @@ -1363,7 +1392,6 @@ public final class NetworkCapabilities implements Parcelable { * Sets the SSID of this network. * @hide */ - @SystemApi public @NonNull NetworkCapabilities setSSID(@Nullable String ssid) { mSSID = ssid; return this; @@ -1374,7 +1402,8 @@ public final class NetworkCapabilities implements Parcelable { * @hide */ @SystemApi - public @Nullable String getSSID() { + @TestApi + public @Nullable String getSsid() { return mSSID; } @@ -1854,25 +1883,32 @@ public final class NetworkCapabilities implements Parcelable { } /** - * Set the uid of the app making the request. + * Set the UID of the app making the request. * - * Note: This works only for {@link NetworkAgent} instances. Any capabilities passed in - * via the public {@link ConnectivityManager} API's will have this field overwritten. + * For instances of NetworkCapabilities representing a request, sets the + * UID of the app making the request. For a network created by the system, + * sets the UID of the only app whose requests can match this network. + * This can be set to {@link Process#INVALID_UID} if there is no such app, + * or if this instance of NetworkCapabilities is about to be sent to a + * party that should not learn about this. * * @param uid UID of the app. * @hide */ - @SystemApi public @NonNull NetworkCapabilities setRequestorUid(int uid) { mRequestorUid = uid; return this; } /** - * @return the uid of the app making the request. + * Returns the UID of the app making the request. + * + * For a NetworkRequest being made by an app, contains the app's UID. For a network + * created by the system, contains the UID of the only app whose requests can match + * this network, or {@link Process#INVALID_UID} if none or if the + * caller does not have permission to learn about this. * - * Note: This could return {@link Process#INVALID_UID} if the {@link NetworkRequest} - * object was not obtained from {@link ConnectivityManager}. + * @return the uid of the app making the request. * @hide */ public int getRequestorUid() { @@ -1882,23 +1918,29 @@ public final class NetworkCapabilities implements Parcelable { /** * Set the package name of the app making the request. * - * Note: This works only for {@link NetworkAgent} instances. Any capabilities passed in - * via the public {@link ConnectivityManager} API's will have this field overwritten. + * For instances of NetworkCapabilities representing a request, sets the + * package name of the app making the request. For a network created by the system, + * sets the package name of the only app whose requests can match this network. + * This can be set to null if there is no such app, or if this instance of + * NetworkCapabilities is about to be sent to a party that should not learn about this. * * @param packageName package name of the app. * @hide */ - @SystemApi public @NonNull NetworkCapabilities setRequestorPackageName(@NonNull String packageName) { mRequestorPackageName = packageName; return this; } /** - * @return the package name of the app making the request. + * Returns the package name of the app making the request. * - * Note: This could return {@code null} if the {@link NetworkRequest} object was not obtained - * from {@link ConnectivityManager}. + * For a NetworkRequest being made by an app, contains the app's package name. For a + * network created by the system, contains the package name of the only app whose + * requests can match this network, or null if none or if the caller does not have + * permission to learn about this. + * + * @return the package name of the app making the request. * @hide */ @Nullable @@ -1907,9 +1949,9 @@ public final class NetworkCapabilities implements Parcelable { } /** - * Set the uid and package name of the app making the request. + * Set the uid and package name of the app causing this network to exist. * - * Note: This is intended to be only invoked from within connectivitiy service. + * {@see #setRequestorUid} and {@link #setRequestorPackageName} * * @param uid UID of the app. * @param packageName package name of the app. @@ -1968,4 +2010,316 @@ public final class NetworkCapabilities implements Parcelable { return mRequestorUid == nc.mRequestorUid && TextUtils.equals(mRequestorPackageName, nc.mRequestorPackageName); } + + /** + * Builder class for NetworkCapabilities. + * + * This class is mainly for for {@link NetworkAgent} instances to use. Many fields in + * the built class require holding a signature permission to use - mostly + * {@link android.Manifest.permission.NETWORK_FACTORY}, but refer to the specific + * description of each setter. As this class lives entirely in app space it does not + * enforce these restrictions itself but the system server clears out the relevant + * fields when receiving a NetworkCapabilities object from a caller without the + * appropriate permission. + * + * Apps don't use this builder directly. Instead, they use {@link NetworkRequest} via + * its builder object. + * + * @hide + */ + @SystemApi + @TestApi + public static class Builder { + private final NetworkCapabilities mCaps; + + /** + * Creates a new Builder to construct NetworkCapabilities objects. + */ + public Builder() { + mCaps = new NetworkCapabilities(); + } + + /** + * Creates a new Builder of NetworkCapabilities from an existing instance. + */ + public Builder(@NonNull final NetworkCapabilities nc) { + Objects.requireNonNull(nc); + mCaps = new NetworkCapabilities(nc); + } + + /** + * Adds the given transport type. + * + * Multiple transports may be added. Note that when searching for a network to satisfy a + * request, satisfying any of the transports listed in the request will satisfy the request. + * For example {@code TRANSPORT_WIFI} and {@code TRANSPORT_ETHERNET} added to a + * {@code NetworkCapabilities} would cause either a Wi-Fi network or an Ethernet network + * to be selected. This is logically different than + * {@code NetworkCapabilities.NET_CAPABILITY_*}. + * + * @param transportType the transport type to be added or removed. + * @return this builder + */ + @NonNull + public Builder addTransportType(@Transport int transportType) { + checkValidTransportType(transportType); + mCaps.addTransportType(transportType); + return this; + } + + /** + * Removes the given transport type. + * + * {@see #addTransportType}. + * + * @param transportType the transport type to be added or removed. + * @return this builder + */ + @NonNull + public Builder removeTransportType(@Transport int transportType) { + checkValidTransportType(transportType); + mCaps.removeTransportType(transportType); + return this; + } + + /** + * Adds the given capability. + * + * @param capability the capability + * @return this builder + */ + @NonNull + public Builder addCapability(@NetCapability final int capability) { + mCaps.setCapability(capability, true); + return this; + } + + /** + * Removes the given capability. + * + * @param capability the capability + * @return this builder + */ + @NonNull + public Builder removeCapability(@NetCapability final int capability) { + mCaps.setCapability(capability, false); + return this; + } + + /** + * Sets the owner UID. + * + * The default value is {@link Process#INVALID_UID}. Pass this value to reset. + * + * Note: for security the system will clear out this field when received from a + * non-privileged source. + * + * @param ownerUid the owner UID + * @return this builder + */ + @NonNull + @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) + public Builder setOwnerUid(final int ownerUid) { + mCaps.setOwnerUid(ownerUid); + return this; + } + + /** + * Sets the list of UIDs that are administrators of this network. + * + * <p>UIDs included in administratorUids gain administrator privileges over this + * Network. Examples of UIDs that should be included in administratorUids are: + * <ul> + * <li>Carrier apps with privileges for the relevant subscription + * <li>Active VPN apps + * <li>Other application groups with a particular Network-related role + * </ul> + * + * <p>In general, user-supplied networks (such as WiFi networks) do not have + * administrators. + * + * <p>An app is granted owner privileges over Networks that it supplies. The owner + * UID MUST always be included in administratorUids. + * + * The default value is the empty array. Pass an empty array to reset. + * + * Note: for security the system will clear out this field when received from a + * non-privileged source, such as an app using reflection to call this or + * mutate the member in the built object. + * + * @param administratorUids the UIDs to be set as administrators of this Network. + * @return this builder + */ + @NonNull + @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) + public Builder setAdministratorUids(@NonNull final int[] administratorUids) { + Objects.requireNonNull(administratorUids); + mCaps.setAdministratorUids(administratorUids); + return this; + } + + /** + * Sets the upstream bandwidth of the link. + * + * Sets the upstream bandwidth for this network in Kbps. This always only refers to + * the estimated first hop transport bandwidth. + * <p> + * Note that when used to request a network, this specifies the minimum acceptable. + * When received as the state of an existing network this specifies the typical + * first hop bandwidth expected. This is never measured, but rather is inferred + * from technology type and other link parameters. It could be used to differentiate + * between very slow 1xRTT cellular links and other faster networks or even between + * 802.11b vs 802.11AC wifi technologies. It should not be used to differentiate between + * fast backhauls and slow backhauls. + * + * @param upKbps the estimated first hop upstream (device to network) bandwidth. + * @return this builder + */ + @NonNull + public Builder setLinkUpstreamBandwidthKbps(final int upKbps) { + mCaps.setLinkUpstreamBandwidthKbps(upKbps); + return this; + } + + /** + * Sets the downstream bandwidth for this network in Kbps. This always only refers to + * the estimated first hop transport bandwidth. + * <p> + * Note that when used to request a network, this specifies the minimum acceptable. + * When received as the state of an existing network this specifies the typical + * first hop bandwidth expected. This is never measured, but rather is inferred + * from technology type and other link parameters. It could be used to differentiate + * between very slow 1xRTT cellular links and other faster networks or even between + * 802.11b vs 802.11AC wifi technologies. It should not be used to differentiate between + * fast backhauls and slow backhauls. + * + * @param downKbps the estimated first hop downstream (network to device) bandwidth. + * @return this builder + */ + @NonNull + public Builder setLinkDownstreamBandwidthKbps(final int downKbps) { + mCaps.setLinkDownstreamBandwidthKbps(downKbps); + return this; + } + + /** + * Sets the optional bearer specific network specifier. + * This has no meaning if a single transport is also not specified, so calling + * this without a single transport set will generate an exception, as will + * subsequently adding or removing transports after this is set. + * </p> + * + * @param specifier a concrete, parcelable framework class that extends NetworkSpecifier, + * or null to clear it. + * @return this builder + */ + @NonNull + public Builder setNetworkSpecifier(@Nullable final NetworkSpecifier specifier) { + mCaps.setNetworkSpecifier(specifier); + return this; + } + + /** + * Sets the optional transport specific information. + * + * @param info A concrete, parcelable framework class that extends {@link TransportInfo}, + * or null to clear it. + * @return this builder + */ + @NonNull + public Builder setTransportInfo(@Nullable final TransportInfo info) { + mCaps.setTransportInfo(info); + return this; + } + + /** + * Sets the signal strength. This is a signed integer, with higher values indicating a + * stronger signal. The exact units are bearer-dependent. For example, Wi-Fi uses the + * same RSSI units reported by wifi code. + * <p> + * Note that when used to register a network callback, this specifies the minimum + * acceptable signal strength. When received as the state of an existing network it + * specifies the current value. A value of code SIGNAL_STRENGTH_UNSPECIFIED} means + * no value when received and has no effect when requesting a callback. + * + * Note: for security the system will throw if it receives a NetworkRequest where + * the underlying NetworkCapabilities has this member set from a source that does + * not hold the {@link android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP} + * permission. Apps with this permission can use this indirectly through + * {@link android.net.NetworkRequest}. + * + * @param signalStrength the bearer-specific signal strength. + * @return this builder + */ + @NonNull + @RequiresPermission(android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP) + public Builder setSignalStrength(final int signalStrength) { + mCaps.setSignalStrength(signalStrength); + return this; + } + + /** + * Sets the SSID of this network. + * + * Note: for security the system will clear out this field when received from a + * non-privileged source, like an app using reflection to set this. + * + * @param ssid the SSID, or null to clear it. + * @return this builder + */ + @NonNull + @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) + public Builder setSsid(@Nullable final String ssid) { + mCaps.setSSID(ssid); + return this; + } + + /** + * Set the uid of the app causing this network to exist. + * + * Note: for security the system will clear out this field when received from a + * non-privileged source. + * + * @param uid UID of the app. + * @return this builder + */ + @NonNull + @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) + public Builder setRequestorUid(final int uid) { + mCaps.setRequestorUid(uid); + return this; + } + + /** + * Set the package name of the app causing this network to exist. + * + * Note: for security the system will clear out this field when received from a + * non-privileged source. + * + * @param packageName package name of the app, or null to clear it. + * @return this builder + */ + @NonNull + @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) + public Builder setRequestorPackageName(@Nullable final String packageName) { + mCaps.setRequestorPackageName(packageName); + return this; + } + + /** + * Builds the instance of the capabilities. + * + * @return the built instance of NetworkCapabilities. + */ + @NonNull + public NetworkCapabilities build() { + if (mCaps.getOwnerUid() != Process.INVALID_UID) { + if (!ArrayUtils.contains(mCaps.getAdministratorUids(), mCaps.getOwnerUid())) { + throw new IllegalStateException("The owner UID must be included in " + + " administrator UIDs."); + } + } + return new NetworkCapabilities(mCaps); + } + } } diff --git a/core/java/android/net/OWNERS b/core/java/android/net/OWNERS index 767b69351065..5e2a71876103 100644 --- a/core/java/android/net/OWNERS +++ b/core/java/android/net/OWNERS @@ -8,4 +8,4 @@ lorenzo@google.com reminv@google.com satk@google.com -per-file SSL*, Uri*, Url* = prb@google.com, dauletz@google.com, narayan@google.com, tobiast@google.com +per-file SSL*, Uri*, Url* = prb@google.com, dauletz@google.com, narayan@google.com, ngeoffray@google.com diff --git a/core/java/android/net/RouteInfo.java b/core/java/android/net/RouteInfo.java index fec2df412adb..dbdaa4c2da67 100644 --- a/core/java/android/net/RouteInfo.java +++ b/core/java/android/net/RouteInfo.java @@ -26,6 +26,7 @@ import android.net.util.NetUtils; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; +import android.util.Pair; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -527,23 +528,27 @@ public final class RouteInfo implements Parcelable { } /** - * Compares this RouteInfo object against the specified object and indicates if the - * destinations of both routes are equal. - * @return {@code true} if the route destinations are equal, {@code false} otherwise. + * A helper class that contains the destination and the gateway in a {@code RouteInfo}, + * used by {@link ConnectivityService#updateRoutes} or + * {@link LinkProperties#addRoute} to calculate the list to be updated. * * @hide */ - public boolean isSameDestinationAs(@Nullable Object obj) { - if (this == obj) return true; - - if (!(obj instanceof RouteInfo)) return false; - - RouteInfo target = (RouteInfo) obj; - - if (Objects.equals(mDestination, target.getDestination())) { - return true; + public static class RouteKey extends Pair<IpPrefix, InetAddress> { + RouteKey(@NonNull IpPrefix destination, @Nullable InetAddress gateway) { + super(destination, gateway); } - return false; + } + + /** + * Get {@code RouteKey} of this {@code RouteInfo}. + * @return a {@code RouteKey} object. + * + * @hide + */ + @NonNull + public RouteKey getRouteKey() { + return new RouteKey(mDestination, mGateway); } /** diff --git a/core/java/android/net/http/OWNERS b/core/java/android/net/http/OWNERS index 309261277024..3271d243e2cd 100644 --- a/core/java/android/net/http/OWNERS +++ b/core/java/android/net/http/OWNERS @@ -1,4 +1,4 @@ narayan@google.com -tobiast@google.com +ngeoffray@google.com include platform/libcore:/OWNERS include platform/external/conscrypt:/OWNERS diff --git a/core/java/android/os/incremental/IncrementalFileSystemControlParcel.aidl b/core/java/android/os/incremental/IncrementalFileSystemControlParcel.aidl index 0ae353d2741f..5d8f6d126a89 100644 --- a/core/java/android/os/incremental/IncrementalFileSystemControlParcel.aidl +++ b/core/java/android/os/incremental/IncrementalFileSystemControlParcel.aidl @@ -17,11 +17,12 @@ package android.os.incremental; /** - * Wraps two file descriptors that Incremental Service uses to communicate + * Wraps the file descriptors Incremental Service uses to communicate * with Incremental FileSystem. * @hide */ parcelable IncrementalFileSystemControlParcel { @nullable ParcelFileDescriptor cmd; + @nullable ParcelFileDescriptor pendingReads; @nullable ParcelFileDescriptor log; } diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java index ab31d247bb73..f8b9f584c6c9 100644 --- a/core/java/android/telephony/PhoneStateListener.java +++ b/core/java/android/telephony/PhoneStateListener.java @@ -176,7 +176,6 @@ public class PhoneStateListener { * @hide */ @RequiresPermission(android.Manifest.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH) - @SystemApi public static final int LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH = 0x00000200; /** diff --git a/core/java/android/telephony/SubscriptionPlan.java b/core/java/android/telephony/SubscriptionPlan.java index 28a5c2086ede..901957f6ca4a 100644 --- a/core/java/android/telephony/SubscriptionPlan.java +++ b/core/java/android/telephony/SubscriptionPlan.java @@ -91,10 +91,11 @@ public final class SubscriptionPlan implements Parcelable { private long dataUsageBytes = BYTES_UNKNOWN; private long dataUsageTime = TIME_UNKNOWN; private @NetworkType int[] networkTypes; - private long networkTypesBitMask; private SubscriptionPlan(RecurrenceRule cycleRule) { this.cycleRule = Preconditions.checkNotNull(cycleRule); + this.networkTypes = Arrays.copyOf(TelephonyManager.getAllNetworkTypes(), + TelephonyManager.getAllNetworkTypes().length); } private SubscriptionPlan(Parcel source) { @@ -221,28 +222,10 @@ public final class SubscriptionPlan implements Parcelable { /** * Return an array containing all {@link NetworkType}s this SubscriptionPlan applies to. - * A null value means this SubscriptionPlan applies to all network types. + * @see TelephonyManager for network types values */ - public @Nullable @NetworkType int[] getNetworkTypes() { - return networkTypes; - } - - /** - * Return the networkTypes array converted to a {@link TelephonyManager.NetworkTypeBitMask} - * @hide - */ - public long getNetworkTypesBitMask() { - // calculate bitmask the first time and save for future calls - if (networkTypesBitMask == 0) { - if (networkTypes == null) { - networkTypesBitMask = ~0; - } else { - for (int networkType : networkTypes) { - networkTypesBitMask |= TelephonyManager.getBitMaskForNetworkType(networkType); - } - } - } - return networkTypesBitMask; + public @NonNull @NetworkType int[] getNetworkTypes() { + return Arrays.copyOf(networkTypes, networkTypes.length); } /** @@ -379,14 +362,14 @@ public final class SubscriptionPlan implements Parcelable { } /** - * Set the network types this SubscriptionPlan applies to. + * Set the network types this SubscriptionPlan applies to. By default the plan will apply + * to all network types. An empty array means this plan applies to no network types. * - * @param networkTypes a set of all {@link NetworkType}s that apply to this plan. - * A null value means the plan applies to all network types, - * and an empty array means the plan applies to no network types. + * @param networkTypes an array of all {@link NetworkType}s that apply to this plan. + * @see TelephonyManager for network type values */ - public @NonNull Builder setNetworkTypes(@Nullable @NetworkType int[] networkTypes) { - plan.networkTypes = networkTypes; + public @NonNull Builder setNetworkTypes(@NonNull @NetworkType int[] networkTypes) { + plan.networkTypes = Arrays.copyOf(networkTypes, networkTypes.length); return this; } } diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java index 73cd708f43f7..e3620426049f 100644 --- a/core/java/android/telephony/TelephonyRegistryManager.java +++ b/core/java/android/telephony/TelephonyRegistryManager.java @@ -26,8 +26,10 @@ import android.os.ServiceManager; import android.telephony.Annotation.CallState; import android.telephony.Annotation.DataActivityType; import android.telephony.Annotation.DataFailureCause; +import android.telephony.Annotation.DisconnectCauses; import android.telephony.Annotation.NetworkType; import android.telephony.Annotation.PreciseCallStates; +import android.telephony.Annotation.PreciseDisconnectCauses; import android.telephony.Annotation.RadioPowerState; import android.telephony.Annotation.SimActivationState; import android.telephony.Annotation.SrvccState; @@ -229,11 +231,9 @@ public class TelephonyRegistryManager { * invalid. * @param state latest call state. e.g, offhook, ringing * @param incomingNumber incoming phone number. - * - * @hide */ public void notifyCallStateChanged(int subId, int slotIndex, @CallState int state, - String incomingNumber) { + @Nullable String incomingNumber) { try { sRegistry.notifyCallState(slotIndex, subId, state, incomingNumber); } catch (RemoteException ex) { @@ -266,10 +266,8 @@ public class TelephonyRegistryManager { * @param slotIndex for which the service state changed. Can be derived from subId except * subId is invalid. * @param state service state e.g, in service, out of service or roaming status. - * - * @hide */ - public void notifyServiceStateChanged(int subId, int slotIndex, ServiceState state) { + public void notifyServiceStateChanged(int subId, int slotIndex, @NonNull ServiceState state) { try { sRegistry.notifyServiceStateForPhoneId(slotIndex, subId, state); } catch (RemoteException ex) { @@ -284,11 +282,9 @@ public class TelephonyRegistryManager { * @param slotIndex for which the signalstrength changed. Can be derived from subId except when * subId is invalid. * @param signalStrength e.g, signalstrength level {@see SignalStrength#getLevel()} - * - * @hide */ public void notifySignalStrengthChanged(int subId, int slotIndex, - SignalStrength signalStrength) { + @NonNull SignalStrength signalStrength) { try { sRegistry.notifySignalStrengthForPhoneId(slotIndex, subId, signalStrength); } catch (RemoteException ex) { @@ -305,8 +301,6 @@ public class TelephonyRegistryManager { * except when subId is invalid. * @param msgWaitingInd {@code true} indicates there is message-waiting indicator, {@code false} * otherwise. - * - * @hide */ public void notifyMessageWaitingChanged(int subId, int slotIndex, boolean msgWaitingInd) { try { @@ -322,8 +316,6 @@ public class TelephonyRegistryManager { * @param subId for which call forwarding status changed. * @param callForwardInd {@code true} indicates there is call forwarding, {@code false} * otherwise. - * - * @hide */ public void notifyCallForwardingChanged(int subId, boolean callForwardInd) { try { @@ -339,8 +331,6 @@ public class TelephonyRegistryManager { * @param subId for which data activity state changed. * @param dataActivityType indicates the latest data activity type e.g, {@link * TelephonyManager#DATA_ACTIVITY_IN} - * - * @hide */ public void notifyDataActivityChanged(int subId, @DataActivityType int dataActivityType) { try { @@ -361,10 +351,9 @@ public class TelephonyRegistryManager { * * @see android.telephony.PreciseDataConnection * @see TelephonyManager#DATA_DISCONNECTED - * @hide */ public void notifyDataConnectionForSubscriber(int slotIndex, int subId, - String apnType, PreciseDataConnectionState preciseState) { + String apnType, @Nullable PreciseDataConnectionState preciseState) { try { sRegistry.notifyDataConnectionForSubscriber( slotIndex, subId, apnType, preciseState); @@ -381,10 +370,8 @@ public class TelephonyRegistryManager { * subId is invalid. * @param callQuality Information about call quality e.g, call quality level * @param networkType associated with this data connection. e.g, LTE - * - * @hide */ - public void notifyCallQualityChanged(int subId, int slotIndex, CallQuality callQuality, + public void notifyCallQualityChanged(int subId, int slotIndex, @NonNull CallQuality callQuality, @NetworkType int networkType) { try { sRegistry.notifyCallQualityChanged(callQuality, slotIndex, subId, networkType); @@ -399,8 +386,6 @@ public class TelephonyRegistryManager { * @param subId for which emergency number list changed. * @param slotIndex for which emergency number list changed. Can be derived from subId except * when subId is invalid. - * - * @hide */ public void notifyEmergencyNumberList(int subId, int slotIndex) { try { @@ -417,8 +402,6 @@ public class TelephonyRegistryManager { * @param slotIndex for which radio power state changed. Can be derived from subId except when * subId is invalid. * @param radioPowerState the current modem radio state. - * - * @hide */ public void notifyRadioPowerStateChanged(int subId, int slotIndex, @RadioPowerState int radioPowerState) { @@ -433,10 +416,8 @@ public class TelephonyRegistryManager { * Notify {@link PhoneCapability} changed. * * @param phoneCapability the capability of the modem group. - * - * @hide */ - public void notifyPhoneCapabilityChanged(PhoneCapability phoneCapability) { + public void notifyPhoneCapabilityChanged(@NonNull PhoneCapability phoneCapability) { try { sRegistry.notifyPhoneCapabilityChanged(phoneCapability); } catch (RemoteException ex) { @@ -465,8 +446,6 @@ public class TelephonyRegistryManager { * @param slotIndex for which data activation state changed. Can be derived from subId except * when subId is invalid. * @param activationState sim activation state e.g, activated. - * - * @hide */ public void notifyDataActivationStateChanged(int subId, int slotIndex, @SimActivationState int activationState) { @@ -486,8 +465,6 @@ public class TelephonyRegistryManager { * @param slotIndex for which voice activation state changed. Can be derived from subId except * subId is invalid. * @param activationState sim activation state e.g, activated. - * - * @hide */ public void notifyVoiceActivationStateChanged(int subId, int slotIndex, @SimActivationState int activationState) { @@ -507,8 +484,6 @@ public class TelephonyRegistryManager { * @param slotIndex for which mobile data state has changed. Can be derived from subId except * when subId is invalid. * @param state {@code true} indicates mobile data is enabled/on. {@code false} otherwise. - * - * @hide */ public void notifyUserMobileDataStateChanged(int slotIndex, int subId, boolean state) { try { @@ -519,23 +494,6 @@ public class TelephonyRegistryManager { } /** - * TODO: this is marked as deprecated, can we move this one safely? - * - * @param subId - * @param slotIndex - * @param rawData - * - * @hide - */ - public void notifyOemHookRawEventForSubscriber(int subId, int slotIndex, byte[] rawData) { - try { - sRegistry.notifyOemHookRawEventForSubscriber(slotIndex, subId, rawData); - } catch (RemoteException ex) { - // system process is dead - } - } - - /** * Notify display info changed. * * @param slotIndex The SIM slot index for which display info has changed. Can be @@ -558,10 +516,8 @@ public class TelephonyRegistryManager { * * @param subId for which ims call disconnect. * @param imsReasonInfo the reason for ims call disconnect. - * - * @hide */ - public void notifyImsDisconnectCause(int subId, ImsReasonInfo imsReasonInfo) { + public void notifyImsDisconnectCause(int subId, @NonNull ImsReasonInfo imsReasonInfo) { try { sRegistry.notifyImsDisconnectCause(subId, imsReasonInfo); } catch (RemoteException ex) { @@ -578,11 +534,9 @@ public class TelephonyRegistryManager { * @param apnType the apnType, "ims" for IMS APN, "emergency" for EMERGENCY APN. * @param apn the APN {@link ApnSetting#getApnName()} of this data connection. * @param failCause data fail cause. - * - * @hide */ public void notifyPreciseDataConnectionFailed(int subId, int slotIndex, String apnType, - String apn, @DataFailureCause int failCause) { + @Nullable String apn, @DataFailureCause int failCause) { try { sRegistry.notifyPreciseDataConnectionFailed(slotIndex, subId, apnType, apn, failCause); } catch (RemoteException ex) { @@ -596,8 +550,6 @@ public class TelephonyRegistryManager { * * @param subId for which srvcc state changed. * @param state srvcc state - * - * @hide */ public void notifySrvccStateChanged(int subId, @SrvccState int state) { try { @@ -617,8 +569,6 @@ public class TelephonyRegistryManager { * @param ringCallPreciseState ringCall state. * @param foregroundCallPreciseState foreground call state. * @param backgroundCallPreciseState background call state. - * - * @hide */ public void notifyPreciseCallState(int subId, int slotIndex, @PreciseCallStates int ringCallPreciseState, @@ -642,10 +592,9 @@ public class TelephonyRegistryManager { * @param cause {@link DisconnectCause} for the disconnected call. * @param preciseCause {@link android.telephony.PreciseDisconnectCause} for the disconnected * call. - * - * @hide */ - public void notifyDisconnectCause(int slotIndex, int subId, int cause, int preciseCause) { + public void notifyDisconnectCause(int slotIndex, int subId, @DisconnectCauses int cause, + @PreciseDisconnectCauses int preciseCause) { try { sRegistry.notifyDisconnectCause(slotIndex, subId, cause, preciseCause); } catch (RemoteException ex) { @@ -658,10 +607,8 @@ public class TelephonyRegistryManager { * * <p>To be compatible with {@link TelephonyRegistry}, use {@link CellIdentity} which is * parcelable, and convert to CellLocation in client code. - * - * @hide */ - public void notifyCellLocation(int subId, CellIdentity cellLocation) { + public void notifyCellLocation(int subId, @NonNull CellIdentity cellLocation) { try { sRegistry.notifyCellLocationForSubscriber(subId, cellLocation); } catch (RemoteException ex) { @@ -675,10 +622,8 @@ public class TelephonyRegistryManager { * * @param subId for which cellinfo changed. * @param cellInfo A list of cellInfo associated with the given subscription. - * - * @hide */ - public void notifyCellInfoChanged(int subId, List<CellInfo> cellInfo) { + public void notifyCellInfoChanged(int subId, @NonNull List<CellInfo> cellInfo) { try { sRegistry.notifyCellInfoForSubscriber(subId, cellInfo); } catch (RemoteException ex) { @@ -687,8 +632,8 @@ public class TelephonyRegistryManager { } /** - * @param activeDataSubId - * @hide + * Notify that the active data subscription ID has changed. + * @param activeDataSubId The new subscription ID for active data */ public void notifyActiveDataSubIdChanged(int activeDataSubId) { try { diff --git a/core/jni/android_app_admin_SecurityLog.cpp b/core/jni/android_app_admin_SecurityLog.cpp index b3bcaa0f7f03..e5a13db3dfb0 100644 --- a/core/jni/android_app_admin_SecurityLog.cpp +++ b/core/jni/android_app_admin_SecurityLog.cpp @@ -41,7 +41,7 @@ static void android_app_admin_SecurityLog_readEvents(JNIEnv* env, jobject /* cla jniThrowNullPointerException(env, NULL); return; } - SLog::readEvents(env, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 0, out); + SLog::readEvents(env, ANDROID_LOG_NONBLOCK, 0, out); } static void android_app_admin_SecurityLog_readEventsSince(JNIEnv* env, jobject /* clazz */, @@ -52,7 +52,7 @@ static void android_app_admin_SecurityLog_readEventsSince(JNIEnv* env, jobject / jniThrowNullPointerException(env, NULL); return; } - SLog::readEvents(env, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, timestamp, out); + SLog::readEvents(env, ANDROID_LOG_NONBLOCK, timestamp, out); } static void android_app_admin_SecurityLog_readPreviousEvents(JNIEnv* env, jobject /* clazz */, @@ -62,7 +62,7 @@ static void android_app_admin_SecurityLog_readPreviousEvents(JNIEnv* env, jobjec jniThrowNullPointerException(env, NULL); return; } - SLog::readEvents(env, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK | ANDROID_LOG_PSTORE, 0, out); + SLog::readEvents(env, ANDROID_LOG_NONBLOCK | ANDROID_LOG_PSTORE, 0, out); } static void android_app_admin_SecurityLog_readEventsOnWrapping(JNIEnv* env, jobject /* clazz */, @@ -72,8 +72,7 @@ static void android_app_admin_SecurityLog_readEventsOnWrapping(JNIEnv* env, jobj jniThrowNullPointerException(env, NULL); return; } - SLog::readEvents(env, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK | ANDROID_LOG_WRAP, timestamp, - out); + SLog::readEvents(env, ANDROID_LOG_NONBLOCK | ANDROID_LOG_WRAP, timestamp, out); } /* diff --git a/core/jni/android_util_EventLog.cpp b/core/jni/android_util_EventLog.cpp index 3b5a144a4e61..0a5e78617568 100644 --- a/core/jni/android_util_EventLog.cpp +++ b/core/jni/android_util_EventLog.cpp @@ -44,7 +44,7 @@ static void android_util_EventLog_readEvents(JNIEnv* env, jobject clazz ATTRIBUT return; } - ELog::readEvents(env, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, tags, 0, out); + ELog::readEvents(env, ANDROID_LOG_NONBLOCK, tags, 0, out); } /* * In class android.util.EventLog: @@ -60,8 +60,7 @@ static void android_util_EventLog_readEventsOnWrapping(JNIEnv* env, jobject claz jniThrowNullPointerException(env, NULL); return; } - ELog::readEvents(env, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK | ANDROID_LOG_WRAP, tags, - timestamp, out); + ELog::readEvents(env, ANDROID_LOG_NONBLOCK | ANDROID_LOG_WRAP, tags, timestamp, out); } /* diff --git a/core/proto/android/stats/dnsresolver/dns_resolver.proto b/core/proto/android/stats/dnsresolver/dns_resolver.proto index 15ef12285e24..afd109996722 100644 --- a/core/proto/android/stats/dnsresolver/dns_resolver.proto +++ b/core/proto/android/stats/dnsresolver/dns_resolver.proto @@ -43,6 +43,7 @@ enum ReturnCode { RC_EAI_BADHINTS = 12; RC_EAI_PROTOCOL = 13; RC_EAI_OVERFLOW = 14; + RC_RESOLV_INTERNAL_ERROR = 254; RC_RESOLV_TIMEOUT = 255; RC_EAI_MAX = 256; } @@ -197,6 +198,144 @@ enum CacheStatus{ CS_SKIP = 3; } +// The enum LinuxErrno is defined in the following 2 files. +// 1. bionic/libc/kernel/uapi/asm-generic/errno-base.h +// 2. bionic/libc/kernel/uapi/asm-generic/errno.h +enum LinuxErrno { + SYS_UNKNOWN = 0; + SYS_EPERM = 1; // Not super-user + SYS_ENOENT = 2; // No such file or directory + SYS_ESRCH = 3; // No such process + SYS_EINTR = 4; // Interrupted system call + SYS_EIO = 5; // I/O error + SYS_ENXIO = 6; // No such device or address + SYS_E2BIG = 7; // Arg list too long + SYS_ENOEXEC = 8; // Exec format error + SYS_EBADF = 9; // Bad file number + SYS_ECHILD = 10; // No children + SYS_EAGAIN = 11; // No more processes + SYS_ENOMEM = 12; // Not enough core + SYS_EACCES = 13; // Permission denied + SYS_EFAULT = 14; // Bad address + SYS_ENOTBLK = 15; // Block device required + SYS_EBUSY = 16; // Mount device busy + SYS_EEXIST = 17; // File exists + SYS_EXDEV = 18; // Cross-device link + SYS_ENODEV = 19; // No such device + SYS_ENOTDIR = 20; // Not a directory + SYS_EISDIR = 21; // Is a directory + SYS_EINVAL = 22; // Invalid argument + SYS_ENFILE = 23; // Too many open files in system + SYS_EMFILE = 24; // Too many open files + SYS_ENOTTY = 25; // Not a typewriter + SYS_ETXTBSY = 26; // Text file busy + SYS_EFBIG = 27; // File too large + SYS_ENOSPC = 28; // No space left on device + SYS_ESPIPE = 29; // Illegal seek + SYS_EROFS = 30; // Read only file system + SYS_EMLINK = 31; // Too many links + SYS_EPIPE = 32; // Broken pipe + SYS_EDOM = 33; // Math arg out of domain of func + SYS_ERANGE = 34; // Math result not representable + SYS_EDEADLOCK = 35; // File locking deadlock error + SYS_ENAMETOOLONG = 36; // File or path name too long + SYS_ENOLCK = 37; // No record locks available + SYS_ENOSYS = 38; // Function not implemented + SYS_ENOTEMPTY = 39; // Directory not empty + SYS_ELOOP = 40; // Too many symbolic links + SYS_ENOMSG = 42; // No message of desired type + SYS_EIDRM = 43; // Identifier removed + SYS_ECHRNG = 44; // Channel number out of range + SYS_EL2NSYNC = 45; // Level 2 not synchronized + SYS_EL3HLT = 46; // Level 3 halted + SYS_EL3RST = 47; // Level 3 reset + SYS_ELNRNG = 48; // Link number out of range + SYS_EUNATCH = 49; // rotocol driver not attached + SYS_ENOCSI = 50; // No CSI structure available + SYS_EL2HLT = 51; // Level 2 halted + SYS_EBADE = 52; // Invalid exchange + SYS_EBADR = 53; // Invalid request descriptor + SYS_EXFULL = 54; // Exchange full + SYS_ENOANO = 55; // No anode + SYS_EBADRQC = 56; // Invalid request code + SYS_EBADSLT = 57; // Invalid slot + SYS_EBFONT = 59; // Bad font file fmt + SYS_ENOSTR = 60; // Device not a stream + SYS_ENODATA = 61; // No data (for no delay io) + SYS_ETIME = 62; // Timer expired + SYS_ENOSR = 63; // Out of streams resources + SYS_ENONET = 64; // Machine is not on the network + SYS_ENOPKG = 65; // Package not installed + SYS_EREMOTE = 66; // The object is remote + SYS_ENOLINK = 67; // The link has been severed + SYS_EADV = 68; // Advertise error + SYS_ESRMNT = 69; // Srmount error + SYS_ECOMM = 70; // Communication error on send + SYS_EPROTO = 71; // Protocol error + SYS_EMULTIHOP = 72; // Multihop attempted + SYS_EDOTDOT = 73; // Cross mount point (not really error) + SYS_EBADMSG = 74; // Trying to read unreadable message + SYS_EOVERFLOW = 75; // Value too large for defined data type + SYS_ENOTUNIQ = 76; // Given log. name not unique + SYS_EBADFD = 77; // f.d. invalid for this operation + SYS_EREMCHG = 78; // Remote address changed + SYS_ELIBACC = 79; // Can't access a needed shared lib + SYS_ELIBBAD = 80; // Accessing a corrupted shared lib + SYS_ELIBSCN = 81; // .lib section in a.out corrupted + SYS_ELIBMAX = 82; // Attempting to link in too many libs + SYS_ELIBEXEC = 83; // Attempting to exec a shared library + SYS_EILSEQ = 84; + SYS_ERESTART = 85; + SYS_ESTRPIPE = 86; + SYS_EUSERS = 87; + SYS_ENOTSOCK = 88; // Socket operation on non-socket + SYS_EDESTADDRREQ = 89; // Destination address required + SYS_EMSGSIZE = 90; // Message too long + SYS_EPROTOTYPE = 91; // Protocol wrong type for socket + SYS_ENOPROTOOPT = 92; // Protocol not available + SYS_EPROTONOSUPPORT = 93; // Unknown protocol + SYS_ESOCKTNOSUPPORT = 94; // Socket type not supported + SYS_EOPNOTSUPP = 95; // Operation not supported on transport endpoint + SYS_EPFNOSUPPORT = 96; // Protocol family not supported + SYS_EAFNOSUPPORT = 97; // Address family not supported by protocol family + SYS_EADDRINUSE = 98; // Address already in use + SYS_EADDRNOTAVAIL = 99; // Address not available + SYS_ENETDOWN = 100; // Network interface is not configured + SYS_ENETUNREACH = 101; // Network is unreachable + SYS_ENETRESET = 102; + SYS_ECONNABORTED = 103; // Connection aborted + SYS_ECONNRESET = 104; // Connection reset by peer + SYS_ENOBUFS = 105; // No buffer space available + SYS_EISCONN = 106; // Socket is already connected + SYS_ENOTCONN = 107; // Socket is not connected + SYS_ESHUTDOWN = 108; // Can't send after socket shutdown + SYS_ETOOMANYREFS = 109; + SYS_ETIMEDOUT = 110; // Connection timed out + SYS_ECONNREFUSED = 111; // Connection refused + SYS_EHOSTDOWN = 112; // Host is down + SYS_EHOSTUNREACH = 113; // Host is unreachable + SYS_EALREADY = 114; // Socket already connected + SYS_EINPROGRESS = 115; // Connection already in progress + SYS_ESTALE = 116; + SYS_EUCLEAN = 117; + SYS_ENOTNAM = 118; + SYS_ENAVAIL = 119; + SYS_EISNAM = 120; + SYS_EREMOTEIO = 121; + SYS_EDQUOT = 122; + SYS_ENOMEDIUM = 123; // No medium (in tape drive) + SYS_EMEDIUMTYPE = 124; + SYS_ECANCELED = 125; + SYS_ENOKEY = 126; + SYS_EKEYEXPIRED = 127; + SYS_EKEYREVOKED = 128; + SYS_EKEYREJECTED = 129; + SYS_EOWNERDEAD = 130; + SYS_ENOTRECOVERABLE = 131; + SYS_ERFKILL = 132; + SYS_EHWPOISON = 133; +} + message DnsQueryEvent { optional android.stats.dnsresolver.NsRcode rcode = 1; @@ -218,6 +357,8 @@ message DnsQueryEvent { optional bool connected = 8; optional int32 latency_micros = 9; + + optional android.stats.dnsresolver.LinuxErrno linux_errno = 10; } message DnsQueryEvents { diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 93080e9a8016..8a7b515ee436 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -3010,8 +3010,6 @@ </public-group> <public-group type="string" first-id="0x01040025"> - <!-- @hide @SystemApi --> - <public name="low_memory" /> </public-group> <public-group type="bool" first-id="0x01110005"> @@ -3026,14 +3024,7 @@ <public-group type="array" first-id="0x01070006"> <!-- @hide @SystemApi --> <public name="simColors" /> - <!-- @hide @SystemApi --> - <public name="config_restrictedPreinstalledCarrierApps" /> - <!-- @hide @SystemApi --> - <public name="config_sms_enabled_single_shift_tables" /> - <!-- @hide @SystemApi --> - <public name="config_sms_enabled_locking_shift_tables" /> </public-group> - <!-- =============================================================== DO NOT ADD UN-GROUPED ITEMS HERE diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 492ea68dd515..7f463807e1e9 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -5421,4 +5421,236 @@ <!-- ChooserActivity - Alphabetically sorted apps list label. [CHAR LIMIT=NONE] --> <string name="chooser_all_apps_button_label">Apps list</string> + <!-- Icc depersonalization related strings --> + <!-- Label text for PIN entry widget on SIM Network Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY">SIM network unlock PIN</string> + <!-- Label text for PIN entry widget on SIM Network Subset Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY">SIM network subset unlock PIN</string> + <!-- Label text for PIN entry widget on SIM Corporate Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY">SIM corporate unlock PIN</string> + <!-- Label text for PIN entry widget on SIM Service Provider Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ENTRY">SIM service provider unlock PIN</string> + <!-- Label text for PIN entry widget on SIM SIM Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_SIM_ENTRY">SIM unlock PIN</string> + <!-- Label text for PUK entry widget on Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_ENTRY">Enter PUK</string> + <!-- Label text for Subset PUK entry widget on Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_ENTRY">Enter PUK</string> + <!-- Label text for Corporate PUK entry widget on Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_ENTRY">Enter PUK</string> + <!-- Label text for SIM service provider PUK entry widget on Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_ENTRY">Enter PUK</string> + <!-- Label text for SIM PUK entry widget on Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_SIM_PUK_ENTRY">Enter PUK</string> + <!-- Label text for PIN entry widget on RUIM Network1 Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_RUIM_NETWORK1_ENTRY">RUIM network1 unlock PIN</string> + <!-- Label text for PIN entry widget on RUIM Network2 Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_RUIM_NETWORK2_ENTRY">RUIM network2 unlock PIN</string> + <!-- Label text for PIN entry widget on RUIM Hrpd Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_RUIM_HRPD_ENTRY">RUIM hrpd unlock PIN</string> + <!-- Label text for PIN entry widget on RUIM Corporate Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_RUIM_CORPORATE_ENTRY">RUIM corporate unlock PIN</string> + <!-- Label text for PIN entry widget on RUIM Service Provider Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ENTRY">RUIM service provider unlock PIN</string> + <!-- Label text for PIN entry widget on RUIM RUIM Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_RUIM_RUIM_ENTRY">RUIM unlock PIN</string> + <!-- Label text for PUK entry widget on Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_ENTRY">Enter PUK</string> + <!-- Label text for PUK entry widget on Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_ENTRY">Enter PUK</string> + <!-- Label text for PUK entry widget on Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_ENTRY">Enter PUK</string> + <!-- Label text for PUK entry widget on Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_ENTRY">Enter PUK</string> + <!-- Label text for PUK entry widget on Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_ENTRY">Enter PUK</string> + <!-- Label text for PUK entry widget on Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_ENTRY">Enter PUK</string> + + <!-- Label text for PIN entry widget on SIM SPN Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_SPN_ENTRY">SPN unlock PIN</string> + <!-- Label text for PIN entry widget on SIM SP EHPLMN Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_ENTRY">SP Equivalent Home PLMN unlock PIN</string> + <!-- Label text for PIN entry widget on SIM ICCID Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_ICCID_ENTRY">ICCID unlock PIN</string> + <!-- Label text for PIN entry widget on SIM IMPI Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_IMPI_ENTRY">IMPI unlock PIN</string> + <!-- Label text for PIN entry widget on SIM NS_SP Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_NS_SP_ENTRY">Network subset service provider unlock PIN</string> + + <!-- Status message displayed on SIM Network Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_NETWORK_IN_PROGRESS">Requesting SIM network unlock\u2026</string> + <!-- Status message displayed on SIM Network Subset Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_IN_PROGRESS">Requesting SIM network subset unlock +\u2026</string> + <!-- Status message displayed on SIM Service Provider Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_IN_PROGRESS">Requesting SIM service provider un +lock\u2026</string> + <!-- Status message displayed on SIM Corporate Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_CORPORATE_IN_PROGRESS">Requesting SIM corporate unlock\u2026</string> + <!-- Status message displayed on PUK Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_IN_PROGRESS">Requesting PUK unlock\u2026</string> + <!-- Status message displayed on PUK Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_IN_PROGRESS">Requesting PUK unlock\u2026</string> + <!-- Status message displayed on Corporate PUK entry widget on Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_IN_PROGRESS">Requesting PUK unlock\u2026</string> + <!-- Status message displayed on SIM Service provider PUK entry widget on Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_IN_PROGRESS">Requesting PUK unlock\u2026</string> + <!-- Status message displayed on SIM PUK entry widget on Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_SIM_PUK_IN_PROGRESS">Requesting PUK unlock\u2026</string> + <!-- Status message displayed on SIM SIM Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_SIM_IN_PROGRESS">Requesting SIM unlock\u2026</string> + <!-- Status message displayed on RUIM Network1 Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_RUIM_NETWORK1_IN_PROGRESS">Requesting RUIM network1 unlock\u2026</string> + <!-- Status message displayed on RUIM Network2 Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_RUIM_NETWORK2_IN_PROGRESS">Requesting RUIM network2 unlock\u2026</string> + <!-- Status message displayed on RUIM Hrpd Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_RUIM_HRPD_IN_PROGRESS">Requesting RUIM hrpd unlock\u2026</string> + <!-- Status message displayed on RUIM Service Provider Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_IN_PROGRESS">Requesting RUIM service provider +unlock\u2026</string> + <!-- Status message displayed on RUIM Corporate Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_RUIM_CORPORATE_IN_PROGRESS">Requesting RUIM corporate unlock\u2026</string> + + <!-- Status message displayed on SIM SPN Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_SPN_IN_PROGRESS">Requesting SPN unlock\u2026</string> + <!-- Status message displayed on SIM SP EHPLMN Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_IN_PROGRESS">Requesting SP Equivalent Home PLMN unlock\u2026</string> + <!-- Status message displayed on SIM ICCID Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_ICCID_IN_PROGRESS">Requesting ICCID unlock\u2026</string> + <!-- Status message displayed on SIM IMPI Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_IMPI_IN_PROGRESS">Requesting IMPI unlock\u2026</string> + <!-- Status message displayed on SIM NS_SP Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_NS_SP_IN_PROGRESS">Requesting Network subset service provider unlock\u2026</string> + + <!-- Status message displayed on RUIM RUIM Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_RUIM_RUIM_IN_PROGRESS">Requesting RUIM unlock\u2026</string> + <!-- Status message displayed on PUK Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_IN_PROGRESS">Requesting PUK unlock\u2026</string> + <!-- Status message displayed on PUK Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_IN_PROGRESS">Requesting PUK unlock\u2026</string> + <!-- Status message displayed on PUK Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_IN_PROGRESS">Requesting PUK unlock\u2026</string> + <!-- Status message displayed on PUK Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_IN_PROGRESS">Requesting PUK unlock\u2026</string> + <!-- Status message displayed on PUK Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_IN_PROGRESS">Requesting PUK unlock\u2026</string> + <!-- Status message displayed on PUK Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_IN_PROGRESS">Requesting PUK unlock\u2026</string> + <!-- Error message displayed on SIM Network Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_NETWORK_ERROR">SIM Network unlock request unsuccessful.</string> + <!-- Error message displayed on SIM Network Subset Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ERROR">SIM Network Subset unlock request unsucces +sful.</string> + <!-- Error message displayed on SIM Service Provider Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ERROR">SIM Service Provider unlock request unsu +ccessful.</string> + <!-- Error message displayed on SIM Corporate Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_CORPORATE_ERROR">SIM Corporate unlock request unsuccessful.</string> + <!-- Error message displayed on SIM SIM Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_SIM_ERROR">SIM unlock request unsuccessful.</string> + <!-- Error message displayed on RUIM Network1 Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_RUIM_NETWORK1_ERROR">RUIM Network1 unlock request unsuccessful.</string> + <!-- Error message displayed on RUIM Network2 Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_RUIM_NETWORK2_ERROR">RUIM Network2 unlock request unsuccessful.</string> + <!-- Error message displayed on RUIM Hrpd Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_RUIM_HRPD_ERROR">RUIM Hrpd unlock request unsuccessful.</string> + <!-- Error message displayed on RUIM Corporate Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_RUIM_CORPORATE_ERROR">RUIM Corporate unlock request unsuccessful.</string> + <!-- Error message displayed on RUIM Service Provider Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ERROR">RUIM Service Provider unlock request un +successful.</string> + <!-- Error message displayed on RUIM RUIM Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_RUIM_RUIM_ERROR">RUIM unlock request unsuccessful.</string> + <!-- Error message displayed on PUK Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_ERROR">PUK unlock unsuccessful.</string> + <!-- Error message displayed on PUK Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_ERROR">PUK unlock unsuccessful.</string> + <!-- Error message displayed on PUK Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_ERROR">PUK unlock unsuccessful.</string> + <!-- Error message displayed on PUK Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_ERROR">PUK unlock unsuccessful.</string> + <!-- Error message displayed on PUK Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_SIM_PUK_ERROR">PUK unlock unsuccessful.</string> + <!-- Error message displayed on PUK Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_ERROR">PUK unlock unsuccessful.</string> + <!-- Error message displayed on PUK Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_ERROR">PUK unlock unsuccessful.</string> + <!-- Error message displayed on PUK Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_ERROR">PUK unlock unsuccessful.</string> + <!-- Error message displayed on PUK Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_ERROR">PUK unlock unsuccessful.</string> + <!-- Error message displayed on PUK Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_ERROR">PUK unlock unsuccessful.</string> + <!-- Error message displayed on PUK Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_ERROR">PUK unlock unsuccessful.</string> + + <!-- Error message displayed on SIM SPN Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_SPN_ERROR">SPN unlock request unsuccessful.</string> + <!-- Error message displayed on SIM SP EHPLMN Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_ERROR">SP Equivalent Home PLMN unlock request unsuccessful.</string> + <!-- Error message displayed on SIM ICCID Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_ICCID_ERROR">ICCID unlock request unsuccessful.</string> + <!-- Error message displayed on SIM IMPI Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_IMPI_ERROR">IMPI unlock request unsuccessful.</string> + <!-- Error message displayed on SIM NS_SP Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_NS_SP_ERROR">Network subset service provider unlock request unsuccessful.</string> + + <!-- Success message displayed on SIM Network Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_NETWORK_SUCCESS">SIM Network unlock successful.</string> + <!-- Success message displayed on SIM Network Subset Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_SUCCESS">SIM Network Subset unlock successful.</string> + <!-- Success message displayed on SIM Service Provider Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_SUCCESS">SIM Service Provider unlock successful +.</string> + <!-- Success message displayed on SIM Corporate Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_CORPORATE_SUCCESS">SIM Corporate unlock successful.</string> + <!-- Success message displayed on SIM SIM Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_SIM_SUCCESS">SIM unlock successful.</string> + <!-- Success message displayed on RUIM Network1 Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_RUIM_NETWORK1_SUCCESS">RUIM Network1 unlock successful.</string> + <!-- Success message displayed on RUIM Network2 Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_RUIM_NETWORK2_SUCCESS">RUIM Network2 unlock successful.</string> + <!-- Success message displayed on RUIM Hrpd Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_RUIM_HRPD_SUCCESS">RUIM Hrpd unlock successful.</string> + <!-- Success message displayed on RUIM Service Provider Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_SUCCESS">RUIM Service Provider unlock successf +ul.</string> + <!-- Success message displayed on RUIM Corporate Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_RUIM_CORPORATE_SUCCESS">RUIM Corporate unlock successful.</string> + <!-- Success message displayed on RUIM RUIM Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_RUIM_RUIM_SUCCESS">RUIM unlock successful.</string> + <!-- Success message displayed on PUK Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_SUCCESS">PUK unlock successful.</string> + <!-- Success message displayed on PUK Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_SUCCESS">PUK unlock successful.</string> + <!-- Success message displayed on PUK Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_SUCCESS">PUK unlock successful.</string> + <!-- Success message displayed on PUK Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_SUCCESS">PUK unlock successful.</string> + <!-- Success message displayed on PUK Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_SIM_PUK_SUCCESS">PUK unlock successful.</string> + <!-- Success message displayed on PUK Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_SUCCESS">PUK unlock successful.</string> + <!-- Success message displayed on PUK Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_SUCCESS">PUK unlock successful.</string> + <!-- Success message displayed on PUK Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_SUCCESS">PUK unlock successful.</string> + <!-- Success message displayed on PUK Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_SUCCESS">PUK unlock successful.</string> + <!-- Success message displayed on PUK Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_SUCCESS">PUK unlock successful.</string> + <!-- Success message displayed on PUK Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_SUCCESS">PUK unlock successful.</string> + + <!-- Success message displayed on SIM SPN Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_SPN_SUCCESS">SPN unlock successful.</string> + <!-- Success message displayed on SIM SP EHPLMN Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_SUCCESS">SP Equivalent Home PLMN unlock successful.</string> + <!-- Success message displayed on SIM ICCID Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_ICCID_SUCCESS">ICCID unlock successful.</string> + <!-- Success message displayed on SIM IMPI Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_IMPI_SUCCESS">IMPI unlock successful.</string> + <!-- Success message displayed on SIM NS_SP Depersonalization panel [CHAR LIMIT=none] --> + <string name="PERSOSUBSTATE_SIM_NS_SP_SUCCESS">Network subset service provider unlock successful.</string> </resources> diff --git a/data/etc/hiddenapi-package-whitelist.xml b/data/etc/hiddenapi-package-whitelist.xml index d282744bc3a0..e9de02e82432 100644 --- a/data/etc/hiddenapi-package-whitelist.xml +++ b/data/etc/hiddenapi-package-whitelist.xml @@ -57,7 +57,6 @@ platform cert need to be included, as apps signed with the platform cert are exe <hidden-api-whitelisted-app package="com.android.terminal" /> <hidden-api-whitelisted-app package="com.android.wallpaper" /> <hidden-api-whitelisted-app package="jp.co.omronsoft.openwnn" /> - <!-- STOPSHIP: Remove this when fixing all @hide usage for tethering.--> - <hidden-api-whitelisted-app package="com.android.networkstack.tethering" /> + <!-- TODO: Remove NetworkStack whitelisting --> <hidden-api-whitelisted-app package="com.android.networkstack" /> </config> diff --git a/libs/androidfw/OWNERS b/libs/androidfw/OWNERS index 8cffd6a3e548..bc056df23a36 100644 --- a/libs/androidfw/OWNERS +++ b/libs/androidfw/OWNERS @@ -3,4 +3,4 @@ toddke@google.com rtmitchell@google.com per-file CursorWindow.cpp=omakoto@google.com -per-file LocaleDataTables.cpp=vichang@google.com,tobiast@google.com,nikitai@google.com +per-file LocaleDataTables.cpp=vichang@google.com,ngeoffray@google.com,nikitai@google.com diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index 94d32c63edb1..59943eb546b4 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -4213,6 +4213,7 @@ public class AudioManager { * {@hide} */ @UnsupportedAppUsage + @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setWiredDeviceConnectionState(int type, int state, String address, String name) { final IAudioService service = getService(); try { diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java index d17f242d5d63..a1fba4a018e2 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java @@ -174,7 +174,7 @@ public class HearingAidProfile implements LocalBluetoothProfile { @Override public boolean isEnabled(BluetoothDevice device) { - if (mService == null) { + if (mService == null || device == null) { return false; } return mService.getConnectionPolicy(device) > CONNECTION_POLICY_FORBIDDEN; @@ -182,7 +182,7 @@ public class HearingAidProfile implements LocalBluetoothProfile { @Override public int getConnectionPolicy(BluetoothDevice device) { - if (mService == null) { + if (mService == null || device == null) { return CONNECTION_POLICY_FORBIDDEN; } return mService.getConnectionPolicy(device); @@ -191,7 +191,7 @@ public class HearingAidProfile implements LocalBluetoothProfile { @Override public boolean setEnabled(BluetoothDevice device, boolean enabled) { boolean isEnabled = false; - if (mService == null) { + if (mService == null || device == null) { return false; } if (enabled) { @@ -213,7 +213,7 @@ public class HearingAidProfile implements LocalBluetoothProfile { } public long getHiSyncId(BluetoothDevice device) { - if (mService == null) { + if (mService == null || device == null) { return BluetoothHearingAid.HI_SYNC_ID_INVALID; } return mService.getHiSyncId(device); diff --git a/packages/SystemUI/OWNERS b/packages/SystemUI/OWNERS index 656827a80117..c8cf7f503468 100644 --- a/packages/SystemUI/OWNERS +++ b/packages/SystemUI/OWNERS @@ -4,7 +4,6 @@ dsandler@android.com adamcohen@google.com asc@google.com -ashaikh@google.com beverlyt@google.com brockman@google.com cinek@google.com @@ -12,8 +11,8 @@ cwren@google.com dupin@google.com ethibodeau@google.com evanlaird@google.com +hwwang@google.com hyunyoungs@google.com -jmonk@google.com jaggies@google.com jjaggi@google.com joshmcgrath@google.com @@ -29,16 +28,16 @@ mrcasey@google.com mrenouf@google.com nbenbernou@google.com nesciosquid@google.com -ngmatthew@google.com ogunwale@google.com +peanutbutter@google.com pixel@google.com roosa@google.com -shahrk@google.com snoeberger@google.com steell@google.com stwu@google.com sunnygoyal@google.com susikp@google.com +tracyzhou@google.com tsuji@google.com twickham@google.com winsonc@google.com diff --git a/packages/Tethering/common/TetheringLib/Android.bp b/packages/Tethering/common/TetheringLib/Android.bp index 2fbba68f1e03..00d0d9c428ff 100644 --- a/packages/Tethering/common/TetheringLib/Android.bp +++ b/packages/Tethering/common/TetheringLib/Android.bp @@ -60,6 +60,7 @@ java_library { hostdex: true, // for hiddenapi check visibility: ["//frameworks/base/packages/Tethering:__subpackages__"], apex_available: ["com.android.tethering"], + permitted_packages: ["android.net"], } stubs_defaults { diff --git a/packages/Tethering/common/TetheringLib/api/system-current.txt b/packages/Tethering/common/TetheringLib/api/system-current.txt index 2f5ea6af719a..edd1ebb5f751 100644 --- a/packages/Tethering/common/TetheringLib/api/system-current.txt +++ b/packages/Tethering/common/TetheringLib/api/system-current.txt @@ -23,7 +23,6 @@ package android.net { method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerTetheringEventCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.TetheringEventCallback); method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void requestLatestTetheringEntitlementResult(int, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.OnTetheringEntitlementResultListener); method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void startTethering(@NonNull android.net.TetheringManager.TetheringRequest, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.StartTetheringCallback); - method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void startTethering(int, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.StartTetheringCallback); method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void stopAllTethering(); method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void stopTethering(int); method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.ACCESS_NETWORK_STATE}) public void unregisterTetheringEventCallback(@NonNull android.net.TetheringManager.TetheringEventCallback); diff --git a/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java b/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java index b70165ab74b4..0107a7ef5b59 100644 --- a/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java +++ b/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java @@ -571,9 +571,8 @@ public class TetheringManager { /** * Configure tethering with static IPv4 assignment. * - * The clientAddress must be in the localIPv4Address prefix. A DHCP server will be - * started, but will only be able to offer the client address. The two addresses must - * be in the same prefix. + * A DHCP server will be started, but will only be able to offer the client address. + * The two addresses must be in the same prefix. * * @param localIPv4Address The preferred local IPv4 link address to use. * @param clientAddress The static client address. @@ -584,10 +583,7 @@ public class TetheringManager { @NonNull final LinkAddress clientAddress) { Objects.requireNonNull(localIPv4Address); Objects.requireNonNull(clientAddress); - if (localIPv4Address.getPrefixLength() != clientAddress.getPrefixLength() - || !localIPv4Address.isIpv4() || !clientAddress.isIpv4() - || !new IpPrefix(localIPv4Address.toString()).equals( - new IpPrefix(clientAddress.toString()))) { + if (!checkStaticAddressConfiguration(localIPv4Address, clientAddress)) { throw new IllegalArgumentException("Invalid server or client addresses"); } @@ -657,6 +653,19 @@ public class TetheringManager { } /** + * Check whether the two addresses are ipv4 and in the same prefix. + * @hide + */ + public static boolean checkStaticAddressConfiguration( + @NonNull final LinkAddress localIPv4Address, + @NonNull final LinkAddress clientAddress) { + return localIPv4Address.getPrefixLength() == clientAddress.getPrefixLength() + && localIPv4Address.isIpv4() && clientAddress.isIpv4() + && new IpPrefix(localIPv4Address.toString()).equals( + new IpPrefix(clientAddress.toString())); + } + + /** * Get a TetheringRequestParcel from the configuration * @hide */ @@ -739,11 +748,13 @@ public class TetheringManager { * @param type The tethering type, on of the {@code TetheringManager#TETHERING_*} constants. * @param executor {@link Executor} to specify the thread upon which the callback of * TetheringRequest will be invoked. + * @hide */ @RequiresPermission(anyOf = { android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS }) + @SystemApi(client = MODULE_LIBRARIES) public void startTethering(int type, @NonNull final Executor executor, @NonNull final StartTetheringCallback callback) { startTethering(new TetheringRequest.Builder(type).build(), executor, callback); diff --git a/packages/Tethering/src/android/net/dhcp/DhcpServingParamsParcelExt.java b/packages/Tethering/src/android/net/dhcp/DhcpServingParamsParcelExt.java index d6bc063210b3..82a26beadacf 100644 --- a/packages/Tethering/src/android/net/dhcp/DhcpServingParamsParcelExt.java +++ b/packages/Tethering/src/android/net/dhcp/DhcpServingParamsParcelExt.java @@ -18,10 +18,12 @@ package android.net.dhcp; import static android.net.shared.Inet4AddressUtils.inet4AddressToIntHTH; -import android.annotation.NonNull; import android.net.LinkAddress; import android.util.ArraySet; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import java.net.Inet4Address; import java.util.Collection; import java.util.Collections; @@ -160,6 +162,17 @@ public class DhcpServingParamsParcelExt extends DhcpServingParamsParcel { return this; } + /** + * Set the client address to tell DHCP server only offer this address. + * The client's prefix length is the same as server's. + * + * <p>If not set, the default value is null. + */ + public DhcpServingParamsParcelExt setSingleClientAddr(@Nullable Inet4Address clientAddr) { + this.clientAddr = clientAddr == null ? 0 : inet4AddressToIntHTH(clientAddr); + return this; + } + private static int[] toIntArray(@NonNull Collection<Inet4Address> addrs) { int[] res = new int[addrs.size()]; int i = 0; diff --git a/packages/Tethering/src/android/net/ip/IpServer.java b/packages/Tethering/src/android/net/ip/IpServer.java index c5478d2e1a14..82b17acae592 100644 --- a/packages/Tethering/src/android/net/ip/IpServer.java +++ b/packages/Tethering/src/android/net/ip/IpServer.java @@ -18,6 +18,7 @@ package android.net.ip; import static android.net.InetAddresses.parseNumericAddress; import static android.net.RouteInfo.RTN_UNICAST; +import static android.net.TetheringManager.TetheringRequest.checkStaticAddressConfiguration; import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS; import static android.net.shared.Inet4AddressUtils.intToInet4AddressHTH; import static android.net.util.NetworkConstants.FF; @@ -492,17 +493,24 @@ public class IpServer extends StateMachine { } } - private boolean startDhcp(Inet4Address addr, int prefixLen) { + private boolean startDhcp(final LinkAddress serverLinkAddr, final LinkAddress clientLinkAddr) { if (mUsingLegacyDhcp) { return true; } + + final Inet4Address addr = (Inet4Address) serverLinkAddr.getAddress(); + final int prefixLen = serverLinkAddr.getPrefixLength(); + final Inet4Address clientAddr = clientLinkAddr == null ? null : + (Inet4Address) clientLinkAddr.getAddress(); + final DhcpServingParamsParcel params; params = new DhcpServingParamsParcelExt() .setDefaultRouters(addr) .setDhcpLeaseTimeSecs(DHCP_LEASE_TIME_SECS) .setDnsServers(addr) - .setServerAddr(new LinkAddress(addr, prefixLen)) - .setMetered(true); + .setServerAddr(serverLinkAddr) + .setMetered(true) + .setSingleClientAddr(clientAddr); // TODO: also advertise link MTU mDhcpServerStartIndex++; @@ -537,9 +545,10 @@ public class IpServer extends StateMachine { } } - private boolean configureDhcp(boolean enable, Inet4Address addr, int prefixLen) { + private boolean configureDhcp(boolean enable, final LinkAddress serverAddr, + final LinkAddress clientAddr) { if (enable) { - return startDhcp(addr, prefixLen); + return startDhcp(serverAddr, clientAddr); } else { stopDhcp(); return true; @@ -587,7 +596,7 @@ public class IpServer extends StateMachine { // code that calls into NetworkManagementService directly. srvAddr = (Inet4Address) parseNumericAddress(BLUETOOTH_IFACE_ADDR); mIpv4Address = new LinkAddress(srvAddr, BLUETOOTH_DHCP_PREFIX_LENGTH); - return configureDhcp(enabled, srvAddr, BLUETOOTH_DHCP_PREFIX_LENGTH); + return configureDhcp(enabled, mIpv4Address, null /* clientAddress */); } mIpv4Address = new LinkAddress(srvAddr, prefixLen); } catch (IllegalArgumentException e) { @@ -624,7 +633,7 @@ public class IpServer extends StateMachine { mLinkProperties.removeRoute(route); } - return configureDhcp(enabled, srvAddr, prefixLen); + return configureDhcp(enabled, mIpv4Address, mStaticIpv4ClientAddr); } private String getRandomWifiIPv4Address() { @@ -945,7 +954,14 @@ public class IpServer extends StateMachine { } private void maybeConfigureStaticIp(final TetheringRequestParcel request) { - if (request == null) return; + // Ignore static address configuration if they are invalid or null. In theory, static + // addresses should not be invalid here because TetheringManager do not allow caller to + // specify invalid static address configuration. + if (request == null || request.localIPv4Address == null + || request.staticClientAddress == null || !checkStaticAddressConfiguration( + request.localIPv4Address, request.staticClientAddress)) { + return; + } mStaticIpv4ServerAddr = request.localIPv4Address; mStaticIpv4ClientAddr = request.staticClientAddress; 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 3dcc15f92c06..343ed4b16cd6 100644 --- a/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java +++ b/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java @@ -303,31 +303,26 @@ public class Tethering { final UserManager userManager = (UserManager) mContext.getSystemService( Context.USER_SERVICE); - mTetheringRestriction = new UserRestrictionActionListener(userManager, this); + mTetheringRestriction = new UserRestrictionActionListener( + userManager, this, mNotificationUpdater); mExecutor = new TetheringThreadExecutor(mHandler); mActiveDataSubIdListener = new ActiveDataSubIdListener(mExecutor); + mNetdCallback = new NetdCallback(); // Load tethering configuration. updateConfiguration(); - // NetdCallback should be registered after updateConfiguration() to ensure - // TetheringConfiguration is created. - mNetdCallback = new NetdCallback(); + } + + /** + * Start to register callbacks. + * Call this function when tethering is ready to handle callback events. + */ + public void startStateMachineUpdaters() { try { mNetd.registerUnsolicitedEventListener(mNetdCallback); } catch (RemoteException e) { mLog.e("Unable to register netd UnsolicitedEventListener"); } - - startStateMachineUpdaters(mHandler); - startTrackDefaultNetwork(); - - final WifiManager wifiManager = getWifiManager(); - if (wifiManager != null) { - wifiManager.registerSoftApCallback(mExecutor, new TetheringSoftApCallback()); - } - } - - private void startStateMachineUpdaters(Handler handler) { mCarrierConfigChange.startListening(); mContext.getSystemService(TelephonyManager.class).listen(mActiveDataSubIdListener, PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE); @@ -340,7 +335,14 @@ public class Tethering { filter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION); filter.addAction(UserManager.ACTION_USER_RESTRICTIONS_CHANGED); filter.addAction(ACTION_RESTRICT_BACKGROUND_CHANGED); - mContext.registerReceiver(mStateReceiver, filter, null, handler); + mContext.registerReceiver(mStateReceiver, filter, null, mHandler); + + final WifiManager wifiManager = getWifiManager(); + if (wifiManager != null) { + wifiManager.registerSoftApCallback(mExecutor, new TetheringSoftApCallback()); + } + + startTrackDefaultNetwork(); } private class TetheringThreadExecutor implements Executor { @@ -369,9 +371,10 @@ public class Tethering { mActiveDataSubId = subId; updateConfiguration(); + mNotificationUpdater.onActiveDataSubscriptionIdChanged(subId); // To avoid launching unexpected provisioning checks, ignore re-provisioning // when no CarrierConfig loaded yet. Assume reevaluateSimCardProvisioning() - // ill be triggered again when CarrierConfig is loaded. + // will be triggered again when CarrierConfig is loaded. if (mEntitlementMgr.getCarrierConfig(mConfig) != null) { mEntitlementMgr.reevaluateSimCardProvisioning(mConfig); } else { @@ -431,9 +434,7 @@ public class Tethering { // Called by wifi when the number of soft AP clients changed. @Override public void onConnectedClientsChanged(final List<WifiClient> clients) { - if (mConnectedClientsTracker.updateConnectedClients(mForwardedDownstreams, clients)) { - reportTetherClientsChanged(mConnectedClientsTracker.getLastTetheredClients()); - } + updateConnectedClients(clients); } } @@ -635,7 +636,10 @@ public class Tethering { Context.ETHERNET_SERVICE); synchronized (mPublicSync) { if (enable) { - if (mEthernetCallback != null) return TETHER_ERROR_NO_ERROR; + if (mEthernetCallback != null) { + Log.d(TAG, "Ethernet tethering already started"); + return TETHER_ERROR_NO_ERROR; + } mEthernetCallback = new EthernetCallback(); mEthernetIfaceRequest = em.requestTetheredInterface(mExecutor, mEthernetCallback); @@ -996,11 +1000,14 @@ public class Tethering { protected static class UserRestrictionActionListener { private final UserManager mUserManager; private final Tethering mWrapper; + private final TetheringNotificationUpdater mNotificationUpdater; public boolean mDisallowTethering; - public UserRestrictionActionListener(UserManager um, Tethering wrapper) { + public UserRestrictionActionListener(@NonNull UserManager um, @NonNull Tethering wrapper, + @NonNull TetheringNotificationUpdater updater) { mUserManager = um; mWrapper = wrapper; + mNotificationUpdater = updater; mDisallowTethering = false; } @@ -1019,13 +1026,21 @@ public class Tethering { return; } - // TODO: Add user restrictions notification. - final boolean isTetheringActiveOnDevice = (mWrapper.getTetheredIfaces().length != 0); - - if (newlyDisallowed && isTetheringActiveOnDevice) { - mWrapper.untetherAll(); - // TODO(b/148139325): send tetheringSupported on restriction change + if (!newlyDisallowed) { + // Clear the restricted notification when user is allowed to have tethering + // function. + mNotificationUpdater.tetheringRestrictionLifted(); + return; } + + // Restricted notification is shown when tethering function is disallowed on + // user's device. + mNotificationUpdater.notifyTetheringDisabledByRestriction(); + + // Untether from all downstreams since tethering is disallowed. + mWrapper.untetherAll(); + + // TODO(b/148139325): send tetheringSupported on restriction change } } @@ -1494,7 +1509,7 @@ public class Tethering { } else { dnsServers = mConfig.defaultIPv4DNS; } - final int netId = (network != null) ? network.netId : NETID_UNSET; + final int netId = (network != null) ? network.getNetId() : NETID_UNSET; try { mNetd.tetherDnsSet(netId, dnsServers); mLog.log(String.format( @@ -1559,6 +1574,7 @@ public class Tethering { mIPv6TetheringCoordinator.removeActiveDownstream(who); mOffload.excludeDownstreamInterface(who.interfaceName()); mForwardedDownstreams.remove(who); + updateConnectedClients(null /* wifiClients */); // If this is a Wi-Fi interface, tell WifiManager of any errors // or the inactive serving state. @@ -2141,6 +2157,12 @@ public class Tethering { return false; } + private void updateConnectedClients(final List<WifiClient> wifiClients) { + if (mConnectedClientsTracker.updateConnectedClients(mForwardedDownstreams, wifiClients)) { + reportTetherClientsChanged(mConnectedClientsTracker.getLastTetheredClients()); + } + } + private IpServer.Callback makeControlCallback() { return new IpServer.Callback() { @Override @@ -2155,10 +2177,7 @@ public class Tethering { @Override public void dhcpLeasesChanged() { - if (mConnectedClientsTracker.updateConnectedClients( - mForwardedDownstreams, null /* wifiClients */)) { - reportTetherClientsChanged(mConnectedClientsTracker.getLastTetheredClients()); - } + updateConnectedClients(null /* wifiClients */); } }; } diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringNotificationUpdater.java b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringNotificationUpdater.java index b97f75268a3b..992cdd8de6a7 100644 --- a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringNotificationUpdater.java +++ b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringNotificationUpdater.java @@ -29,12 +29,14 @@ import android.content.Intent; import android.content.res.Resources; import android.os.UserHandle; import android.provider.Settings; +import android.telephony.SubscriptionManager; import android.text.TextUtils; import android.util.Log; import android.util.SparseArray; import androidx.annotation.ArrayRes; import androidx.annotation.DrawableRes; +import androidx.annotation.IntDef; import androidx.annotation.IntRange; import androidx.annotation.NonNull; @@ -54,10 +56,15 @@ import com.android.networkstack.tethering.R; public class TetheringNotificationUpdater { private static final String TAG = TetheringNotificationUpdater.class.getSimpleName(); private static final String CHANNEL_ID = "TETHERING_STATUS"; + private static final String WIFI_DOWNSTREAM = "WIFI"; + private static final String USB_DOWNSTREAM = "USB"; + private static final String BLUETOOTH_DOWNSTREAM = "BT"; private static final boolean NOTIFY_DONE = true; private static final boolean NO_NOTIFY = false; // Id to update and cancel tethering notification. Must be unique within the tethering app. - private static final int NOTIFY_ID = 20191115; + private static final int ENABLE_NOTIFICATION_ID = 1000; + // Id to update and cancel restricted notification. Must be unique within the tethering app. + private static final int RESTRICTED_NOTIFICATION_ID = 1001; @VisibleForTesting static final int NO_ICON_ID = 0; @VisibleForTesting @@ -65,14 +72,25 @@ public class TetheringNotificationUpdater { private final Context mContext; private final NotificationManager mNotificationManager; private final NotificationChannel mChannel; - // Downstream type is one of ConnectivityManager.TETHERING_* constants, 0 1 or 2. - // This value has to be made 1 2 and 4, and OR'd with the others. + // WARNING : the constructor is called on a different thread. Thread safety therefore // relies on this value being initialized to 0, and not any other value. If you need // to change this, you will need to change the thread where the constructor is invoked, // or to introduce synchronization. + // Downstream type is one of ConnectivityManager.TETHERING_* constants, 0 1 or 2. + // This value has to be made 1 2 and 4, and OR'd with the others. private int mDownstreamTypesMask = DOWNSTREAM_NONE; + // WARNING : this value is not able to being initialized to 0 and must have volatile because + // telephony service is not guaranteed that is up before tethering service starts. If telephony + // is up later than tethering, TetheringNotificationUpdater will use incorrect and valid + // subscription id(0) to query resources. Therefore, initialized subscription id must be + // INVALID_SUBSCRIPTION_ID. + private volatile int mActiveDataSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; + + @IntDef({ENABLE_NOTIFICATION_ID, RESTRICTED_NOTIFICATION_ID}) + @interface NotificationId {} + public TetheringNotificationUpdater(@NonNull final Context context) { mContext = context; mNotificationManager = (NotificationManager) context.createContextAsUser(UserHandle.ALL, 0) @@ -88,19 +106,46 @@ public class TetheringNotificationUpdater { public void onDownstreamChanged(@IntRange(from = 0, to = 7) final int downstreamTypesMask) { if (mDownstreamTypesMask == downstreamTypesMask) return; mDownstreamTypesMask = downstreamTypesMask; - updateNotification(); + updateEnableNotification(); + } + + /** Called when active data subscription id changed */ + public void onActiveDataSubscriptionIdChanged(final int subId) { + if (mActiveDataSubId == subId) return; + mActiveDataSubId = subId; + updateEnableNotification(); } - private void updateNotification() { + @VisibleForTesting + Resources getResourcesForSubId(@NonNull final Context c, final int subId) { + return SubscriptionManager.getResourcesForSubId(c, subId); + } + + private void updateEnableNotification() { final boolean tetheringInactive = mDownstreamTypesMask <= DOWNSTREAM_NONE; if (tetheringInactive || setupNotification() == NO_NOTIFY) { - clearNotification(); + clearNotification(ENABLE_NOTIFICATION_ID); } } - private void clearNotification() { - mNotificationManager.cancel(null /* tag */, NOTIFY_ID); + @VisibleForTesting + void tetheringRestrictionLifted() { + clearNotification(RESTRICTED_NOTIFICATION_ID); + } + + private void clearNotification(@NotificationId final int id) { + mNotificationManager.cancel(null /* tag */, id); + } + + @VisibleForTesting + void notifyTetheringDisabledByRestriction() { + final Resources res = getResourcesForSubId(mContext, mActiveDataSubId); + final String title = res.getString(R.string.disable_tether_notification_title); + final String message = res.getString(R.string.disable_tether_notification_message); + + showNotification(R.drawable.stat_sys_tether_general, title, message, + RESTRICTED_NOTIFICATION_ID); } /** @@ -110,16 +155,17 @@ public class TetheringNotificationUpdater { * * @return downstream types mask value. */ + @VisibleForTesting @IntRange(from = 0, to = 7) - private int getDownstreamTypesMask(@NonNull final String types) { + int getDownstreamTypesMask(@NonNull final String types) { int downstreamTypesMask = DOWNSTREAM_NONE; final String[] downstreams = types.split("\\|"); for (String downstream : downstreams) { - if ("USB".equals(downstream.trim())) { + if (USB_DOWNSTREAM.equals(downstream.trim())) { downstreamTypesMask |= (1 << TETHERING_USB); - } else if ("WIFI".equals(downstream.trim())) { + } else if (WIFI_DOWNSTREAM.equals(downstream.trim())) { downstreamTypesMask |= (1 << TETHERING_WIFI); - } else if ("BT".equals(downstream.trim())) { + } else if (BLUETOOTH_DOWNSTREAM.equals(downstream.trim())) { downstreamTypesMask |= (1 << TETHERING_BLUETOOTH); } } @@ -134,9 +180,8 @@ public class TetheringNotificationUpdater { * * @return {@link android.util.SparseArray} with downstream types and icon id info. */ - @NonNull - private SparseArray<Integer> getIcons(@ArrayRes int id) { - final Resources res = mContext.getResources(); + @VisibleForTesting + SparseArray<Integer> getIcons(@ArrayRes int id, @NonNull Resources res) { final String[] array = res.getStringArray(id); final SparseArray<Integer> icons = new SparseArray<>(); for (String config : array) { @@ -161,8 +206,9 @@ public class TetheringNotificationUpdater { } private boolean setupNotification() { - final Resources res = mContext.getResources(); - final SparseArray<Integer> downstreamIcons = getIcons(R.array.tethering_notification_icons); + final Resources res = getResourcesForSubId(mContext, mActiveDataSubId); + final SparseArray<Integer> downstreamIcons = + getIcons(R.array.tethering_notification_icons, res); final int iconId = downstreamIcons.get(mDownstreamTypesMask, NO_ICON_ID); if (iconId == NO_ICON_ID) return NO_NOTIFY; @@ -170,12 +216,12 @@ public class TetheringNotificationUpdater { final String title = res.getString(R.string.tethering_notification_title); final String message = res.getString(R.string.tethering_notification_message); - showNotification(iconId, title, message); + showNotification(iconId, title, message, ENABLE_NOTIFICATION_ID); return NOTIFY_DONE; } private void showNotification(@DrawableRes final int iconId, @NonNull final String title, - @NonNull final String message) { + @NonNull final String message, @NotificationId final int id) { final Intent intent = new Intent(Settings.ACTION_TETHER_SETTINGS); final PendingIntent pi = PendingIntent.getActivity( mContext.createContextAsUser(UserHandle.CURRENT, 0), @@ -193,6 +239,6 @@ public class TetheringNotificationUpdater { .setContentIntent(pi) .build(); - mNotificationManager.notify(null /* tag */, NOTIFY_ID, notification); + mNotificationManager.notify(null /* tag */, id, notification); } } diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java index c5329d8d3316..c30be25dbd22 100644 --- a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java +++ b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java @@ -80,6 +80,7 @@ public class TetheringService extends Service { mContext = mDeps.getContext(); mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); mTethering = makeTethering(mDeps); + mTethering.startStateMachineUpdaters(); } /** diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java b/packages/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java index 7ac7f5f06e50..45bb4ab6e5f7 100644 --- a/packages/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java +++ b/packages/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java @@ -586,21 +586,21 @@ public class UpstreamNetworkMonitor { */ @VisibleForTesting public static NetworkCapabilities networkCapabilitiesForType(int type) { - final NetworkCapabilities nc = new NetworkCapabilities(); + final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder(); // Map from type to transports. final int notFound = -1; final int transport = sLegacyTypeToTransport.get(type, notFound); Preconditions.checkArgument(transport != notFound, "unknown legacy type: " + type); - nc.addTransportType(transport); + builder.addTransportType(transport); if (type == TYPE_MOBILE_DUN) { - nc.addCapability(NetworkCapabilities.NET_CAPABILITY_DUN); + builder.addCapability(NetworkCapabilities.NET_CAPABILITY_DUN); // DUN is restricted network, see NetworkCapabilities#FORCE_RESTRICTED_CAPABILITIES. - nc.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); + builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); } else { - nc.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); + builder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); } - return nc; + return builder.build(); } } diff --git a/packages/Tethering/tests/integration/Android.bp b/packages/Tethering/tests/integration/Android.bp new file mode 100644 index 000000000000..1a1c30d1d5f9 --- /dev/null +++ b/packages/Tethering/tests/integration/Android.bp @@ -0,0 +1,42 @@ +// +// 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. +// + +android_test { + name: "TetheringIntegrationTests", + certificate: "platform", + platform_apis: true, + srcs: [ + "src/**/*.java", + "src/**/*.kt", + ], + test_suites: [ + "device-tests", + "mts", + ], + static_libs: [ + "NetworkStackApiStableLib", + "androidx.test.rules", + "frameworks-base-testutils", + "mockito-target-extended-minus-junit4", + "net-tests-utils", + "testables", + ], + libs: [ + "android.test.runner", + "android.test.base", + "android.test.mock", + ], +} diff --git a/packages/Tethering/tests/integration/AndroidManifest.xml b/packages/Tethering/tests/integration/AndroidManifest.xml new file mode 100644 index 000000000000..233ba40b5d35 --- /dev/null +++ b/packages/Tethering/tests/integration/AndroidManifest.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. +--> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.networkstack.tethering.tests.integration"> + + <uses-permission android:name="android.permission.INTERNET"/> + <uses-permission android:name="android.permission.TETHER_PRIVILEGED"/> + + <application android:debuggable="true"> + <uses-library android:name="android.test.runner" /> + </application> + <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" + android:targetPackage="com.android.networkstack.tethering.tests.integration" + android:label="Tethering integration tests"> + </instrumentation> +</manifest> diff --git a/packages/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java b/packages/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java new file mode 100644 index 000000000000..492ce3db3424 --- /dev/null +++ b/packages/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java @@ -0,0 +1,459 @@ +/* + * 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; + +import static android.Manifest.permission.MANAGE_TEST_NETWORKS; +import static android.Manifest.permission.NETWORK_SETTINGS; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.junit.Assume.assumeFalse; +import static org.junit.Assume.assumeTrue; + +import android.app.UiAutomation; +import android.content.Context; +import android.net.EthernetManager.TetheredInterfaceCallback; +import android.net.EthernetManager.TetheredInterfaceRequest; +import android.net.TetheringManager.StartTetheringCallback; +import android.net.TetheringManager.TetheringEventCallback; +import android.net.TetheringManager.TetheringRequest; +import android.net.dhcp.DhcpAckPacket; +import android.net.dhcp.DhcpOfferPacket; +import android.net.dhcp.DhcpPacket; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.SystemClock; +import android.system.Os; +import android.util.Log; + +import androidx.test.InstrumentationRegistry; +import androidx.test.filters.MediumTest; +import androidx.test.runner.AndroidJUnit4; + +import com.android.testutils.HandlerUtilsKt; +import com.android.testutils.TapPacketReader; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.io.FileDescriptor; +import java.net.Inet4Address; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.nio.ByteBuffer; +import java.util.Collection; +import java.util.List; +import java.util.Random; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +@RunWith(AndroidJUnit4.class) +@MediumTest +public class EthernetTetheringTest { + + private static final String TAG = EthernetTetheringTest.class.getSimpleName(); + private static final int TIMEOUT_MS = 1000; + private static final int PACKET_READ_TIMEOUT_MS = 100; + private static final int DHCP_DISCOVER_ATTEMPTS = 10; + private static final byte[] DHCP_REQUESTED_PARAMS = new byte[] { + DhcpPacket.DHCP_SUBNET_MASK, + DhcpPacket.DHCP_ROUTER, + DhcpPacket.DHCP_DNS_SERVER, + DhcpPacket.DHCP_LEASE_TIME, + }; + private static final String DHCP_HOSTNAME = "testhostname"; + + private final Context mContext = InstrumentationRegistry.getContext(); + private final EthernetManager mEm = mContext.getSystemService(EthernetManager.class); + private final TetheringManager mTm = mContext.getSystemService(TetheringManager.class); + + private TestNetworkInterface mTestIface; + private HandlerThread mHandlerThread; + private Handler mHandler; + private TapPacketReader mTapPacketReader; + + private TetheredInterfaceRequester mTetheredInterfaceRequester; + private MyTetheringEventCallback mTetheringEventCallback; + + private UiAutomation mUiAutomation = + InstrumentationRegistry.getInstrumentation().getUiAutomation(); + + @Before + public void setUp() throws Exception { + mHandlerThread = new HandlerThread(getClass().getSimpleName()); + mHandlerThread.start(); + mHandler = new Handler(mHandlerThread.getLooper()); + mTetheredInterfaceRequester = new TetheredInterfaceRequester(mHandler, mEm); + // Needed to create a TestNetworkInterface, to call requestTetheredInterface, and to receive + // tethered client callbacks. + mUiAutomation.adoptShellPermissionIdentity(MANAGE_TEST_NETWORKS, NETWORK_SETTINGS); + } + + private void cleanUp() throws Exception { + mTm.stopTethering(TetheringManager.TETHERING_ETHERNET); + if (mTetheringEventCallback != null) { + mTetheringEventCallback.awaitInterfaceUntethered(); + mTetheringEventCallback.unregister(); + mTetheringEventCallback = null; + } + if (mTapPacketReader != null) { + TapPacketReader reader = mTapPacketReader; + mHandler.post(() -> reader.stop()); + mTapPacketReader = null; + } + mHandlerThread.quitSafely(); + mTetheredInterfaceRequester.release(); + mEm.setIncludeTestInterfaces(false); + maybeDeleteTestInterface(); + } + + @After + public void tearDown() throws Exception { + try { + cleanUp(); + } finally { + mUiAutomation.dropShellPermissionIdentity(); + } + } + + @Test + public void testVirtualEthernetAlreadyExists() throws Exception { + // This test requires manipulating packets. Skip if there is a physical Ethernet connected. + assumeFalse(mEm.isAvailable()); + + mTestIface = createTestInterface(); + // This must be done now because as soon as setIncludeTestInterfaces(true) is called, the + // interface will be placed in client mode, which will delete the link-local address. + // At that point NetworkInterface.getByName() will cease to work on the interface, because + // starting in R NetworkInterface can no longer see interfaces without IP addresses. + int mtu = getMTU(mTestIface); + + Log.d(TAG, "Including test interfaces"); + mEm.setIncludeTestInterfaces(true); + + final String iface = mTetheredInterfaceRequester.getInterface(); + assertEquals("TetheredInterfaceCallback for unexpected interface", + mTestIface.getInterfaceName(), iface); + + checkVirtualEthernet(mTestIface, mtu); + } + + @Test + public void testVirtualEthernet() throws Exception { + // This test requires manipulating packets. Skip if there is a physical Ethernet connected. + assumeFalse(mEm.isAvailable()); + + CompletableFuture<String> futureIface = mTetheredInterfaceRequester.requestInterface(); + + mEm.setIncludeTestInterfaces(true); + + mTestIface = createTestInterface(); + + final String iface = futureIface.get(TIMEOUT_MS, TimeUnit.MILLISECONDS); + assertEquals("TetheredInterfaceCallback for unexpected interface", + mTestIface.getInterfaceName(), iface); + + checkVirtualEthernet(mTestIface, getMTU(mTestIface)); + } + + @Test + public void testPhysicalEthernet() throws Exception { + assumeTrue(mEm.isAvailable()); + + // Get an interface to use. + final String iface = mTetheredInterfaceRequester.getInterface(); + + // Enable Ethernet tethering and check that it starts. + mTetheringEventCallback = enableEthernetTethering(iface); + + // There is nothing more we can do on a physical interface without connecting an actual + // client, which is not possible in this test. + } + + private static final class MyTetheringEventCallback implements TetheringEventCallback { + private final TetheringManager mTm; + private final CountDownLatch mTetheringStartedLatch = new CountDownLatch(1); + private final CountDownLatch mTetheringStoppedLatch = new CountDownLatch(1); + private final CountDownLatch mClientConnectedLatch = new CountDownLatch(1); + private final String mIface; + + private volatile boolean mInterfaceWasTethered = false; + private volatile boolean mUnregistered = false; + private volatile Collection<TetheredClient> mClients = null; + + MyTetheringEventCallback(TetheringManager tm, String iface) { + mTm = tm; + mIface = iface; + } + + public void unregister() { + mTm.unregisterTetheringEventCallback(this); + mUnregistered = true; + } + + @Override + public void onTetheredInterfacesChanged(List<String> interfaces) { + // Ignore stale callbacks registered by previous test cases. + if (mUnregistered) return; + + final boolean wasTethered = mTetheringStartedLatch.getCount() == 0; + if (!mInterfaceWasTethered && (mIface == null || interfaces.contains(mIface))) { + // This interface is being tethered for the first time. + Log.d(TAG, "Tethering started: " + interfaces); + mInterfaceWasTethered = true; + mTetheringStartedLatch.countDown(); + } else if (mInterfaceWasTethered && !interfaces.contains(mIface)) { + Log.d(TAG, "Tethering stopped: " + interfaces); + mTetheringStoppedLatch.countDown(); + } + } + + public void awaitInterfaceTethered() throws Exception { + assertTrue("Ethernet not tethered after " + TIMEOUT_MS + "ms", + mTetheringStartedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); + } + + public void awaitInterfaceUntethered() throws Exception { + // Don't block teardown if the interface was never tethered. + // This is racy because the interface might become tethered right after this check, but + // that can only happen in tearDown if startTethering timed out, which likely means + // the test has already failed. + if (!mInterfaceWasTethered) return; + + assertTrue(mIface + " not untethered after " + TIMEOUT_MS + "ms", + mTetheringStoppedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); + } + + @Override + public void onError(String ifName, int error) { + // Ignore stale callbacks registered by previous test cases. + if (mUnregistered) return; + + fail("TetheringEventCallback got error:" + error + " on iface " + ifName); + } + + @Override + public void onClientsChanged(Collection<TetheredClient> clients) { + // Ignore stale callbacks registered by previous test cases. + if (mUnregistered) return; + + Log.d(TAG, "Got clients changed: " + clients); + mClients = clients; + if (clients.size() > 0) { + mClientConnectedLatch.countDown(); + } + } + + public Collection<TetheredClient> awaitClientConnected() throws Exception { + assertTrue("Did not receive client connected callback after " + TIMEOUT_MS + "ms", + mClientConnectedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); + return mClients; + } + } + + private MyTetheringEventCallback enableEthernetTethering(String iface) throws Exception { + MyTetheringEventCallback callback = new MyTetheringEventCallback(mTm, iface); + mTm.registerTetheringEventCallback(mHandler::post, callback); + + StartTetheringCallback startTetheringCallback = new StartTetheringCallback() { + @Override + public void onTetheringFailed(int resultCode) { + fail("Unexpectedly got onTetheringFailed"); + } + }; + Log.d(TAG, "Starting Ethernet tethering"); + mTm.startTethering( + new TetheringRequest.Builder(TetheringManager.TETHERING_ETHERNET).build(), + mHandler::post /* executor */, startTetheringCallback); + callback.awaitInterfaceTethered(); + return callback; + } + + private int getMTU(TestNetworkInterface iface) throws SocketException { + NetworkInterface nif = NetworkInterface.getByName(iface.getInterfaceName()); + assertNotNull("Can't get NetworkInterface object for " + iface.getInterfaceName(), nif); + return nif.getMTU(); + } + + private void checkVirtualEthernet(TestNetworkInterface iface, int mtu) throws Exception { + FileDescriptor fd = iface.getFileDescriptor().getFileDescriptor(); + mTapPacketReader = new TapPacketReader(mHandler, fd, mtu); + mHandler.post(() -> mTapPacketReader.start()); + HandlerUtilsKt.waitForIdle(mHandler, TIMEOUT_MS); + + mTetheringEventCallback = enableEthernetTethering(iface.getInterfaceName()); + checkTetheredClientCallbacks(fd); + } + + private void checkTetheredClientCallbacks(FileDescriptor fd) throws Exception { + // Create a fake client. + byte[] clientMacAddr = new byte[6]; + new Random().nextBytes(clientMacAddr); + + // We have to retransmit DHCP requests because IpServer declares itself to be ready before + // its DhcpServer is actually started. TODO: fix this race and remove this loop. + DhcpPacket offerPacket = null; + for (int i = 0; i < DHCP_DISCOVER_ATTEMPTS; i++) { + Log.d(TAG, "Sending DHCP discover"); + sendDhcpDiscover(fd, clientMacAddr); + offerPacket = getNextDhcpPacket(); + if (offerPacket instanceof DhcpOfferPacket) break; + } + assertTrue("No DHCPOFFER received on interface within timeout", + offerPacket instanceof DhcpOfferPacket); + + sendDhcpRequest(fd, offerPacket, clientMacAddr); + DhcpPacket ackPacket = getNextDhcpPacket(); + assertTrue("No DHCPACK received on interface within timeout", + ackPacket instanceof DhcpAckPacket); + + final Collection<TetheredClient> clients = mTetheringEventCallback.awaitClientConnected(); + assertEquals(1, clients.size()); + final TetheredClient client = clients.iterator().next(); + + // Check the MAC address. + assertEquals(MacAddress.fromBytes(clientMacAddr), client.getMacAddress()); + assertEquals(TetheringManager.TETHERING_ETHERNET, client.getTetheringType()); + + // Check the hostname. + assertEquals(1, client.getAddresses().size()); + TetheredClient.AddressInfo info = client.getAddresses().get(0); + assertEquals(DHCP_HOSTNAME, info.getHostname()); + + // Check the address is the one that was handed out in the DHCP ACK. + DhcpResults dhcpResults = offerPacket.toDhcpResults(); + assertLinkAddressMatches(dhcpResults.ipAddress, info.getAddress()); + + // Check that the lifetime is correct +/- 10s. + final long now = SystemClock.elapsedRealtime(); + final long actualLeaseDuration = (info.getAddress().getExpirationTime() - now) / 1000; + final String msg = String.format("IP address should have lifetime of %d, got %d", + dhcpResults.leaseDuration, actualLeaseDuration); + assertTrue(msg, Math.abs(dhcpResults.leaseDuration - actualLeaseDuration) < 10); + } + + private DhcpPacket getNextDhcpPacket() throws ParseException { + byte[] packet; + while ((packet = mTapPacketReader.popPacket(PACKET_READ_TIMEOUT_MS)) != null) { + try { + return DhcpPacket.decodeFullPacket(packet, packet.length, DhcpPacket.ENCAP_L2); + } catch (DhcpPacket.ParseException e) { + // Not a DHCP packet. Continue. + } + } + return null; + } + + private static final class TetheredInterfaceRequester implements TetheredInterfaceCallback { + private final CountDownLatch mInterfaceAvailableLatch = new CountDownLatch(1); + private final Handler mHandler; + private final EthernetManager mEm; + + private TetheredInterfaceRequest mRequest; + private final CompletableFuture<String> mFuture = new CompletableFuture<>(); + + TetheredInterfaceRequester(Handler handler, EthernetManager em) { + mHandler = handler; + mEm = em; + } + + @Override + public void onAvailable(String iface) { + Log.d(TAG, "Ethernet interface available: " + iface); + mFuture.complete(iface); + } + + @Override + public void onUnavailable() { + mFuture.completeExceptionally(new IllegalStateException("onUnavailable received")); + } + + public CompletableFuture<String> requestInterface() { + assertNull("BUG: more than one tethered interface request", mRequest); + Log.d(TAG, "Requesting tethered interface"); + mRequest = mEm.requestTetheredInterface(mHandler::post, this); + return mFuture; + } + + public String getInterface() throws Exception { + return requestInterface().get(TIMEOUT_MS, TimeUnit.MILLISECONDS); + } + + public void release() { + if (mRequest != null) { + mFuture.obtrudeException(new IllegalStateException("Request already released")); + mRequest.release(); + mRequest = null; + } + } + } + + private void sendDhcpDiscover(FileDescriptor fd, byte[] macAddress) throws Exception { + ByteBuffer packet = DhcpPacket.buildDiscoverPacket(DhcpPacket.ENCAP_L2, + new Random().nextInt() /* transactionId */, (short) 0 /* secs */, + macAddress, false /* unicast */, DHCP_REQUESTED_PARAMS, + false /* rapid commit */, DHCP_HOSTNAME); + sendPacket(fd, packet); + } + + private void sendDhcpRequest(FileDescriptor fd, DhcpPacket offerPacket, byte[] macAddress) + throws Exception { + DhcpResults results = offerPacket.toDhcpResults(); + Inet4Address clientIp = (Inet4Address) results.ipAddress.getAddress(); + Inet4Address serverIdentifier = results.serverAddress; + ByteBuffer packet = DhcpPacket.buildRequestPacket(DhcpPacket.ENCAP_L2, + 0 /* transactionId */, (short) 0 /* secs */, DhcpPacket.INADDR_ANY /* clientIp */, + false /* broadcast */, macAddress, clientIp /* requestedIpAddress */, + serverIdentifier, DHCP_REQUESTED_PARAMS, DHCP_HOSTNAME); + sendPacket(fd, packet); + } + + private void sendPacket(FileDescriptor fd, ByteBuffer packet) throws Exception { + assertNotNull("Only tests on virtual interfaces can send packets", fd); + Os.write(fd, packet); + } + + public void assertLinkAddressMatches(LinkAddress l1, LinkAddress l2) { + // Check all fields except the deprecation and expiry times. + String msg = String.format("LinkAddresses do not match. expected: %s actual: %s", l1, l2); + assertTrue(msg, l1.isSameAddressAs(l2)); + assertEquals("LinkAddress flags do not match", l1.getFlags(), l2.getFlags()); + assertEquals("LinkAddress scope does not match", l1.getScope(), l2.getScope()); + } + + private TestNetworkInterface createTestInterface() throws Exception { + TestNetworkManager tnm = mContext.getSystemService(TestNetworkManager.class); + TestNetworkInterface iface = tnm.createTapInterface(); + Log.d(TAG, "Created test interface " + iface.getInterfaceName()); + assertNotNull(NetworkInterface.getByName(iface.getInterfaceName())); + return iface; + } + + private void maybeDeleteTestInterface() throws Exception { + if (mTestIface != null) { + mTestIface.getFileDescriptor().close(); + Log.d(TAG, "Deleted test interface " + mTestIface.getInterfaceName()); + mTestIface = null; + } + } +} diff --git a/packages/Tethering/tests/unit/src/android/net/dhcp/DhcpServingParamsParcelExtTest.java b/packages/Tethering/tests/unit/src/android/net/dhcp/DhcpServingParamsParcelExtTest.java index e8add9830b5f..f8eb1476bad0 100644 --- a/packages/Tethering/tests/unit/src/android/net/dhcp/DhcpServingParamsParcelExtTest.java +++ b/packages/Tethering/tests/unit/src/android/net/dhcp/DhcpServingParamsParcelExtTest.java @@ -42,7 +42,9 @@ import java.util.stream.IntStream; @SmallTest public class DhcpServingParamsParcelExtTest { private static final Inet4Address TEST_ADDRESS = inet4Addr("192.168.0.123"); + private static final Inet4Address TEST_CLIENT_ADDRESS = inet4Addr("192.168.0.42"); private static final int TEST_ADDRESS_PARCELED = 0xc0a8007b; + private static final int TEST_CLIENT_ADDRESS_PARCELED = 0xc0a8002a; private static final int TEST_PREFIX_LENGTH = 17; private static final int TEST_LEASE_TIME_SECS = 120; private static final int TEST_MTU = 1000; @@ -105,6 +107,12 @@ public class DhcpServingParamsParcelExtTest { assertFalse(mParcel.metered); } + @Test + public void testSetClientAddr() { + mParcel.setSingleClientAddr(TEST_CLIENT_ADDRESS); + assertEquals(TEST_CLIENT_ADDRESS_PARCELED, mParcel.clientAddr); + } + private static Inet4Address inet4Addr(String addr) { return (Inet4Address) parseNumericAddress(addr); } diff --git a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringNotificationUpdaterTest.kt b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringNotificationUpdaterTest.kt new file mode 100644 index 000000000000..b86949185c69 --- /dev/null +++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringNotificationUpdaterTest.kt @@ -0,0 +1,262 @@ +/* + * 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 com.android.server.connectivity.tethering + +import android.app.Notification +import android.app.NotificationManager +import android.content.Context +import android.content.res.Resources +import android.net.ConnectivityManager.TETHERING_BLUETOOTH +import android.net.ConnectivityManager.TETHERING_USB +import android.net.ConnectivityManager.TETHERING_WIFI +import android.os.UserHandle +import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.filters.SmallTest +import androidx.test.runner.AndroidJUnit4 +import com.android.internal.util.test.BroadcastInterceptingContext +import com.android.networkstack.tethering.R +import com.android.server.connectivity.tethering.TetheringNotificationUpdater.DOWNSTREAM_NONE +import org.junit.Assert.assertEquals +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.ArgumentCaptor +import org.mockito.ArgumentMatchers.any +import org.mockito.ArgumentMatchers.anyInt +import org.mockito.ArgumentMatchers.eq +import org.mockito.Mock +import org.mockito.Mockito.doReturn +import org.mockito.Mockito.never +import org.mockito.Mockito.reset +import org.mockito.Mockito.times +import org.mockito.Mockito.verifyZeroInteractions +import org.mockito.Mockito.verify +import org.mockito.MockitoAnnotations + +const val TEST_SUBID = 1 +const val WIFI_ICON_ID = 1 +const val USB_ICON_ID = 2 +const val BT_ICON_ID = 3 +const val GENERAL_ICON_ID = 4 +const val WIFI_MASK = 1 shl TETHERING_WIFI +const val USB_MASK = 1 shl TETHERING_USB +const val BT_MASK = 1 shl TETHERING_BLUETOOTH +const val TITTLE = "Tethering active" +const val MESSAGE = "Tap here to set up." +const val TEST_TITTLE = "Hotspot active" +const val TEST_MESSAGE = "Tap to set up hotspot." + +@RunWith(AndroidJUnit4::class) +@SmallTest +class TetheringNotificationUpdaterTest { + // lateinit used here for mocks as they need to be reinitialized between each test and the test + // should crash if they are used before being initialized. + @Mock private lateinit var mockContext: Context + @Mock private lateinit var notificationManager: NotificationManager + @Mock private lateinit var defaultResources: Resources + @Mock private lateinit var testResources: Resources + + // lateinit for this class under test, as it should be reset to a different instance for every + // tests but should always be initialized before use (or the test should crash). + private lateinit var notificationUpdater: TetheringNotificationUpdater + + private val ENABLE_ICON_CONFIGS = arrayOf( + "USB;android.test:drawable/usb", "BT;android.test:drawable/bluetooth", + "WIFI|BT;android.test:drawable/general", "WIFI|USB;android.test:drawable/general", + "USB|BT;android.test:drawable/general", "WIFI|USB|BT;android.test:drawable/general") + + private inner class TestContext(c: Context) : BroadcastInterceptingContext(c) { + override fun createContextAsUser(user: UserHandle, flags: Int) = + if (user == UserHandle.ALL) mockContext else this + } + + private inner class WrappedNotificationUpdater(c: Context) : TetheringNotificationUpdater(c) { + override fun getResourcesForSubId(context: Context, subId: Int) = + if (subId == TEST_SUBID) testResources else defaultResources + } + + private fun setupResources() { + doReturn(ENABLE_ICON_CONFIGS).`when`(defaultResources) + .getStringArray(R.array.tethering_notification_icons) + doReturn(arrayOf("WIFI;android.test:drawable/wifi")).`when`(testResources) + .getStringArray(R.array.tethering_notification_icons) + doReturn(TITTLE).`when`(defaultResources).getString(R.string.tethering_notification_title) + doReturn(MESSAGE).`when`(defaultResources) + .getString(R.string.tethering_notification_message) + doReturn(TEST_TITTLE).`when`(testResources).getString(R.string.tethering_notification_title) + doReturn(TEST_MESSAGE).`when`(testResources) + .getString(R.string.tethering_notification_message) + doReturn(USB_ICON_ID).`when`(defaultResources) + .getIdentifier(eq("android.test:drawable/usb"), any(), any()) + doReturn(BT_ICON_ID).`when`(defaultResources) + .getIdentifier(eq("android.test:drawable/bluetooth"), any(), any()) + doReturn(GENERAL_ICON_ID).`when`(defaultResources) + .getIdentifier(eq("android.test:drawable/general"), any(), any()) + doReturn(WIFI_ICON_ID).`when`(testResources) + .getIdentifier(eq("android.test:drawable/wifi"), any(), any()) + } + + @Before + fun setUp() { + MockitoAnnotations.initMocks(this) + val context = TestContext(InstrumentationRegistry.getInstrumentation().context) + doReturn(notificationManager).`when`(mockContext) + .getSystemService(Context.NOTIFICATION_SERVICE) + notificationUpdater = WrappedNotificationUpdater(context) + setupResources() + } + + private fun Notification.title() = this.extras.getString(Notification.EXTRA_TITLE) + private fun Notification.text() = this.extras.getString(Notification.EXTRA_TEXT) + + private fun verifyNotification(iconId: Int = 0, title: String = "", text: String = "") { + verify(notificationManager, never()).cancel(any(), anyInt()) + + val notificationCaptor = ArgumentCaptor.forClass(Notification::class.java) + verify(notificationManager, times(1)) + .notify(any(), anyInt(), notificationCaptor.capture()) + + val notification = notificationCaptor.getValue() + assertEquals(iconId, notification.smallIcon.resId) + assertEquals(title, notification.title()) + assertEquals(text, notification.text()) + + reset(notificationManager) + } + + private fun verifyNoNotification() { + verify(notificationManager, times(1)).cancel(any(), anyInt()) + verify(notificationManager, never()).notify(any(), anyInt(), any()) + + reset(notificationManager) + } + + @Test + fun testNotificationWithDownstreamChanged() { + // Wifi downstream. No notification. + notificationUpdater.onDownstreamChanged(WIFI_MASK) + verifyNoNotification() + + // Same downstream changed. Nothing happened. + notificationUpdater.onDownstreamChanged(WIFI_MASK) + verifyZeroInteractions(notificationManager) + + // Wifi and usb downstreams. Show enable notification + notificationUpdater.onDownstreamChanged(WIFI_MASK or USB_MASK) + verifyNotification(GENERAL_ICON_ID, TITTLE, MESSAGE) + + // Usb downstream. Still show enable notification. + notificationUpdater.onDownstreamChanged(USB_MASK) + verifyNotification(USB_ICON_ID, TITTLE, MESSAGE) + + // No downstream. No notification. + notificationUpdater.onDownstreamChanged(DOWNSTREAM_NONE) + verifyNoNotification() + } + + @Test + fun testNotificationWithActiveDataSubscriptionIdChanged() { + // Usb downstream. Showed enable notification with default resource. + notificationUpdater.onDownstreamChanged(USB_MASK) + verifyNotification(USB_ICON_ID, TITTLE, MESSAGE) + + // Same subId changed. Nothing happened. + notificationUpdater.onActiveDataSubscriptionIdChanged(INVALID_SUBSCRIPTION_ID) + verifyZeroInteractions(notificationManager) + + // Set test sub id. Clear notification with test resource. + notificationUpdater.onActiveDataSubscriptionIdChanged(TEST_SUBID) + verifyNoNotification() + + // Wifi downstream. Show enable notification with test resource. + notificationUpdater.onDownstreamChanged(WIFI_MASK) + verifyNotification(WIFI_ICON_ID, TEST_TITTLE, TEST_MESSAGE) + + // No downstream. No notification. + notificationUpdater.onDownstreamChanged(DOWNSTREAM_NONE) + verifyNoNotification() + } + + private fun assertIconNumbers(number: Int, configs: Array<String?>) { + doReturn(configs).`when`(defaultResources) + .getStringArray(R.array.tethering_notification_icons) + assertEquals(number, notificationUpdater.getIcons( + R.array.tethering_notification_icons, defaultResources).size()) + } + + @Test + fun testGetIcons() { + assertIconNumbers(0, arrayOfNulls<String>(0)) + assertIconNumbers(0, arrayOf(null, "")) + assertIconNumbers(3, arrayOf( + // These configurations are invalid with wrong strings or symbols. + ";", ",", "|", "|,;", "WIFI", "1;2", " U SB; ", "bt;", "WIFI;USB;BT", "WIFI|USB|BT", + "WIFI,BT,USB", " WIFI| | | USB, test:drawable/test", + // This configuration is valid with two downstream types (USB, BT). + "USB|,,,,,|BT;drawable/test ", + // This configuration is valid with one downstream types (WIFI). + " WIFI ; android.test:drawable/xxx ")) + } + + @Test + fun testGetDownstreamTypesMask() { + assertEquals(DOWNSTREAM_NONE, notificationUpdater.getDownstreamTypesMask("")) + assertEquals(DOWNSTREAM_NONE, notificationUpdater.getDownstreamTypesMask("1")) + assertEquals(DOWNSTREAM_NONE, notificationUpdater.getDownstreamTypesMask("WIFI_P2P")) + assertEquals(DOWNSTREAM_NONE, notificationUpdater.getDownstreamTypesMask("usb")) + assertEquals(WIFI_MASK, notificationUpdater.getDownstreamTypesMask(" WIFI ")) + assertEquals(USB_MASK, notificationUpdater.getDownstreamTypesMask("USB | B T")) + assertEquals(BT_MASK, notificationUpdater.getDownstreamTypesMask(" WIFI: | BT")) + assertEquals(WIFI_MASK or USB_MASK, + notificationUpdater.getDownstreamTypesMask("1|2|USB|WIFI|BLUETOOTH||")) + } + + @Test + fun testSetupRestrictedNotification() { + val title = InstrumentationRegistry.getInstrumentation().context.resources + .getString(R.string.disable_tether_notification_title) + val message = InstrumentationRegistry.getInstrumentation().context.resources + .getString(R.string.disable_tether_notification_message) + val disallowTitle = "Tether function is disallowed" + val disallowMessage = "Please contact your admin" + doReturn(title).`when`(defaultResources) + .getString(R.string.disable_tether_notification_title) + doReturn(message).`when`(defaultResources) + .getString(R.string.disable_tether_notification_message) + doReturn(disallowTitle).`when`(testResources) + .getString(R.string.disable_tether_notification_title) + doReturn(disallowMessage).`when`(testResources) + .getString(R.string.disable_tether_notification_message) + + // User restrictions on. Show restricted notification. + notificationUpdater.notifyTetheringDisabledByRestriction() + verifyNotification(R.drawable.stat_sys_tether_general, title, message) + + // User restrictions off. Clear notification. + notificationUpdater.tetheringRestrictionLifted() + verifyNoNotification() + + // Set test sub id. No notification. + notificationUpdater.onActiveDataSubscriptionIdChanged(TEST_SUBID) + verifyNoNotification() + + // User restrictions on again. Show restricted notification with test resource. + notificationUpdater.notifyTetheringDisabledByRestriction() + verifyNotification(R.drawable.stat_sys_tether_general, disallowTitle, disallowMessage) + } +}
\ No newline at end of file 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 d983fae09be4..a418c4a880d2 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 @@ -38,6 +38,7 @@ import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_FAILED; import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STARTED; import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STOPPED; import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS; +import static android.net.shared.Inet4AddressUtils.intToInet4AddressHTH; import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME; import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE; import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE; @@ -210,7 +211,6 @@ public class TetheringTest { private PhoneStateListener mPhoneStateListener; private InterfaceConfigurationParcel mInterfaceConfiguration; - private class TestContext extends BroadcastInterceptingContext { TestContext(Context base) { super(base); @@ -485,6 +485,7 @@ public class TetheringTest { mServiceContext.registerReceiver(mBroadcastReceiver, new IntentFilter(ACTION_TETHER_STATE_CHANGED)); mTethering = makeTethering(); + mTethering.startStateMachineUpdaters(); verify(mStatsManager, times(1)).registerNetworkStatsProvider(anyString(), any()); verify(mNetd).registerUnsolicitedEventListener(any()); final ArgumentCaptor<PhoneStateListener> phoneListenerCaptor = @@ -1073,13 +1074,15 @@ public class TetheringTest { when(mUserManager.getUserRestrictions()).thenReturn(newRestrictions); final Tethering.UserRestrictionActionListener ural = - new Tethering.UserRestrictionActionListener(mUserManager, mockTethering); + new Tethering.UserRestrictionActionListener( + mUserManager, mockTethering, mNotificationUpdater); ural.mDisallowTethering = currentDisallow; ural.onUserRestrictionsChanged(); - verify(mockTethering, times(expectedInteractionsWithShowNotification)) - .untetherAll(); + verify(mNotificationUpdater, times(expectedInteractionsWithShowNotification)) + .notifyTetheringDisabledByRestriction(); + verify(mockTethering, times(expectedInteractionsWithShowNotification)).untetherAll(); } @Test @@ -1087,7 +1090,7 @@ public class TetheringTest { final String[] emptyActiveIfacesList = new String[]{}; final boolean currDisallow = false; final boolean nextDisallow = true; - final int expectedInteractionsWithShowNotification = 0; + final int expectedInteractionsWithShowNotification = 1; runUserRestrictionsChange(currDisallow, nextDisallow, emptyActiveIfacesList, expectedInteractionsWithShowNotification); @@ -1399,6 +1402,7 @@ public class TetheringTest { mPhoneStateListener.onActiveDataSubscriptionIdChanged(fakeSubId); final TetheringConfiguration newConfig = mTethering.getTetheringConfiguration(); assertEquals(fakeSubId, newConfig.activeDataSubId); + verify(mNotificationUpdater, times(1)).onActiveDataSubscriptionIdChanged(eq(fakeSubId)); } @Test @@ -1651,10 +1655,13 @@ public class TetheringTest { } @Test - public void testRequestStaticServerIp() throws Exception { - final LinkAddress serverLinkAddr = new LinkAddress("192.168.20.1/24"); - final LinkAddress clientLinkAddr = new LinkAddress("192.168.20.42/24"); - final String serverAddr = "192.168.20.1"; + public void testRequestStaticIp() throws Exception { + final LinkAddress serverLinkAddr = new LinkAddress("192.168.0.123/24"); + final LinkAddress clientLinkAddr = new LinkAddress("192.168.0.42/24"); + final String serverAddr = "192.168.0.123"; + final int clientAddrParceled = 0xc0a8002a; + final ArgumentCaptor<DhcpServingParamsParcel> dhcpParamsCaptor = + ArgumentCaptor.forClass(DhcpServingParamsParcel.class); mTethering.startTethering(createTetheringRequestParcel(TETHERING_USB, serverLinkAddr, clientLinkAddr), null); mLooper.dispatchAll(); @@ -1663,8 +1670,12 @@ public class TetheringTest { sendUsbBroadcast(true, true, true, TETHERING_USB); mLooper.dispatchAll(); verify(mNetd).interfaceSetCfg(argThat(cfg -> serverAddr.equals(cfg.ipv4Addr))); - - // TODO: test static client address. + verify(mIpServerDependencies, times(1)).makeDhcpServer(any(), dhcpParamsCaptor.capture(), + any()); + final DhcpServingParamsParcel params = dhcpParamsCaptor.getValue(); + assertEquals(serverAddr, intToInet4AddressHTH(params.serverAddr).getHostAddress()); + assertEquals(24, params.serverAddrPrefixLength); + assertEquals(clientAddrParceled, params.clientAddr); } // TODO: Test that a request for hotspot mode doesn't interfere with an diff --git a/services/Android.bp b/services/Android.bp index 8ebad4efc1b5..90f98e2bd7a6 100644 --- a/services/Android.bp +++ b/services/Android.bp @@ -75,10 +75,6 @@ java_library { "framework-tethering-stubs-module_libs_api", ], - plugins: [ - "compat-changeid-annotation-processor", - ], - // Uncomment to enable output of certain warnings (deprecated, unchecked) //javacflags: ["-Xlint"], @@ -94,8 +90,8 @@ cc_library_shared { } platform_compat_config { - name: "services-platform-compat-config", - src: ":services", + name: "services-platform-compat-config", + src: ":services", } filegroup { @@ -110,6 +106,7 @@ droidstubs { name: "services-stubs.sources", srcs: [":services-sources"], installable: false, + api_tag_name: "SYSTEM_SERVER", args: " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.SYSTEM_SERVER\\)" + " --hide-annotation android.annotation.Hide" + " --hide InternalClasses" + // com.android.* classes are okay in this interface @@ -138,7 +135,8 @@ droidstubs { } java_library { - name: "services-stubs", + name: "android_system_server_stubs_current", srcs: [":services-stubs.sources"], installable: false, + static_libs: ["android_module_lib_stubs_current"], } diff --git a/services/core/Android.bp b/services/core/Android.bp index b7fd227ed0bb..7a3a910c0447 100644 --- a/services/core/Android.bp +++ b/services/core/Android.bp @@ -56,10 +56,6 @@ java_library_static { "dnsresolver_aidl_interface-V2-java", "netd_event_listener_interface-java", ], - - plugins: [ - "compat-changeid-annotation-processor", - ], } java_genrule { diff --git a/services/core/java/com/android/server/AppStateTracker.java b/services/core/java/com/android/server/AppStateTracker.java index 207e007cc62f..ecbf9a48931e 100644 --- a/services/core/java/com/android/server/AppStateTracker.java +++ b/services/core/java/com/android/server/AppStateTracker.java @@ -54,7 +54,6 @@ import com.android.internal.app.IAppOpsCallback; import com.android.internal.app.IAppOpsService; import com.android.internal.util.ArrayUtils; import com.android.internal.util.IndentingPrintWriter; -import com.android.internal.util.Preconditions; import com.android.internal.util.StatLogger; import com.android.server.ForceAppStandbyTrackerProto.ExemptedPackage; import com.android.server.ForceAppStandbyTrackerProto.RunAnyInBackgroundRestrictedPackages; @@ -62,6 +61,7 @@ import com.android.server.ForceAppStandbyTrackerProto.RunAnyInBackgroundRestrict import java.io.PrintWriter; import java.util.Arrays; import java.util.List; +import java.util.Objects; /** * Class to keep track of the information related to "force app standby", which includes: @@ -416,12 +416,12 @@ public class AppStateTracker { } mStarted = true; - mIActivityManager = Preconditions.checkNotNull(injectIActivityManager()); - mActivityManagerInternal = Preconditions.checkNotNull(injectActivityManagerInternal()); - mAppOpsManager = Preconditions.checkNotNull(injectAppOpsManager()); - mAppOpsService = Preconditions.checkNotNull(injectIAppOpsService()); - mPowerManagerInternal = Preconditions.checkNotNull(injectPowerManagerInternal()); - mUsageStatsManagerInternal = Preconditions.checkNotNull( + mIActivityManager = Objects.requireNonNull(injectIActivityManager()); + mActivityManagerInternal = Objects.requireNonNull(injectActivityManagerInternal()); + mAppOpsManager = Objects.requireNonNull(injectAppOpsManager()); + mAppOpsService = Objects.requireNonNull(injectIAppOpsService()); + mPowerManagerInternal = Objects.requireNonNull(injectPowerManagerInternal()); + mUsageStatsManagerInternal = Objects.requireNonNull( injectUsageStatsManagerInternal()); mFlagsObserver = new FeatureFlagsObserver(); diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java index fa8eda54e53c..168c8cd713b6 100644 --- a/services/core/java/com/android/server/BluetoothManagerService.java +++ b/services/core/java/com/android/server/BluetoothManagerService.java @@ -106,9 +106,13 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private static final int USER_SWITCHED_TIME_MS = 200; // Delay for the addProxy function in msec private static final int ADD_PROXY_DELAY_MS = 100; + // Delay for retrying enable and disable in msec + private static final int ENABLE_DISABLE_DELAY_MS = 300; private static final int MESSAGE_ENABLE = 1; private static final int MESSAGE_DISABLE = 2; + private static final int MESSAGE_HANDLE_ENABLE_DELAYED = 3; + private static final int MESSAGE_HANDLE_DISABLE_DELAYED = 4; private static final int MESSAGE_REGISTER_ADAPTER = 20; private static final int MESSAGE_UNREGISTER_ADAPTER = 21; private static final int MESSAGE_REGISTER_STATE_CHANGE_CALLBACK = 30; @@ -130,6 +134,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private static final int RESTORE_SETTING_TO_OFF = 0; private static final int MAX_ERROR_RESTART_RETRIES = 6; + private static final int MAX_WAIT_FOR_ENABLE_DISABLE_RETRIES = 10; // Bluetooth persisted setting is off private static final int BLUETOOTH_OFF = 0; @@ -160,6 +165,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private final ReentrantReadWriteLock mBluetoothLock = new ReentrantReadWriteLock(); private boolean mBinding; private boolean mUnbinding; + private int mWaitForEnableRetry; + private int mWaitForDisableRetry; private BluetoothAirplaneModeListener mBluetoothAirplaneModeListener; @@ -740,13 +747,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } } - public int updateBleAppCount(IBinder token, boolean enable, String packageName) { - // Check if packageName belongs to callingUid - final int callingUid = Binder.getCallingUid(); - final boolean isCallerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; - if (!isCallerSystem) { - checkPackage(callingUid, packageName); - } + private int updateBleAppCount(IBinder token, boolean enable, String packageName) { ClientDeathRecipient r = mBleApps.get(token); if (r == null && enable) { ClientDeathRecipient deathRec = new ClientDeathRecipient(packageName); @@ -771,13 +772,94 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (DBG) { Slog.d(TAG, appCount + " registered Ble Apps"); } - if (appCount == 0 && mEnable) { - disableBleScanMode(); + return appCount; + } + + private boolean checkBluetoothPermissions(String packageName, boolean requireForeground) { + if (isBluetoothDisallowed()) { + if (DBG) { + Slog.d(TAG, "checkBluetoothPermissions: bluetooth disallowed"); + } + return false; } - if (appCount == 0 && !mEnableExternal) { - sendBrEdrDownCallback(); + // Check if packageName belongs to callingUid + final int callingUid = Binder.getCallingUid(); + final boolean isCallerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; + if (!isCallerSystem) { + checkPackage(callingUid, packageName); + + if (requireForeground && !checkIfCallerIsForegroundUser()) { + Slog.w(TAG, "Not allowed for non-active and non system user"); + return false; + } + + mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, + "Need BLUETOOTH ADMIN permission"); } - return appCount; + return true; + } + + public boolean enableBle(String packageName, IBinder token) throws RemoteException { + if (!checkBluetoothPermissions(packageName, false)) { + if (DBG) { + Slog.d(TAG, "enableBle(): bluetooth disallowed"); + } + return false; + } + + if (DBG) { + Slog.d(TAG, "enableBle(" + packageName + "): mBluetooth =" + mBluetooth + + " mBinding = " + mBinding + " mState = " + + BluetoothAdapter.nameForState(mState)); + } + updateBleAppCount(token, true, packageName); + + if (mState == BluetoothAdapter.STATE_ON + || mState == BluetoothAdapter.STATE_BLE_ON + || mState == BluetoothAdapter.STATE_TURNING_ON + || mState == BluetoothAdapter.STATE_TURNING_OFF) { + Log.d(TAG, "enableBLE(): Bluetooth already enabled"); + return true; + } + synchronized (mReceiver) { + // waive WRITE_SECURE_SETTINGS permission check + sendEnableMsg(false, + BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName); + } + return true; + } + + public boolean disableBle(String packageName, IBinder token) throws RemoteException { + if (!checkBluetoothPermissions(packageName, false)) { + if (DBG) { + Slog.d(TAG, "disableBLE(): bluetooth disallowed"); + } + return false; + } + + if (DBG) { + Slog.d(TAG, "disableBle(" + packageName + "): mBluetooth =" + mBluetooth + + " mBinding = " + mBinding + " mState = " + + BluetoothAdapter.nameForState(mState)); + } + + if (mState == BluetoothAdapter.STATE_OFF) { + Slog.d(TAG, "disableBLE(): Already disabled"); + return false; + } + updateBleAppCount(token, false, packageName); + + if (mState == BluetoothAdapter.STATE_BLE_ON && !isBleAppPresent()) { + if (mEnable) { + disableBleScanMode(); + } + if (!mEnableExternal) { + addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, + packageName, false); + sendBrEdrDownCallback(); + } + } + return true; } // Clear all apps using BLE scan only mode. @@ -806,6 +888,13 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Slog.e(TAG, "onBluetoothServiceUp: mBluetooth is null!"); return; } + if (!mEnableExternal && !isBleAppPresent() && isAirplaneModeOn()) { + // Airplane mode is turned on while enabling BLE only mode, disable + // BLE now. + disableBleScanMode(); + sendBrEdrDownCallback(); + return; + } if (isBluetoothPersistedStateOnBluetooth() || !isBleAppPresent()) { // This triggers transition to STATE_ON mBluetooth.onLeServiceUp(); @@ -855,29 +944,19 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } public boolean enableNoAutoConnect(String packageName) { - if (isBluetoothDisallowed()) { + if (!checkBluetoothPermissions(packageName, false)) { if (DBG) { Slog.d(TAG, "enableNoAutoConnect(): not enabling - bluetooth disallowed"); } return false; } - // Check if packageName belongs to callingUid - final int callingUid = Binder.getCallingUid(); - final boolean isCallerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; - if (!isCallerSystem) { - checkPackage(callingUid, packageName); - } - - mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, - "Need BLUETOOTH ADMIN permission"); - if (DBG) { Slog.d(TAG, "enableNoAutoConnect(): mBluetooth =" + mBluetooth + " mBinding = " + mBinding); } - int callingAppId = UserHandle.getAppId(callingUid); + int callingAppId = UserHandle.getAppId(Binder.getCallingUid()); if (callingAppId != Process.NFC_UID) { throw new SecurityException("no permission to enable Bluetooth quietly"); } @@ -892,32 +971,19 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } public boolean enable(String packageName) throws RemoteException { - final int callingUid = Binder.getCallingUid(); - final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; - - if (isBluetoothDisallowed()) { + if (!checkBluetoothPermissions(packageName, true)) { if (DBG) { Slog.d(TAG, "enable(): not enabling - bluetooth disallowed"); } return false; } - if (!callerSystem) { - // Check if packageName belongs to callingUid - checkPackage(callingUid, packageName); - - if (!checkIfCallerIsForegroundUser()) { - Slog.w(TAG, "enable(): not allowed for non-active and non system user"); - return false; - } - - mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, - "Need BLUETOOTH ADMIN permission"); - - if (!isEnabled() && mWirelessConsentRequired && startConsentUiIfNeeded(packageName, - callingUid, BluetoothAdapter.ACTION_REQUEST_ENABLE)) { - return false; - } + final int callingUid = Binder.getCallingUid(); + final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; + if (!callerSystem && !isEnabled() && mWirelessConsentRequired + && startConsentUiIfNeeded(packageName, + callingUid, BluetoothAdapter.ACTION_REQUEST_ENABLE)) { + return false; } if (DBG) { @@ -939,25 +1005,19 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } public boolean disable(String packageName, boolean persist) throws RemoteException { - final int callingUid = Binder.getCallingUid(); - final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; - - if (!callerSystem) { - // Check if packageName belongs to callingUid - checkPackage(callingUid, packageName); - - if (!checkIfCallerIsForegroundUser()) { - Slog.w(TAG, "disable(): not allowed for non-active and non system user"); - return false; + if (!checkBluetoothPermissions(packageName, true)) { + if (DBG) { + Slog.d(TAG, "disable(): not disabling - bluetooth disallowed"); } + return false; + } - mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, - "Need BLUETOOTH ADMIN permission"); - - if (isEnabled() && mWirelessConsentRequired && startConsentUiIfNeeded(packageName, - callingUid, BluetoothAdapter.ACTION_REQUEST_DISABLE)) { - return false; - } + final int callingUid = Binder.getCallingUid(); + final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; + if (!callerSystem && isEnabled() && mWirelessConsentRequired + && startConsentUiIfNeeded(packageName, + callingUid, BluetoothAdapter.ACTION_REQUEST_DISABLE)) { + return false; } if (DBG) { @@ -1597,8 +1657,18 @@ class BluetoothManagerService extends IBluetoothManager.Stub { break; case MESSAGE_ENABLE: + int quietEnable = msg.arg1; + if (mHandler.hasMessages(MESSAGE_HANDLE_DISABLE_DELAYED) + || mHandler.hasMessages(MESSAGE_HANDLE_ENABLE_DELAYED)) { + // We are handling enable or disable right now, wait for it. + mHandler.sendMessageDelayed(mHandler.obtainMessage(MESSAGE_ENABLE, + quietEnable, 0), ENABLE_DISABLE_DELAY_MS); + break; + } + if (DBG) { - Slog.d(TAG, "MESSAGE_ENABLE(" + msg.arg1 + "): mBluetooth = " + mBluetooth); + Slog.d(TAG, "MESSAGE_ENABLE(" + quietEnable + "): mBluetooth = " + + mBluetooth); } mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE); mEnable = true; @@ -1621,7 +1691,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mBluetoothLock.readLock().unlock(); } - mQuietEnable = (msg.arg1 == 1); + mQuietEnable = (quietEnable == 1); if (mBluetooth == null) { handleEnable(mQuietEnable); } else { @@ -1630,7 +1700,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // the previous Bluetooth process has exited. The // waiting period has three components: // (a) Wait until the local state is STATE_OFF. This - // is accomplished by "waitForOnOff(false, true)". + // is accomplished by sending delay a message + // MESSAGE_HANDLE_ENABLE_DELAYED // (b) Wait until the STATE_OFF state is updated to // all components. // (c) Wait until the Bluetooth process exits, and @@ -1640,28 +1711,108 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // message. The delay time is backed off if Bluetooth // continuously failed to turn on itself. // - waitForOnOff(false, true); - Message restartMsg = - mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE); - mHandler.sendMessageDelayed(restartMsg, getServiceRestartMs()); + mWaitForEnableRetry = 0; + Message enableDelayedMsg = + mHandler.obtainMessage(MESSAGE_HANDLE_ENABLE_DELAYED); + mHandler.sendMessageDelayed(enableDelayedMsg, ENABLE_DISABLE_DELAY_MS); } break; case MESSAGE_DISABLE: + if (mHandler.hasMessages(MESSAGE_HANDLE_DISABLE_DELAYED) || mBinding + || mHandler.hasMessages(MESSAGE_HANDLE_ENABLE_DELAYED)) { + // We are handling enable or disable right now, wait for it. + mHandler.sendMessageDelayed(mHandler.obtainMessage(MESSAGE_DISABLE), + ENABLE_DISABLE_DELAY_MS); + break; + } + if (DBG) { - Slog.d(TAG, "MESSAGE_DISABLE: mBluetooth = " + mBluetooth); + Slog.d(TAG, "MESSAGE_DISABLE: mBluetooth = " + mBluetooth + + ", mBinding = " + mBinding); } mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE); + if (mEnable && mBluetooth != null) { - waitForOnOff(true, false); + mWaitForDisableRetry = 0; + Message disableDelayedMsg = + mHandler.obtainMessage(MESSAGE_HANDLE_DISABLE_DELAYED, 0, 0); + mHandler.sendMessageDelayed(disableDelayedMsg, ENABLE_DISABLE_DELAY_MS); + } else { mEnable = false; handleDisable(); - waitForOnOff(false, false); - } else { + } + break; + + case MESSAGE_HANDLE_ENABLE_DELAYED: { + // The Bluetooth is turning off, wait for STATE_OFF + if (mState != BluetoothAdapter.STATE_OFF) { + if (mWaitForEnableRetry < MAX_WAIT_FOR_ENABLE_DISABLE_RETRIES) { + mWaitForEnableRetry++; + Message enableDelayedMsg = + mHandler.obtainMessage(MESSAGE_HANDLE_ENABLE_DELAYED); + mHandler.sendMessageDelayed(enableDelayedMsg, ENABLE_DISABLE_DELAY_MS); + break; + } else { + Slog.e(TAG, "Wait for STATE_OFF timeout"); + } + } + // Either state is changed to STATE_OFF or reaches the maximum retry, we + // should move forward to the next step. + mWaitForEnableRetry = 0; + Message restartMsg = + mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE); + mHandler.sendMessageDelayed(restartMsg, getServiceRestartMs()); + Slog.d(TAG, "Handle enable is finished"); + break; + } + + case MESSAGE_HANDLE_DISABLE_DELAYED: { + boolean disabling = (msg.arg1 == 1); + Slog.d(TAG, "MESSAGE_HANDLE_DISABLE_DELAYED: disabling:" + disabling); + if (!disabling) { + // The Bluetooth is turning on, wait for STATE_ON + if (mState != BluetoothAdapter.STATE_ON) { + if (mWaitForDisableRetry < MAX_WAIT_FOR_ENABLE_DISABLE_RETRIES) { + mWaitForDisableRetry++; + Message disableDelayedMsg = mHandler.obtainMessage( + MESSAGE_HANDLE_DISABLE_DELAYED, 0, 0); + mHandler.sendMessageDelayed(disableDelayedMsg, + ENABLE_DISABLE_DELAY_MS); + break; + } else { + Slog.e(TAG, "Wait for STATE_ON timeout"); + } + } + // Either state is changed to STATE_ON or reaches the maximum retry, we + // should move forward to the next step. + mWaitForDisableRetry = 0; mEnable = false; handleDisable(); + // Wait for state exiting STATE_ON + Message disableDelayedMsg = + mHandler.obtainMessage(MESSAGE_HANDLE_DISABLE_DELAYED, 1, 0); + mHandler.sendMessageDelayed(disableDelayedMsg, ENABLE_DISABLE_DELAY_MS); + } else { + // The Bluetooth is turning off, wait for exiting STATE_ON + if (mState == BluetoothAdapter.STATE_ON) { + if (mWaitForDisableRetry < MAX_WAIT_FOR_ENABLE_DISABLE_RETRIES) { + mWaitForDisableRetry++; + Message disableDelayedMsg = mHandler.obtainMessage( + MESSAGE_HANDLE_DISABLE_DELAYED, 1, 0); + mHandler.sendMessageDelayed(disableDelayedMsg, + ENABLE_DISABLE_DELAY_MS); + break; + } else { + Slog.e(TAG, "Wait for exiting STATE_ON timeout"); + } + } + // Either state is exited from STATE_ON or reaches the maximum retry, we + // should move forward to the next step. + Slog.d(TAG, "Handle disable is finished"); } break; + } case MESSAGE_RESTORE_USER_SETTING: if ((msg.arg1 == RESTORE_SETTING_TO_OFF) && mEnable) { @@ -2031,6 +2182,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { try { mBluetoothLock.writeLock().lock(); if ((mBluetooth == null) && (!mBinding)) { + Slog.d(TAG, "binding Bluetooth service"); //Start bind timeout and bind Message timeoutMsg = mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND); mHandler.sendMessageDelayed(timeoutMsg, TIMEOUT_BIND_MS); @@ -2418,6 +2570,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub { writer.println(" " + app.getPackageName()); } + writer.println("\nBluetoothManagerService:"); + writer.println(" mEnable:" + mEnable); + writer.println(" mQuietEnable:" + mQuietEnable); + writer.println(" mEnableExternal:" + mEnableExternal); + writer.println(" mQuietEnableExternal:" + mQuietEnableExternal); + writer.println(""); writer.flush(); if (args.length == 0) { diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 1ec4bc310546..1484fe7c7c6c 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -40,6 +40,7 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN; import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY; import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; +import static android.net.NetworkCapabilities.TRANSPORT_TEST; import static android.net.NetworkCapabilities.TRANSPORT_VPN; import static android.net.NetworkPolicyManager.RULE_NONE; import static android.net.NetworkPolicyManager.uidRulesToString; @@ -48,10 +49,9 @@ import static android.os.Process.INVALID_UID; import static android.system.OsConstants.IPPROTO_TCP; import static android.system.OsConstants.IPPROTO_UDP; -import static com.android.internal.util.Preconditions.checkNotNull; - import static java.util.Map.Entry; +import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.AppOpsManager; @@ -63,6 +63,7 @@ import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.pm.PackageManager; import android.content.res.Configuration; import android.database.ContentObserver; import android.net.CaptivePortal; @@ -236,7 +237,6 @@ import java.util.SortedSet; import java.util.StringJoiner; import java.util.TreeSet; import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.Function; /** * @hide @@ -928,7 +928,7 @@ public class ConnectivityService extends IConnectivityManager.Stub * @see IpConnectivityMetrics.Logger */ public IpConnectivityMetrics.Logger getMetricsLogger() { - return checkNotNull(LocalServices.getService(IpConnectivityMetrics.Logger.class), + return Objects.requireNonNull(LocalServices.getService(IpConnectivityMetrics.Logger.class), "no IpConnectivityMetrics service"); } @@ -957,10 +957,10 @@ public class ConnectivityService extends IConnectivityManager.Stub IDnsResolver dnsresolver, IpConnectivityLog logger, INetd netd, Dependencies deps) { if (DBG) log("ConnectivityService starting up"); - mDeps = checkNotNull(deps, "missing Dependencies"); + mDeps = Objects.requireNonNull(deps, "missing Dependencies"); mSystemProperties = mDeps.getSystemProperties(); mNetIdManager = mDeps.makeNetIdManager(); - mContext = checkNotNull(context, "missing Context"); + mContext = Objects.requireNonNull(context, "missing Context"); mMetricsLog = logger; mDefaultRequest = createDefaultInternetRequestForTransport(-1, NetworkRequest.Type.REQUEST); @@ -990,13 +990,13 @@ public class ConnectivityService extends IConnectivityManager.Stub mLingerDelayMs = mSystemProperties.getInt(LINGER_DELAY_PROPERTY, DEFAULT_LINGER_DELAY_MS); - mNMS = checkNotNull(netManager, "missing INetworkManagementService"); - mStatsService = checkNotNull(statsService, "missing INetworkStatsService"); - mPolicyManager = checkNotNull(policyManager, "missing INetworkPolicyManager"); - mPolicyManagerInternal = checkNotNull( + mNMS = Objects.requireNonNull(netManager, "missing INetworkManagementService"); + mStatsService = Objects.requireNonNull(statsService, "missing INetworkStatsService"); + mPolicyManager = Objects.requireNonNull(policyManager, "missing INetworkPolicyManager"); + mPolicyManagerInternal = Objects.requireNonNull( LocalServices.getService(NetworkPolicyManagerInternal.class), "missing NetworkPolicyManagerInternal"); - mDnsResolver = checkNotNull(dnsresolver, "missing IDnsResolver"); + mDnsResolver = Objects.requireNonNull(dnsresolver, "missing IDnsResolver"); mProxyTracker = mDeps.makeProxyTracker(mContext, mHandler); mNetd = netd; @@ -2696,10 +2696,18 @@ public class ConnectivityService extends IConnectivityManager.Stub switch (msg.what) { case NetworkAgent.EVENT_NETWORK_CAPABILITIES_CHANGED: { - final NetworkCapabilities networkCapabilities = (NetworkCapabilities) msg.obj; + NetworkCapabilities networkCapabilities = (NetworkCapabilities) msg.obj; if (networkCapabilities.hasConnectivityManagedCapability()) { Slog.wtf(TAG, "BUG: " + nai + " has CS-managed capability."); } + if (networkCapabilities.hasTransport(TRANSPORT_TEST)) { + // Make sure the original object is not mutated. NetworkAgent normally + // makes a copy of the capabilities when sending the message through + // the Messenger, but if this ever changes, not making a defensive copy + // here will give attack vectors to clients using this code path. + networkCapabilities = new NetworkCapabilities(networkCapabilities); + networkCapabilities.restrictCapabilitesForTestNetwork(); + } updateCapabilities(nai.getCurrentScore(), nai, networkCapabilities); break; } @@ -5324,7 +5332,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // specific SSID/SignalStrength, or the calling app has permission to do so. private void ensureSufficientPermissionsForRequest(NetworkCapabilities nc, int callerPid, int callerUid, String callerPackageName) { - if (null != nc.getSSID() && !checkSettingsPermission(callerPid, callerUid)) { + if (null != nc.getSsid() && !checkSettingsPermission(callerPid, callerUid)) { throw new SecurityException("Insufficient permissions to request a specific SSID"); } @@ -5389,12 +5397,25 @@ public class ConnectivityService extends IConnectivityManager.Stub } } + private boolean checkUnsupportedStartingFrom(int version, String callingPackageName) { + final PackageManager pm = mContext.getPackageManager(); + final int userId = UserHandle.getCallingUserId(); + try { + final int callingVersion = pm.getApplicationInfoAsUser( + callingPackageName, 0 /* flags */, userId).targetSdkVersion; + if (callingVersion < version) return false; + } catch (PackageManager.NameNotFoundException e) { } + return true; + } + @Override public NetworkRequest requestNetwork(NetworkCapabilities networkCapabilities, Messenger messenger, int timeoutMs, IBinder binder, int legacyType, @NonNull String callingPackageName) { if (legacyType != TYPE_NONE && !checkNetworkStackPermission()) { - throw new SecurityException("Insufficient permissions to specify legacy type"); + if (checkUnsupportedStartingFrom(Build.VERSION_CODES.M, callingPackageName)) { + throw new SecurityException("Insufficient permissions to specify legacy type"); + } } final int callingUid = Binder.getCallingUid(); final NetworkRequest.Type type = (networkCapabilities == null) @@ -5499,7 +5520,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public NetworkRequest pendingRequestForNetwork(NetworkCapabilities networkCapabilities, PendingIntent operation, @NonNull String callingPackageName) { - checkNotNull(operation, "PendingIntent cannot be null."); + Objects.requireNonNull(operation, "PendingIntent cannot be null."); final int callingUid = Binder.getCallingUid(); networkCapabilities = new NetworkCapabilities(networkCapabilities); enforceNetworkRequestPermissions(networkCapabilities); @@ -5528,7 +5549,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public void releasePendingNetworkRequest(PendingIntent operation) { - checkNotNull(operation, "PendingIntent cannot be null."); + Objects.requireNonNull(operation, "PendingIntent cannot be null."); mHandler.sendMessage(mHandler.obtainMessage(EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT, getCallingUid(), 0, operation)); } @@ -5587,7 +5608,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public void pendingListenForNetwork(NetworkCapabilities networkCapabilities, PendingIntent operation, @NonNull String callingPackageName) { - checkNotNull(operation, "PendingIntent cannot be null."); + Objects.requireNonNull(operation, "PendingIntent cannot be null."); final int callingUid = Binder.getCallingUid(); if (!hasWifiNetworkListenPermission(networkCapabilities)) { enforceAccessPermission(); @@ -5772,7 +5793,16 @@ public class ConnectivityService extends IConnectivityManager.Stub public Network registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo, LinkProperties linkProperties, NetworkCapabilities networkCapabilities, int currentScore, NetworkAgentConfig networkAgentConfig, int providerId) { - enforceNetworkFactoryPermission(); + if (networkCapabilities.hasTransport(TRANSPORT_TEST)) { + enforceAnyPermissionOf(Manifest.permission.MANAGE_TEST_NETWORKS); + // Strictly, sanitizing here is unnecessary as the capabilities will be sanitized in + // the call to mixInCapabilities below anyway, but sanitizing here means the NAI never + // sees capabilities that may be malicious, which might prevent mistakes in the future. + networkCapabilities = new NetworkCapabilities(networkCapabilities); + networkCapabilities.restrictCapabilitesForTestNetwork(); + } else { + enforceNetworkFactoryPermission(); + } LinkProperties lp = new LinkProperties(linkProperties); lp.ensureDirectlyConnectedRoutes(); @@ -5787,7 +5817,7 @@ public class ConnectivityService extends IConnectivityManager.Stub nai.getAndSetNetworkCapabilities(mixInCapabilities(nai, nc)); final String extraInfo = networkInfo.getExtraInfo(); final String name = TextUtils.isEmpty(extraInfo) - ? nai.networkCapabilities.getSSID() : extraInfo; + ? nai.networkCapabilities.getSsid() : extraInfo; if (DBG) log("registerNetworkAgent " + nai); final long token = Binder.clearCallingIdentity(); try { @@ -5982,12 +6012,12 @@ public class ConnectivityService extends IConnectivityManager.Stub * @return true if routes changed between oldLp and newLp */ private boolean updateRoutes(LinkProperties newLp, LinkProperties oldLp, int netId) { - Function<RouteInfo, IpPrefix> getDestination = (r) -> r.getDestination(); // compare the route diff to determine which routes have been updated - CompareOrUpdateResult<IpPrefix, RouteInfo> routeDiff = new CompareOrUpdateResult<>( - oldLp != null ? oldLp.getAllRoutes() : null, - newLp != null ? newLp.getAllRoutes() : null, - getDestination); + final CompareOrUpdateResult<RouteInfo.RouteKey, RouteInfo> routeDiff = + new CompareOrUpdateResult<>( + oldLp != null ? oldLp.getAllRoutes() : null, + newLp != null ? newLp.getAllRoutes() : null, + (r) -> r.getRouteKey()); // add routes before removing old in case it helps with continuous connectivity diff --git a/services/core/java/com/android/server/ExplicitHealthCheckController.java b/services/core/java/com/android/server/ExplicitHealthCheckController.java index f7c4aac2e04f..77059d918052 100644 --- a/services/core/java/com/android/server/ExplicitHealthCheckController.java +++ b/services/core/java/com/android/server/ExplicitHealthCheckController.java @@ -47,6 +47,7 @@ import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; +import java.util.Objects; import java.util.Set; import java.util.function.Consumer; @@ -113,9 +114,9 @@ class ExplicitHealthCheckController { Slog.wtf(TAG, "Resetting health check controller callbacks"); } - mPassedConsumer = Preconditions.checkNotNull(passedConsumer); - mSupportedConsumer = Preconditions.checkNotNull(supportedConsumer); - mNotifySyncRunnable = Preconditions.checkNotNull(notifySyncRunnable); + mPassedConsumer = Objects.requireNonNull(passedConsumer); + mSupportedConsumer = Objects.requireNonNull(supportedConsumer); + mNotifySyncRunnable = Objects.requireNonNull(notifySyncRunnable); } } diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 98ac4cb7122a..905c489e1dcb 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -25,8 +25,6 @@ import static android.system.OsConstants.EINVAL; import static android.system.OsConstants.IPPROTO_UDP; import static android.system.OsConstants.SOCK_DGRAM; -import static com.android.internal.util.Preconditions.checkNotNull; - import android.annotation.NonNull; import android.app.AppOpsManager; import android.content.Context; @@ -48,6 +46,7 @@ import android.net.TrafficStats; import android.net.util.NetdService; import android.os.Binder; import android.os.IBinder; +import android.os.INetworkManagementService; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.os.ServiceSpecificException; @@ -76,6 +75,7 @@ import java.net.InetSocketAddress; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * A service to manage multiple clients that want to access the IpSec API. The service is @@ -115,6 +115,9 @@ public class IpSecService extends IIpSecService.Stub { /* Binder context for this service */ private final Context mContext; + /* NetworkManager instance */ + private final INetworkManagementService mNetworkManager; + /** * The next non-repeating global ID for tracking resources between users, this service, and * kernel data structures. Accessing this variable is not thread safe, so it is only read or @@ -360,10 +363,14 @@ public class IpSecService extends IIpSecService.Stub { @VisibleForTesting static final class UserRecord { /* Maximum number of each type of resource that a single UID may possess */ - public static final int MAX_NUM_TUNNEL_INTERFACES = 2; - public static final int MAX_NUM_ENCAP_SOCKETS = 2; - public static final int MAX_NUM_TRANSFORMS = 4; - public static final int MAX_NUM_SPIS = 8; + + // Up to 4 active VPNs/IWLAN with potential soft handover. + public static final int MAX_NUM_TUNNEL_INTERFACES = 8; + public static final int MAX_NUM_ENCAP_SOCKETS = 16; + + // SPIs and Transforms are both cheap, and are 1:1 correlated. + public static final int MAX_NUM_TRANSFORMS = 64; + public static final int MAX_NUM_SPIS = 64; /** * Store each of the OwnedResource types in an (thinly wrapped) sparse array for indexing @@ -566,7 +573,7 @@ public class IpSecService extends IIpSecService.Stub { } void put(int key, RefcountedResource<T> obj) { - checkNotNull(obj, "Null resources cannot be added"); + Objects.requireNonNull(obj, "Null resources cannot be added"); mArray.put(key, obj); } @@ -989,12 +996,13 @@ public class IpSecService extends IIpSecService.Stub { * * @param context Binder context for this service */ - private IpSecService(Context context) { - this(context, IpSecServiceConfiguration.GETSRVINSTANCE); + private IpSecService(Context context, INetworkManagementService networkManager) { + this(context, networkManager, IpSecServiceConfiguration.GETSRVINSTANCE); } - static IpSecService create(Context context) throws InterruptedException { - final IpSecService service = new IpSecService(context); + static IpSecService create(Context context, INetworkManagementService networkManager) + throws InterruptedException { + final IpSecService service = new IpSecService(context, networkManager); service.connectNativeNetdService(); return service; } @@ -1008,9 +1016,11 @@ public class IpSecService extends IIpSecService.Stub { /** @hide */ @VisibleForTesting - public IpSecService(Context context, IpSecServiceConfiguration config) { + public IpSecService(Context context, INetworkManagementService networkManager, + IpSecServiceConfiguration config) { this( context, + networkManager, config, (fd, uid) -> { try { @@ -1024,9 +1034,10 @@ public class IpSecService extends IIpSecService.Stub { /** @hide */ @VisibleForTesting - public IpSecService( - Context context, IpSecServiceConfiguration config, UidFdTagger uidFdTagger) { + public IpSecService(Context context, INetworkManagementService networkManager, + IpSecServiceConfiguration config, UidFdTagger uidFdTagger) { mContext = context; + mNetworkManager = Objects.requireNonNull(networkManager); mSrvConfig = config; mUidFdTagger = uidFdTagger; } @@ -1101,7 +1112,7 @@ public class IpSecService extends IIpSecService.Stub { if (requestedSpi > 0 && requestedSpi < 256) { throw new IllegalArgumentException("ESP SPI must not be in the range of 0-255."); } - checkNotNull(binder, "Null Binder passed to allocateSecurityParameterIndex"); + Objects.requireNonNull(binder, "Null Binder passed to allocateSecurityParameterIndex"); int callingUid = Binder.getCallingUid(); UserRecord userRecord = mUserResourceTracker.getUserRecord(callingUid); @@ -1218,7 +1229,7 @@ public class IpSecService extends IIpSecService.Stub { throw new IllegalArgumentException( "Specified port number must be a valid non-reserved UDP port"); } - checkNotNull(binder, "Null Binder passed to openUdpEncapsulationSocket"); + Objects.requireNonNull(binder, "Null Binder passed to openUdpEncapsulationSocket"); int callingUid = Binder.getCallingUid(); UserRecord userRecord = mUserResourceTracker.getUserRecord(callingUid); @@ -1278,8 +1289,8 @@ public class IpSecService extends IIpSecService.Stub { String localAddr, String remoteAddr, Network underlyingNetwork, IBinder binder, String callingPackage) { enforceTunnelFeatureAndPermissions(callingPackage); - checkNotNull(binder, "Null Binder passed to createTunnelInterface"); - checkNotNull(underlyingNetwork, "No underlying network was specified"); + Objects.requireNonNull(binder, "Null Binder passed to createTunnelInterface"); + Objects.requireNonNull(underlyingNetwork, "No underlying network was specified"); checkInetAddress(localAddr); checkInetAddress(remoteAddr); @@ -1305,6 +1316,10 @@ public class IpSecService extends IIpSecService.Stub { final INetd netd = mSrvConfig.getNetdInstance(); netd.ipSecAddTunnelInterface(intfName, localAddr, remoteAddr, ikey, okey, resourceId); + Binder.withCleanCallingIdentity(() -> { + mNetworkManager.setInterfaceUp(intfName); + }); + for (int selAddrFamily : ADDRESS_FAMILIES) { // Always send down correct local/remote addresses for template. netd.ipSecAddSecurityPolicy( @@ -1556,7 +1571,7 @@ public class IpSecService extends IIpSecService.Stub { "IPsec Tunnel Mode requires PackageManager.FEATURE_IPSEC_TUNNELS"); } - checkNotNull(callingPackage, "Null calling package cannot create IpSec tunnels"); + Objects.requireNonNull(callingPackage, "Null calling package cannot create IpSec tunnels"); // OP_MANAGE_IPSEC_TUNNELS will return MODE_ERRORED by default, including for the system // server. If the appop is not granted, require that the caller has the MANAGE_IPSEC_TUNNELS @@ -1625,12 +1640,12 @@ public class IpSecService extends IIpSecService.Stub { @Override public synchronized IpSecTransformResponse createTransform( IpSecConfig c, IBinder binder, String callingPackage) throws RemoteException { - checkNotNull(c); + Objects.requireNonNull(c); if (c.getMode() == IpSecTransform.MODE_TUNNEL) { enforceTunnelFeatureAndPermissions(callingPackage); } checkIpSecConfig(c); - checkNotNull(binder, "Null Binder passed to createTransform"); + Objects.requireNonNull(binder, "Null Binder passed to createTransform"); final int resourceId = mNextResourceId++; UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java index 90e467034e6a..f4b769f5b11b 100644 --- a/services/core/java/com/android/server/LocationManagerService.java +++ b/services/core/java/com/android/server/LocationManagerService.java @@ -25,7 +25,6 @@ import static android.location.LocationProvider.AVAILABLE; import static android.os.PowerManager.locationPowerSaveModeToString; import static android.provider.Settings.Global.LOCATION_DISABLE_STATUS_CALLBACKS; -import static com.android.internal.util.Preconditions.checkNotNull; import static com.android.internal.util.Preconditions.checkState; import android.Manifest; @@ -133,6 +132,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Objects; import java.util.NoSuchElementException; import java.util.function.Consumer; import java.util.function.Function; @@ -986,7 +986,7 @@ public class LocationManagerService extends ILocationManager.Stub { @GuardedBy("mLock") public void attachLocked(AbstractLocationProvider provider) { - checkNotNull(provider); + Objects.requireNonNull(provider); checkState(mProvider == null); if (D) { diff --git a/services/core/java/com/android/server/NativeDaemonConnector.java b/services/core/java/com/android/server/NativeDaemonConnector.java index ad02aad6e4cd..eac767f7355c 100644 --- a/services/core/java/com/android/server/NativeDaemonConnector.java +++ b/services/core/java/com/android/server/NativeDaemonConnector.java @@ -46,6 +46,7 @@ import java.util.concurrent.BlockingQueue; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.LinkedList; +import java.util.Objects; /** * Generic connector class for interfacing with a native daemon which uses the @@ -126,7 +127,7 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo */ public void setWarnIfHeld(Object warnIfHeld) { Preconditions.checkState(mWarnIfHeld == null); - mWarnIfHeld = Preconditions.checkNotNull(warnIfHeld); + mWarnIfHeld = Objects.requireNonNull(warnIfHeld); } @Override diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java index 7d6ae21a830b..1bb3c3ac0cda 100644 --- a/services/core/java/com/android/server/NetworkManagementService.java +++ b/services/core/java/com/android/server/NetworkManagementService.java @@ -111,6 +111,7 @@ import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; /** * @hide @@ -458,7 +459,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub { @Override public void registerTetheringStatsProvider(ITetheringStatsProvider provider, String name) { NetworkStack.checkNetworkStackPermission(mContext); - Preconditions.checkNotNull(provider); + Objects.requireNonNull(provider); synchronized(mTetheringStatsProviders) { mTetheringStatsProviders.put(provider, name); } diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java index 39ad3546e452..ba1d8ac31bc4 100644 --- a/services/core/java/com/android/server/StorageManagerService.java +++ b/services/core/java/com/android/server/StorageManagerService.java @@ -1934,7 +1934,7 @@ class StorageManagerService extends IStorageManager.Stub public void setVolumeNickname(String fsUuid, String nickname) { enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); - Preconditions.checkNotNull(fsUuid); + Objects.requireNonNull(fsUuid); synchronized (mLock) { final VolumeRecord rec = mRecords.get(fsUuid); rec.nickname = nickname; @@ -1947,7 +1947,7 @@ class StorageManagerService extends IStorageManager.Stub public void setVolumeUserFlags(String fsUuid, int flags, int mask) { enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); - Preconditions.checkNotNull(fsUuid); + Objects.requireNonNull(fsUuid); synchronized (mLock) { final VolumeRecord rec = mRecords.get(fsUuid); rec.userFlags = (rec.userFlags & ~mask) | (flags & mask); @@ -1960,7 +1960,7 @@ class StorageManagerService extends IStorageManager.Stub public void forgetVolume(String fsUuid) { enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); - Preconditions.checkNotNull(fsUuid); + Objects.requireNonNull(fsUuid); synchronized (mLock) { final VolumeRecord rec = mRecords.remove(fsUuid); @@ -2361,7 +2361,7 @@ class StorageManagerService extends IStorageManager.Stub @Override public String getMountedObbPath(String rawPath) { - Preconditions.checkNotNull(rawPath, "rawPath cannot be null"); + Objects.requireNonNull(rawPath, "rawPath cannot be null"); warnOnNotMounted(); @@ -2379,7 +2379,7 @@ class StorageManagerService extends IStorageManager.Stub @Override public boolean isObbMounted(String rawPath) { - Preconditions.checkNotNull(rawPath, "rawPath cannot be null"); + Objects.requireNonNull(rawPath, "rawPath cannot be null"); synchronized (mObbMounts) { return mObbPathToStateMap.containsKey(rawPath); } @@ -2388,10 +2388,10 @@ class StorageManagerService extends IStorageManager.Stub @Override public void mountObb(String rawPath, String canonicalPath, String key, IObbActionListener token, int nonce, ObbInfo obbInfo) { - Preconditions.checkNotNull(rawPath, "rawPath cannot be null"); - Preconditions.checkNotNull(canonicalPath, "canonicalPath cannot be null"); - Preconditions.checkNotNull(token, "token cannot be null"); - Preconditions.checkNotNull(obbInfo, "obbIfno cannot be null"); + Objects.requireNonNull(rawPath, "rawPath cannot be null"); + Objects.requireNonNull(canonicalPath, "canonicalPath cannot be null"); + Objects.requireNonNull(token, "token cannot be null"); + Objects.requireNonNull(obbInfo, "obbIfno cannot be null"); final int callingUid = Binder.getCallingUid(); final ObbState obbState = new ObbState(rawPath, canonicalPath, @@ -2405,7 +2405,7 @@ class StorageManagerService extends IStorageManager.Stub @Override public void unmountObb(String rawPath, boolean force, IObbActionListener token, int nonce) { - Preconditions.checkNotNull(rawPath, "rawPath cannot be null"); + Objects.requireNonNull(rawPath, "rawPath cannot be null"); final ObbState existingState; synchronized (mObbMounts) { diff --git a/services/core/java/com/android/server/SystemServerInitThreadPool.java b/services/core/java/com/android/server/SystemServerInitThreadPool.java index ff6a5375565a..ba829381b9d4 100644 --- a/services/core/java/com/android/server/SystemServerInitThreadPool.java +++ b/services/core/java/com/android/server/SystemServerInitThreadPool.java @@ -26,6 +26,7 @@ import com.android.server.am.ActivityManagerService; import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java index 45868932be2b..ac897e464659 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -168,14 +168,13 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { @Override public String toString() { - return "{callingPackage=" + callingPackage + " binder=" + binder - + " callback=" + callback + return "{callingPackage=" + pii(callingPackage) + " callerUid=" + callerUid + " binder=" + + binder + " callback=" + callback + " onSubscriptionsChangedListenererCallback=" + onSubscriptionsChangedListenerCallback + " onOpportunisticSubscriptionsChangedListenererCallback=" - + onOpportunisticSubscriptionsChangedListenerCallback - + " callerUid=" + callerUid + " subId=" + subId + " phoneId=" + phoneId - + " events=" + Integer.toHexString(events) + "}"; + + onOpportunisticSubscriptionsChangedListenerCallback + " subId=" + subId + + " phoneId=" + phoneId + " events=" + Integer.toHexString(events) + "}"; } } @@ -598,9 +597,9 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { int callerUserId = UserHandle.getCallingUserId(); mAppOps.checkPackage(Binder.getCallingUid(), callingPackage); if (VDBG) { - log("listen oscl: E pkg=" + callingPackage + " myUserId=" + UserHandle.myUserId() - + " callerUserId=" + callerUserId + " callback=" + callback - + " callback.asBinder=" + callback.asBinder()); + log("listen oscl: E pkg=" + pii(callingPackage) + " uid=" + Binder.getCallingUid() + + " myUserId=" + UserHandle.myUserId() + " callerUserId=" + callerUserId + + " callback=" + callback + " callback.asBinder=" + callback.asBinder()); } synchronized (mRecords) { @@ -652,9 +651,9 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { int callerUserId = UserHandle.getCallingUserId(); mAppOps.checkPackage(Binder.getCallingUid(), callingPackage); if (VDBG) { - log("listen ooscl: E pkg=" + callingPackage + " myUserId=" + UserHandle.myUserId() - + " callerUserId=" + callerUserId + " callback=" + callback - + " callback.asBinder=" + callback.asBinder()); + log("listen ooscl: E pkg=" + pii(callingPackage) + " uid=" + Binder.getCallingUid() + + " myUserId=" + UserHandle.myUserId() + " callerUserId=" + callerUserId + + " callback=" + callback + " callback.asBinder=" + callback.asBinder()); } synchronized (mRecords) { @@ -769,9 +768,9 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { IPhoneStateListener callback, int events, boolean notifyNow, int subId) { int callerUserId = UserHandle.getCallingUserId(); mAppOps.checkPackage(Binder.getCallingUid(), callingPackage); - String str = "listen: E pkg=" + callingPackage + " events=0x" + Integer.toHexString(events) - + " notifyNow=" + notifyNow + " subId=" + subId + " myUserId=" - + UserHandle.myUserId() + " callerUserId=" + callerUserId; + String str = "listen: E pkg=" + pii(callingPackage) + " uid=" + Binder.getCallingUid() + + " events=0x" + Integer.toHexString(events) + " notifyNow=" + notifyNow + " subId=" + + subId + " myUserId=" + UserHandle.myUserId() + " callerUserId=" + callerUserId; mListenLog.log(str); if (VDBG) { log(str); @@ -1538,17 +1537,15 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } synchronized (mRecords) { if (validatePhoneId(phoneId)) { - if (mDisplayInfos[phoneId] != null) { - mDisplayInfos[phoneId] = displayInfo; - for (Record r : mRecords) { - if (r.matchPhoneStateListenerEvent( - PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED) - && idMatch(r.subId, subId, phoneId)) { - try { - r.callback.onDisplayInfoChanged(displayInfo); - } catch (RemoteException ex) { - mRemoveList.add(r.binder); - } + mDisplayInfos[phoneId] = displayInfo; + for (Record r : mRecords) { + if (r.matchPhoneStateListenerEvent( + PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED) + && idMatch(r.subId, subId, phoneId)) { + try { + r.callback.onDisplayInfoChanged(displayInfo); + } catch (RemoteException ex) { + mRemoveList.add(r.binder); } } } @@ -2937,4 +2934,14 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { if (info == null) return INVALID_SIM_SLOT_INDEX; return info.getSimSlotIndex(); } + + /** + * On certain build types, we should redact information by default. UID information will be + * preserved in the same log line, so no debugging capability is lost in full bug reports. + * However, privacy-constrained bug report types (e.g. connectivity) cannot display raw + * package names on user builds as it's considered an information leak. + */ + private static String pii(String packageName) { + return Build.IS_DEBUGGABLE ? packageName : "***"; + } } diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java index 454941ccdb03..5f9d1d801441 100644 --- a/services/core/java/com/android/server/Watchdog.java +++ b/services/core/java/com/android/server/Watchdog.java @@ -115,6 +115,7 @@ public class Watchdog extends Thread { "android.hardware.media.c2@1.0::IComponentStore", "android.hardware.media.omx@1.0::IOmx", "android.hardware.media.omx@1.0::IOmxStore", + "android.hardware.neuralnetworks@1.0::IDevice", "android.hardware.power.stats@1.0::IPowerStats", "android.hardware.sensors@1.0::ISensors", "android.hardware.vr@1.0::IVr", diff --git a/services/core/java/com/android/server/accounts/TokenCache.java b/services/core/java/com/android/server/accounts/TokenCache.java index 2af2f38d8ba7..2aa9776fcab1 100644 --- a/services/core/java/com/android/server/accounts/TokenCache.java +++ b/services/core/java/com/android/server/accounts/TokenCache.java @@ -148,7 +148,7 @@ import java.util.Objects; accountEvictor = new Evictor(); } accountEvictor.add(k); - mAccountEvictors.put(k.account, tokenEvictor); + mAccountEvictors.put(k.account, accountEvictor); // Only cache the token once we can remove it directly or by account. put(k, v); diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java index d935162a629b..f5cefb3ff1ea 100644 --- a/services/core/java/com/android/server/am/ProcessList.java +++ b/services/core/java/com/android/server/am/ProcessList.java @@ -106,7 +106,6 @@ import com.android.server.pm.dex.DexManager; import com.android.server.wm.ActivityServiceConnectionsHolder; import com.android.server.wm.WindowManagerService; -import dalvik.annotation.compat.VersionCodes; import dalvik.system.VMRuntime; import java.io.File; @@ -290,7 +289,7 @@ public final class ProcessList { * Pointers</a> */ @ChangeId - @EnabledAfter(targetSdkVersion = VersionCodes.Q) + @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.Q) private static final long NATIVE_HEAP_POINTER_TAGGING = 135754954; // This is a bug id. ActivityManagerService mService = null; diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index e5cd783f2047..fc6d9f7b7849 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -4318,6 +4318,7 @@ public class AudioService extends IAudioService.Stub public void setWiredDeviceConnectionState(int type, @ConnectionState int state, String address, String name, String caller) { + enforceModifyAudioRoutingPermission(); if (state != CONNECTION_STATE_CONNECTED && state != CONNECTION_STATE_DISCONNECTED) { throw new IllegalArgumentException("Invalid state " + state); diff --git a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java index 5059a4861a7b..7c8fb5aefd1e 100644 --- a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java +++ b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java @@ -220,9 +220,9 @@ public class KeepaliveTracker { + " network=" + mNai.network + " startedState=" + startedStateString(mStartedState) + " " - + IpUtils.addressAndPortToString(mPacket.srcAddress, mPacket.srcPort) + + IpUtils.addressAndPortToString(mPacket.getSrcAddress(), mPacket.getSrcPort()) + "->" - + IpUtils.addressAndPortToString(mPacket.dstAddress, mPacket.dstPort) + + IpUtils.addressAndPortToString(mPacket.getDstAddress(), mPacket.getDstPort()) + " interval=" + mInterval + " uid=" + mUid + " pid=" + mPid + " privileged=" + mPrivileged + " packetData=" + HexDump.toHexString(mPacket.getPacket()) @@ -250,7 +250,7 @@ public class KeepaliveTracker { private int checkSourceAddress() { // Check that we have the source address. for (InetAddress address : mNai.linkProperties.getAddresses()) { - if (address.equals(mPacket.srcAddress)) { + if (address.equals(mPacket.getSrcAddress())) { return SUCCESS; } } @@ -619,7 +619,7 @@ public class KeepaliveTracker { packet = NattKeepalivePacketData.nattKeepalivePacket( srcAddress, srcPort, dstAddress, NATT_PORT); } catch (InvalidPacketException e) { - notifyErrorCallback(cb, e.error); + notifyErrorCallback(cb, e.getError()); return; } KeepaliveInfo ki = null; @@ -662,7 +662,7 @@ public class KeepaliveTracker { notifyErrorCallback(cb, e.error); return; } catch (InvalidPacketException e) { - notifyErrorCallback(cb, e.error); + notifyErrorCallback(cb, e.getError()); return; } KeepaliveInfo ki = null; diff --git a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java index 0925de8f9577..34b0aa246433 100644 --- a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java +++ b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java @@ -150,7 +150,7 @@ public class NetworkNotificationManager { if (nai != null) { transportType = approximateTransportType(nai); final String extraInfo = nai.networkInfo.getExtraInfo(); - name = TextUtils.isEmpty(extraInfo) ? nai.networkCapabilities.getSSID() : extraInfo; + name = TextUtils.isEmpty(extraInfo) ? nai.networkCapabilities.getSsid() : extraInfo; // Only notify for Internet-capable networks. if (!nai.networkCapabilities.hasCapability(NET_CAPABILITY_INTERNET)) return; } else { @@ -183,14 +183,14 @@ public class NetworkNotificationManager { int icon = getIcon(transportType); if (notifyType == NotificationType.NO_INTERNET && transportType == TRANSPORT_WIFI) { title = r.getString(R.string.wifi_no_internet, - WifiInfo.sanitizeSsid(nai.networkCapabilities.getSSID())); + WifiInfo.sanitizeSsid(nai.networkCapabilities.getSsid())); details = r.getString(R.string.wifi_no_internet_detailed); } else if (notifyType == NotificationType.PRIVATE_DNS_BROKEN) { if (transportType == TRANSPORT_CELLULAR) { title = r.getString(R.string.mobile_no_internet); } else if (transportType == TRANSPORT_WIFI) { title = r.getString(R.string.wifi_no_internet, - WifiInfo.sanitizeSsid(nai.networkCapabilities.getSSID())); + WifiInfo.sanitizeSsid(nai.networkCapabilities.getSsid())); } else { title = r.getString(R.string.other_networks_no_internet); } @@ -198,19 +198,19 @@ public class NetworkNotificationManager { } else if (notifyType == NotificationType.PARTIAL_CONNECTIVITY && transportType == TRANSPORT_WIFI) { title = r.getString(R.string.network_partial_connectivity, - WifiInfo.sanitizeSsid(nai.networkCapabilities.getSSID())); + WifiInfo.sanitizeSsid(nai.networkCapabilities.getSsid())); details = r.getString(R.string.network_partial_connectivity_detailed); } else if (notifyType == NotificationType.LOST_INTERNET && transportType == TRANSPORT_WIFI) { title = r.getString(R.string.wifi_no_internet, - WifiInfo.sanitizeSsid(nai.networkCapabilities.getSSID())); + WifiInfo.sanitizeSsid(nai.networkCapabilities.getSsid())); details = r.getString(R.string.wifi_no_internet_detailed); } else if (notifyType == NotificationType.SIGN_IN) { switch (transportType) { case TRANSPORT_WIFI: title = r.getString(R.string.wifi_available_sign_in, 0); details = r.getString(R.string.network_available_sign_in_detailed, - WifiInfo.sanitizeSsid(nai.networkCapabilities.getSSID())); + WifiInfo.sanitizeSsid(nai.networkCapabilities.getSsid())); break; case TRANSPORT_CELLULAR: title = r.getString(R.string.network_available_sign_in, 0); diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index 0392807bcb37..22ed661b03c0 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -3091,31 +3091,64 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { private void enforceSubscriptionPlanValidity(SubscriptionPlan[] plans) { // nothing to check if no plans if (plans.length == 0) { + Log.d(TAG, "Received empty plans list. Clearing existing SubscriptionPlans."); return; } - long applicableNetworkTypes = 0; - boolean allNetworks = false; - for (SubscriptionPlan plan : plans) { - if (plan.getNetworkTypes() == null) { - allNetworks = true; + final int[] allNetworkTypes = TelephonyManager.getAllNetworkTypes(); + final ArraySet<Integer> allNetworksSet = new ArraySet<>(); + addAll(allNetworksSet, allNetworkTypes); + + final ArraySet<Integer> applicableNetworkTypes = new ArraySet<>(); + boolean hasGeneralPlan = false; + for (int i = 0; i < plans.length; i++) { + final int[] planNetworkTypes = plans[i].getNetworkTypes(); + final ArraySet<Integer> planNetworksSet = new ArraySet<>(); + for (int j = 0; j < planNetworkTypes.length; j++) { + // ensure all network types are valid + if (allNetworksSet.contains(planNetworkTypes[j])) { + // ensure no duplicate network types in the same SubscriptionPlan + if (!planNetworksSet.add(planNetworkTypes[j])) { + throw new IllegalArgumentException( + "Subscription plan contains duplicate network types."); + } + } else { + throw new IllegalArgumentException("Invalid network type: " + + planNetworkTypes[j]); + } + } + + if (planNetworkTypes.length == allNetworkTypes.length) { + hasGeneralPlan = true; } else { - if ((applicableNetworkTypes & plan.getNetworkTypesBitMask()) != 0) { + // ensure no network type applies to multiple plans + if (!addAll(applicableNetworkTypes, planNetworkTypes)) { throw new IllegalArgumentException( "Multiple subscription plans defined for a single network type."); - } else { - applicableNetworkTypes |= plan.getNetworkTypesBitMask(); } } } // ensure at least one plan applies for every network type - if (!allNetworks) { + if (!hasGeneralPlan) { throw new IllegalArgumentException( "No generic subscription plan that applies to all network types."); } } + /** + * Adds all of the {@code elements} to the {@code set}. + * + * @return {@code false} if any element is not added because the set already has the value. + */ + private static boolean addAll(@NonNull ArraySet<Integer> set, @NonNull int... elements) { + boolean result = true; + for (int i = 0; i < elements.length; i++) { + result &= set.add(elements[i]); + } + return result; + } + @Override public SubscriptionPlan[] getSubscriptionPlans(int subId, String callingPackage) { enforceSubscriptionPlanAccess(subId, Binder.getCallingUid(), callingPackage); diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java index ebc41916d034..0e3268b8b9f2 100644 --- a/services/core/java/com/android/server/notification/ZenModeHelper.java +++ b/services/core/java/com/android/server/notification/ZenModeHelper.java @@ -844,13 +844,13 @@ public class ZenModeHelper { final boolean policyChanged = !Objects.equals(getNotificationPolicy(mConfig), getNotificationPolicy(config)); if (!config.equals(mConfig)) { + mConfig = config; dispatchOnConfigChanged(); updateConsolidatedPolicy(reason); } if (policyChanged) { dispatchOnPolicyChanged(); } - mConfig = config; mHandler.postApplyConfig(config, reason, triggeringComponent, setRingerMode); return true; } catch (SecurityException e) { diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index d0167c58df9f..6f6c3152fb9d 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -1090,19 +1090,6 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { assertMultiPackageConsistencyLocked(childSessions); } - if (params.isStaged) { - final PackageInstallerSession activeSession = mStagingManager.getActiveSession(); - final boolean anotherSessionAlreadyInProgress = - activeSession != null && sessionId != activeSession.sessionId - && mParentSessionId != activeSession.sessionId; - if (anotherSessionAlreadyInProgress) { - throw new PackageManagerException( - PackageManager.INSTALL_FAILED_OTHER_STAGED_SESSION_IN_PROGRESS, - "There is already in-progress committed staged session " - + activeSession.sessionId, null); - } - } - // Read transfers from the original owner stay open, but as the session's data // cannot be modified anymore, there is no leak of information. For staged sessions, // further validation is performed by the staging manager. @@ -1125,6 +1112,10 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { throw new PackageManagerException(e); } } + + if (params.isStaged) { + mStagingManager.checkNonOverlappingWithStagedSessions(this); + } } catch (PackageManagerException e) { // Session is sealed but could not be verified, we need to destroy it. destroyInternal(); @@ -1449,7 +1440,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { /** * Validate apex install. * <p> - * Sets {@link #mResolvedBaseFile} for RollbackManager to use. + * Sets {@link #mResolvedBaseFile} for RollbackManager to use. Sets {@link #mPackageName} for + * StagingManager to use. */ @GuardedBy("mLock") private void validateApexInstallLocked() @@ -1478,8 +1470,22 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { final File targetFile = new File(stageDir, targetName); resolveAndStageFile(addedFile, targetFile); - mResolvedBaseFile = targetFile; + + // Populate package name of the apex session + mPackageName = null; + final ApkLite apk; + try { + apk = PackageParser.parseApkLite( + mResolvedBaseFile, PackageParser.PARSE_COLLECT_CERTIFICATES); + } catch (PackageParserException e) { + throw PackageManagerException.from(e); + } + + if (mPackageName == null) { + mPackageName = apk.packageName; + mVersionCode = apk.getLongVersionCode(); + } } /** @@ -1848,6 +1854,15 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } /** + * @return the package name of this session + */ + String getPackageName() { + synchronized (mLock) { + return mPackageName; + } + } + + /** * @return the timestamp of when this session last changed state */ public long getUpdatedMillis() { diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java index 15e2fd579cc4..96ccba5b4d6f 100644 --- a/services/core/java/com/android/server/pm/StagingManager.java +++ b/services/core/java/com/android/server/pm/StagingManager.java @@ -539,25 +539,95 @@ public class StagingManager { mPreRebootVerificationHandler.startPreRebootVerification(session.sessionId); } - @Nullable - PackageInstallerSession getActiveSession() { + /** + * <p> Check if the session provided is non-overlapping with the active staged sessions. + * + * <p> A session is non-overlapping if it meets one of the following conditions: </p> + * <ul> + * <li>It is a parent session</li> + * <li>It is already one of the active sessions</li> + * <li>Its package name is not same as any of the active sessions</li> + * </ul> + * @throws PackageManagerException if session fails the check + */ + void checkNonOverlappingWithStagedSessions(@NonNull PackageInstallerSession session) + throws PackageManagerException { + if (session.isMultiPackage()) { + // We cannot say a parent session overlaps until we process its children + return; + } + if (session.getPackageName() == null) { + throw new PackageManagerException(PackageManager.INSTALL_FAILED_INVALID_APK, + "Cannot stage session " + session.sessionId + " with package name null"); + } + synchronized (mStagedSessions) { for (int i = 0; i < mStagedSessions.size(); i++) { - final PackageInstallerSession session = mStagedSessions.valueAt(i); - if (!session.isCommitted()) { + final PackageInstallerSession stagedSession = mStagedSessions.valueAt(i); + if (!stagedSession.isCommitted() || stagedSession.isStagedAndInTerminalState()) { continue; } - if (session.hasParentSessionId()) { - // Staging manager will finalize only parent session. Ignore child sessions - // picking the active. + if (stagedSession.isMultiPackage()) { + // This active parent staged session is useless as it doesn't have a package + // name and the session we are checking is not a parent session either. + continue; + } + + // From here on, stagedSession is a non-parent active staged session + + // Check if stagedSession has an active parent session or not + if (stagedSession.hasParentSessionId()) { + int parentId = stagedSession.getParentSessionId(); + PackageInstallerSession parentSession = mStagedSessions.get(parentId); + if (parentSession == null || parentSession.isStagedAndInTerminalState()) { + // Parent session has been abandoned or terminated already + continue; + } + } + + // Check if session is one of the active sessions + if (session.sessionId == stagedSession.sessionId) { + Slog.w(TAG, "Session " + session.sessionId + " is already staged"); continue; } - if (!session.isStagedSessionApplied() && !session.isStagedSessionFailed()) { - return session; + + // If session is not among the active sessions, then it cannot have same package + // name as any of the active sessions. + if (session.getPackageName().equals(stagedSession.getPackageName())) { + throw new PackageManagerException( + PackageManager.INSTALL_FAILED_OTHER_STAGED_SESSION_IN_PROGRESS, + "Package: " + session.getPackageName() + " in session: " + + session.sessionId + " has been staged already by session: " + + stagedSession.sessionId, null); + } + + // TODO(b/141843321): Add support for staging multiple sessions in apexd + // Since apexd doesn't support multiple staged sessions yet, we have to careful how + // we handle apex sessions. We want to allow a set of apex sessions under the same + // parent to be staged when there is no previously staged apex sessions. + if (isApexSession(session) && isApexSession(stagedSession)) { + // session is apex and it can co-exist with stagedSession only if they are from + // same parent + final boolean coExist; + if (!session.hasParentSessionId() && !stagedSession.hasParentSessionId()) { + // Both single package apex sessions. Cannot co-exist. + coExist = false; + } else { + // At least one of the session has parent. Both must be from same parent. + coExist = + session.getParentSessionId() == stagedSession.getParentSessionId(); + } + if (!coExist) { + throw new PackageManagerException( + PackageManager.INSTALL_FAILED_OTHER_STAGED_SESSION_IN_PROGRESS, + "Package: " + session.getPackageName() + " in session: " + + session.sessionId + " cannot be staged as there is " + + "already another apex staged session: " + + stagedSession.sessionId, null); + } } } } - return null; } void createSession(@NonNull PackageInstallerSession sessionInfo) { @@ -584,7 +654,8 @@ public class StagingManager { ApexSessionInfo apexSession = mApexManager.getStagedSessionInfo(session.sessionId); if (apexSession == null || isApexSessionFinalized(apexSession)) { Slog.w(TAG, - "Cannot abort session because it is not active or APEXD is not reachable"); + "Cannot abort session " + session.sessionId + + " because it is not active or APEXD is not reachable"); return; } mApexManager.abortActiveSession(); diff --git a/services/core/java/com/android/server/wm/OWNERS b/services/core/java/com/android/server/wm/OWNERS index 0ab1a3e916e3..4be4c896cbff 100644 --- a/services/core/java/com/android/server/wm/OWNERS +++ b/services/core/java/com/android/server/wm/OWNERS @@ -10,3 +10,4 @@ roosa@google.com erosky@google.com riddlehsu@google.com louischang@google.com +winsonc@google.com diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 2b28ca228b1f..afa8c468cb48 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -1328,7 +1328,7 @@ public final class SystemServer { traceBeginAndSlog("StartIpSecService"); try { - ipSecService = IpSecService.create(context); + ipSecService = IpSecService.create(context, networkManagement); ServiceManager.addService(Context.IPSEC_SERVICE, ipSecService); } catch (Throwable e) { reportWtf("starting IpSec Service", e); diff --git a/services/net/java/android/net/TcpKeepalivePacketData.java b/services/net/java/android/net/TcpKeepalivePacketData.java index fcf3a56de448..c0c386b3046e 100644 --- a/services/net/java/android/net/TcpKeepalivePacketData.java +++ b/services/net/java/android/net/TcpKeepalivePacketData.java @@ -152,10 +152,12 @@ public class TcpKeepalivePacketData extends KeepalivePacketData implements Parce public boolean equals(@Nullable final Object o) { if (!(o instanceof TcpKeepalivePacketData)) return false; final TcpKeepalivePacketData other = (TcpKeepalivePacketData) o; - return this.srcAddress.equals(other.srcAddress) - && this.dstAddress.equals(other.dstAddress) - && this.srcPort == other.srcPort - && this.dstPort == other.dstPort + final InetAddress srcAddress = getSrcAddress(); + final InetAddress dstAddress = getDstAddress(); + return srcAddress.equals(other.getSrcAddress()) + && dstAddress.equals(other.getDstAddress()) + && getSrcPort() == other.getSrcPort() + && getDstPort() == other.getDstPort() && this.tcpAck == other.tcpAck && this.tcpSeq == other.tcpSeq && this.tcpWnd == other.tcpWnd @@ -166,8 +168,8 @@ public class TcpKeepalivePacketData extends KeepalivePacketData implements Parce @Override public int hashCode() { - return Objects.hash(srcAddress, dstAddress, srcPort, dstPort, tcpAck, tcpSeq, tcpWnd, - tcpWndScale, ipTos, ipTtl); + return Objects.hash(getSrcAddress(), getDstAddress(), getSrcPort(), getDstPort(), + tcpAck, tcpSeq, tcpWnd, tcpWndScale, ipTos, ipTtl); } /** @@ -182,10 +184,10 @@ public class TcpKeepalivePacketData extends KeepalivePacketData implements Parce /** Write to parcel. */ public void writeToParcel(Parcel out, int flags) { - out.writeString(srcAddress.getHostAddress()); - out.writeString(dstAddress.getHostAddress()); - out.writeInt(srcPort); - out.writeInt(dstPort); + out.writeString(getSrcAddress().getHostAddress()); + out.writeString(getDstAddress().getHostAddress()); + out.writeInt(getSrcPort()); + out.writeInt(getDstPort()); out.writeByteArray(getPacket()); out.writeInt(tcpSeq); out.writeInt(tcpAck); @@ -219,7 +221,7 @@ public class TcpKeepalivePacketData extends KeepalivePacketData implements Parce return readFromParcel(in); } catch (InvalidPacketException e) { throw new IllegalArgumentException( - "Invalid NAT-T keepalive data: " + e.error); + "Invalid NAT-T keepalive data: " + e.getError()); } } @@ -234,10 +236,12 @@ public class TcpKeepalivePacketData extends KeepalivePacketData implements Parce @NonNull public TcpKeepalivePacketDataParcelable toStableParcelable() { final TcpKeepalivePacketDataParcelable parcel = new TcpKeepalivePacketDataParcelable(); + final InetAddress srcAddress = getSrcAddress(); + final InetAddress dstAddress = getDstAddress(); parcel.srcAddress = srcAddress.getAddress(); - parcel.srcPort = srcPort; + parcel.srcPort = getSrcPort(); parcel.dstAddress = dstAddress.getAddress(); - parcel.dstPort = dstPort; + parcel.dstPort = getDstPort(); parcel.seq = tcpSeq; parcel.ack = tcpAck; parcel.rcvWnd = tcpWnd; @@ -249,10 +253,10 @@ public class TcpKeepalivePacketData extends KeepalivePacketData implements Parce @Override public String toString() { - return "saddr: " + srcAddress - + " daddr: " + dstAddress - + " sport: " + srcPort - + " dport: " + dstPort + return "saddr: " + getSrcAddress() + + " daddr: " + getDstAddress() + + " sport: " + getSrcPort() + + " dport: " + getDstPort() + " seq: " + tcpSeq + " ack: " + tcpAck + " wnd: " + tcpWnd diff --git a/services/net/java/android/net/util/KeepalivePacketDataUtil.java b/services/net/java/android/net/util/KeepalivePacketDataUtil.java index 9a51729212f7..4466ea0abe0e 100644 --- a/services/net/java/android/net/util/KeepalivePacketDataUtil.java +++ b/services/net/java/android/net/util/KeepalivePacketDataUtil.java @@ -20,6 +20,8 @@ import android.annotation.NonNull; import android.net.NattKeepalivePacketData; import android.net.NattKeepalivePacketDataParcelable; +import java.net.InetAddress; + /** @hide */ public final class KeepalivePacketDataUtil { /** @@ -29,11 +31,12 @@ public final class KeepalivePacketDataUtil { public static NattKeepalivePacketDataParcelable toStableParcelable( NattKeepalivePacketData pkt) { final NattKeepalivePacketDataParcelable parcel = new NattKeepalivePacketDataParcelable(); - - parcel.srcAddress = pkt.srcAddress.getAddress(); - parcel.srcPort = pkt.srcPort; - parcel.dstAddress = pkt.dstAddress.getAddress(); - parcel.dstPort = pkt.dstPort; + final InetAddress srcAddress = pkt.getSrcAddress(); + final InetAddress dstAddress = pkt.getDstAddress(); + parcel.srcAddress = srcAddress.getAddress(); + parcel.srcPort = pkt.getSrcPort(); + parcel.dstAddress = dstAddress.getAddress(); + parcel.dstPort = pkt.getDstPort(); return parcel; } } diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java index c5fcf67c9be9..ead90bb4561f 100755 --- a/telecomm/java/android/telecom/Call.java +++ b/telecomm/java/android/telecom/Call.java @@ -2075,6 +2075,17 @@ public final class Call { /** * Returns the child {@link Call} in a generic conference that is currently active. + * + * A "generic conference" is the mechanism used to support two simultaneous calls on a device + * in CDMA networks. It is effectively equivalent to having one call active and one call on hold + * in GSM or IMS calls. This method returns the currently active call. + * + * In a generic conference, the network exposes the conference to us as a single call, and we + * switch between talking to the two participants using a CDMA flash command. Since the network + * exposes no additional information about the call, the only way we know which caller we're + * currently talking to is by keeping track of the flash commands that we've sent to the + * network. + * * For calls that are not generic conferences, or when the generic conference has more than * 2 children, returns {@code null}. * @see Details#PROPERTY_GENERIC_CONFERENCE diff --git a/telecomm/java/android/telecom/ParcelableCallAnalytics.java b/telecomm/java/android/telecom/ParcelableCallAnalytics.java index 2b9213ba9dbc..b8ad9e2fbe6c 100644 --- a/telecomm/java/android/telecom/ParcelableCallAnalytics.java +++ b/telecomm/java/android/telecom/ParcelableCallAnalytics.java @@ -258,27 +258,6 @@ public class ParcelableCallAnalytics implements Parcelable { public static final int SIP_PHONE = 0x8; public static final int THIRD_PARTY_PHONE = 0x10; - /** - * Indicating the call source is not specified. - * - * @hide - */ - public static final int CALL_SOURCE_UNSPECIFIED = 0; - - /** - * Indicating the call is initiated via emergency dialer's dialpad. - * - * @hide - */ - public static final int CALL_SOURCE_EMERGENCY_DIALPAD = 1; - - /** - * Indicating the call is initiated via emergency dialer's shortcut button. - * - * @hide - */ - public static final int CALL_SOURCE_EMERGENCY_SHORTCUT = 2; - public static final long MILLIS_IN_5_MINUTES = 1000 * 60 * 5; public static final long MILLIS_IN_1_SECOND = 1000; @@ -343,7 +322,7 @@ public class ParcelableCallAnalytics implements Parcelable { private List<VideoEvent> videoEvents; // The source where user initiated this call. ONE OF the CALL_SOURCE_* constants. - private int callSource = CALL_SOURCE_UNSPECIFIED; + private int callSource = TelecomManager.CALL_SOURCE_UNSPECIFIED; public ParcelableCallAnalytics(long startTimeMillis, long callDurationMillis, int callType, boolean isAdditionalCall, boolean isInterrupted, int callTechnologies, diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java index 6ae4a08abaa3..768c8eebf067 100644 --- a/telecomm/java/android/telecom/PhoneAccount.java +++ b/telecomm/java/android/telecom/PhoneAccount.java @@ -82,8 +82,10 @@ public final class PhoneAccount implements Parcelable { public static final String EXTRA_CALL_SUBJECT_CHARACTER_ENCODING = "android.telecom.extra.CALL_SUBJECT_CHARACTER_ENCODING"; - /** - * Indicating flag for phone account whether to use voip audio mode for voip calls + /** + * Boolean {@link PhoneAccount} extras key (see {@link PhoneAccount#getExtras()}) which + * indicates that all calls from this {@link PhoneAccount} should be treated as VoIP calls + * rather than cellular calls. * @hide */ public static final String EXTRA_ALWAYS_USE_VOIP_AUDIO_MODE = diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java index 19a1021e57e2..8be146dd02fe 100644 --- a/telecomm/java/android/telecom/TelecomManager.java +++ b/telecomm/java/android/telecom/TelecomManager.java @@ -312,6 +312,9 @@ public class TelecomManager { "android.telecom.extra.IS_USER_INTENT_EMERGENCY_CALL"; /** + * A mandatory extra containing a {@link Uri} to be passed in when calling + * {@link #addNewUnknownCall(PhoneAccountHandle, Bundle)}. The {@link Uri} value indicates + * the remote handle of the new call. * @hide */ public static final String EXTRA_UNKNOWN_CALL_HANDLE = @@ -373,8 +376,15 @@ public class TelecomManager { "android.telecom.extra.CONNECTION_SERVICE"; /** - * Optional extra for communicating the call technology used by a - * {@link com.android.internal.telephony.Connection} to Telecom + * Optional extra for communicating the call technology used by a {@link ConnectionService} + * to Telecom. Valid values are: + * <ul> + * <li>{@link TelephonyManager#PHONE_TYPE_CDMA}</li> + * <li>{@link TelephonyManager#PHONE_TYPE_GSM}</li> + * <li>{@link TelephonyManager#PHONE_TYPE_IMS}</li> + * <li>{@link TelephonyManager#PHONE_TYPE_THIRD_PARTY}</li> + * <li>{@link TelephonyManager#PHONE_TYPE_SIP}</li> + * </ul> * @hide */ public static final String EXTRA_CALL_TECHNOLOGY_TYPE = @@ -725,15 +735,16 @@ public class TelecomManager { /** * The lookup key for an int that indicates the current TTY mode. * Valid modes are: - * - {@link #TTY_MODE_OFF} - * - {@link #TTY_MODE_FULL} - * - {@link #TTY_MODE_HCO} - * - {@link #TTY_MODE_VCO} - * + * <ul> + * <li>{@link #TTY_MODE_OFF}</li> + * <li>{@link #TTY_MODE_FULL}</li> + * <li>{@link #TTY_MODE_HCO}</li> + * <li>{@link #TTY_MODE_VCO}</li> + * </ul> * @hide */ public static final String EXTRA_CURRENT_TTY_MODE = - "android.telecom.intent.extra.CURRENT_TTY_MODE"; + "android.telecom.extra.CURRENT_TTY_MODE"; /** * Broadcast intent action indicating that the TTY preferred operating mode has changed. An @@ -753,7 +764,7 @@ public class TelecomManager { * @hide */ public static final String EXTRA_TTY_PREFERRED_MODE = - "android.telecom.intent.extra.TTY_PREFERRED"; + "android.telecom.extra.TTY_PREFERRED_MODE"; /** * Broadcast intent action for letting custom component know to show the missed call @@ -822,16 +833,37 @@ public class TelecomManager { /** * Optional extra for {@link #placeCall(Uri, Bundle)} containing an integer that specifies * the source where user initiated this call. This data is used in metrics. - * Valid source are: - * {@link ParcelableCallAnalytics#CALL_SOURCE_UNSPECIFIED}, - * {@link ParcelableCallAnalytics#CALL_SOURCE_EMERGENCY_DIALPAD}, - * {@link ParcelableCallAnalytics#CALL_SOURCE_EMERGENCY_SHORTCUT}. + * Valid sources are: + * {@link TelecomManager#CALL_SOURCE_UNSPECIFIED}, + * {@link TelecomManager#CALL_SOURCE_EMERGENCY_DIALPAD}, + * {@link TelecomManager#CALL_SOURCE_EMERGENCY_SHORTCUT}. * * @hide */ public static final String EXTRA_CALL_SOURCE = "android.telecom.extra.CALL_SOURCE"; /** + * Indicating the call is initiated via emergency dialer's shortcut button. + * + * @hide + */ + public static final int CALL_SOURCE_EMERGENCY_SHORTCUT = 2; + + /** + * Indicating the call is initiated via emergency dialer's dialpad. + * + * @hide + */ + public static final int CALL_SOURCE_EMERGENCY_DIALPAD = 1; + + /** + * Indicating the call source is not specified. + * + * @hide + */ + public static final int CALL_SOURCE_UNSPECIFIED = 0; + + /** * The following 4 constants define how properties such as phone numbers and names are * displayed to the user. */ diff --git a/telephony/common/com/android/internal/telephony/CarrierAppUtils.java b/telephony/common/com/android/internal/telephony/CarrierAppUtils.java index de0221c7c2b1..3c1e707ab1dd 100644 --- a/telephony/common/com/android/internal/telephony/CarrierAppUtils.java +++ b/telephony/common/com/android/internal/telephony/CarrierAppUtils.java @@ -31,6 +31,7 @@ import android.util.ArrayMap; import android.util.ArraySet; import android.util.Log; +import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telephony.util.ArrayUtils; import com.android.server.SystemConfig; @@ -156,7 +157,7 @@ public final class CarrierAppUtils { for (ApplicationInfo ai : candidates) { String packageName = ai.packageName; String[] restrictedCarrierApps = Resources.getSystem().getStringArray( - android.R.array.config_restrictedPreinstalledCarrierApps); + R.array.config_restrictedPreinstalledCarrierApps); boolean hasPrivileges = telephonyManager != null && telephonyManager.checkCarrierPrivilegesForPackageAnyPhone(packageName) == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS diff --git a/telephony/common/com/android/internal/telephony/GsmAlphabet.java b/telephony/common/com/android/internal/telephony/GsmAlphabet.java index 2201452e9011..60cd40094950 100644 --- a/telephony/common/com/android/internal/telephony/GsmAlphabet.java +++ b/telephony/common/com/android/internal/telephony/GsmAlphabet.java @@ -19,10 +19,12 @@ package com.android.internal.telephony; import android.compat.annotation.UnsupportedAppUsage; import android.content.res.Resources; import android.os.Build; -import android.text.TextUtils; import android.util.Log; +import android.text.TextUtils; import android.util.SparseIntArray; +import com.android.internal.R; + import java.nio.ByteBuffer; import java.nio.charset.Charset; import java.util.ArrayList; @@ -1085,10 +1087,8 @@ public class GsmAlphabet { private static void enableCountrySpecificEncodings() { Resources r = Resources.getSystem(); // See comments in frameworks/base/core/res/res/values/config.xml for allowed values - sEnabledSingleShiftTables = r.getIntArray( - android.R.array.config_sms_enabled_single_shift_tables); - sEnabledLockingShiftTables = r.getIntArray( - android.R.array.config_sms_enabled_locking_shift_tables); + sEnabledSingleShiftTables = r.getIntArray(R.array.config_sms_enabled_single_shift_tables); + sEnabledLockingShiftTables = r.getIntArray(R.array.config_sms_enabled_locking_shift_tables); if (sEnabledSingleShiftTables.length > 0) { sHighestEnabledSingleShiftCode = diff --git a/telephony/common/com/google/android/mms/util/SqliteWrapper.java b/telephony/common/com/google/android/mms/util/SqliteWrapper.java index 4871434ebc31..31fe4d7683d6 100644 --- a/telephony/common/com/google/android/mms/util/SqliteWrapper.java +++ b/telephony/common/com/google/android/mms/util/SqliteWrapper.java @@ -60,7 +60,8 @@ public final class SqliteWrapper { @UnsupportedAppUsage public static void checkSQLiteException(Context context, SQLiteException e) { if (isLowMemory(e)) { - Toast.makeText(context, android.R.string.low_memory, Toast.LENGTH_SHORT).show(); + Toast.makeText(context, com.android.internal.R.string.low_memory, + Toast.LENGTH_SHORT).show(); } else { throw e; } diff --git a/telephony/java/android/service/carrier/CarrierService.java b/telephony/java/android/service/carrier/CarrierService.java index eefc1b70bac9..d06ec11f3e61 100644 --- a/telephony/java/android/service/carrier/CarrierService.java +++ b/telephony/java/android/service/carrier/CarrierService.java @@ -25,6 +25,9 @@ import android.os.ResultReceiver; import android.telephony.TelephonyRegistryManager; import android.util.Log; +import java.io.FileDescriptor; +import java.io.PrintWriter; + /** * A service that exposes carrier-specific functionality to the system. * <p> @@ -156,5 +159,10 @@ public abstract class CarrierService extends Service { result.send(RESULT_ERROR, null); } } + + @Override + protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + CarrierService.this.dump(fd, pw, args); + } } } diff --git a/telephony/java/android/telephony/Annotation.java b/telephony/java/android/telephony/Annotation.java index 85db35d1ca08..ccda88f717c3 100644 --- a/telephony/java/android/telephony/Annotation.java +++ b/telephony/java/android/telephony/Annotation.java @@ -611,48 +611,6 @@ public class Annotation { } /** - * Call forwarding function status - */ - @IntDef(prefix = { "STATUS_" }, value = { - CallForwardingInfo.STATUS_ACTIVE, - CallForwardingInfo.STATUS_INACTIVE, - CallForwardingInfo.STATUS_UNKNOWN_ERROR, - CallForwardingInfo.STATUS_NOT_SUPPORTED, - CallForwardingInfo.STATUS_FDN_CHECK_FAILURE - }) - @Retention(RetentionPolicy.SOURCE) - public @interface CallForwardingStatus { - } - - /** - * Call forwarding reason types - */ - @IntDef(flag = true, prefix = { "REASON_" }, value = { - CallForwardingInfo.REASON_UNCONDITIONAL, - CallForwardingInfo.REASON_BUSY, - CallForwardingInfo.REASON_NO_REPLY, - CallForwardingInfo.REASON_NOT_REACHABLE, - CallForwardingInfo.REASON_ALL, - CallForwardingInfo.REASON_ALL_CONDITIONAL - }) - @Retention(RetentionPolicy.SOURCE) - public @interface CallForwardingReason { - } - - /** - * Call waiting function status - */ - @IntDef(prefix = { "CALL_WAITING_STATUS_" }, value = { - TelephonyManager.CALL_WAITING_STATUS_ACTIVE, - TelephonyManager.CALL_WAITING_STATUS_INACTIVE, - TelephonyManager.CALL_WAITING_STATUS_NOT_SUPPORTED, - TelephonyManager.CALL_WAITING_STATUS_UNKNOWN_ERROR - }) - @Retention(RetentionPolicy.SOURCE) - public @interface CallWaitingStatus { - } - - /** * UICC SIM Application Types */ @IntDef(prefix = { "APPTYPE_" }, value = { diff --git a/telephony/java/android/telephony/CallForwardingInfo.java b/telephony/java/android/telephony/CallForwardingInfo.java index 1dd7539420ac..7e777fae46eb 100644 --- a/telephony/java/android/telephony/CallForwardingInfo.java +++ b/telephony/java/android/telephony/CallForwardingInfo.java @@ -15,24 +15,24 @@ */ package android.telephony; + +import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SuppressLint; -import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; -import android.telephony.Annotation.CallForwardingReason; -import android.telephony.Annotation.CallForwardingStatus; import com.android.telephony.Rlog; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.Objects; /** * Defines the call forwarding information. * @hide */ -@SystemApi public final class CallForwardingInfo implements Parcelable { private static final String TAG = "CallForwardingInfo"; @@ -41,7 +41,6 @@ public final class CallForwardingInfo implements Parcelable { * * @hide */ - @SystemApi public static final int STATUS_INACTIVE = 0; /** @@ -49,7 +48,6 @@ public final class CallForwardingInfo implements Parcelable { * * @hide */ - @SystemApi public static final int STATUS_ACTIVE = 1; /** @@ -58,7 +56,6 @@ public final class CallForwardingInfo implements Parcelable { * * @hide */ - @SystemApi public static final int STATUS_FDN_CHECK_FAILURE = 2; /** @@ -66,7 +63,6 @@ public final class CallForwardingInfo implements Parcelable { * * @hide */ - @SystemApi public static final int STATUS_UNKNOWN_ERROR = 3; /** @@ -74,7 +70,6 @@ public final class CallForwardingInfo implements Parcelable { * * @hide */ - @SystemApi public static final int STATUS_NOT_SUPPORTED = 4; /** @@ -83,7 +78,6 @@ public final class CallForwardingInfo implements Parcelable { * and conditions +CCFC * @hide */ - @SystemApi public static final int REASON_UNCONDITIONAL = 0; /** @@ -92,7 +86,6 @@ public final class CallForwardingInfo implements Parcelable { * and conditions +CCFC * @hide */ - @SystemApi public static final int REASON_BUSY = 1; /** @@ -101,7 +94,6 @@ public final class CallForwardingInfo implements Parcelable { * and conditions +CCFC * @hide */ - @SystemApi public static final int REASON_NO_REPLY = 2; /** @@ -110,7 +102,6 @@ public final class CallForwardingInfo implements Parcelable { * and conditions +CCFC * @hide */ - @SystemApi public static final int REASON_NOT_REACHABLE = 3; /** @@ -120,7 +111,6 @@ public final class CallForwardingInfo implements Parcelable { * and conditions +CCFC * @hide */ - @SystemApi public static final int REASON_ALL = 4; /** @@ -130,20 +120,48 @@ public final class CallForwardingInfo implements Parcelable { * and conditions +CCFC * @hide */ - @SystemApi public static final int REASON_ALL_CONDITIONAL = 5; /** + * Call forwarding function status + */ + @IntDef(prefix = { "STATUS_" }, value = { + STATUS_ACTIVE, + STATUS_INACTIVE, + STATUS_UNKNOWN_ERROR, + STATUS_NOT_SUPPORTED, + STATUS_FDN_CHECK_FAILURE + }) + @Retention(RetentionPolicy.SOURCE) + public @interface CallForwardingStatus { + } + + /** + * Call forwarding reason types + */ + @IntDef(flag = true, prefix = { "REASON_" }, value = { + REASON_UNCONDITIONAL, + REASON_BUSY, + REASON_NO_REPLY, + REASON_NOT_REACHABLE, + REASON_ALL, + REASON_ALL_CONDITIONAL + }) + @Retention(RetentionPolicy.SOURCE) + public @interface CallForwardingReason { + } + + /** * The call forwarding status. */ - private @CallForwardingStatus int mStatus; + private int mStatus; /** * The call forwarding reason indicates the condition under which calls will be forwarded. * Reference: 3GPP TS 27.007 version 10.3.0 Release 10 - 7.11 Call forwarding number * and conditions +CCFC */ - private @CallForwardingReason int mReason; + private int mReason; /** * The phone number to which calls will be forwarded. @@ -166,7 +184,6 @@ public final class CallForwardingInfo implements Parcelable { * @param timeSeconds the timeout (in seconds) before the forwarding is attempted * @hide */ - @SystemApi public CallForwardingInfo(@CallForwardingStatus int status, @CallForwardingReason int reason, @Nullable String number, int timeSeconds) { mStatus = status; @@ -182,7 +199,6 @@ public final class CallForwardingInfo implements Parcelable { * * @hide */ - @SystemApi public @CallForwardingStatus int getStatus() { return mStatus; } @@ -196,7 +212,6 @@ public final class CallForwardingInfo implements Parcelable { * * @hide */ - @SystemApi public @CallForwardingReason int getReason() { return mReason; } @@ -209,7 +224,6 @@ public final class CallForwardingInfo implements Parcelable { * * @hide */ - @SystemApi @Nullable public String getNumber() { return mNumber; @@ -227,7 +241,6 @@ public final class CallForwardingInfo implements Parcelable { * * @hide */ - @SystemApi @SuppressLint("MethodNameUnits") public int getTimeoutSeconds() { return mTimeSeconds; diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index de35c00c8059..8cbeba14405b 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -1553,6 +1553,7 @@ public class CarrierConfigManager { /** * The string is used to compare with operator name. * If it matches the pattern then show specific data icon. + * @hide */ public static final String KEY_SHOW_CARRIER_DATA_ICON_PATTERN_STRING = "show_carrier_data_icon_pattern_string"; @@ -2967,9 +2968,9 @@ public class CarrierConfigManager { * UE wants to display 5G_Plus icon for scenario#1, and 5G icon for scenario#2; otherwise not * define. * The configuration is: "connected_mmwave:5G_Plus,connected:5G" + * @hide */ - public static final String KEY_5G_ICON_CONFIGURATION_STRING = - "5g_icon_configuration_string"; + public static final String KEY_5G_ICON_CONFIGURATION_STRING = "5g_icon_configuration_string"; /** * Timeout in seconds for displaying 5G icon, default value is 0 which means the timer is @@ -2981,12 +2982,14 @@ public class CarrierConfigManager { * * If 5G is reacquired during this timer, the timer is canceled and restarted when 5G is next * lost. Allows us to momentarily lose 5G without blinking the icon. + * @hide */ public static final String KEY_5G_ICON_DISPLAY_GRACE_PERIOD_SEC_INT = "5g_icon_display_grace_period_sec_int"; /** * 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"; @@ -3723,7 +3726,7 @@ public class CarrierConfigManager { sDefaults.putInt(KEY_IMS_DTMF_TONE_DELAY_INT, 0); sDefaults.putInt(KEY_CDMA_DTMF_TONE_DELAY_INT, 100); sDefaults.putBoolean(KEY_CALL_FORWARDING_MAP_NON_NUMBER_TO_VOICEMAIL_BOOL, false); - sDefaults.putBoolean(KEY_IGNORE_RTT_MODE_SETTING_BOOL, false); + sDefaults.putBoolean(KEY_IGNORE_RTT_MODE_SETTING_BOOL, true); sDefaults.putInt(KEY_CDMA_3WAYCALL_FLASH_DELAY_INT , 0); sDefaults.putBoolean(KEY_SUPPORT_ADHOC_CONFERENCE_CALLS_BOOL, false); sDefaults.putBoolean(KEY_SUPPORT_ADD_CONFERENCE_PARTICIPANTS_BOOL, false); diff --git a/telephony/java/android/telephony/CellIdentityLte.java b/telephony/java/android/telephony/CellIdentityLte.java index d672c77bed01..b4ce162274fb 100644 --- a/telephony/java/android/telephony/CellIdentityLte.java +++ b/telephony/java/android/telephony/CellIdentityLte.java @@ -25,10 +25,9 @@ import android.telephony.gsm.GsmCellLocation; import android.text.TextUtils; import android.util.ArraySet; -import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; -import java.util.List; import java.util.Objects; import java.util.Set; @@ -56,7 +55,7 @@ public final class CellIdentityLte extends CellIdentity { // cell bandwidth, in kHz private final int mBandwidth; // cell bands - private final List<Integer> mBands; + private final int[] mBands; // a list of additional PLMN-IDs reported for this cell private final ArraySet<String> mAdditionalPlmns; @@ -73,7 +72,7 @@ public final class CellIdentityLte extends CellIdentity { mPci = CellInfo.UNAVAILABLE; mTac = CellInfo.UNAVAILABLE; mEarfcn = CellInfo.UNAVAILABLE; - mBands = Collections.emptyList(); + mBands = new int[] {}; mBandwidth = CellInfo.UNAVAILABLE; mAdditionalPlmns = new ArraySet<>(); mCsgInfo = null; @@ -91,7 +90,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, Collections.emptyList(), CellInfo.UNAVAILABLE, + this(ci, pci, tac, CellInfo.UNAVAILABLE, new int[] {}, CellInfo.UNAVAILABLE, String.valueOf(mcc), String.valueOf(mnc), null, null, new ArraySet<>(), null); } @@ -112,16 +111,17 @@ public final class CellIdentityLte extends CellIdentity { * * @hide */ - public CellIdentityLte(int ci, int pci, int tac, int earfcn, List<Integer> bands, int bandwidth, - @Nullable String mccStr, @Nullable String mncStr, @Nullable String alphal, - @Nullable String alphas, @NonNull Collection<String> additionalPlmns, + public CellIdentityLte(int ci, int pci, int tac, int earfcn, @NonNull int[] bands, + int bandwidth, @Nullable String mccStr, @Nullable String mncStr, + @Nullable String alphal, @Nullable String alphas, + @NonNull Collection<String> additionalPlmns, @Nullable 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); - mBands = new ArrayList<>(bands); + mBands = bands; mBandwidth = inRangeOrUnavailable(bandwidth, 0, MAX_BANDWIDTH); mAdditionalPlmns = new ArraySet<>(additionalPlmns.size()); for (String plmn : additionalPlmns) { @@ -134,13 +134,13 @@ public final class CellIdentityLte extends CellIdentity { /** @hide */ public CellIdentityLte(@NonNull android.hardware.radio.V1_0.CellIdentityLte cid) { - this(cid.ci, cid.pci, cid.tac, cid.earfcn, Collections.emptyList(), + this(cid.ci, cid.pci, cid.tac, cid.earfcn, new int[] {}, CellInfo.UNAVAILABLE, cid.mcc, cid.mnc, "", "", new ArraySet<>(), null); } /** @hide */ public CellIdentityLte(@NonNull android.hardware.radio.V1_2.CellIdentityLte cid) { - this(cid.base.ci, cid.base.pci, cid.base.tac, cid.base.earfcn, Collections.emptyList(), + this(cid.base.ci, cid.base.pci, cid.base.tac, cid.base.earfcn, new int[] {}, cid.bandwidth, cid.base.mcc, cid.base.mnc, cid.operatorNames.alphaLong, cid.operatorNames.alphaShort, new ArraySet<>(), null); } @@ -148,9 +148,10 @@ public final class CellIdentityLte extends CellIdentity { /** @hide */ public CellIdentityLte(@NonNull 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.bands, 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 + cid.bands.stream().mapToInt(Integer::intValue).toArray(), 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); } @@ -228,11 +229,11 @@ public final class CellIdentityLte extends CellIdentity { * * Reference: 3GPP TS 36.101 section 5.5 * - * @return List of band number or empty list if not available. + * @return Array of band number or empty array if not available. */ @NonNull - public List<Integer> getBands() { - return Collections.unmodifiableList(mBands); + public int[] getBands() { + return Arrays.copyOf(mBands, mBands.length); } /** @@ -314,8 +315,8 @@ public final class CellIdentityLte extends CellIdentity { @Override public int hashCode() { - return Objects.hash(mCi, mPci, mTac, - mAdditionalPlmns.hashCode(), mCsgInfo, super.hashCode()); + return Objects.hash(mCi, mPci, mTac, mEarfcn, Arrays.hashCode(mBands), + mBandwidth, mAdditionalPlmns.hashCode(), mCsgInfo, super.hashCode()); } @Override @@ -333,6 +334,7 @@ public final class CellIdentityLte extends CellIdentity { && mPci == o.mPci && mTac == o.mTac && mEarfcn == o.mEarfcn + && Arrays.equals(mBands, o.mBands) && mBandwidth == o.mBandwidth && TextUtils.equals(mMccStr, o.mMccStr) && TextUtils.equals(mMncStr, o.mMncStr) @@ -368,7 +370,7 @@ public final class CellIdentityLte extends CellIdentity { dest.writeInt(mPci); dest.writeInt(mTac); dest.writeInt(mEarfcn); - dest.writeList(mBands); + dest.writeIntArray(mBands); dest.writeInt(mBandwidth); dest.writeArraySet(mAdditionalPlmns); dest.writeParcelable(mCsgInfo, flags); @@ -381,7 +383,7 @@ public final class CellIdentityLte extends CellIdentity { mPci = in.readInt(); mTac = in.readInt(); mEarfcn = in.readInt(); - mBands = in.readArrayList(null); + mBands = in.createIntArray(); mBandwidth = in.readInt(); mAdditionalPlmns = (ArraySet<String>) in.readArraySet(null); mCsgInfo = in.readParcelable(null); diff --git a/telephony/java/android/telephony/CellIdentityNr.java b/telephony/java/android/telephony/CellIdentityNr.java index cba500a00d3a..69cf7e7d4814 100644 --- a/telephony/java/android/telephony/CellIdentityNr.java +++ b/telephony/java/android/telephony/CellIdentityNr.java @@ -24,10 +24,9 @@ import android.telephony.AccessNetworkConstants.NgranBands.NgranBand; import android.telephony.gsm.GsmCellLocation; import android.util.ArraySet; -import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; -import java.util.List; import java.util.Objects; import java.util.Set; @@ -46,7 +45,7 @@ public final class CellIdentityNr extends CellIdentity { private final int mPci; private final int mTac; private final long mNci; - private final List<Integer> mBands; + private final int[] mBands; // a list of additional PLMN-IDs reported for this cell private final ArraySet<String> mAdditionalPlmns; @@ -66,7 +65,7 @@ public final class CellIdentityNr extends CellIdentity { * * @hide */ - public CellIdentityNr(int pci, int tac, int nrArfcn, @NgranBand List<Integer> bands, + public CellIdentityNr(int pci, int tac, int nrArfcn, @NonNull @NgranBand int[] bands, @Nullable String mccStr, @Nullable String mncStr, long nci, @Nullable String alphal, @Nullable String alphas, @NonNull Collection<String> additionalPlmns) { @@ -74,7 +73,8 @@ public final class CellIdentityNr extends CellIdentity { mPci = inRangeOrUnavailable(pci, 0, MAX_PCI); mTac = inRangeOrUnavailable(tac, 0, MAX_TAC); mNrArfcn = inRangeOrUnavailable(nrArfcn, 0, MAX_NRARFCN); - mBands = new ArrayList<>(bands); + // TODO: input validation for bands + mBands = bands; mNci = inRangeOrUnavailable(nci, 0, MAX_NCI); mAdditionalPlmns = new ArraySet<>(additionalPlmns.size()); for (String plmn : additionalPlmns) { @@ -86,15 +86,16 @@ public final class CellIdentityNr extends CellIdentity { /** @hide */ public CellIdentityNr(@NonNull android.hardware.radio.V1_4.CellIdentityNr cid) { - this(cid.pci, cid.tac, cid.nrarfcn, Collections.emptyList(), cid.mcc, cid.mnc, cid.nci, + this(cid.pci, cid.tac, cid.nrarfcn, new int[] {}, cid.mcc, cid.mnc, cid.nci, cid.operatorNames.alphaLong, cid.operatorNames.alphaShort, new ArraySet<>()); } /** @hide */ public CellIdentityNr(@NonNull 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, + this(cid.base.pci, cid.base.tac, cid.base.nrarfcn, + cid.bands.stream().mapToInt(Integer::intValue).toArray(), cid.base.mcc, + cid.base.mnc, cid.base.nci, cid.base.operatorNames.alphaLong, cid.base.operatorNames.alphaShort, cid.additionalPlmns); } @@ -119,18 +120,22 @@ public final class CellIdentityNr extends CellIdentity { @Override public int hashCode() { return Objects.hash(super.hashCode(), mPci, mTac, - mNrArfcn, mBands.hashCode(), mNci, mAdditionalPlmns.hashCode()); + mNrArfcn, Arrays.hashCode(mBands), mNci, mAdditionalPlmns.hashCode()); } @Override public boolean equals(Object other) { + if (this == other) { + return true; + } + if (!(other instanceof CellIdentityNr)) { return false; } CellIdentityNr o = (CellIdentityNr) other; return super.equals(o) && mPci == o.mPci && mTac == o.mTac && mNrArfcn == o.mNrArfcn - && mBands.equals(o.mBands) && mNci == o.mNci + && Arrays.equals(mBands, o.mBands) && mNci == o.mNci && mAdditionalPlmns.equals(o.mAdditionalPlmns); } @@ -163,12 +168,12 @@ public final class CellIdentityNr extends CellIdentity { * 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. + * @return Array of band number or empty array if not available. */ @NgranBand @NonNull - public List<Integer> getBands() { - return Collections.unmodifiableList(mBands); + public int[] getBands() { + return Arrays.copyOf(mBands, mBands.length); } /** @@ -242,7 +247,7 @@ public final class CellIdentityNr extends CellIdentity { dest.writeInt(mPci); dest.writeInt(mTac); dest.writeInt(mNrArfcn); - dest.writeList(mBands); + dest.writeIntArray(mBands); dest.writeLong(mNci); dest.writeArraySet(mAdditionalPlmns); } @@ -253,7 +258,7 @@ public final class CellIdentityNr extends CellIdentity { mPci = in.readInt(); mTac = in.readInt(); mNrArfcn = in.readInt(); - mBands = in.readArrayList(null); + mBands = in.createIntArray(); mNci = in.readLong(); mAdditionalPlmns = (ArraySet<String>) in.readArraySet(null); } diff --git a/telephony/java/android/telephony/CellSignalStrengthCdma.java b/telephony/java/android/telephony/CellSignalStrengthCdma.java index 1c92705b9422..d00049c1ebe5 100644 --- a/telephony/java/android/telephony/CellSignalStrengthCdma.java +++ b/telephony/java/android/telephony/CellSignalStrengthCdma.java @@ -314,6 +314,8 @@ public final class CellSignalStrengthCdma extends CellSignalStrength implements /** * Get the signal strength as dBm + * + * @return min(CDMA RSSI, EVDO RSSI) of the measured cell. */ @Override public int getDbm() { diff --git a/telephony/java/android/telephony/CellSignalStrengthGsm.java b/telephony/java/android/telephony/CellSignalStrengthGsm.java index 76d2df918423..9d55f109f751 100644 --- a/telephony/java/android/telephony/CellSignalStrengthGsm.java +++ b/telephony/java/android/telephony/CellSignalStrengthGsm.java @@ -145,6 +145,8 @@ public final class CellSignalStrengthGsm extends CellSignalStrength implements P /** * Get the signal strength as dBm. + * + * @return the RSSI of the measured cell. */ @Override public int getDbm() { diff --git a/telephony/java/android/telephony/DataSpecificRegistrationInfo.java b/telephony/java/android/telephony/DataSpecificRegistrationInfo.java index 270eafe642b7..c667165e7a0e 100644 --- a/telephony/java/android/telephony/DataSpecificRegistrationInfo.java +++ b/telephony/java/android/telephony/DataSpecificRegistrationInfo.java @@ -208,7 +208,6 @@ public final class DataSpecificRegistrationInfo implements Parcelable { * @return {@code true} if using carrier aggregation. * @hide */ - @SystemApi public boolean isUsingCarrierAggregation() { return mIsUsingCarrierAggregation; } diff --git a/telephony/java/android/telephony/ImsManager.java b/telephony/java/android/telephony/ImsManager.java index 704e5aa78188..34bac5de4c43 100644 --- a/telephony/java/android/telephony/ImsManager.java +++ b/telephony/java/android/telephony/ImsManager.java @@ -34,8 +34,9 @@ public class ImsManager { private Context mContext; /** - * <p>Broadcast Action: Indicates that an IMS operation was rejected by the network due to it - * not being authorized on the network. + * <p>Broadcast Action: Indicates that a previously allowed IMS operation was rejected by the + * network due to the network returning a "forbidden" response. This may be due to a + * provisioning change from the network. * May include the {@link SubscriptionManager#EXTRA_SUBSCRIPTION_INDEX} extra to also specify * which subscription the operation was rejected for. * <p class="note"> @@ -74,17 +75,17 @@ public class ImsManager { "android.telephony.ims.action.WFC_IMS_REGISTRATION_ERROR"; /** - * An extra key corresponding to a String value which contains the carrier specific title to be - * displayed as part of the message shown to the user when there is an error registering for - * WiFi calling. + * An extra key corresponding to a {@link CharSequence} value which contains the carrier + * specific title to be displayed as part of the message shown to the user when there is an + * error registering for WiFi calling. */ public static final String EXTRA_WFC_REGISTRATION_FAILURE_TITLE = "android.telephony.ims.extra.WFC_REGISTRATION_FAILURE_TITLE"; /** - * An extra key corresponding to a String value which contains the carrier specific message to - * be displayed as part of the message shown to the user when there is an error registering for - * WiFi calling. + * An extra key corresponding to a {@link CharSequence} value which contains the carrier + * specific message to be displayed as part of the message shown to the user when there is an + * error registering for WiFi calling. */ public static final String EXTRA_WFC_REGISTRATION_FAILURE_MESSAGE = "android.telephony.ims.extra.WFC_REGISTRATION_FAILURE_MESSAGE"; @@ -103,10 +104,7 @@ public class ImsManager { * @param subscriptionId The ID of the subscription that this ImsRcsManager will use. * @throws IllegalArgumentException if the subscription is invalid. * @return a ImsRcsManager instance with the specific subscription ID. - * @hide */ - @SystemApi - @TestApi @NonNull public ImsRcsManager getImsRcsManager(int subscriptionId) { if (!SubscriptionManager.isValidSubscriptionId(subscriptionId)) { diff --git a/telephony/java/android/telephony/NetworkRegistrationInfo.java b/telephony/java/android/telephony/NetworkRegistrationInfo.java index 3e901e241e01..93fbb00ff9d5 100644 --- a/telephony/java/android/telephony/NetworkRegistrationInfo.java +++ b/telephony/java/android/telephony/NetworkRegistrationInfo.java @@ -367,6 +367,7 @@ public final class NetworkRegistrationInfo implements Parcelable { * Get the 5G NR connection state. * * @return the 5G NR connection state. + * @hide */ public @NRState int getNrState() { return mNrState; @@ -689,7 +690,7 @@ public final class NetworkRegistrationInfo implements Parcelable { */ public void updateNrState() { mNrState = NR_STATE_NONE; - if (mDataSpecificInfo.isEnDcAvailable) { + if (mDataSpecificInfo != null && mDataSpecificInfo.isEnDcAvailable) { if (!mDataSpecificInfo.isDcNrRestricted && mDataSpecificInfo.isNrAvailable) { mNrState = NR_STATE_NOT_RESTRICTED; } else { diff --git a/telephony/java/android/telephony/PreciseDataConnectionState.java b/telephony/java/android/telephony/PreciseDataConnectionState.java index 708adebb6db3..a9abe89abab0 100644 --- a/telephony/java/android/telephony/PreciseDataConnectionState.java +++ b/telephony/java/android/telephony/PreciseDataConnectionState.java @@ -95,7 +95,6 @@ public final class PreciseDataConnectionState implements Parcelable { * if there is no valid APN setting for the specific type, then this will be null * @hide */ - @SystemApi public PreciseDataConnectionState(@DataState int state, @NetworkType int networkType, @ApnType int apnTypes, @NonNull String apn, diff --git a/telephony/java/android/telephony/RadioAccessFamily.java b/telephony/java/android/telephony/RadioAccessFamily.java index bc8473865466..90ddf2cd4730 100644 --- a/telephony/java/android/telephony/RadioAccessFamily.java +++ b/telephony/java/android/telephony/RadioAccessFamily.java @@ -260,24 +260,6 @@ public class RadioAccessFamily implements Parcelable { return raf; } - /** - * Returns the highest capability of the RadioAccessFamily (4G > 3G > 2G). - * @param raf The RadioAccessFamily that we wish to filter - * @return The highest radio capability - */ - public static int getHighestRafCapability(int raf) { - if ((LTE & raf) > 0) { - return TelephonyManager.NETWORK_CLASS_4_G; - } - if ((EVDO|HS|WCDMA & raf) > 0) { - return TelephonyManager.NETWORK_CLASS_3_G; - } - if((GSM|CDMA & raf) > 0) { - return TelephonyManager.NETWORK_CLASS_2_G; - } - return TelephonyManager.NETWORK_CLASS_UNKNOWN; - } - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) @PrefNetworkMode public static int getNetworkTypeFromRaf(int raf) { @@ -395,4 +377,34 @@ public class RadioAccessFamily implements Parcelable { } return result; } + + /** + * Compare two sets of network types to see which is more capable. + * + * This algorithm first tries to see see if a set has a strict superset of RAT support for + * each generation, from newest to oldest; if that results in a tie, then it returns the set + * that supports the most RAT types. + */ + public static int compare(long networkTypeBitmaskL, long networkTypeBitmaskR) { + final long[] prioritizedNetworkClassBitmasks = new long[] { + TelephonyManager.NETWORK_CLASS_BITMASK_5G, + TelephonyManager.NETWORK_CLASS_BITMASK_4G, + TelephonyManager.NETWORK_CLASS_BITMASK_3G, + TelephonyManager.NETWORK_CLASS_BITMASK_2G, + }; + + long lhsUnique = networkTypeBitmaskL & ~networkTypeBitmaskR; + long rhsUnique = networkTypeBitmaskR & ~networkTypeBitmaskL; + + // See if one has a strict super-set of capabilities, generation by generation. + for (long classBitmask : prioritizedNetworkClassBitmasks) { + int result = 0; + if ((lhsUnique & classBitmask) != 0) ++result; + if ((rhsUnique & classBitmask) != 0) --result; + if (result != 0) return result; + } + + // Without a clear winner, return the one that supports the most types. + return Long.bitCount(networkTypeBitmaskL) - Long.bitCount(networkTypeBitmaskR); + } } diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java index 5cf33dec25ea..82470d41842d 100644 --- a/telephony/java/android/telephony/ServiceState.java +++ b/telephony/java/android/telephony/ServiceState.java @@ -1421,7 +1421,6 @@ public class ServiceState implements Parcelable { * @return the frequency range of 5G NR. * @hide */ - @SystemApi public @FrequencyRange int getNrFrequencyRange() { return mNrFrequencyRange; } diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index ffbcbb0d2633..c37262c6d2cc 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -70,14 +70,13 @@ import android.telecom.PhoneAccount; import android.telecom.PhoneAccountHandle; import android.telecom.TelecomManager; import android.telephony.Annotation.ApnType; -import android.telephony.Annotation.CallForwardingReason; import android.telephony.Annotation.CallState; -import android.telephony.Annotation.CallWaitingStatus; import android.telephony.Annotation.CarrierPrivilegeStatus; import android.telephony.Annotation.NetworkType; import android.telephony.Annotation.RadioPowerState; import android.telephony.Annotation.SimActivationState; import android.telephony.Annotation.UiccAppType; +import android.telephony.CallForwardingInfo.CallForwardingReason; import android.telephony.VisualVoicemailService.VisualVoicemailTask; import android.telephony.data.ApnSetting; import android.telephony.data.ApnSetting.MvnoType; @@ -3011,64 +3010,6 @@ public class TelephonyManager { } /** - * Network Class Definitions. - * Do not change this order, it is used for sorting during emergency calling in - * {@link TelephonyConnectionService#getFirstPhoneForEmergencyCall()}. Any newer technologies - * should be added after the current definitions. - */ - /** Unknown network class. {@hide} */ - public static final int NETWORK_CLASS_UNKNOWN = 0; - /** Class of broadly defined "2G" networks. {@hide} */ - @UnsupportedAppUsage - public static final int NETWORK_CLASS_2_G = 1; - /** Class of broadly defined "3G" networks. {@hide} */ - @UnsupportedAppUsage - public static final int NETWORK_CLASS_3_G = 2; - /** Class of broadly defined "4G" networks. {@hide} */ - @UnsupportedAppUsage - public static final int NETWORK_CLASS_4_G = 3; - /** Class of broadly defined "5G" networks. {@hide} */ - public static final int NETWORK_CLASS_5_G = 4; - - /** - * Return general class of network type, such as "3G" or "4G". In cases - * where classification is contentious, this method is conservative. - * - * @hide - */ - @UnsupportedAppUsage - public static int getNetworkClass(int networkType) { - switch (networkType) { - case NETWORK_TYPE_GPRS: - case NETWORK_TYPE_GSM: - case NETWORK_TYPE_EDGE: - case NETWORK_TYPE_CDMA: - case NETWORK_TYPE_1xRTT: - case NETWORK_TYPE_IDEN: - return NETWORK_CLASS_2_G; - case NETWORK_TYPE_UMTS: - case NETWORK_TYPE_EVDO_0: - case NETWORK_TYPE_EVDO_A: - case NETWORK_TYPE_HSDPA: - case NETWORK_TYPE_HSUPA: - case NETWORK_TYPE_HSPA: - case NETWORK_TYPE_EVDO_B: - case NETWORK_TYPE_EHRPD: - case NETWORK_TYPE_HSPAP: - case NETWORK_TYPE_TD_SCDMA: - return NETWORK_CLASS_3_G; - case NETWORK_TYPE_LTE: - case NETWORK_TYPE_IWLAN: - case NETWORK_TYPE_LTE_CA: - return NETWORK_CLASS_4_G; - case NETWORK_TYPE_NR: - return NETWORK_CLASS_5_G; - default: - return NETWORK_CLASS_UNKNOWN; - } - } - - /** * Returns a string representation of the radio technology (network type) * currently in use on the device. * @return the name of the radio technology @@ -7933,21 +7874,19 @@ public class TelephonyManager { * app has carrier privileges (see {@link #hasCarrierPrivileges}). * * @param operatorNumeric the PLMN ID of the network to select. + * @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. * @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 + * network types specified by the preferred network types, 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) { + boolean persistSelection, @AccessNetworkConstants.RadioAccessNetworkType int ran) { return setNetworkSelectionModeManual(new OperatorInfo("" /* operatorAlphaLong */, "" /* operatorAlphaShort */, operatorNumeric, ran), persistSelection); } @@ -9808,32 +9747,12 @@ public class TelephonyManager { } /** - * Get baseband version for the default phone using the legacy approach. - * This change was added in P, to ensure backward compatiblity. - * - * @return baseband version. - * @hide - */ - private String getBasebandVersionLegacy(int phoneId) { - if (SubscriptionManager.isValidPhoneId(phoneId)) { - String prop = "gsm.version.baseband" - + ((phoneId == 0) ? "" : Integer.toString(phoneId)); - return SystemProperties.get(prop); - } - return null; - } - - /** * Get baseband version by phone id. * * @return baseband version. * @hide */ public String getBasebandVersionForPhone(int phoneId) { - String version = getBasebandVersionLegacy(phoneId); - if (version != null && !version.isEmpty()) { - setBasebandVersionForPhone(phoneId, version); - } return getTelephonyProperty(phoneId, TelephonyProperties.baseband_version(), ""); } @@ -11495,6 +11414,55 @@ public class TelephonyManager { @SystemApi public static final long NETWORK_TYPE_BITMASK_IWLAN = (1 << (NETWORK_TYPE_IWLAN -1)); + /** @hide */ + public static final long NETWORK_CLASS_BITMASK_2G = NETWORK_TYPE_BITMASK_GSM + | NETWORK_TYPE_BITMASK_GPRS + | NETWORK_TYPE_BITMASK_EDGE + | NETWORK_TYPE_BITMASK_CDMA + | NETWORK_TYPE_BITMASK_1xRTT; + + /** @hide */ + public static final long NETWORK_CLASS_BITMASK_3G = NETWORK_TYPE_BITMASK_EVDO_0 + | NETWORK_TYPE_BITMASK_EVDO_A + | NETWORK_TYPE_BITMASK_EVDO_B + | NETWORK_TYPE_BITMASK_EHRPD + | NETWORK_TYPE_BITMASK_HSUPA + | NETWORK_TYPE_BITMASK_HSDPA + | NETWORK_TYPE_BITMASK_HSPA + | NETWORK_TYPE_BITMASK_HSPAP + | NETWORK_TYPE_BITMASK_UMTS + | NETWORK_TYPE_BITMASK_TD_SCDMA; + + /** @hide */ + public static final long NETWORK_CLASS_BITMASK_4G = NETWORK_TYPE_BITMASK_LTE + | NETWORK_TYPE_BITMASK_LTE_CA + | NETWORK_TYPE_BITMASK_IWLAN; + + /** @hide */ + public static final long NETWORK_CLASS_BITMASK_5G = NETWORK_TYPE_BITMASK_NR; + + /** @hide */ + public static final long NETWORK_STANDARDS_FAMILY_BITMASK_3GPP = NETWORK_TYPE_BITMASK_GSM + | NETWORK_TYPE_BITMASK_GPRS + | NETWORK_TYPE_BITMASK_EDGE + | NETWORK_TYPE_BITMASK_HSUPA + | NETWORK_TYPE_BITMASK_HSDPA + | NETWORK_TYPE_BITMASK_HSPA + | NETWORK_TYPE_BITMASK_HSPAP + | NETWORK_TYPE_BITMASK_UMTS + | NETWORK_TYPE_BITMASK_TD_SCDMA + | NETWORK_TYPE_BITMASK_LTE + | NETWORK_TYPE_BITMASK_LTE_CA + | NETWORK_TYPE_BITMASK_NR; + + /** @hide */ + public static final long NETWORK_STANDARDS_FAMILY_BITMASK_3GPP2 = NETWORK_TYPE_BITMASK_CDMA + | NETWORK_TYPE_BITMASK_1xRTT + | NETWORK_TYPE_BITMASK_EVDO_0 + | NETWORK_TYPE_BITMASK_EVDO_A + | NETWORK_TYPE_BITMASK_EVDO_B + | NETWORK_TYPE_BITMASK_EHRPD; + /** * @return Modem supported radio access family bitmask * @@ -12189,6 +12157,17 @@ public class TelephonyManager { "android.telephony.extra.NETWORK_COUNTRY"; /** + * The extra used with an {@link #ACTION_NETWORK_COUNTRY_CHANGED} to specify the + * last known the country code in ISO-3166-1 alpha-2 format. + * <p class="note"> + * Retrieve with {@link android.content.Intent#getStringExtra(String)}. + * + * @hide + */ + public static final String EXTRA_LAST_KNOWN_NETWORK_COUNTRY = + "android.telephony.extra.LAST_KNOWN_NETWORK_COUNTRY"; + + /** * Indicate if the user is allowed to use multiple SIM cards at the same time to register * on the network (e.g. Dual Standby or Dual Active) when the device supports it, or if the * usage is restricted. This API is used to prevent usage of multiple SIM card, based on @@ -12625,7 +12604,6 @@ public class TelephonyManager { * * @hide */ - @SystemApi @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @NonNull public CallForwardingInfo getCallForwarding(@CallForwardingReason int callForwardingReason) { @@ -12672,7 +12650,6 @@ public class TelephonyManager { * * @hide */ - @SystemApi @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setCallForwarding(@NonNull CallForwardingInfo callForwardingInfo) { if (callForwardingInfo == null) { @@ -12713,7 +12690,6 @@ public class TelephonyManager { * * @hide */ - @SystemApi public static final int CALL_WAITING_STATUS_ACTIVE = 1; /** @@ -12721,7 +12697,6 @@ public class TelephonyManager { * * @hide */ - @SystemApi public static final int CALL_WAITING_STATUS_INACTIVE = 2; /** @@ -12729,7 +12704,6 @@ public class TelephonyManager { * * @hide */ - @SystemApi public static final int CALL_WAITING_STATUS_UNKNOWN_ERROR = 3; /** @@ -12737,10 +12711,24 @@ public class TelephonyManager { * * @hide */ - @SystemApi public static final int CALL_WAITING_STATUS_NOT_SUPPORTED = 4; /** + * Call waiting function status + * + * @hide + */ + @IntDef(prefix = { "CALL_WAITING_STATUS_" }, value = { + CALL_WAITING_STATUS_ACTIVE, + CALL_WAITING_STATUS_INACTIVE, + CALL_WAITING_STATUS_NOT_SUPPORTED, + CALL_WAITING_STATUS_UNKNOWN_ERROR + }) + @Retention(RetentionPolicy.SOURCE) + public @interface CallWaitingStatus { + } + + /** * Gets the status of voice call waiting function. Call waiting function enables the waiting * for the incoming call when it reaches the user who is busy to make another call and allows * users to decide whether to switch to the incoming call. @@ -12748,7 +12736,6 @@ public class TelephonyManager { * @return the status of call waiting function. * @hide */ - @SystemApi @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public @CallWaitingStatus int getCallWaitingStatus() { try { @@ -12774,7 +12761,6 @@ public class TelephonyManager { * * @hide */ - @SystemApi @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setCallWaitingStatus(boolean isEnable) { try { diff --git a/telephony/java/android/telephony/ims/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java index 9e466aea9776..1e8fdceac1e6 100644 --- a/telephony/java/android/telephony/ims/ImsCallProfile.java +++ b/telephony/java/android/telephony/ims/ImsCallProfile.java @@ -18,7 +18,6 @@ package android.telephony.ims; import android.annotation.IntDef; import android.annotation.NonNull; -import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; @@ -721,11 +720,16 @@ public final class ImsCallProfile implements Parcelable { * @return A {@link Bundle} containing proprietary call extras that were not set by the * platform. */ - public @Nullable Bundle getProprietaryCallExtras() { + public @NonNull Bundle getProprietaryCallExtras() { if (mCallExtras == null) { - return null; + return new Bundle(); + } + Bundle proprietaryExtras = mCallExtras.getBundle(EXTRA_OEM_EXTRAS); + if (proprietaryExtras == null) { + return new Bundle(); } - return mCallExtras.getBundle(EXTRA_OEM_EXTRAS); + // Make a copy so users do not accidentally change this copy of the extras. + return new Bundle(proprietaryExtras); } public ImsStreamMediaProfile getMediaProfile() { diff --git a/telephony/java/android/telephony/ims/ImsCallSessionListener.java b/telephony/java/android/telephony/ims/ImsCallSessionListener.java index 025721c89f70..81af99fb40b7 100644 --- a/telephony/java/android/telephony/ims/ImsCallSessionListener.java +++ b/telephony/java/android/telephony/ims/ImsCallSessionListener.java @@ -58,7 +58,7 @@ public class ImsCallSessionListener { try { mListener.callSessionProgressing(profile); } catch (RemoteException e) { - throw new RuntimeException(e); + e.rethrowFromSystemServer(); } } @@ -71,7 +71,7 @@ public class ImsCallSessionListener { try { mListener.callSessionInitiated(profile); } catch (RemoteException e) { - throw new RuntimeException(e); + e.rethrowFromSystemServer(); } } @@ -85,7 +85,7 @@ public class ImsCallSessionListener { try { mListener.callSessionInitiatedFailed(reasonInfo); } catch (RemoteException e) { - throw new RuntimeException(e); + e.rethrowFromSystemServer(); } } @@ -98,7 +98,7 @@ public class ImsCallSessionListener { try { mListener.callSessionTerminated(reasonInfo); } catch (RemoteException e) { - throw new RuntimeException(e); + e.rethrowFromSystemServer(); } } @@ -115,7 +115,7 @@ public class ImsCallSessionListener { try { mListener.callSessionHeld(profile); } catch (RemoteException e) { - throw new RuntimeException(e); + e.rethrowFromSystemServer(); } } @@ -128,7 +128,7 @@ public class ImsCallSessionListener { try { mListener.callSessionHoldFailed(reasonInfo); } catch (RemoteException e) { - throw new RuntimeException(e); + e.rethrowFromSystemServer(); } } @@ -141,7 +141,7 @@ public class ImsCallSessionListener { try { mListener.callSessionHoldReceived(profile); } catch (RemoteException e) { - throw new RuntimeException(e); + e.rethrowFromSystemServer(); } } @@ -155,7 +155,7 @@ public class ImsCallSessionListener { try { mListener.callSessionResumed(profile); } catch (RemoteException e) { - throw new RuntimeException(e); + e.rethrowFromSystemServer(); } } @@ -169,7 +169,7 @@ public class ImsCallSessionListener { try { mListener.callSessionResumeFailed(reasonInfo); } catch (RemoteException e) { - throw new RuntimeException(e); + e.rethrowFromSystemServer(); } } @@ -182,7 +182,7 @@ public class ImsCallSessionListener { try { mListener.callSessionResumeReceived(profile); } catch (RemoteException e) { - throw new RuntimeException(e); + e.rethrowFromSystemServer(); } } @@ -201,7 +201,7 @@ public class ImsCallSessionListener { mListener.callSessionMergeStarted(newSession != null ? newSession.getServiceImpl() : null, profile); } catch (RemoteException e) { - throw new RuntimeException(e); + e.rethrowFromSystemServer(); } } @@ -216,7 +216,7 @@ public class ImsCallSessionListener { try { mListener.callSessionMergeStarted(newSession, profile); } catch (RemoteException e) { - throw new RuntimeException(e); + e.rethrowFromSystemServer(); } } @@ -232,7 +232,7 @@ public class ImsCallSessionListener { mListener.callSessionMergeComplete(newSession != null ? newSession.getServiceImpl() : null); } catch (RemoteException e) { - throw new RuntimeException(e); + e.rethrowFromSystemServer(); } } @@ -247,7 +247,7 @@ public class ImsCallSessionListener { try { mListener.callSessionMergeComplete(newSession); } catch (RemoteException e) { - throw new RuntimeException(e); + e.rethrowFromSystemServer(); } } @@ -260,7 +260,7 @@ public class ImsCallSessionListener { try { mListener.callSessionMergeFailed(reasonInfo); } catch (RemoteException e) { - throw new RuntimeException(e); + e.rethrowFromSystemServer(); } } @@ -273,7 +273,7 @@ public class ImsCallSessionListener { try { mListener.callSessionUpdated(profile); } catch (RemoteException e) { - throw new RuntimeException(e); + e.rethrowFromSystemServer(); } } @@ -286,7 +286,7 @@ public class ImsCallSessionListener { try { mListener.callSessionUpdateFailed(reasonInfo); } catch (RemoteException e) { - throw new RuntimeException(e); + e.rethrowFromSystemServer(); } } @@ -299,7 +299,7 @@ public class ImsCallSessionListener { try { mListener.callSessionUpdateReceived(profile); } catch (RemoteException e) { - throw new RuntimeException(e); + e.rethrowFromSystemServer(); } } @@ -319,7 +319,7 @@ public class ImsCallSessionListener { mListener.callSessionConferenceExtended( newSession != null ? newSession.getServiceImpl() : null, profile); } catch (RemoteException e) { - throw new RuntimeException(e); + e.rethrowFromSystemServer(); } } @@ -333,7 +333,7 @@ public class ImsCallSessionListener { try { mListener.callSessionConferenceExtended(newSession, profile); } catch (RemoteException e) { - throw new RuntimeException(e); + e.rethrowFromSystemServer(); } } @@ -347,7 +347,7 @@ public class ImsCallSessionListener { try { mListener.callSessionConferenceExtendFailed(reasonInfo); } catch (RemoteException e) { - throw new RuntimeException(e); + e.rethrowFromSystemServer(); } } @@ -364,7 +364,7 @@ public class ImsCallSessionListener { mListener.callSessionConferenceExtendReceived(newSession != null ? newSession.getServiceImpl() : null, profile); } catch (RemoteException e) { - throw new RuntimeException(e); + e.rethrowFromSystemServer(); } } @@ -379,7 +379,7 @@ public class ImsCallSessionListener { try { mListener.callSessionConferenceExtendReceived(newSession, profile); } catch (RemoteException e) { - throw new RuntimeException(e); + e.rethrowFromSystemServer(); } } @@ -391,7 +391,7 @@ public class ImsCallSessionListener { try { mListener.callSessionInviteParticipantsRequestDelivered(); } catch (RemoteException e) { - throw new RuntimeException(e); + e.rethrowFromSystemServer(); } } @@ -407,7 +407,7 @@ public class ImsCallSessionListener { try { mListener.callSessionInviteParticipantsRequestFailed(reasonInfo); } catch (RemoteException e) { - throw new RuntimeException(e); + e.rethrowFromSystemServer(); } } @@ -419,7 +419,7 @@ public class ImsCallSessionListener { try { mListener.callSessionRemoveParticipantsRequestDelivered(); } catch (RemoteException e) { - throw new RuntimeException(e); + e.rethrowFromSystemServer(); } } @@ -435,7 +435,7 @@ public class ImsCallSessionListener { try { mListener.callSessionInviteParticipantsRequestFailed(reasonInfo); } catch (RemoteException e) { - throw new RuntimeException(e); + e.rethrowFromSystemServer(); } } @@ -448,7 +448,7 @@ public class ImsCallSessionListener { try { mListener.callSessionConferenceStateUpdated(state); } catch (RemoteException e) { - throw new RuntimeException(e); + e.rethrowFromSystemServer(); } } @@ -465,7 +465,7 @@ public class ImsCallSessionListener { try { mListener.callSessionUssdMessageReceived(mode, ussdMessage); } catch (RemoteException e) { - throw new RuntimeException(e); + e.rethrowFromSystemServer(); } } @@ -501,7 +501,7 @@ public class ImsCallSessionListener { try { mListener.callSessionMayHandover(srcNetworkType, targetNetworkType); } catch (RemoteException e) { - throw new RuntimeException(e); + e.rethrowFromSystemServer(); } } @@ -537,7 +537,7 @@ public class ImsCallSessionListener { try { mListener.callSessionHandover(srcNetworkType, targetNetworkType, reasonInfo); } catch (RemoteException e) { - throw new RuntimeException(e); + e.rethrowFromSystemServer(); } } @@ -570,7 +570,7 @@ public class ImsCallSessionListener { try { mListener.callSessionHandoverFailed(srcNetworkType, targetNetworkType, reasonInfo); } catch (RemoteException e) { - throw new RuntimeException(e); + e.rethrowFromSystemServer(); } } @@ -587,7 +587,7 @@ public class ImsCallSessionListener { try { mListener.callSessionTtyModeReceived(mode); } catch (RemoteException e) { - throw new RuntimeException(e); + e.rethrowFromSystemServer(); } } @@ -600,7 +600,7 @@ public class ImsCallSessionListener { try { mListener.callSessionMultipartyStateChanged(isMultiParty); } catch (RemoteException e) { - throw new RuntimeException(e); + e.rethrowFromSystemServer(); } } @@ -614,7 +614,7 @@ public class ImsCallSessionListener { try { mListener.callSessionSuppServiceReceived(suppSrvNotification); } catch (RemoteException e) { - throw new RuntimeException(e); + e.rethrowFromSystemServer(); } } @@ -628,7 +628,7 @@ public class ImsCallSessionListener { try { mListener.callSessionRttModifyRequestReceived(callProfile); } catch (RemoteException e) { - throw new RuntimeException(e); + e.rethrowFromSystemServer(); } } @@ -641,7 +641,7 @@ public class ImsCallSessionListener { try { mListener.callSessionRttModifyResponseReceived(status); } catch (RemoteException e) { - throw new RuntimeException(e); + e.rethrowFromSystemServer(); } } @@ -654,7 +654,7 @@ public class ImsCallSessionListener { try { mListener.callSessionRttMessageReceived(rttMessage); } catch (RemoteException e) { - throw new RuntimeException(e); + e.rethrowFromSystemServer(); } } @@ -667,7 +667,7 @@ public class ImsCallSessionListener { try { mListener.callSessionRttAudioIndicatorChanged(profile); } catch (RemoteException e) { - throw new RuntimeException(e); + e.rethrowFromSystemServer(); } } @@ -680,7 +680,7 @@ public class ImsCallSessionListener { try { mListener.callQualityChanged(callQuality); } catch (RemoteException e) { - throw new RuntimeException(e); + e.rethrowFromSystemServer(); } } } diff --git a/telephony/java/android/telephony/ims/ImsException.java b/telephony/java/android/telephony/ims/ImsException.java index 643f452d2e75..1c3d58d98b4a 100644 --- a/telephony/java/android/telephony/ims/ImsException.java +++ b/telephony/java/android/telephony/ims/ImsException.java @@ -47,11 +47,12 @@ public final class ImsException extends Exception { public static final int CODE_ERROR_SERVICE_UNAVAILABLE = 1; /** - * This device or carrier configuration does not support IMS for this subscription. + * This device or carrier configuration does not support this feature for this subscription. * <p> - * This is a permanent configuration error and there should be no retry. Usually this is - * because {@link PackageManager#FEATURE_TELEPHONY_IMS} is not available - * or the device has no ImsService implementation to service this request. + * This is a permanent configuration error and there should be no retry until the subscription + * changes if this operation is denied due to a carrier configuration. If this is due to a + * device configuration, the feature {@link PackageManager#FEATURE_TELEPHONY_IMS} is not + * available or the device has no ImsService implementation to service this request. */ public static final int CODE_ERROR_UNSUPPORTED_OPERATION = 2; diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java index 494009f35dba..dc8d750f6be4 100644 --- a/telephony/java/android/telephony/ims/ImsMmTelManager.java +++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java @@ -21,7 +21,6 @@ import android.Manifest; import android.annotation.CallbackExecutor; import android.annotation.IntDef; import android.annotation.NonNull; -import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SuppressAutoDoc; import android.annotation.SuppressLint; @@ -125,7 +124,7 @@ public class ImsMmTelManager implements RegistrationManager { * @param info the {@link ImsReasonInfo} associated with why registration was disconnected. */ @Override - public void onUnregistered(@Nullable ImsReasonInfo info) { + public void onUnregistered(@NonNull ImsReasonInfo info) { } /** @@ -137,7 +136,7 @@ public class ImsMmTelManager implements RegistrationManager { @Override public void onTechnologyChangeFailed( @AccessNetworkConstants.TransportType int imsTransportType, - @Nullable ImsReasonInfo info) { + @NonNull ImsReasonInfo info) { } } diff --git a/telephony/java/android/telephony/ims/ImsRcsManager.java b/telephony/java/android/telephony/ims/ImsRcsManager.java index a2ad21c03f98..ed9b94b3d85e 100644 --- a/telephony/java/android/telephony/ims/ImsRcsManager.java +++ b/telephony/java/android/telephony/ims/ImsRcsManager.java @@ -20,14 +20,16 @@ import android.Manifest; import android.annotation.CallbackExecutor; import android.annotation.NonNull; import android.annotation.RequiresPermission; -import android.annotation.SystemApi; -import android.annotation.TestApi; +import android.annotation.SdkConstant; import android.content.Context; +import android.content.Intent; import android.os.Binder; import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; +import android.provider.Settings; import android.telephony.AccessNetworkConstants; +import android.telephony.CarrierConfigManager; import android.telephony.SubscriptionManager; import android.telephony.ims.aidl.IImsCapabilityCallback; import android.telephony.ims.aidl.IImsRcsController; @@ -46,14 +48,34 @@ import java.util.function.Consumer; * (UCE) service, as well as managing user settings. * * Use {@link ImsManager#getImsRcsManager(int)} to create an instance of this manager. - * @hide */ -@SystemApi -@TestApi public class ImsRcsManager implements RegistrationManager { private static final String TAG = "ImsRcsManager"; /** + * Activity Action: Show the opt-in dialog for enabling or disabling RCS contact discovery + * using User Capability Exchange (UCE). + * <p> + * An application that depends on contact discovery being enabled may send this intent + * using {@link Context#startActivity(Intent)} to ask the user to opt-in for contacts upload for + * capability exchange if it is currently disabled. Whether or not this setting has been enabled + * can be queried using {@link RcsUceAdapter#isUceSettingEnabled()}. + * <p> + * This intent should only be sent if the carrier supports RCS capability exchange, which can be + * queried using the key {@link CarrierConfigManager#KEY_USE_RCS_PRESENCE_BOOL}. Otherwise, the + * setting will not be present. + * <p> + * Input: A mandatory {@link Settings#EXTRA_SUB_ID} extra containing the subscription that the + * setting will be be shown for. + * <p> + * Output: Nothing + * @see RcsUceAdapter + */ + @SdkConstant(SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_SHOW_CAPABILITY_DISCOVERY_OPT_IN = + "android.telephony.ims.action.SHOW_CAPABILITY_DISCOVERY_OPT_IN"; + + /** * Receives RCS availability status updates from the ImsService. * * @see #isAvailable(int) @@ -145,11 +167,10 @@ public class ImsRcsManager implements RegistrationManager { */ @NonNull public RcsUceAdapter getUceAdapter() { - return new RcsUceAdapter(mSubId); + return new RcsUceAdapter(mContext, mSubId); } /** - * {@inheritDoc} * @hide */ @Override @@ -181,7 +202,6 @@ public class ImsRcsManager implements RegistrationManager { } /** - * {@inheritDoc * @hide */ @Override @@ -206,7 +226,6 @@ public class ImsRcsManager implements RegistrationManager { } /** - * {@inheritDoc} * @hide */ @Override @@ -239,7 +258,6 @@ public class ImsRcsManager implements RegistrationManager { } /** - * {@inheritDoc} * @hide */ @Override diff --git a/telephony/java/android/telephony/ims/ImsUtListener.java b/telephony/java/android/telephony/ims/ImsUtListener.java index bc12404461c7..460a032ce7e0 100644 --- a/telephony/java/android/telephony/ims/ImsUtListener.java +++ b/telephony/java/android/telephony/ims/ImsUtListener.java @@ -49,7 +49,8 @@ public class ImsUtListener { * {@link ImsSsInfo#CLIR_STATUS_TEMPORARILY_RESTRICTED}, and * {@link ImsSsInfo#CLIR_STATUS_TEMPORARILY_ALLOWED}. * @deprecated Use {@link #onLineIdentificationSupplementaryServiceResponse(int, ImsSsInfo)} - * instead. + * instead, this key has been added for backwards compatibility with older proprietary + * implementations only and is being phased out. */ @Deprecated public static final String BUNDLE_KEY_CLIR = "queryClir"; @@ -60,7 +61,8 @@ public class ImsUtListener { * response. The value will be an instance of {@link ImsSsInfo}, which contains the response to * the query. * @deprecated Use {@link #onLineIdentificationSupplementaryServiceResponse(int, ImsSsInfo)} - * instead. + * instead, this key has been added for backwards compatibility with older proprietary + * implementations only and is being phased out. */ @Deprecated public static final String BUNDLE_KEY_SSINFO = "imsSsInfo"; @@ -123,7 +125,7 @@ public class ImsUtListener { try { mServiceInterface.lineIdentificationSupplementaryServiceResponse(id, configuration); } catch (RemoteException e) { - Log.w(LOG_TAG, "onLineIdentificationSupplementaryServicesResponse: remote exception"); + e.rethrowFromSystemServer(); } } diff --git a/telephony/java/android/telephony/ims/ProvisioningManager.java b/telephony/java/android/telephony/ims/ProvisioningManager.java index 6125001850db..ad54cbf3daea 100644 --- a/telephony/java/android/telephony/ims/ProvisioningManager.java +++ b/telephony/java/android/telephony/ims/ProvisioningManager.java @@ -306,13 +306,13 @@ public class ProvisioningManager { /** * An integer key associated with the carrier configured expiration time in seconds for - * RCS presence published offline availability in RCS presence. + * published offline availability in RCS presence provided, which is provided to the network. * <p> * Value is in Integer format. * @see #setProvisioningIntValue(int, int) * @see #getProvisioningIntValue(int) */ - public static final int KEY_RCS_PUBLISH_TIMER_EXTENDED_SEC = 16; + public static final int KEY_RCS_PUBLISH_OFFLINE_AVAILABILITY_TIMER_SEC = 16; /** * An integer key associated with whether or not capability discovery is provisioned for this @@ -327,8 +327,10 @@ public class ProvisioningManager { public static final int KEY_RCS_CAPABILITY_DISCOVERY_ENABLED = 17; /** - * An integer key associated with the period of time the capability information of each contact - * is cached on the device. + * An integer key associated with the period of time in seconds the capability information of + * each contact is cached on the device. + * <p> + * Seconds are used because this is usually measured in the span of days. * <p> * Value is in Integer format. * @see #setProvisioningIntValue(int, int) @@ -338,7 +340,8 @@ public class ProvisioningManager { /** * An integer key associated with the period of time in seconds that the availability - * information of a contact is cached on the device. + * information of a contact is cached on the device, which is based on the carrier provisioning + * configuration from the network. * <p> * Value is in Integer format. * @see #setProvisioningIntValue(int, int) @@ -348,7 +351,8 @@ public class ProvisioningManager { /** * An integer key associated with the carrier configured interval in seconds expected between - * successive capability polling attempts. + * successive capability polling attempts, which is based on the carrier provisioning + * configuration from the network. * <p> * Value is in Integer format. * @see #setProvisioningIntValue(int, int) @@ -358,7 +362,7 @@ public class ProvisioningManager { /** * An integer key representing the minimum time allowed between two consecutive presence publish - * messages from the device. + * messages from the device in milliseconds. * <p> * Value is in Integer format. * @see #setProvisioningIntValue(int, int) @@ -379,7 +383,7 @@ public class ProvisioningManager { /** * An integer associated with the expiration timer used during the SIP subscription of a * Request Contained List (RCL), which is used to retrieve the RCS capabilities of the contact - * book. + * book. This timer value is sent in seconds to the network. * <p> * Value is in Integer format. * @see #setProvisioningIntValue(int, int) @@ -471,7 +475,8 @@ public class ProvisioningManager { public static final int KEY_SIP_KEEP_ALIVE_ENABLED = 32; /** - * Registration retry Base Time value in seconds. + * Registration retry Base Time value in seconds, which is based off of the carrier + * configuration. * Value is in Integer format. * @see #setProvisioningIntValue(int, int) * @see #getProvisioningIntValue(int) @@ -479,7 +484,8 @@ public class ProvisioningManager { public static final int KEY_REGISTRATION_RETRY_BASE_TIME_SEC = 33; /** - * Registration retry Max Time value in seconds. + * Registration retry Max Time value in seconds, which is based off of the carrier + * configuration. * Value is in Integer format. * @see #setProvisioningIntValue(int, int) * @see #getProvisioningIntValue(int) diff --git a/telephony/java/android/telephony/ims/RcsUceAdapter.java b/telephony/java/android/telephony/ims/RcsUceAdapter.java index 32fd8638f761..70edb758bb70 100644 --- a/telephony/java/android/telephony/ims/RcsUceAdapter.java +++ b/telephony/java/android/telephony/ims/RcsUceAdapter.java @@ -43,10 +43,7 @@ import java.util.concurrent.Executor; * Manages RCS User Capability Exchange for the subscription specified. * * @see ImsRcsManager#getUceAdapter() for information on creating an instance of this class. - * @hide */ -@SystemApi -@TestApi public class RcsUceAdapter { private static final String TAG = "RcsUceAdapter"; @@ -216,6 +213,7 @@ public class RcsUceAdapter { } } + private final Context mContext; private final int mSubId; /** @@ -223,7 +221,8 @@ public class RcsUceAdapter { * {@link ImsRcsManager#getUceAdapter()} to instantiate this manager class. * @hide */ - RcsUceAdapter(int subId) { + RcsUceAdapter(Context context, int subId) { + mContext = context; mSubId = subId; } @@ -291,7 +290,8 @@ public class RcsUceAdapter { }; try { - imsRcsController.requestCapabilities(mSubId, contactNumbers, internalCallback); + imsRcsController.requestCapabilities(mSubId, mContext.getOpPackageName(), + null /*featureId*/, contactNumbers, internalCallback); } catch (RemoteException e) { Log.e(TAG, "Error calling IImsRcsController#requestCapabilities", e); throw new ImsException("Remote IMS Service is not available", @@ -341,7 +341,7 @@ public class RcsUceAdapter { * available. This can happen if the ImsService has crashed, for example, or if the subscription * becomes inactive. See {@link ImsException#getCode()} for more information on the error codes. */ - @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + @RequiresPermission(Manifest.permission.READ_PHONE_STATE) public boolean isUceSettingEnabled() throws ImsException { IImsRcsController imsRcsController = getIImsRcsController(); if (imsRcsController == null) { @@ -349,9 +349,10 @@ public class RcsUceAdapter { throw new ImsException("Can not find remote IMS service", ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); } - try { - return imsRcsController.isUceSettingEnabled(mSubId); + // Telephony.SimInfo#IMS_RCS_UCE_ENABLED can also be used to listen to changes to this. + return imsRcsController.isUceSettingEnabled(mSubId, mContext.getOpPackageName(), + null /*featureId*/); } catch (RemoteException e) { Log.e(TAG, "Error calling IImsRcsController#isUceSettingEnabled", e); throw new ImsException("Remote IMS Service is not available", @@ -362,6 +363,10 @@ public class RcsUceAdapter { /** * Change the user’s setting for whether or not UCE is enabled for the associated subscription. * <p> + * If an application Requires UCE, they may launch an Activity using the Intent + * {@link ImsRcsManager#ACTION_SHOW_CAPABILITY_DISCOVERY_OPT_IN}, which will ask the user if + * they wish to enable this feature. + * <p> * Note: This setting does not affect whether or not the device publishes its service * capabilities if the subscription supports presence publication. * @@ -371,7 +376,10 @@ public class RcsUceAdapter { * {@link RcsUceAdapter} is valid, but the ImsService associated with the subscription is not * available. This can happen if the ImsService has crashed, for example, or if the subscription * becomes inactive. See {@link ImsException#getCode()} for more information on the error codes. + * @hide */ + @SystemApi + @TestApi @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) public void setUceSettingEnabled(boolean isEnabled) throws ImsException { IImsRcsController imsRcsController = getIImsRcsController(); diff --git a/telephony/java/android/telephony/ims/RegistrationManager.java b/telephony/java/android/telephony/ims/RegistrationManager.java index 5c86ba732701..1dbaff5df802 100644 --- a/telephony/java/android/telephony/ims/RegistrationManager.java +++ b/telephony/java/android/telephony/ims/RegistrationManager.java @@ -196,11 +196,11 @@ public interface RegistrationManager { } /** - * Notifies the framework when the IMS Provider is deregistered from the IMS network. + * Notifies the framework when the IMS Provider is unregistered from the IMS network. * * @param info the {@link ImsReasonInfo} associated with why registration was disconnected. */ - public void onUnregistered(@Nullable ImsReasonInfo info) { + public void onUnregistered(@NonNull ImsReasonInfo info) { } /** @@ -211,7 +211,7 @@ public interface RegistrationManager { */ public void onTechnologyChangeFailed( @AccessNetworkConstants.TransportType int imsTransportType, - @Nullable ImsReasonInfo info) { + @NonNull ImsReasonInfo info) { } /** diff --git a/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl b/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl index 6f6aa44371fa..483c66eedc0c 100644 --- a/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl +++ b/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl @@ -42,8 +42,9 @@ interface IImsRcsController { boolean isAvailable(int subId, int capability); // ImsUceAdapter specific - void requestCapabilities(int subId, in List<Uri> contactNumbers, IRcsUceControllerCallback c); + void requestCapabilities(int subId, String callingPackage, String callingFeatureId, + in List<Uri> contactNumbers, IRcsUceControllerCallback c); int getUcePublishState(int subId); - boolean isUceSettingEnabled(int subId); + boolean isUceSettingEnabled(int subId, String callingPackage, String callingFeatureId); void setUceSettingEnabled(int subId, boolean isEnabled); } diff --git a/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java index 14a64d2585ed..7069e0ab9b1e 100644 --- a/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java +++ b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java @@ -175,9 +175,11 @@ public class ImsRegistrationImplBase { */ public final void onDeregistered(ImsReasonInfo info) { updateToDisconnectedState(info); + // ImsReasonInfo should never be null. + final ImsReasonInfo reasonInfo = (info != null) ? info : new ImsReasonInfo(); mCallbacks.broadcastAction((c) -> { try { - c.onDeregistered(info); + c.onDeregistered(reasonInfo); } catch (RemoteException e) { Log.w(LOG_TAG, e + " " + "onRegistrationDisconnected() - Skipping " + "callback."); @@ -194,9 +196,10 @@ public class ImsRegistrationImplBase { */ public final void onTechnologyChangeFailed(@ImsRegistrationTech int imsRadioTech, ImsReasonInfo info) { + final ImsReasonInfo reasonInfo = (info != null) ? info : new ImsReasonInfo(); mCallbacks.broadcastAction((c) -> { try { - c.onTechnologyChangeFailed(imsRadioTech, info); + c.onTechnologyChangeFailed(imsRadioTech, reasonInfo); } catch (RemoteException e) { Log.w(LOG_TAG, e + " " + "onRegistrationChangeFailed() - Skipping " + "callback."); diff --git a/telephony/java/com/android/ims/ImsConfig.java b/telephony/java/com/android/ims/ImsConfig.java index 96f77d809183..d0cec52dfc86 100644 --- a/telephony/java/com/android/ims/ImsConfig.java +++ b/telephony/java/com/android/ims/ImsConfig.java @@ -270,11 +270,12 @@ public class ImsConfig { /** * Requested expiration for Published Offline availability. * Value is in Integer format. - * @deprecated use {@link ProvisioningManager#KEY_RCS_PUBLISH_TIMER_EXTENDED_SEC}. + * @deprecated use + * {@link ProvisioningManager#KEY_RCS_PUBLISH_OFFLINE_AVAILABILITY_TIMER_SEC}. */ @Deprecated public static final int PUBLISH_TIMER_EXTENDED = - ProvisioningManager.KEY_RCS_PUBLISH_TIMER_EXTENDED_SEC; + ProvisioningManager.KEY_RCS_PUBLISH_OFFLINE_AVAILABILITY_TIMER_SEC; /** * diff --git a/tests/net/common/java/android/net/LinkPropertiesTest.java b/tests/net/common/java/android/net/LinkPropertiesTest.java index 2b5720a47eb6..8de27e8eb281 100644 --- a/tests/net/common/java/android/net/LinkPropertiesTest.java +++ b/tests/net/common/java/android/net/LinkPropertiesTest.java @@ -445,14 +445,20 @@ public class LinkPropertiesTest { // Check comparisons work. LinkProperties lp2 = new LinkProperties(lp); assertAllRoutesHaveInterface("wlan0", lp2); - assertEquals(0, lp.compareAllRoutes(lp2).added.size()); - assertEquals(0, lp.compareAllRoutes(lp2).removed.size()); + // LinkProperties#compareAllRoutes exists both in R and before R, but the return type + // changed in R, so a test compiled with the R version of LinkProperties cannot run on Q. + if (isAtLeastR()) { + assertEquals(0, lp.compareAllRoutes(lp2).added.size()); + assertEquals(0, lp.compareAllRoutes(lp2).removed.size()); + } lp2.setInterfaceName("p2p0"); assertAllRoutesHaveInterface("p2p0", lp2); assertAllRoutesNotHaveInterface("wlan0", lp2); - assertEquals(3, lp.compareAllRoutes(lp2).added.size()); - assertEquals(3, lp.compareAllRoutes(lp2).removed.size()); + if (isAtLeastR()) { + assertEquals(3, lp.compareAllRoutes(lp2).added.size()); + assertEquals(3, lp.compareAllRoutes(lp2).removed.size()); + } // Remove route with incorrect interface, no route removed. lp.removeRoute(new RouteInfo(prefix2, null, null)); @@ -480,6 +486,8 @@ public class LinkPropertiesTest { assertEquals(1, rmnet0.getLinkAddresses().size()); assertEquals(1, rmnet0.getAllAddresses().size()); assertEquals(1, rmnet0.getAllLinkAddresses().size()); + assertEquals(1, rmnet0.getAllInterfaceNames().size()); + assertEquals("rmnet0", rmnet0.getAllInterfaceNames().get(0)); rmnet0.addStackedLink(clat4); assertEquals(1, rmnet0.getStackedLinks().size()); @@ -487,6 +495,9 @@ public class LinkPropertiesTest { assertEquals(1, rmnet0.getLinkAddresses().size()); assertEquals(2, rmnet0.getAllAddresses().size()); assertEquals(2, rmnet0.getAllLinkAddresses().size()); + assertEquals(2, rmnet0.getAllInterfaceNames().size()); + assertEquals("rmnet0", rmnet0.getAllInterfaceNames().get(0)); + assertEquals("clat4", rmnet0.getAllInterfaceNames().get(1)); rmnet0.addStackedLink(clat4); assertEquals(1, rmnet0.getStackedLinks().size()); @@ -494,6 +505,9 @@ public class LinkPropertiesTest { assertEquals(1, rmnet0.getLinkAddresses().size()); assertEquals(2, rmnet0.getAllAddresses().size()); assertEquals(2, rmnet0.getAllLinkAddresses().size()); + assertEquals(2, rmnet0.getAllInterfaceNames().size()); + assertEquals("rmnet0", rmnet0.getAllInterfaceNames().get(0)); + assertEquals("clat4", rmnet0.getAllInterfaceNames().get(1)); assertEquals(0, clat4.getStackedLinks().size()); @@ -513,6 +527,8 @@ public class LinkPropertiesTest { assertEquals(1, rmnet0.getLinkAddresses().size()); assertEquals(1, rmnet0.getAllAddresses().size()); assertEquals(1, rmnet0.getAllLinkAddresses().size()); + assertEquals(1, rmnet0.getAllInterfaceNames().size()); + assertEquals("rmnet0", rmnet0.getAllInterfaceNames().get(0)); assertFalse(rmnet0.removeStackedLink("clat4")); } @@ -936,7 +952,7 @@ public class LinkPropertiesTest { } - @Test + @Test @IgnoreUpTo(Build.VERSION_CODES.Q) public void testCompareResult() { // Either adding or removing items compareResult(Arrays.asList(1, 2, 3, 4), Arrays.asList(1), @@ -1197,4 +1213,48 @@ public class LinkPropertiesTest { lp.clear(); assertNull(lp.getCaptivePortalData()); } + + private LinkProperties makeIpv4LinkProperties() { + final LinkProperties linkProperties = new LinkProperties(); + linkProperties.setInterfaceName(NAME); + linkProperties.addLinkAddress(LINKADDRV4); + linkProperties.addDnsServer(DNS1); + linkProperties.addRoute(new RouteInfo(GATEWAY1)); + linkProperties.addRoute(new RouteInfo(GATEWAY2)); + return linkProperties; + } + + private LinkProperties makeIpv6LinkProperties() { + final LinkProperties linkProperties = new LinkProperties(); + linkProperties.setInterfaceName(NAME); + linkProperties.addLinkAddress(LINKADDRV6); + linkProperties.addDnsServer(DNS6); + linkProperties.addRoute(new RouteInfo(GATEWAY61)); + linkProperties.addRoute(new RouteInfo(GATEWAY62)); + return linkProperties; + } + + @Test + public void testHasIpv4DefaultRoute() { + final LinkProperties Ipv4 = makeIpv4LinkProperties(); + assertTrue(Ipv4.hasIpv4DefaultRoute()); + final LinkProperties Ipv6 = makeIpv6LinkProperties(); + assertFalse(Ipv6.hasIpv4DefaultRoute()); + } + + @Test + public void testHasIpv4DnsServer() { + final LinkProperties Ipv4 = makeIpv4LinkProperties(); + assertTrue(Ipv4.hasIpv4DnsServer()); + final LinkProperties Ipv6 = makeIpv6LinkProperties(); + assertFalse(Ipv6.hasIpv4DnsServer()); + } + + @Test + public void testHasIpv6DnsServer() { + final LinkProperties Ipv4 = makeIpv4LinkProperties(); + assertFalse(Ipv4.hasIpv6DnsServer()); + final LinkProperties Ipv6 = makeIpv6LinkProperties(); + assertTrue(Ipv6.hasIpv6DnsServer()); + } } diff --git a/tests/net/common/java/android/net/MatchAllNetworkSpecifierTest.kt b/tests/net/common/java/android/net/MatchAllNetworkSpecifierTest.kt new file mode 100644 index 000000000000..ef15b668e24c --- /dev/null +++ b/tests/net/common/java/android/net/MatchAllNetworkSpecifierTest.kt @@ -0,0 +1,50 @@ +/* + * 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 + +import android.net.wifi.aware.DiscoverySession +import android.net.wifi.aware.PeerHandle +import android.net.wifi.aware.WifiAwareNetworkSpecifier +import androidx.test.filters.SmallTest +import androidx.test.runner.AndroidJUnit4 + +import com.android.testutils.assertParcelSane + +import java.lang.IllegalStateException + +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mockito + +@RunWith(AndroidJUnit4::class) +@SmallTest +class MatchAllNetworkSpecifierTest { + @Test + fun testParcel() { + assertParcelSane(MatchAllNetworkSpecifier(), 0) + } + + @Test(expected = IllegalStateException::class) + fun testSatisfiedBy() { + val specifier = MatchAllNetworkSpecifier() + val discoverySession = Mockito.mock(DiscoverySession::class.java) + val peerHandle = Mockito.mock(PeerHandle::class.java) + val wifiAwareNetworkSpecifier = WifiAwareNetworkSpecifier.Builder(discoverySession, + peerHandle).build() + specifier.satisfiedBy(wifiAwareNetworkSpecifier) + } +} diff --git a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java index 9fe1883010b7..916c33981171 100644 --- a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java +++ b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java @@ -463,7 +463,9 @@ public class NetworkCapabilitiesTest { nc1.setSSID(TEST_SSID); nc2.combineCapabilities(nc1); - assertTrue(TEST_SSID.equals(nc2.getSSID())); + if (isAtLeastR()) { + assertTrue(TEST_SSID.equals(nc2.getSsid())); + } // Because they now have the same SSID, the following call should not throw nc2.combineCapabilities(nc1); @@ -601,12 +603,16 @@ public class NetworkCapabilitiesTest { // from nc2. assertFalse(nc2.hasCapability(NET_CAPABILITY_NOT_ROAMING)); assertTrue(nc2.hasUnwantedCapability(NET_CAPABILITY_NOT_ROAMING)); - assertTrue(TEST_SSID.equals(nc2.getSSID())); + if (isAtLeastR()) { + assertTrue(TEST_SSID.equals(nc2.getSsid())); + } nc1.setSSID(DIFFERENT_TEST_SSID); nc2.set(nc1); assertEquals(nc1, nc2); - assertTrue(DIFFERENT_TEST_SSID.equals(nc2.getSSID())); + if (isAtLeastR()) { + assertTrue(DIFFERENT_TEST_SSID.equals(nc2.getSsid())); + } nc1.setUids(uidRange(10, 13)); nc2.set(nc1); // Overwrites, as opposed to combineCapabilities diff --git a/tests/net/common/java/android/net/apf/ApfCapabilitiesTest.java b/tests/net/common/java/android/net/apf/ApfCapabilitiesTest.java index f4f804aff08d..84805442e5c7 100644 --- a/tests/net/common/java/android/net/apf/ApfCapabilitiesTest.java +++ b/tests/net/common/java/android/net/apf/ApfCapabilitiesTest.java @@ -21,17 +21,31 @@ import static com.android.testutils.ParcelUtilsKt.assertParcelSane; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import android.content.Context; + +import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import java.util.Arrays; + @RunWith(AndroidJUnit4.class) @SmallTest public class ApfCapabilitiesTest { + private Context mContext; + + @Before + public void setUp() { + mContext = InstrumentationRegistry.getContext(); + } + @Test public void testConstructAndParcel() { final ApfCapabilities caps = new ApfCapabilities(123, 456, 789); @@ -59,4 +73,27 @@ public class ApfCapabilitiesTest { caps = new ApfCapabilities(4 /* apfVersionSupported */, 5, 6); assertTrue(caps.hasDataAccess()); } + + @Test + public void testGetApfDrop8023Frames() { + // Get com.android.internal.R.bool.config_apfDrop802_3Frames. The test cannot directly + // use R.bool.config_apfDrop802_3Frames because that is not a stable resource ID. + final int resId = mContext.getResources().getIdentifier("config_apfDrop802_3Frames", + "bool", "android"); + final boolean shouldDrop8023Frames = mContext.getResources().getBoolean(resId); + final boolean actual = ApfCapabilities.getApfDrop8023Frames(); + assertEquals(shouldDrop8023Frames, actual); + } + + @Test + public void testGetApfEtherTypeBlackList() { + // Get com.android.internal.R.array.config_apfEthTypeBlackList. The test cannot directly + // use R.array.config_apfEthTypeBlackList because that is not a stable resource ID. + final int resId = mContext.getResources().getIdentifier("config_apfEthTypeBlackList", + "array", "android"); + final int[] blacklistedEtherTypeArray = mContext.getResources().getIntArray(resId); + final int[] actual = ApfCapabilities.getApfEtherTypeBlackList(); + assertNotNull(actual); + assertTrue(Arrays.equals(blacklistedEtherTypeArray, actual)); + } } diff --git a/tests/net/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt b/tests/net/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt index 23caf4952991..eec3cdbe8d7f 100644 --- a/tests/net/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt +++ b/tests/net/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt @@ -24,7 +24,6 @@ import android.net.Network import android.net.metrics.IpConnectivityLog import android.net.util.SharedLog import android.os.IBinder -import com.android.networkstack.metrics.DataStallStatsUtils import com.android.networkstack.netlink.TcpSocketTracker import com.android.server.NetworkStackService import com.android.server.NetworkStackService.NetworkMonitorConnector @@ -91,7 +90,6 @@ class TestNetworkStackService : Service() { mock(IpConnectivityLog::class.java), mock(SharedLog::class.java), mock(NetworkStackService.NetworkStackServiceManager::class.java), NetworkMonitorDeps(privateDnsBypassNetwork), - mock(DataStallStatsUtils::class.java), mock(TcpSocketTracker::class.java)) cb.onNetworkMonitorCreated(NetworkMonitorConnector(nm, TestPermissionChecker())) } diff --git a/tests/net/java/android/net/TcpKeepalivePacketDataTest.java b/tests/net/java/android/net/TcpKeepalivePacketDataTest.java index e632aafde70e..cea8c5713a6b 100644 --- a/tests/net/java/android/net/TcpKeepalivePacketDataTest.java +++ b/tests/net/java/android/net/TcpKeepalivePacketDataTest.java @@ -66,10 +66,10 @@ public final class TcpKeepalivePacketDataTest { fail("InvalidPacketException: " + e); } - assertEquals(InetAddress.getByAddress(testInfo.srcAddress), resultData.srcAddress); - assertEquals(InetAddress.getByAddress(testInfo.dstAddress), resultData.dstAddress); - assertEquals(testInfo.srcPort, resultData.srcPort); - assertEquals(testInfo.dstPort, resultData.dstPort); + assertEquals(InetAddress.getByAddress(testInfo.srcAddress), resultData.getSrcAddress()); + assertEquals(InetAddress.getByAddress(testInfo.dstAddress), resultData.getDstAddress()); + assertEquals(testInfo.srcPort, resultData.getSrcPort()); + assertEquals(testInfo.dstPort, resultData.getDstPort()); assertEquals(testInfo.seq, resultData.tcpSeq); assertEquals(testInfo.ack, resultData.tcpAck); assertEquals(testInfo.rcvWnd, resultData.tcpWnd); diff --git a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java index 71b72b84de81..23098ec067d2 100644 --- a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java +++ b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java @@ -46,6 +46,7 @@ import android.net.LinkAddress; import android.net.Network; import android.net.NetworkUtils; import android.os.Binder; +import android.os.INetworkManagementService; import android.os.ParcelFileDescriptor; import android.system.Os; import android.test.mock.MockContext; @@ -135,6 +136,7 @@ public class IpSecServiceParameterizedTest { }; INetd mMockNetd; + INetworkManagementService mNetworkManager; PackageManager mMockPkgMgr; IpSecService.IpSecServiceConfiguration mMockIpSecSrvConfig; IpSecService mIpSecService; @@ -160,9 +162,10 @@ public class IpSecServiceParameterizedTest { @Before public void setUp() throws Exception { mMockNetd = mock(INetd.class); + mNetworkManager = mock(INetworkManagementService.class); mMockPkgMgr = mock(PackageManager.class); mMockIpSecSrvConfig = mock(IpSecService.IpSecServiceConfiguration.class); - mIpSecService = new IpSecService(mMockContext, mMockIpSecSrvConfig); + mIpSecService = new IpSecService(mMockContext, mNetworkManager, mMockIpSecSrvConfig); // Injecting mock netd when(mMockIpSecSrvConfig.getNetdInstance()).thenReturn(mMockNetd); @@ -609,6 +612,7 @@ public class IpSecServiceParameterizedTest { anyInt(), anyInt(), anyInt()); + verify(mNetworkManager).setInterfaceUp(createTunnelResp.interfaceName); } @Test diff --git a/tests/net/java/com/android/server/IpSecServiceRefcountedResourceTest.java b/tests/net/java/com/android/server/IpSecServiceRefcountedResourceTest.java index 22a2c94fc194..788e4efe097e 100644 --- a/tests/net/java/com/android/server/IpSecServiceRefcountedResourceTest.java +++ b/tests/net/java/com/android/server/IpSecServiceRefcountedResourceTest.java @@ -31,6 +31,7 @@ import static org.mockito.Mockito.verify; import android.content.Context; import android.os.Binder; import android.os.IBinder; +import android.os.INetworkManagementService; import android.os.RemoteException; import androidx.test.filters.SmallTest; @@ -61,7 +62,8 @@ public class IpSecServiceRefcountedResourceTest { public void setUp() throws Exception { mMockContext = mock(Context.class); mMockIpSecSrvConfig = mock(IpSecService.IpSecServiceConfiguration.class); - mIpSecService = new IpSecService(mMockContext, mMockIpSecSrvConfig); + mIpSecService = new IpSecService( + mMockContext, mock(INetworkManagementService.class), mMockIpSecSrvConfig); } private void assertResourceState( diff --git a/tests/net/java/com/android/server/IpSecServiceTest.java b/tests/net/java/com/android/server/IpSecServiceTest.java index 4a35015044ff..536e98327e1f 100644 --- a/tests/net/java/com/android/server/IpSecServiceTest.java +++ b/tests/net/java/com/android/server/IpSecServiceTest.java @@ -42,6 +42,7 @@ import android.net.IpSecManager; import android.net.IpSecSpiResponse; import android.net.IpSecUdpEncapResponse; import android.os.Binder; +import android.os.INetworkManagementService; import android.os.ParcelFileDescriptor; import android.os.Process; import android.system.ErrnoException; @@ -115,6 +116,7 @@ public class IpSecServiceTest { } Context mMockContext; + INetworkManagementService mMockNetworkManager; INetd mMockNetd; IpSecService.IpSecServiceConfiguration mMockIpSecSrvConfig; IpSecService mIpSecService; @@ -122,9 +124,10 @@ public class IpSecServiceTest { @Before public void setUp() throws Exception { mMockContext = mock(Context.class); + mMockNetworkManager = mock(INetworkManagementService.class); mMockNetd = mock(INetd.class); mMockIpSecSrvConfig = mock(IpSecService.IpSecServiceConfiguration.class); - mIpSecService = new IpSecService(mMockContext, mMockIpSecSrvConfig); + mIpSecService = new IpSecService(mMockContext, mMockNetworkManager, mMockIpSecSrvConfig); // Injecting mock netd when(mMockIpSecSrvConfig.getNetdInstance()).thenReturn(mMockNetd); @@ -132,7 +135,7 @@ public class IpSecServiceTest { @Test public void testIpSecServiceCreate() throws InterruptedException { - IpSecService ipSecSrv = IpSecService.create(mMockContext); + IpSecService ipSecSrv = IpSecService.create(mMockContext, mMockNetworkManager); assertNotNull(ipSecSrv); } @@ -604,8 +607,8 @@ public class IpSecServiceTest { @Test public void testOpenUdpEncapSocketTagsSocket() throws Exception { IpSecService.UidFdTagger mockTagger = mock(IpSecService.UidFdTagger.class); - IpSecService testIpSecService = - new IpSecService(mMockContext, mMockIpSecSrvConfig, mockTagger); + IpSecService testIpSecService = new IpSecService( + mMockContext, mMockNetworkManager, mMockIpSecSrvConfig, mockTagger); IpSecUdpEncapResponse udpEncapResp = testIpSecService.openUdpEncapsulationSocket(0, new Binder()); |