diff options
287 files changed, 12430 insertions, 2280 deletions
diff --git a/StubLibraries.bp b/StubLibraries.bp index d8661169526c..fd614a7e3dc3 100644 --- a/StubLibraries.bp +++ b/StubLibraries.bp @@ -422,10 +422,6 @@ droidstubs { name: "hwbinder-stubs-docs", srcs: [ "core/java/android/os/HidlSupport.java", - "core/java/android/annotation/IntDef.java", - "core/java/android/annotation/IntRange.java", - "core/java/android/annotation/NonNull.java", - "core/java/android/annotation/SystemApi.java", "core/java/android/os/HidlMemory.java", "core/java/android/os/HwBinder.java", "core/java/android/os/HwBlob.java", @@ -451,6 +447,7 @@ droidstubs { java_library_static { name: "hwbinder.stubs", sdk_version: "core_current", + libs: ["stub-annotations"], srcs: [ ":hwbinder-stubs-docs", ], diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java index 565ed959aeb4..15e5e843674d 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java +++ b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java @@ -31,6 +31,7 @@ import android.content.Intent; import android.content.ServiceConnection; import android.net.Uri; import android.os.Binder; +import android.os.Build; import android.os.Handler; import android.os.IBinder; import android.os.Looper; @@ -73,11 +74,12 @@ public final class JobServiceContext implements ServiceConnection { private static final String TAG = "JobServiceContext"; /** Amount of time a job is allowed to execute for before being considered timed-out. */ - public static final long EXECUTING_TIMESLICE_MILLIS = 10 * 60 * 1000; // 10mins. + public static final long EXECUTING_TIMESLICE_MILLIS = + 10 * 60 * 1000 * Build.HW_TIMEOUT_MULTIPLIER; // 10mins. /** Amount of time the JobScheduler waits for the initial service launch+bind. */ - private static final long OP_BIND_TIMEOUT_MILLIS = 18 * 1000; + private static final long OP_BIND_TIMEOUT_MILLIS = 18 * 1000 * Build.HW_TIMEOUT_MULTIPLIER; /** Amount of time the JobScheduler will wait for a response from an app for a message. */ - private static final long OP_TIMEOUT_MILLIS = 8 * 1000; + private static final long OP_TIMEOUT_MILLIS = 8 * 1000 * Build.HW_TIMEOUT_MULTIPLIER; private static final String[] VERB_STRINGS = { "VERB_BINDING", "VERB_STARTING", "VERB_EXECUTING", "VERB_STOPPING", "VERB_FINISHED" diff --git a/cmds/app_process/Android.bp b/cmds/app_process/Android.bp index 4e5b3bac5713..0eff83c99282 100644 --- a/cmds/app_process/Android.bp +++ b/cmds/app_process/Android.bp @@ -22,13 +22,9 @@ cc_binary { multilib: { lib32: { - // TODO(b/142944043): Remove version script when libsigchain is a DSO. - version_script: "version-script32.txt", suffix: "32", }, lib64: { - // TODO(b/142944043): Remove version script when libsigchain is a DSO. - version_script: "version-script64.txt", suffix: "64", }, }, @@ -43,6 +39,13 @@ cc_binary { "libhidlbase", "liblog", "libnativeloader", + + // Even though app_process doesn't call into libsigchain, we need to + // make sure it's in the DT list of app_process, as we want all code + // in app_process and the libraries it loads to find libsigchain + // symbols before libc symbols. + "libsigchain", + "libutils", // This is a list of libraries that need to be included in order to avoid @@ -52,8 +55,6 @@ cc_binary { "libwilhelm", ], - whole_static_libs: ["libsigchain"], - compile_multilib: "both", cflags: [ diff --git a/cmds/app_process/version-script32.txt b/cmds/app_process/version-script32.txt deleted file mode 100644 index 70810e0b7173..000000000000 --- a/cmds/app_process/version-script32.txt +++ /dev/null @@ -1,15 +0,0 @@ -{ -global: - EnsureFrontOfChain; - AddSpecialSignalHandlerFn; - RemoveSpecialSignalHandlerFn; - SkipAddSignalHandler; - bsd_signal; - sigaction; - sigaction64; - signal; - sigprocmask; - sigprocmask64; -local: - *; -}; diff --git a/cmds/app_process/version-script64.txt b/cmds/app_process/version-script64.txt deleted file mode 100644 index 7bcd76b50f87..000000000000 --- a/cmds/app_process/version-script64.txt +++ /dev/null @@ -1,14 +0,0 @@ -{ -global: - EnsureFrontOfChain; - AddSpecialSignalHandlerFn; - RemoveSpecialSignalHandlerFn; - SkipAddSignalHandler; - sigaction; - sigaction64; - signal; - sigprocmask; - sigprocmask64; -local: - *; -}; diff --git a/core/api/current.txt b/core/api/current.txt index 0e7ecefbdbdc..04d5f0f5137e 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -7999,13 +7999,13 @@ package android.app.usage { } public class NetworkStatsManager { - method public android.app.usage.NetworkStats queryDetails(int, String, long, long) throws android.os.RemoteException, java.lang.SecurityException; - method public android.app.usage.NetworkStats queryDetailsForUid(int, String, long, long, int) throws java.lang.SecurityException; - method public android.app.usage.NetworkStats queryDetailsForUidTag(int, String, long, long, int, int) throws java.lang.SecurityException; - method public android.app.usage.NetworkStats queryDetailsForUidTagState(int, String, long, long, int, int, int) throws java.lang.SecurityException; - method public android.app.usage.NetworkStats querySummary(int, String, long, long) throws android.os.RemoteException, java.lang.SecurityException; - method public android.app.usage.NetworkStats.Bucket querySummaryForDevice(int, String, long, long) throws android.os.RemoteException, java.lang.SecurityException; - method public android.app.usage.NetworkStats.Bucket querySummaryForUser(int, String, long, long) throws android.os.RemoteException, java.lang.SecurityException; + method @WorkerThread public android.app.usage.NetworkStats queryDetails(int, String, long, long) throws android.os.RemoteException, java.lang.SecurityException; + method @WorkerThread public android.app.usage.NetworkStats queryDetailsForUid(int, String, long, long, int) throws java.lang.SecurityException; + method @WorkerThread public android.app.usage.NetworkStats queryDetailsForUidTag(int, String, long, long, int, int) throws java.lang.SecurityException; + method @WorkerThread public android.app.usage.NetworkStats queryDetailsForUidTagState(int, String, long, long, int, int, int) throws java.lang.SecurityException; + method @WorkerThread public android.app.usage.NetworkStats querySummary(int, String, long, long) throws android.os.RemoteException, java.lang.SecurityException; + method @WorkerThread public android.app.usage.NetworkStats.Bucket querySummaryForDevice(int, String, long, long) throws android.os.RemoteException, java.lang.SecurityException; + method @WorkerThread public android.app.usage.NetworkStats.Bucket querySummaryForUser(int, String, long, long) throws android.os.RemoteException, java.lang.SecurityException; method public void registerUsageCallback(int, String, long, android.app.usage.NetworkStatsManager.UsageCallback); method public void registerUsageCallback(int, String, long, android.app.usage.NetworkStatsManager.UsageCallback, @Nullable android.os.Handler); method public void unregisterUsageCallback(android.app.usage.NetworkStatsManager.UsageCallback); @@ -8689,6 +8689,8 @@ package android.bluetooth { field public static final String ACTION_NAME_CHANGED = "android.bluetooth.device.action.NAME_CHANGED"; field public static final String ACTION_PAIRING_REQUEST = "android.bluetooth.device.action.PAIRING_REQUEST"; field public static final String ACTION_UUID = "android.bluetooth.device.action.UUID"; + field public static final int ADDRESS_TYPE_PUBLIC = 0; // 0x0 + field public static final int ADDRESS_TYPE_RANDOM = 1; // 0x1 field public static final int BOND_BONDED = 12; // 0xc field public static final int BOND_BONDING = 11; // 0xb field public static final int BOND_NONE = 10; // 0xa @@ -19852,6 +19854,7 @@ package android.media { method public android.media.AudioDeviceInfo getPreferredDevice(); method public android.media.AudioDeviceInfo getRoutedDevice(); method public int getSampleRate(); + method @IntRange(from=1) public int getStartThresholdInFrames(); method public int getState(); method public int getStreamType(); method public boolean getTimestamp(android.media.AudioTimestamp); @@ -19882,6 +19885,7 @@ package android.media { method public int setPositionNotificationPeriod(int); method public boolean setPreferredDevice(android.media.AudioDeviceInfo); method public int setPresentation(@NonNull android.media.AudioPresentation); + method @IntRange(from=1) public int setStartThresholdInFrames(@IntRange(from=1) int); method @Deprecated protected void setState(int); method @Deprecated public int setStereoVolume(float, float); method public int setVolume(float); @@ -25690,17 +25694,14 @@ package android.net.vcn { public final class VcnGatewayConnectionConfig { method @NonNull public int[] getExposedCapabilities(); method @IntRange(from=android.net.vcn.VcnGatewayConnectionConfig.MIN_MTU_V6) public int getMaxMtu(); - method @NonNull public int[] getRequiredUnderlyingCapabilities(); method @NonNull public long[] getRetryInterval(); } public static final class VcnGatewayConnectionConfig.Builder { ctor public VcnGatewayConnectionConfig.Builder(@NonNull android.net.vcn.VcnControlPlaneConfig); method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder addExposedCapability(int); - method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder addRequiredUnderlyingCapability(int); method @NonNull public android.net.vcn.VcnGatewayConnectionConfig build(); method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder removeExposedCapability(int); - method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder removeRequiredUnderlyingCapability(int); method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder setMaxMtu(@IntRange(from=android.net.vcn.VcnGatewayConnectionConfig.MIN_MTU_V6) int); method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder setRetryInterval(@NonNull long[]); } @@ -39225,6 +39226,7 @@ package android.telephony { field public static final String KEY_GSM_ROAMING_NETWORKS_STRING_ARRAY = "gsm_roaming_networks_string_array"; field public static final String KEY_HAS_IN_CALL_NOISE_SUPPRESSION_BOOL = "has_in_call_noise_suppression_bool"; field public static final String KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL = "hide_carrier_network_settings_bool"; + field public static final String KEY_HIDE_ENABLE_2G = "hide_enable_2g_bool"; field public static final String KEY_HIDE_ENHANCED_4G_LTE_BOOL = "hide_enhanced_4g_lte_bool"; field public static final String KEY_HIDE_IMS_APN_BOOL = "hide_ims_apn_bool"; field public static final String KEY_HIDE_LTE_PLUS_DATA_ICON_BOOL = "hide_lte_plus_data_icon_bool"; @@ -39304,6 +39306,7 @@ package android.telephony { field public static final String KEY_RTT_SUPPORTED_FOR_VT_BOOL = "rtt_supported_for_vt_bool"; field public static final String KEY_RTT_SUPPORTED_WHILE_ROAMING_BOOL = "rtt_supported_while_roaming_bool"; field public static final String KEY_RTT_UPGRADE_SUPPORTED_BOOL = "rtt_upgrade_supported_bool"; + field public static final String KEY_RTT_UPGRADE_SUPPORTED_FOR_DOWNGRADED_VT_CALL_BOOL = "rtt_upgrade_supported_for_downgraded_vt_call"; field public static final String KEY_SHOW_4G_FOR_3G_DATA_ICON_BOOL = "show_4g_for_3g_data_icon_bool"; field public static final String KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL = "show_4g_for_lte_data_icon_bool"; field public static final String KEY_SHOW_APN_SETTING_CDMA_BOOL = "show_apn_setting_cdma_bool"; @@ -39346,6 +39349,7 @@ package android.telephony { field public static final String KEY_VOICEMAIL_NOTIFICATION_PERSISTENT_BOOL = "voicemail_notification_persistent_bool"; field public static final String KEY_VOICE_PRIVACY_DISABLE_UI_BOOL = "voice_privacy_disable_ui_bool"; field public static final String KEY_VOLTE_REPLACEMENT_RAT_INT = "volte_replacement_rat_int"; + field public static final String KEY_VT_UPGRADE_SUPPORTED_FOR_DOWNGRADED_RTT_CALL_BOOL = "vt_upgrade_supported_for_downgraded_rtt_call"; field public static final String KEY_VVM_CELLULAR_DATA_REQUIRED_BOOL = "vvm_cellular_data_required_bool"; field public static final String KEY_VVM_CLIENT_PREFIX_STRING = "vvm_client_prefix_string"; field public static final String KEY_VVM_DESTINATION_NUMBER_STRING = "vvm_destination_number_string"; @@ -40905,6 +40909,10 @@ package android.telephony { method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public void onMessageWaitingIndicatorChanged(boolean); } + public static interface TelephonyCallback.PhysicalChannelConfigListener { + method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onPhysicalChannelConfigChanged(@NonNull java.util.List<android.telephony.PhysicalChannelConfig>); + } + public static interface TelephonyCallback.PreciseDataConnectionStateListener { method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onPreciseDataConnectionStateChanged(@NonNull android.telephony.PreciseDataConnectionState); } diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt index 992b57f356c5..f155a5f07fd7 100644 --- a/core/api/module-lib-current.txt +++ b/core/api/module-lib-current.txt @@ -22,6 +22,10 @@ package android.app.usage { package android.content { + public abstract class Context { + field public static final String TEST_NETWORK_SERVICE = "test_network"; + } + public class Intent implements java.lang.Cloneable android.os.Parcelable { field public static final String ACTION_CLEAR_DNS_CACHE = "android.intent.action.CLEAR_DNS_CACHE"; } @@ -42,6 +46,29 @@ package android.net { method public int getResourceId(); } + public class NetworkPolicyManager { + method @NonNull public static String blockedReasonsToString(int); + method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public int getMultipathPreference(@NonNull android.net.Network); + method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public int getRestrictBackgroundStatus(int); + method public static boolean isUidBlocked(int, boolean); + method @RequiresPermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY) public boolean isUidNetworkingBlocked(int, boolean); + method @RequiresPermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY) public boolean isUidRestrictedOnMeteredNetworks(int); + method @RequiresPermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY) public void registerNetworkPolicyCallback(@Nullable java.util.concurrent.Executor, @NonNull android.net.NetworkPolicyManager.NetworkPolicyCallback); + method @RequiresPermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY) public void unregisterNetworkPolicyCallback(@NonNull android.net.NetworkPolicyManager.NetworkPolicyCallback); + field public static final int BLOCKED_METERED_REASON_ADMIN_DISABLED = 262144; // 0x40000 + field public static final int BLOCKED_METERED_REASON_DATA_SAVER = 65536; // 0x10000 + field public static final int BLOCKED_METERED_REASON_USER_RESTRICTED = 131072; // 0x20000 + field public static final int BLOCKED_REASON_APP_STANDBY = 4; // 0x4 + field public static final int BLOCKED_REASON_BATTERY_SAVER = 1; // 0x1 + field public static final int BLOCKED_REASON_DOZE = 2; // 0x2 + field public static final int BLOCKED_REASON_NONE = 0; // 0x0 + field public static final int BLOCKED_REASON_RESTRICTED_MODE = 8; // 0x8 + } + + public static interface NetworkPolicyManager.NetworkPolicyCallback { + method public default void onUidBlockedReasonChanged(int, int); + } + public final class NetworkStateSnapshot implements android.os.Parcelable { ctor public NetworkStateSnapshot(@NonNull android.net.Network, @NonNull android.net.NetworkCapabilities, @NonNull android.net.LinkProperties, @Nullable String, int); method public int describeContents(); @@ -85,6 +112,7 @@ package android.net { public class VpnManager { field @Deprecated public static final int TYPE_VPN_LEGACY = 3; // 0x3 field public static final int TYPE_VPN_NONE = -1; // 0xffffffff + field public static final int TYPE_VPN_OEM = 4; // 0x4 field public static final int TYPE_VPN_PLATFORM = 2; // 0x2 field public static final int TYPE_VPN_SERVICE = 1; // 0x1 } @@ -109,6 +137,10 @@ package android.os { method public default int getStability(); } + public class Process { + field public static final int VPN_UID = 1016; // 0x3f8 + } + public class StatsServiceManager { method @NonNull public android.os.StatsServiceManager.ServiceRegisterer getStatsCompanionServiceRegisterer(); method @NonNull public android.os.StatsServiceManager.ServiceRegisterer getStatsManagerServiceRegisterer(); diff --git a/core/api/system-current.txt b/core/api/system-current.txt index da56f45e9d6e..b20f63784430 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -113,6 +113,7 @@ package android { field public static final String LOOP_RADIO = "android.permission.LOOP_RADIO"; field public static final String MANAGE_ACCESSIBILITY = "android.permission.MANAGE_ACCESSIBILITY"; field public static final String MANAGE_ACTIVITY_STACKS = "android.permission.MANAGE_ACTIVITY_STACKS"; + field public static final String MANAGE_APP_HIBERNATION = "android.permission.MANAGE_APP_HIBERNATION"; field public static final String MANAGE_APP_OPS_RESTRICTIONS = "android.permission.MANAGE_APP_OPS_RESTRICTIONS"; field public static final String MANAGE_APP_PREDICTIONS = "android.permission.MANAGE_APP_PREDICTIONS"; field public static final String MANAGE_APP_TOKENS = "android.permission.MANAGE_APP_TOKENS"; @@ -1421,10 +1422,11 @@ package android.app.usage { package android.apphibernation { public final class AppHibernationManager { - method public boolean isHibernatingForUser(@NonNull String); - method public boolean isHibernatingGlobally(@NonNull String); - method public void setHibernatingForUser(@NonNull String, boolean); - method public void setHibernatingGlobally(@NonNull String, boolean); + method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_APP_HIBERNATION) public java.util.List<java.lang.String> getHibernatingPackagesForUser(); + method @RequiresPermission(android.Manifest.permission.MANAGE_APP_HIBERNATION) public boolean isHibernatingForUser(@NonNull String); + method @RequiresPermission(android.Manifest.permission.MANAGE_APP_HIBERNATION) public boolean isHibernatingGlobally(@NonNull String); + method @RequiresPermission(android.Manifest.permission.MANAGE_APP_HIBERNATION) public void setHibernatingForUser(@NonNull String, boolean); + method @RequiresPermission(android.Manifest.permission.MANAGE_APP_HIBERNATION) public void setHibernatingGlobally(@NonNull String, boolean); } } @@ -1480,6 +1482,7 @@ package android.bluetooth { public final class BluetoothDevice implements android.os.Parcelable { method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean cancelBondProcess(); + method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean createBondOutOfBand(int, @Nullable android.bluetooth.OobData, @Nullable android.bluetooth.OobData); method @Nullable @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public byte[] getMetadata(int); method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public int getSimAccessPermission(); method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public boolean isConnected(); @@ -1656,6 +1659,55 @@ package android.bluetooth { field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BufferConstraints> CREATOR; } + public final class OobData implements android.os.Parcelable { + method @NonNull public static android.bluetooth.OobData.ClassicBuilder createClassicBuilder(@NonNull byte[], @NonNull byte[], @NonNull byte[]); + method @NonNull public static android.bluetooth.OobData.LeBuilder createLeBuilder(@NonNull byte[], @NonNull byte[], int); + method @NonNull public byte[] getClassOfDevice(); + method @NonNull public byte[] getClassicLength(); + method @NonNull public byte[] getConfirmationHash(); + method @NonNull public byte[] getDeviceAddressWithType(); + method @Nullable public byte[] getDeviceName(); + method @Nullable public byte[] getLeAppearance(); + method @NonNull public int getLeDeviceRole(); + method @NonNull public int getLeFlags(); + method @Nullable public byte[] getLeTemporaryKey(); + method @NonNull public byte[] getRandomizerHash(); + field public static final int CLASS_OF_DEVICE_OCTETS = 3; // 0x3 + field public static final int CONFIRMATION_OCTETS = 16; // 0x10 + field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.OobData> CREATOR; + field public static final int DEVICE_ADDRESS_OCTETS = 7; // 0x7 + field public static final int LE_APPEARANCE_OCTETS = 2; // 0x2 + field public static final int LE_DEVICE_FLAG_OCTETS = 1; // 0x1 + field public static final int LE_DEVICE_ROLE_BOTH_PREFER_CENTRAL = 3; // 0x3 + field public static final int LE_DEVICE_ROLE_BOTH_PREFER_PERIPHERAL = 2; // 0x2 + field public static final int LE_DEVICE_ROLE_CENTRAL_ONLY = 1; // 0x1 + field public static final int LE_DEVICE_ROLE_OCTETS = 1; // 0x1 + field public static final int LE_DEVICE_ROLE_PERIPHERAL_ONLY = 0; // 0x0 + field public static final int LE_FLAG_BREDR_NOT_SUPPORTED = 2; // 0x2 + field public static final int LE_FLAG_GENERAL_DISCOVERY_MODE = 1; // 0x1 + field public static final int LE_FLAG_LIMITED_DISCOVERY_MODE = 0; // 0x0 + field public static final int LE_FLAG_SIMULTANEOUS_CONTROLLER = 3; // 0x3 + field public static final int LE_FLAG_SIMULTANEOUS_HOST = 4; // 0x4 + field public static final int LE_TK_OCTETS = 16; // 0x10 + field public static final int OOB_LENGTH_OCTETS = 2; // 0x2 + field public static final int RANDOMIZER_OCTETS = 16; // 0x10 + } + + public static final class OobData.ClassicBuilder { + method @NonNull public android.bluetooth.OobData build(); + method @NonNull public android.bluetooth.OobData.ClassicBuilder setClassOfDevice(@NonNull byte[]); + method @NonNull public android.bluetooth.OobData.ClassicBuilder setDeviceName(@NonNull byte[]); + method @NonNull public android.bluetooth.OobData.ClassicBuilder setRandomizerHash(@NonNull byte[]); + } + + public static final class OobData.LeBuilder { + method @NonNull public android.bluetooth.OobData build(); + method @NonNull public android.bluetooth.OobData.LeBuilder setDeviceName(@NonNull byte[]); + method @NonNull public android.bluetooth.OobData.LeBuilder setLeFlags(int); + method @NonNull public android.bluetooth.OobData.LeBuilder setLeTemporaryKey(@NonNull byte[]); + method @NonNull public android.bluetooth.OobData.LeBuilder setRandomizerHash(@NonNull byte[]); + } + } package android.bluetooth.le { @@ -1676,7 +1728,19 @@ package android.bluetooth.le { field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.ResultStorageDescriptor> CREATOR; } + public final class ScanFilter implements android.os.Parcelable { + method public int getAddressType(); + method @Nullable public byte[] getIrk(); + } + + public static final class ScanFilter.Builder { + method @NonNull public android.bluetooth.le.ScanFilter.Builder setDeviceAddress(@NonNull String, int); + method @NonNull public android.bluetooth.le.ScanFilter.Builder setDeviceAddress(@NonNull String, int, @NonNull byte[]); + field public static final int LEN_IRK_OCTETS = 16; // 0x10 + } + public final class ScanSettings implements android.os.Parcelable { + field public static final int SCAN_MODE_AMBIENT_DISCOVERY = 3; // 0x3 field public static final int SCAN_RESULT_TYPE_ABBREVIATED = 1; // 0x1 field public static final int SCAN_RESULT_TYPE_FULL = 0; // 0x0 } @@ -9475,7 +9539,8 @@ package android.telephony { public final class DataSpecificRegistrationInfo implements android.os.Parcelable { method public int describeContents(); - method @NonNull public android.telephony.LteVopsSupportInfo getLteVopsSupportInfo(); + method @Deprecated @NonNull public android.telephony.LteVopsSupportInfo getLteVopsSupportInfo(); + method @Nullable public android.telephony.VopsSupportInfo getVopsSupportInfo(); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.telephony.DataSpecificRegistrationInfo> CREATOR; } @@ -9507,14 +9572,29 @@ package android.telephony { field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ImsiEncryptionInfo> CREATOR; } - public final class LteVopsSupportInfo implements android.os.Parcelable { - ctor public LteVopsSupportInfo(int, int); + public final class LinkCapacityEstimate implements android.os.Parcelable { + ctor public LinkCapacityEstimate(int, int, int); method public int describeContents(); + method public int getDownlinkCapacityKbps(); + method public int getType(); + method public int getUplinkCapacityKbps(); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.LinkCapacityEstimate> CREATOR; + field public static final int INVALID = -1; // 0xffffffff + field public static final int LCE_TYPE_COMBINED = 2; // 0x2 + field public static final int LCE_TYPE_PRIMARY = 0; // 0x0 + field public static final int LCE_TYPE_SECONDARY = 1; // 0x1 + } + + public final class LteVopsSupportInfo extends android.telephony.VopsSupportInfo { + ctor public LteVopsSupportInfo(int, int); method public int getEmcBearerSupport(); method public int getVopsSupport(); - method public void writeToParcel(android.os.Parcel, int); + method public boolean isEmergencyServiceFallbackSupported(); + method public boolean isEmergencyServiceSupported(); + method public boolean isVopsSupported(); + method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.telephony.LteVopsSupportInfo> CREATOR; - field public static final int LTE_STATUS_NOT_AVAILABLE = 1; // 0x1 + field @Deprecated public static final int LTE_STATUS_NOT_AVAILABLE = 1; // 0x1 field public static final int LTE_STATUS_NOT_SUPPORTED = 3; // 0x3 field public static final int LTE_STATUS_SUPPORTED = 2; // 0x2 } @@ -9585,6 +9665,29 @@ package android.telephony { field public static final int RESULT_SUCCESS = 0; // 0x0 } + public final class NrVopsSupportInfo extends android.telephony.VopsSupportInfo { + ctor public NrVopsSupportInfo(int, int, int); + method public int getEmcSupport(); + method public int getEmfSupport(); + method public int getVopsSupport(); + method public boolean isEmergencyServiceFallbackSupported(); + method public boolean isEmergencyServiceSupported(); + method public boolean isVopsSupported(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.NrVopsSupportInfo> CREATOR; + field public static final int NR_STATUS_EMC_5GCN_ONLY = 1; // 0x1 + field public static final int NR_STATUS_EMC_EUTRA_5GCN_ONLY = 2; // 0x2 + field public static final int NR_STATUS_EMC_NOT_SUPPORTED = 0; // 0x0 + field public static final int NR_STATUS_EMC_NR_EUTRA_5GCN = 3; // 0x3 + field public static final int NR_STATUS_EMF_5GCN_ONLY = 1; // 0x1 + field public static final int NR_STATUS_EMF_EUTRA_5GCN_ONLY = 2; // 0x2 + field public static final int NR_STATUS_EMF_NOT_SUPPORTED = 0; // 0x0 + field public static final int NR_STATUS_EMF_NR_EUTRA_5GCN = 3; // 0x3 + field public static final int NR_STATUS_VOPS_3GPP_SUPPORTED = 1; // 0x1 + field public static final int NR_STATUS_VOPS_NON_3GPP_SUPPORTED = 2; // 0x2 + field public static final int NR_STATUS_VOPS_NOT_SUPPORTED = 0; // 0x0 + } + public interface NumberVerificationCallback { method public default void onCallReceived(@NonNull String); method public default void onVerificationFailed(int); @@ -9983,6 +10086,8 @@ package android.telephony { field public static final int EVENT_DISPLAY_INFO_CHANGED = 21; // 0x15 field @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public static final int EVENT_EMERGENCY_NUMBER_LIST_CHANGED = 25; // 0x19 field @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int EVENT_IMS_CALL_DISCONNECT_CAUSE_CHANGED = 28; // 0x1c + field @RequiresPermission(android.Manifest.permission.READ_CALL_LOG) public static final int EVENT_LEGACY_CALL_STATE_CHANGED = 36; // 0x24 + field @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int EVENT_LINK_CAPACITY_ESTIMATE_CHANGED = 37; // 0x25 field @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public static final int EVENT_MESSAGE_WAITING_INDICATOR_CHANGED = 3; // 0x3 field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int EVENT_OEM_HOOK_RAW = 15; // 0xf field @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int EVENT_OUTGOING_EMERGENCY_CALL = 29; // 0x1d @@ -10002,7 +10107,7 @@ package android.telephony { } public static interface TelephonyCallback.AllowedNetworkTypesListener { - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void onAllowedNetworkTypesChanged(@NonNull java.util.Map<java.lang.Integer,java.lang.Long>); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void onAllowedNetworkTypesChanged(int, long); } public static interface TelephonyCallback.CallAttributesListener { @@ -10013,6 +10118,10 @@ package android.telephony { method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onDataEnabledChanged(boolean, int); } + public static interface TelephonyCallback.LinkCapacityEstimateChangedListener { + method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onLinkCapacityEstimateChanged(@NonNull java.util.List<android.telephony.LinkCapacityEstimate>); + } + public static interface TelephonyCallback.OutgoingEmergencyCallListener { method @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public void onOutgoingEmergencyCall(@NonNull android.telephony.emergency.EmergencyNumber, int); } @@ -10025,10 +10134,6 @@ package android.telephony { method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void onPhoneCapabilityChanged(@NonNull android.telephony.PhoneCapability); } - public static interface TelephonyCallback.PhysicalChannelConfigListener { - method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onPhysicalChannelConfigChanged(@NonNull java.util.List<android.telephony.PhysicalChannelConfig>); - } - public static interface TelephonyCallback.PreciseCallStateListener { method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onPreciseCallStateChanged(@NonNull android.telephony.PreciseCallState); } @@ -10084,7 +10189,6 @@ package android.telephony { method @Nullable @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public android.content.ComponentName getAndUpdateDefaultRespondViaMessageApplication(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getCallForwarding(int, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CallForwardingInfoCallback); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getCallWaitingStatus(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); - method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.CarrierBandwidth getCarrierBandwidth(); 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); @@ -10220,6 +10324,7 @@ package android.telephony { 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 ALLOWED_NETWORK_TYPES_REASON_CARRIER = 2; // 0x2 + field public static final int ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G = 3; // 0x3 field public static final int ALLOWED_NETWORK_TYPES_REASON_POWER = 1; // 0x1 field public static final int ALLOWED_NETWORK_TYPES_REASON_USER = 0; // 0x0 field public static final int CALL_WAITING_STATUS_DISABLED = 2; // 0x2 @@ -10382,6 +10487,16 @@ package android.telephony { method public static final void setSmsFilterSettings(android.content.Context, android.telecom.PhoneAccountHandle, android.telephony.VisualVoicemailSmsFilterSettings); } + public abstract class VopsSupportInfo implements android.os.Parcelable { + method public int describeContents(); + method public abstract boolean equals(Object); + method public abstract int hashCode(); + method public abstract boolean isEmergencyServiceFallbackSupported(); + method public abstract boolean isEmergencyServiceSupported(); + method public abstract boolean isVopsSupported(); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.VopsSupportInfo> CREATOR; + } + } package android.telephony.cdma { diff --git a/core/api/test-current.txt b/core/api/test-current.txt index a0ff97e1f338..11df05812e21 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -996,6 +996,8 @@ package android.net { public class NetworkPolicyManager { method public boolean getRestrictBackground(); + method @RequiresPermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY) public boolean isUidNetworkingBlocked(int, boolean); + method @RequiresPermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY) public boolean isUidRestrictedOnMeteredNetworks(int); method @NonNull public static String resolveNetworkId(@NonNull android.net.wifi.WifiConfiguration); method public void setRestrictBackground(boolean); } diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index 098d8b6c6058..9f1132b605ef 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -24,6 +24,7 @@ import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.SystemService; import android.annotation.TestApi; +import android.annotation.WorkerThread; import android.app.usage.NetworkStats.Bucket; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; @@ -201,6 +202,7 @@ public class NetworkStatsManager { * default network {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL}, * metered {@link NetworkStats.Bucket#METERED_ALL}, * and roaming {@link NetworkStats.Bucket#ROAMING_ALL}. + * This may take a long time, and apps should avoid calling this on their main thread. * * @param networkType As defined in {@link ConnectivityManager}, e.g. * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI} @@ -219,6 +221,7 @@ public class NetworkStatsManager { * @return Bucket object or null if permissions are insufficient or error happened during * statistics collection. */ + @WorkerThread public Bucket querySummaryForDevice(int networkType, String subscriberId, long startTime, long endTime) throws SecurityException, RemoteException { NetworkTemplate template; @@ -240,6 +243,7 @@ public class NetworkStatsManager { * uid {@link NetworkStats.Bucket#UID_ALL}, tag {@link NetworkStats.Bucket#TAG_NONE}, * metered {@link NetworkStats.Bucket#METERED_ALL}, and roaming * {@link NetworkStats.Bucket#ROAMING_ALL}. + * This may take a long time, and apps should avoid calling this on their main thread. * * @param networkType As defined in {@link ConnectivityManager}, e.g. * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI} @@ -258,6 +262,7 @@ public class NetworkStatsManager { * @return Bucket object or null if permissions are insufficient or error happened during * statistics collection. */ + @WorkerThread public Bucket querySummaryForUser(int networkType, String subscriberId, long startTime, long endTime) throws SecurityException, RemoteException { NetworkTemplate template; @@ -283,6 +288,7 @@ public class NetworkStatsManager { * means buckets' start and end timestamps are going to be the same as the 'startTime' and * 'endTime' parameters. State, uid, metered, and roaming are going to vary, and tag is going to * be the same. + * This may take a long time, and apps should avoid calling this on their main thread. * * @param networkType As defined in {@link ConnectivityManager}, e.g. * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI} @@ -301,6 +307,7 @@ public class NetworkStatsManager { * @return Statistics object or null if permissions are insufficient or error happened during * statistics collection. */ + @WorkerThread public NetworkStats querySummary(int networkType, String subscriberId, long startTime, long endTime) throws SecurityException, RemoteException { NetworkTemplate template; @@ -326,9 +333,11 @@ public class NetworkStatsManager { /** * Query network usage statistics details for a given uid. + * This may take a long time, and apps should avoid calling this on their main thread. * * @see #queryDetailsForUidTagState(int, String, long, long, int, int, int) */ + @WorkerThread public NetworkStats queryDetailsForUid(int networkType, String subscriberId, long startTime, long endTime, int uid) throws SecurityException { return queryDetailsForUidTagState(networkType, subscriberId, startTime, endTime, uid, @@ -344,9 +353,11 @@ public class NetworkStatsManager { /** * Query network usage statistics details for a given uid and tag. + * This may take a long time, and apps should avoid calling this on their main thread. * * @see #queryDetailsForUidTagState(int, String, long, long, int, int, int) */ + @WorkerThread public NetworkStats queryDetailsForUidTag(int networkType, String subscriberId, long startTime, long endTime, int uid, int tag) throws SecurityException { return queryDetailsForUidTagState(networkType, subscriberId, startTime, endTime, uid, @@ -365,6 +376,7 @@ public class NetworkStatsManager { * <p>Only includes buckets that atomically occur in the inclusive time range. Doesn't * interpolate across partial buckets. Since bucket length is in the order of hours, this * method cannot be used to measure data usage on a fine grained time scale. + * This may take a long time, and apps should avoid calling this on their main thread. * * @param networkType As defined in {@link ConnectivityManager}, e.g. * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI} @@ -387,6 +399,7 @@ public class NetworkStatsManager { * @return Statistics object or null if an error happened during statistics collection. * @throws SecurityException if permissions are insufficient to read network statistics. */ + @WorkerThread public NetworkStats queryDetailsForUidTagState(int networkType, String subscriberId, long startTime, long endTime, int uid, int tag, int state) throws SecurityException { NetworkTemplate template; @@ -425,6 +438,7 @@ public class NetworkStatsManager { * <p>Only includes buckets that atomically occur in the inclusive time range. Doesn't * interpolate across partial buckets. Since bucket length is in the order of hours, this * method cannot be used to measure data usage on a fine grained time scale. + * This may take a long time, and apps should avoid calling this on their main thread. * * @param networkType As defined in {@link ConnectivityManager}, e.g. * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI} @@ -443,6 +457,7 @@ public class NetworkStatsManager { * @return Statistics object or null if permissions are insufficient or error happened during * statistics collection. */ + @WorkerThread public NetworkStats queryDetails(int networkType, String subscriberId, long startTime, long endTime) throws SecurityException, RemoteException { NetworkTemplate template; diff --git a/core/java/android/apphibernation/AppHibernationManager.java b/core/java/android/apphibernation/AppHibernationManager.java index 7281d50a33a5..de778488df03 100644 --- a/core/java/android/apphibernation/AppHibernationManager.java +++ b/core/java/android/apphibernation/AppHibernationManager.java @@ -17,12 +17,15 @@ package android.apphibernation; import android.annotation.NonNull; +import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.SystemService; import android.content.Context; import android.os.RemoteException; import android.os.ServiceManager; +import java.util.List; + /** * This class provides an API surface for system apps to manipulate the app hibernation * state of a package for the user provided in the context. @@ -54,6 +57,7 @@ public final class AppHibernationManager { * @hide */ @SystemApi + @RequiresPermission(value = android.Manifest.permission.MANAGE_APP_HIBERNATION) public boolean isHibernatingForUser(@NonNull String packageName) { try { return mIAppHibernationService.isHibernatingForUser(packageName, mContext.getUserId()); @@ -68,6 +72,7 @@ public final class AppHibernationManager { * @hide */ @SystemApi + @RequiresPermission(value = android.Manifest.permission.MANAGE_APP_HIBERNATION) public void setHibernatingForUser(@NonNull String packageName, boolean isHibernating) { try { mIAppHibernationService.setHibernatingForUser(packageName, mContext.getUserId(), @@ -83,6 +88,7 @@ public final class AppHibernationManager { * @hide */ @SystemApi + @RequiresPermission(value = android.Manifest.permission.MANAGE_APP_HIBERNATION) public boolean isHibernatingGlobally(@NonNull String packageName) { try { return mIAppHibernationService.isHibernatingGlobally(packageName); @@ -99,6 +105,7 @@ public final class AppHibernationManager { * @hide */ @SystemApi + @RequiresPermission(value = android.Manifest.permission.MANAGE_APP_HIBERNATION) public void setHibernatingGlobally(@NonNull String packageName, boolean isHibernating) { try { mIAppHibernationService.setHibernatingGlobally(packageName, isHibernating); @@ -106,4 +113,20 @@ public final class AppHibernationManager { throw e.rethrowFromSystemServer(); } } + + /** + * Get the hibernating packages for the user. This is equivalent to the list of packages for + * the user that return true for {@link #isHibernatingForUser}. + * + * @hide + */ + @SystemApi + @RequiresPermission(value = android.Manifest.permission.MANAGE_APP_HIBERNATION) + public @NonNull List<String> getHibernatingPackagesForUser() { + try { + return mIAppHibernationService.getHibernatingPackagesForUser(mContext.getUserId()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } } diff --git a/core/java/android/apphibernation/IAppHibernationService.aidl b/core/java/android/apphibernation/IAppHibernationService.aidl index 6a068ee2b147..afdb3fe03dad 100644 --- a/core/java/android/apphibernation/IAppHibernationService.aidl +++ b/core/java/android/apphibernation/IAppHibernationService.aidl @@ -25,4 +25,5 @@ interface IAppHibernationService { void setHibernatingForUser(String packageName, int userId, boolean isHibernating); boolean isHibernatingGlobally(String packageName); void setHibernatingGlobally(String packageName, boolean isHibernating); + List<String> getHibernatingPackagesForUser(int userId); }
\ No newline at end of file diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index cc0b22afe38d..38863c2c8ccf 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -52,6 +52,8 @@ import android.os.SystemProperties; import android.util.Log; import android.util.Pair; +import com.android.internal.util.Preconditions; + import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -3118,6 +3120,25 @@ public final class BluetoothAdapter { return true; } + /** + * Determines whether a String Bluetooth address, such as "00:43:A8:23:10:F0" + * is a RANDOM STATIC address. + * + * RANDOM STATIC: (addr & 0b11) == 0b11 + * RANDOM RESOLVABLE: (addr & 0b11) == 0b10 + * RANDOM non-RESOLVABLE: (addr & 0b11) == 0b00 + * + * @param address Bluetooth address as string + * @return true if the 2 Least Significant Bits of the address equals 0b11. + * + * @hide + */ + public static boolean isAddressRandomStatic(@NonNull String address) { + Preconditions.checkNotNull(address); + return checkBluetoothAddress(address) + && (Integer.parseInt(address.split(":")[5], 16) & 0b11) == 0b11; + } + @UnsupportedAppUsage /*package*/ IBluetoothManager getBluetoothManager() { return mManagerService; diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java index 89030bcf12e0..c30b8af3da53 100644 --- a/core/java/android/bluetooth/BluetoothDevice.java +++ b/core/java/android/bluetooth/BluetoothDevice.java @@ -1002,6 +1002,24 @@ public final class BluetoothDevice implements Parcelable { public static final String EXTRA_MAS_INSTANCE = "android.bluetooth.device.extra.MAS_INSTANCE"; + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef( + prefix = { "ADDRESS_TYPE_" }, + value = { + /** Hardware MAC Address */ + ADDRESS_TYPE_PUBLIC, + /** Address is either resolvable, non-resolvable or static.*/ + ADDRESS_TYPE_RANDOM, + } + ) + public @interface AddressType {} + + /** Hardware MAC Address of the device */ + public static final int ADDRESS_TYPE_PUBLIC = 0; + /** Address is either resolvable, non-resolvable or static. */ + public static final int ADDRESS_TYPE_RANDOM = 1; + /** * Lazy initialization. Guaranteed final after first object constructed, or * getService() called. @@ -1010,6 +1028,7 @@ public final class BluetoothDevice implements Parcelable { private static volatile IBluetooth sService; private final String mAddress; + @AddressType private final int mAddressType; /*package*/ @UnsupportedAppUsage @@ -1064,6 +1083,7 @@ public final class BluetoothDevice implements Parcelable { } mAddress = address; + mAddressType = ADDRESS_TYPE_PUBLIC; } @Override @@ -1279,7 +1299,6 @@ public final class BluetoothDevice implements Parcelable { * the bonding process completes, and its result. * <p>Android system services will handle the necessary user interactions * to confirm and complete the bonding process. - * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}. * * @param transport The transport to use for the pairing procedure. * @return false on immediate error, true if bonding will begin @@ -1287,8 +1306,9 @@ public final class BluetoothDevice implements Parcelable { * @hide */ @UnsupportedAppUsage + @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) public boolean createBond(int transport) { - return createBondOutOfBand(transport, null); + return createBondInternal(transport, null, null); } /** @@ -1302,21 +1322,38 @@ public final class BluetoothDevice implements Parcelable { * <p>Android system services will handle the necessary user interactions * to confirm and complete the bonding process. * - * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}. + * <p>There are two possible versions of OOB Data. This data can come in as + * P192 or P256. This is a reference to the cryptography used to generate the key. + * The caller may pass one or both. If both types of data are passed, then the + * P256 data will be preferred, and thus used. * * @param transport - Transport to use - * @param oobData - Out Of Band data + * @param remoteP192Data - Out Of Band data (P192) or null + * @param remoteP256Data - Out Of Band data (P256) or null * @return false on immediate error, true if bonding will begin * @hide */ - public boolean createBondOutOfBand(int transport, OobData oobData) { + @SystemApi + @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) + public boolean createBondOutOfBand(int transport, @Nullable OobData remoteP192Data, + @Nullable OobData remoteP256Data) { + if (remoteP192Data == null && remoteP256Data == null) { + throw new IllegalArgumentException( + "One or both arguments for the OOB data types are required to not be null." + + " Please use createBond() instead if you do not have OOB data to pass."); + } + return createBondInternal(transport, remoteP192Data, remoteP256Data); + } + + private boolean createBondInternal(int transport, @Nullable OobData remoteP192Data, + @Nullable OobData remoteP256Data) { final IBluetooth service = sService; if (service == null) { Log.w(TAG, "BT not enabled, createBondOutOfBand failed"); return false; } try { - return service.createBond(this, transport, oobData); + return service.createBond(this, transport, remoteP192Data, remoteP256Data); } catch (RemoteException e) { Log.e(TAG, "", e); } @@ -1347,27 +1384,6 @@ public final class BluetoothDevice implements Parcelable { } /** - * Set the Out Of Band data for a remote device to be used later - * in the pairing mechanism. Users can obtain this data through other - * trusted channels - * - * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}. - * - * @param hash Simple Secure pairing hash - * @param randomizer The random key obtained using OOB - * @return false on error; true otherwise - * @hide - */ - public boolean setDeviceOutOfBandData(byte[] hash, byte[] randomizer) { - //TODO(BT) - /* - try { - return sService.setDeviceOutOfBandData(this, hash, randomizer); - } catch (RemoteException e) {Log.e(TAG, "", e);} */ - return false; - } - - /** * Cancel an in-progress bonding request started with {@link #createBond}. * * @return true on success, false on error diff --git a/core/java/android/bluetooth/OobData.java b/core/java/android/bluetooth/OobData.java index 0d0c6ab2efa9..08d694eb93e2 100644 --- a/core/java/android/bluetooth/OobData.java +++ b/core/java/android/bluetooth/OobData.java @@ -1,4 +1,4 @@ -/* +/** * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,88 +16,949 @@ package android.bluetooth; +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; +import com.android.internal.util.Preconditions; + +import java.lang.IllegalArgumentException; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + /** * Out Of Band Data for Bluetooth device pairing. * * <p>This object represents optional data obtained from a remote device through - * an out-of-band channel (eg. NFC). + * an out-of-band channel (eg. NFC, QR). + * + * <p>References: + * NFC AD Forum SSP 1.1 (AD) + * {@link https://members.nfc-forum.org//apps/group_public/download.php/24620/NFCForum-AD-BTSSP_1_1.pdf} + * Core Specification Supplement (CSS) V9 + * + * <p>There are several BR/EDR Examples + * + * <p>Negotiated Handover: + * Bluetooth Carrier Configuration Record: + * - OOB Data Length + * - Device Address + * - Class of Device + * - Simple Pairing Hash C + * - Simple Pairing Randomizer R + * - Service Class UUID + * - Bluetooth Local Name + * + * <p>Static Handover: + * Bluetooth Carrier Configuration Record: + * - OOB Data Length + * - Device Address + * - Class of Device + * - Service Class UUID + * - Bluetooth Local Name + * + * <p>Simplified Tag Format for Single BT Carrier: + * Bluetooth OOB Data Record: + * - OOB Data Length + * - Device Address + * - Class of Device + * - Service Class UUID + * - Bluetooth Local Name * * @hide */ -public class OobData implements Parcelable { - private byte[] mLeBluetoothDeviceAddress; - private byte[] mSecurityManagerTk; - private byte[] mLeSecureConnectionsConfirmation; - private byte[] mLeSecureConnectionsRandom; +@SystemApi +public final class OobData implements Parcelable { + + private static final String TAG = "OobData"; + /** The {@link OobData#mClassicLength} may be. (AD 3.1.1) (CSS 1.6.2) @hide */ + @SystemApi + public static final int OOB_LENGTH_OCTETS = 2; + /** + * The length for the {@link OobData#mDeviceAddressWithType}(6) and Address Type(1). + * (AD 3.1.2) (CSS 1.6.2) + * @hide + */ + @SystemApi + public static final int DEVICE_ADDRESS_OCTETS = 7; + /** The Class of Device is 3 octets. (AD 3.1.3) (CSS 1.6.2) @hide */ + @SystemApi + public static final int CLASS_OF_DEVICE_OCTETS = 3; + /** The Confirmation data must be 16 octets. (AD 3.2.2) (CSS 1.6.2) @hide */ + @SystemApi + public static final int CONFIRMATION_OCTETS = 16; + /** The Randomizer data must be 16 octets. (AD 3.2.3) (CSS 1.6.2) @hide */ + @SystemApi + public static final int RANDOMIZER_OCTETS = 16; + /** The LE Device Role length is 1 octet. (AD 3.3.2) (CSS 1.17) @hide */ + @SystemApi + public static final int LE_DEVICE_ROLE_OCTETS = 1; + /** The {@link OobData#mLeTemporaryKey} length. (3.4.1) @hide */ + @SystemApi + public static final int LE_TK_OCTETS = 16; + /** The {@link OobData#mLeAppearance} length. (3.4.1) @hide */ + @SystemApi + public static final int LE_APPEARANCE_OCTETS = 2; + /** The {@link OobData#mLeFlags} length. (3.4.1) @hide */ + @SystemApi + public static final int LE_DEVICE_FLAG_OCTETS = 1; // 1 octet to hold the 0-4 value. + + // Le Roles + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef( + prefix = { "LE_DEVICE_ROLE_" }, + value = { + LE_DEVICE_ROLE_PERIPHERAL_ONLY, + LE_DEVICE_ROLE_CENTRAL_ONLY, + LE_DEVICE_ROLE_BOTH_PREFER_PERIPHERAL, + LE_DEVICE_ROLE_BOTH_PREFER_CENTRAL + } + ) + public @interface LeRole {} + + /** @hide */ + @SystemApi + public static final int LE_DEVICE_ROLE_PERIPHERAL_ONLY = 0x00; + /** @hide */ + @SystemApi + public static final int LE_DEVICE_ROLE_CENTRAL_ONLY = 0x01; + /** @hide */ + @SystemApi + public static final int LE_DEVICE_ROLE_BOTH_PREFER_PERIPHERAL = 0x02; + /** @hide */ + @SystemApi + public static final int LE_DEVICE_ROLE_BOTH_PREFER_CENTRAL = 0x03; + + // Le Flags + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef( + prefix = { "LE_FLAG_" }, + value = { + LE_FLAG_LIMITED_DISCOVERY_MODE, + LE_FLAG_GENERAL_DISCOVERY_MODE, + LE_FLAG_BREDR_NOT_SUPPORTED, + LE_FLAG_SIMULTANEOUS_CONTROLLER, + LE_FLAG_SIMULTANEOUS_HOST + } + ) + public @interface LeFlag {} + + /** @hide */ + @SystemApi + public static final int LE_FLAG_LIMITED_DISCOVERY_MODE = 0x00; + /** @hide */ + @SystemApi + public static final int LE_FLAG_GENERAL_DISCOVERY_MODE = 0x01; + /** @hide */ + @SystemApi + public static final int LE_FLAG_BREDR_NOT_SUPPORTED = 0x02; + /** @hide */ + @SystemApi + public static final int LE_FLAG_SIMULTANEOUS_CONTROLLER = 0x03; + /** @hide */ + @SystemApi + public static final int LE_FLAG_SIMULTANEOUS_HOST = 0x04; + + /** + * Main creation method for creating a Classic version of {@link OobData}. + * + * <p>This object will allow the caller to call {@link ClassicBuilder#build()} + * to build the data object or add any option information to the builder. + * + * @param confirmationHash byte array consisting of {@link OobData#CONFIRMATION_OCTETS} octets + * of data. Data is derived from controller/host stack and is required for pairing OOB. + * @param classicLength byte array representing the length of data from 8-65535 across 2 + * octets (0xXXXX). + * @param deviceAddressWithType byte array representing the Bluetooth Address of the device + * that owns the OOB data. (i.e. the originator) [6 octets] + * + * @return a Classic Builder instance with all the given data set or null. + * + * @throws IllegalArgumentException if any of the values fail to be set. + * @throws NullPointerException if any argument is null. + * + * @hide + */ + @NonNull + @SystemApi + public static ClassicBuilder createClassicBuilder(@NonNull byte[] confirmationHash, + @NonNull byte[] classicLength, @NonNull byte[] deviceAddressWithType) { + return new ClassicBuilder(confirmationHash, classicLength, deviceAddressWithType); + } + + /** + * Main creation method for creating a LE version of {@link OobData}. + * + * <p>This object will allow the caller to call {@link LeBuilder#build()} + * to build the data object or add any option information to the builder. + * + * @param deviceAddressWithType the LE device address plus the address type (7 octets); + * not null. + * @param leDeviceRole whether the device supports Peripheral, Central, + * Both including preference; not null. (1 octet) + * @param confirmationHash Array consisting of {@link OobData#CONFIRMATION_OCTETS} octets + * of data. Data is derived from controller/host stack and is + * required for pairing OOB. + * + * <p>Possible LE Device Role Values: + * 0x00 Only Peripheral supported + * 0x01 Only Central supported + * 0x02 Central & Peripheral supported; Peripheral Preferred + * 0x03 Only peripheral supported; Central Preferred + * 0x04 - 0xFF Reserved + * + * @return a LeBuilder instance with all the given data set or null. + * + * @throws IllegalArgumentException if any of the values fail to be set. + * @throws NullPointerException if any argument is null. + * + * @hide + */ + @NonNull + @SystemApi + public static LeBuilder createLeBuilder(@NonNull byte[] confirmationHash, + @NonNull byte[] deviceAddressWithType, @LeRole int leDeviceRole) { + return new LeBuilder(confirmationHash, deviceAddressWithType, leDeviceRole); + } + + /** + * Builds an {@link OobData} object and validates that the required combination + * of values are present to create the LE specific OobData type. + * + * @hide + */ + @SystemApi + public static final class LeBuilder { + + /** + * It is recommended that this Hash C is generated anew for each + * pairing. + * + * <p>It should be noted that on passive NFC this isn't possible as the data is static + * and immutable. + */ + private byte[] mConfirmationHash = null; + + /** + * Optional, but adds more validity to the pairing. + * + * <p>If not present a value of 0 is assumed. + */ + private byte[] mRandomizerHash = new byte[] { + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + }; + + /** + * The Bluetooth Device user-friendly name presented over Bluetooth Technology. + * + * <p>This is the name that may be displayed to the device user as part of the UI. + */ + private byte[] mDeviceName = null; + + /** + * Sets the Bluetooth Device name to be used for UI purposes. + * + * <p>Optional attribute. + * + * @param deviceName byte array representing the name, may be 0 in length, not null. + * + * @return {@link OobData#ClassicBuilder} + * + * @throws NullPointerException if deviceName is null. + * + * @hide + */ + @NonNull + @SystemApi + public LeBuilder setDeviceName(@NonNull byte[] deviceName) { + Preconditions.checkNotNull(deviceName); + this.mDeviceName = deviceName; + return this; + } + + /** + * The Bluetooth Device Address is the address to which the OOB data belongs. + * + * <p>The length MUST be {@link OobData#DEVICE_ADDRESS_OCTETS} octets. + * + * <p> Address is encoded in Little Endian order. + * + * <p>e.g. 00:01:02:03:04:05 would be x05x04x03x02x01x00 + */ + private final byte[] mDeviceAddressWithType; + + /** + * During an LE connection establishment, one must be in the Peripheral mode and the other + * in the Central role. + * + * <p>Possible Values: + * {@link LE_DEVICE_ROLE_PERIPHERAL_ONLY} Only Peripheral supported + * {@link LE_DEVICE_ROLE_CENTRAL_ONLY} Only Central supported + * {@link LE_DEVICE_ROLE_BOTH_PREFER_PERIPHERAL} Central & Peripheral supported; + * Peripheral Preferred + * {@link LE_DEVICE_ROLE_BOTH_PREFER_CENTRAL} Only peripheral supported; Central Preferred + * 0x04 - 0xFF Reserved + */ + private final @LeRole int mLeDeviceRole; + + /** + * Temporary key value from the Security Manager. + * + * <p> Must be {@link LE_TK_OCTETS} in size + */ + private byte[] mLeTemporaryKey = null; + + /** + * Defines the representation of the external appearance of the device. + * + * <p>For example, a mouse, remote control, or keyboard. + * + * <p>Used for visual on discovering device to represent icon/string/etc... + */ + private byte[] mLeAppearance = null; + + /** + * Contains which discoverable mode to use, BR/EDR support and capability. + * + * <p>Possible LE Flags: + * {@link LE_FLAG_LIMITED_DISCOVERY_MODE} LE Limited Discoverable Mode. + * {@link LE_FLAG_GENERAL_DISCOVERY_MODE} LE General Discoverable Mode. + * {@link LE_FLAG_BREDR_NOT_SUPPORTED} BR/EDR Not Supported. Bit 37 of + * LMP Feature Mask Definitions. + * {@link LE_FLAG_SIMULTANEOUS_CONTROLLER} Simultaneous LE and BR/EDR to + * Same Device Capable (Controller). + * Bit 49 of LMP Feature Mask Definitions. + * {@link LE_FLAG_SIMULTANEOUS_HOST} Simultaneous LE and BR/EDR to + * Same Device Capable (Host). + * Bit 55 of LMP Feature Mask Definitions. + * <b>0x05- 0x07 Reserved</b> + */ + private @LeFlag int mLeFlags = LE_FLAG_GENERAL_DISCOVERY_MODE; // Invalid default + + /** + * Constructing an OobData object for use with LE requires + * a LE Device Address and LE Device Role as well as the Confirmation + * and optionally, the Randomizer, however it is recommended to use. + * + * @param confirmationHash byte array consisting of {@link OobData#CONFIRMATION_OCTETS} + * octets of data. Data is derived from controller/host stack and is required for + * pairing OOB. + * @param deviceAddressWithType 7 bytes containing the 6 byte address with the 1 byte + * address type. + * @param leDeviceRole indicating device's role and preferences (Central or Peripheral) + * + * <p>Possible Values: + * {@link LE_DEVICE_ROLE_PERIPHERAL_ONLY} Only Peripheral supported + * {@link LE_DEVICE_ROLE_CENTRAL_ONLY} Only Central supported + * {@link LE_DEVICE_ROLE_BOTH_PREFER_PERIPHERAL} Central & Peripheral supported; + * Peripheral Preferred + * {@link LE_DEVICE_ROLE_BOTH_PREFER_CENTRAL} Only peripheral supported; Central Preferred + * 0x04 - 0xFF Reserved + * + * @throws IllegalArgumentException if deviceAddressWithType is not + * {@link LE_DEVICE_ADDRESS_OCTETS} octets + * @throws NullPointerException if any argument is null. + */ + private LeBuilder(@NonNull byte[] confirmationHash, @NonNull byte[] deviceAddressWithType, + @LeRole int leDeviceRole) { + Preconditions.checkNotNull(confirmationHash); + Preconditions.checkNotNull(deviceAddressWithType); + if (confirmationHash.length != OobData.CONFIRMATION_OCTETS) { + throw new IllegalArgumentException("confirmationHash must be " + + OobData.CONFIRMATION_OCTETS + " octets in length."); + } + this.mConfirmationHash = confirmationHash; + if (deviceAddressWithType.length != OobData.DEVICE_ADDRESS_OCTETS) { + throw new IllegalArgumentException("confirmationHash must be " + + OobData.DEVICE_ADDRESS_OCTETS+ " octets in length."); + } + this.mDeviceAddressWithType = deviceAddressWithType; + if (leDeviceRole < LE_DEVICE_ROLE_PERIPHERAL_ONLY + || leDeviceRole > LE_DEVICE_ROLE_BOTH_PREFER_CENTRAL) { + throw new IllegalArgumentException("leDeviceRole must be a valid value."); + } + this.mLeDeviceRole = leDeviceRole; + } + + /** + * Sets the Temporary Key value to be used by the LE Security Manager during + * LE pairing. + * + * @param leTemporaryKey byte array that shall be 16 bytes. Please see Bluetooth CSSv6, + * Part A 1.8 for a detailed description. + * + * @return {@link OobData#Builder} + * + * @throws IllegalArgumentException if the leTemporaryKey is an invalid format. + * @throws NullinterException if leTemporaryKey is null. + * + * @hide + */ + @NonNull + @SystemApi + public LeBuilder setLeTemporaryKey(@NonNull byte[] leTemporaryKey) { + Preconditions.checkNotNull(leTemporaryKey); + if (leTemporaryKey.length != LE_TK_OCTETS) { + throw new IllegalArgumentException("leTemporaryKey must be " + + LE_TK_OCTETS + " octets in length."); + } + this.mLeTemporaryKey = leTemporaryKey; + return this; + } + + /** + * @param randomizerHash byte array consisting of {@link OobData#RANDOMIZER_OCTETS} octets + * of data. Data is derived from controller/host stack and is required for pairing OOB. + * Also, randomizerHash may be all 0s or null in which case it becomes all 0s. + * + * @throws IllegalArgumentException if null or incorrect length randomizerHash was passed. + * @throws NullPointerException if randomizerHash is null. + * + * @hide + */ + @NonNull + @SystemApi + public LeBuilder setRandomizerHash(@NonNull byte[] randomizerHash) { + Preconditions.checkNotNull(randomizerHash); + if (randomizerHash.length != OobData.RANDOMIZER_OCTETS) { + throw new IllegalArgumentException("randomizerHash must be " + + OobData.RANDOMIZER_OCTETS + " octets in length."); + } + this.mRandomizerHash = randomizerHash; + return this; + } + + /** + * Sets the LE Flags necessary for the pairing scenario or discovery mode. + * + * @param leFlags enum value representing the 1 octet of data about discovery modes. + * + * <p>Possible LE Flags: + * {@link LE_FLAG_LIMITED_DISCOVERY_MODE} LE Limited Discoverable Mode. + * {@link LE_FLAG_GENERAL_DISCOVERY_MODE} LE General Discoverable Mode. + * {@link LE_FLAG_BREDR_NOT_SUPPORTED} BR/EDR Not Supported. Bit 37 of + * LMP Feature Mask Definitions. + * {@link LE_FLAG_SIMULTANEOUS_CONTROLLER} Simultaneous LE and BR/EDR to + * Same Device Capable (Controller) Bit 49 of LMP Feature Mask Definitions. + * {@link LE_FLAG_SIMULTANEOUS_HOST} Simultaneous LE and BR/EDR to + * Same Device Capable (Host). + * Bit 55 of LMP Feature Mask Definitions. + * 0x05- 0x07 Reserved + * + * @throws IllegalArgumentException for invalid flag + * @hide + */ + @NonNull + @SystemApi + public LeBuilder setLeFlags(@LeFlag int leFlags) { + if (leFlags < LE_FLAG_LIMITED_DISCOVERY_MODE || leFlags > LE_FLAG_SIMULTANEOUS_HOST) { + throw new IllegalArgumentException("leFlags must be a valid value."); + } + this.mLeFlags = leFlags; + return this; + } + + /** + * Validates and builds the {@link OobData} object for LE Security. + * + * @return {@link OobData} with given builder values + * + * @throws IllegalStateException if either of the 2 required fields were not set. + * + * @hide + */ + @NonNull + @SystemApi + public OobData build() { + final OobData oob = + new OobData(this.mDeviceAddressWithType, this.mLeDeviceRole, + this.mConfirmationHash); + + // If we have values, set them, otherwise use default + oob.mLeTemporaryKey = + (this.mLeTemporaryKey != null) ? this.mLeTemporaryKey : oob.mLeTemporaryKey; + oob.mLeAppearance = (this.mLeAppearance != null) + ? this.mLeAppearance : oob.mLeAppearance; + oob.mLeFlags = (this.mLeFlags != 0xF) ? this.mLeFlags : oob.mLeFlags; + oob.mDeviceName = (this.mDeviceName != null) ? this.mDeviceName : oob.mDeviceName; + oob.mRandomizerHash = this.mRandomizerHash; + return oob; + } + } + + /** + * Builds an {@link OobData} object and validates that the required combination + * of values are present to create the Classic specific OobData type. + * + * @hide + */ + @SystemApi + public static final class ClassicBuilder { + // Used by both Classic and LE + /** + * It is recommended that this Hash C is generated anew for each + * pairing. + * + * <p>It should be noted that on passive NFC this isn't possible as the data is static + * and immutable. + * + * @hide + */ + private byte[] mConfirmationHash = null; + + /** + * Optional, but adds more validity to the pairing. + * + * <p>If not present a value of 0 is assumed. + * + * @hide + */ + private byte[] mRandomizerHash = new byte[] { + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + }; + + /** + * The Bluetooth Device user-friendly name presented over Bluetooth Technology. + * + * <p>This is the name that may be displayed to the device user as part of the UI. + * + * @hide + */ + private byte[] mDeviceName = null; + + /** + * This length value provides the absolute length of total OOB data block used for + * Bluetooth BR/EDR + * + * <p>OOB communication, which includes the length field itself and the Bluetooth + * Device Address. + * + * <p>The minimum length that may be represented in this field is 8. + * + * @hide + */ + private final byte[] mClassicLength; + + /** + * The Bluetooth Device Address is the address to which the OOB data belongs. + * + * <p>The length MUST be {@link OobData#DEVICE_ADDRESS_OCTETS} octets. + * + * <p> Address is encoded in Little Endian order. + * + * <p>e.g. 00:01:02:03:04:05 would be x05x04x03x02x01x00 + * + * @hide + */ + private final byte[] mDeviceAddressWithType; + + /** + * Class of Device information is to be used to provide a graphical representation + * to the user as part of UI involving operations. + * + * <p>This is not to be used to determine a particular service can be used. + * + * <p>The length MUST be {@link OobData#CLASS_OF_DEVICE_OCTETS} octets. + * + * @hide + */ + private byte[] mClassOfDevice = null; + + /** + * @param confirmationHash byte array consisting of {@link OobData#CONFIRMATION_OCTETS} + * octets of data. Data is derived from controller/host stack and is required for pairing + * OOB. + * @param randomizerHash byte array consisting of {@link OobData#RANDOMIZER_OCTETS} octets + * of data. Data is derived from controller/host stack and is required + * for pairing OOB. Also, randomizerHash may be all 0s or null in which case + * it becomes all 0s. + * @param classicLength byte array representing the length of data from 8-65535 across 2 + * octets (0xXXXX). Inclusive of this value in the length. + * @param deviceAddressWithType byte array representing the Bluetooth Address of the device + * that owns the OOB data. (i.e. the originator) [7 octets] this includes the Address Type + * as the last octet. + * + * @throws IllegalArgumentException if any value is not the correct length + * @throws NullPointerException if anything passed is null + * + * @hide + */ + private ClassicBuilder(@NonNull byte[] confirmationHash, @NonNull byte[] classicLength, + @NonNull byte[] deviceAddressWithType) { + Preconditions.checkNotNull(confirmationHash); + Preconditions.checkNotNull(classicLength); + Preconditions.checkNotNull(deviceAddressWithType); + if (confirmationHash.length != OobData.CONFIRMATION_OCTETS) { + throw new IllegalArgumentException("confirmationHash must be " + + OobData.CONFIRMATION_OCTETS + " octets in length."); + } + this.mConfirmationHash = confirmationHash; + if (classicLength.length != OOB_LENGTH_OCTETS) { + throw new IllegalArgumentException("classicLength must be " + + OOB_LENGTH_OCTETS + " octets in length."); + } + this.mClassicLength = classicLength; + if (deviceAddressWithType.length != DEVICE_ADDRESS_OCTETS) { + throw new IllegalArgumentException("deviceAddressWithType must be " + + DEVICE_ADDRESS_OCTETS + " octets in length."); + } + this.mDeviceAddressWithType = deviceAddressWithType; + } - public byte[] getLeBluetoothDeviceAddress() { - return mLeBluetoothDeviceAddress; + /** + * @param randomizerHash byte array consisting of {@link OobData#RANDOMIZER_OCTETS} octets + * of data. Data is derived from controller/host stack and is required for pairing OOB. + * Also, randomizerHash may be all 0s or null in which case it becomes all 0s. + * + * @throws IllegalArgumentException if null or incorrect length randomizerHash was passed. + * @throws NullPointerException if randomizerHash is null. + * + * @hide + */ + @NonNull + @SystemApi + public ClassicBuilder setRandomizerHash(@NonNull byte[] randomizerHash) { + Preconditions.checkNotNull(randomizerHash); + if (randomizerHash.length != OobData.RANDOMIZER_OCTETS) { + throw new IllegalArgumentException("randomizerHash must be " + + OobData.RANDOMIZER_OCTETS + " octets in length."); + } + this.mRandomizerHash = randomizerHash; + return this; + } + + /** + * Sets the Bluetooth Device name to be used for UI purposes. + * + * <p>Optional attribute. + * + * @param deviceName byte array representing the name, may be 0 in length, not null. + * + * @return {@link OobData#ClassicBuilder} + * + * @throws NullPointerException if deviceName is null + * + * @hide + */ + @NonNull + @SystemApi + public ClassicBuilder setDeviceName(@NonNull byte[] deviceName) { + Preconditions.checkNotNull(deviceName); + this.mDeviceName = deviceName; + return this; + } + + /** + * Sets the Bluetooth Class of Device; used for UI purposes only. + * + * <p>Not an indicator of available services! + * + * <p>Optional attribute. + * + * @param classOfDevice byte array of {@link OobData#CLASS_OF_DEVICE_OCTETS} octets. + * + * @return {@link OobData#ClassicBuilder} + * + * @throws IllegalArgumentException if length is not equal to + * {@link OobData#CLASS_OF_DEVICE_OCTETS} octets. + * @throws NullPointerException if classOfDevice is null. + * + * @hide + */ + @NonNull + @SystemApi + public ClassicBuilder setClassOfDevice(@NonNull byte[] classOfDevice) { + Preconditions.checkNotNull(classOfDevice); + if (classOfDevice.length != OobData.CLASS_OF_DEVICE_OCTETS) { + throw new IllegalArgumentException("classOfDevice must be " + + OobData.CLASS_OF_DEVICE_OCTETS + " octets in length."); + } + this.mClassOfDevice = classOfDevice; + return this; + } + + /** + * Validates and builds the {@link OobDat object for Classic Security. + * + * @return {@link OobData} with previously given builder values. + * + * @hide + */ + @NonNull + @SystemApi + public OobData build() { + final OobData oob = + new OobData(this.mClassicLength, this.mDeviceAddressWithType, + this.mConfirmationHash); + // If we have values, set them, otherwise use default + oob.mDeviceName = (this.mDeviceName != null) ? this.mDeviceName : oob.mDeviceName; + oob.mClassOfDevice = (this.mClassOfDevice != null) + ? this.mClassOfDevice : oob.mClassOfDevice; + oob.mRandomizerHash = this.mRandomizerHash; + return oob; + } + } + + // Members (Defaults for Optionals must be set or Parceling fails on NPE) + // Both + private final byte[] mDeviceAddressWithType; + private final byte[] mConfirmationHash; + private byte[] mRandomizerHash = new byte[] { + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + }; + // Default the name to "Bluetooth Device" + private byte[] mDeviceName = new byte[] { + // Bluetooth + 0x42, 0x6c, 0x75, 0x65, 0x74, 0x6f, 0x6f, 0x74, 0x68, + // <space>Device + 0x20, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65 + }; + + // Classic + private final byte[] mClassicLength; + private byte[] mClassOfDevice = new byte[CLASS_OF_DEVICE_OCTETS]; + + // LE + private final @LeRole int mLeDeviceRole; + private byte[] mLeTemporaryKey = new byte[LE_TK_OCTETS]; + private byte[] mLeAppearance = new byte[LE_APPEARANCE_OCTETS]; + private @LeFlag int mLeFlags = LE_FLAG_LIMITED_DISCOVERY_MODE; + + /** + * @return byte array representing the MAC address of a bluetooth device. + * The Address is 6 octets long with a 1 octet address type associated with the address. + * + * <p>For classic this will be 6 byte address plus the default of PUBLIC_ADDRESS Address Type. + * For LE there are more choices for Address Type. + * + * @hide + */ + @NonNull + @SystemApi + public byte[] getDeviceAddressWithType() { + return mDeviceAddressWithType; + } + + /** + * @return byte array representing the confirmationHash value + * which is used to confirm the identity to the controller. + * + * @hide + */ + @NonNull + @SystemApi + public byte[] getConfirmationHash() { + return mConfirmationHash; } /** - * Sets the LE Bluetooth Device Address value to be used during LE pairing. - * The value shall be 7 bytes. Please see Bluetooth CSSv6, Part A 1.16 for - * a detailed description. + * @return byte array representing the randomizerHash value + * which is used to verify the identity of the controller. + * + * @hide */ - public void setLeBluetoothDeviceAddress(byte[] leBluetoothDeviceAddress) { - mLeBluetoothDeviceAddress = leBluetoothDeviceAddress; + @NonNull + @SystemApi + public byte[] getRandomizerHash() { + return mRandomizerHash; } - public byte[] getSecurityManagerTk() { - return mSecurityManagerTk; + /** + * @return Device Name used for displaying name in UI. + * + * <p>Also, this will be populated with the LE Local Name if the data is for LE. + * + * @hide + */ + @Nullable + @SystemApi + public byte[] getDeviceName() { + return mDeviceName; + } + + /** + * @return byte array representing the oob data length which is the length + * of all of the data including these octets. + * + * @hide + */ + @NonNull + @SystemApi + public byte[] getClassicLength() { + return mClassicLength; + } + + /** + * @return byte array representing the class of device for UI display. + * + * <p>Does not indicate services available; for display only. + * + * @hide + */ + @NonNull + @SystemApi + public byte[] getClassOfDevice() { + return mClassOfDevice; } /** - * Sets the Temporary Key value to be used by the LE Security Manager during - * LE pairing. The value shall be 16 bytes. Please see Bluetooth CSSv6, - * Part A 1.8 for a detailed description. + * @return Temporary Key used for LE pairing. + * + * @hide */ - public void setSecurityManagerTk(byte[] securityManagerTk) { - mSecurityManagerTk = securityManagerTk; + @Nullable + @SystemApi + public byte[] getLeTemporaryKey() { + return mLeTemporaryKey; } - public byte[] getLeSecureConnectionsConfirmation() { - return mLeSecureConnectionsConfirmation; + /** + * @return Appearance used for LE pairing. For use in UI situations + * when determining what sort of icons or text to display regarding + * the device. + * + * @hide + */ + @Nullable + @SystemApi + public byte[] getLeAppearance() { + return mLeTemporaryKey; } - public void setLeSecureConnectionsConfirmation(byte[] leSecureConnectionsConfirmation) { - mLeSecureConnectionsConfirmation = leSecureConnectionsConfirmation; + /** + * @return Flags used to determing discoverable mode to use, BR/EDR Support, and Capability. + * + * <p>Possible LE Flags: + * {@link LE_FLAG_LIMITED_DISCOVERY_MODE} LE Limited Discoverable Mode. + * {@link LE_FLAG_GENERAL_DISCOVERY_MODE} LE General Discoverable Mode. + * {@link LE_FLAG_BREDR_NOT_SUPPORTED} BR/EDR Not Supported. Bit 37 of + * LMP Feature Mask Definitions. + * {@link LE_FLAG_SIMULTANEOUS_CONTROLLER} Simultaneous LE and BR/EDR to + * Same Device Capable (Controller). + * Bit 49 of LMP Feature Mask Definitions. + * {@link LE_FLAG_SIMULTANEOUS_HOST} Simultaneous LE and BR/EDR to + * Same Device Capable (Host). + * Bit 55 of LMP Feature Mask Definitions. + * <b>0x05- 0x07 Reserved</b> + * + * @hide + */ + @NonNull + @SystemApi + @LeFlag + public int getLeFlags() { + return mLeFlags; } - public byte[] getLeSecureConnectionsRandom() { - return mLeSecureConnectionsRandom; + /** + * @return the supported and preferred roles of the LE device. + * + * <p>Possible Values: + * {@link LE_DEVICE_ROLE_PERIPHERAL_ONLY} Only Peripheral supported + * {@link LE_DEVICE_ROLE_CENTRAL_ONLY} Only Central supported + * {@link LE_DEVICE_ROLE_BOTH_PREFER_PERIPHERAL} Central & Peripheral supported; + * Peripheral Preferred + * {@link LE_DEVICE_ROLE_BOTH_PREFER_CENTRAL} Only peripheral supported; Central Preferred + * 0x04 - 0xFF Reserved + * + * @hide + */ + @NonNull + @SystemApi + @LeRole + public int getLeDeviceRole() { + return mLeDeviceRole; } - public void setLeSecureConnectionsRandom(byte[] leSecureConnectionsRandom) { - mLeSecureConnectionsRandom = leSecureConnectionsRandom; + /** + * Classic Security Constructor + */ + private OobData(@NonNull byte[] classicLength, @NonNull byte[] deviceAddressWithType, + @NonNull byte[] confirmationHash) { + mClassicLength = classicLength; + mDeviceAddressWithType = deviceAddressWithType; + mConfirmationHash = confirmationHash; + mLeDeviceRole = -1; // Satisfy final } - public OobData() { + /** + * LE Security Constructor + */ + private OobData(@NonNull byte[] deviceAddressWithType, @LeRole int leDeviceRole, + @NonNull byte[] confirmationHash) { + mDeviceAddressWithType = deviceAddressWithType; + mLeDeviceRole = leDeviceRole; + mConfirmationHash = confirmationHash; + mClassicLength = new byte[OOB_LENGTH_OCTETS]; // Satisfy final } private OobData(Parcel in) { - mLeBluetoothDeviceAddress = in.createByteArray(); - mSecurityManagerTk = in.createByteArray(); - mLeSecureConnectionsConfirmation = in.createByteArray(); - mLeSecureConnectionsRandom = in.createByteArray(); + // Both + mDeviceAddressWithType = in.createByteArray(); + mConfirmationHash = in.createByteArray(); + mRandomizerHash = in.createByteArray(); + mDeviceName = in.createByteArray(); + + // Classic + mClassicLength = in.createByteArray(); + mClassOfDevice = in.createByteArray(); + + // LE + mLeDeviceRole = in.readInt(); + mLeTemporaryKey = in.createByteArray(); + mLeAppearance = in.createByteArray(); + mLeFlags = in.readInt(); } + /** + * @hide + */ @Override public int describeContents() { return 0; } + /** + * @hide + */ @Override - public void writeToParcel(Parcel out, int flags) { - out.writeByteArray(mLeBluetoothDeviceAddress); - out.writeByteArray(mSecurityManagerTk); - out.writeByteArray(mLeSecureConnectionsConfirmation); - out.writeByteArray(mLeSecureConnectionsRandom); + public void writeToParcel(@NonNull Parcel out, int flags) { + // Both + // Required + out.writeByteArray(mDeviceAddressWithType); + // Required + out.writeByteArray(mConfirmationHash); + // Optional + out.writeByteArray(mRandomizerHash); + // Optional + out.writeByteArray(mDeviceName); + + // Classic + // Required + out.writeByteArray(mClassicLength); + // Optional + out.writeByteArray(mClassOfDevice); + + // LE + // Required + out.writeInt(mLeDeviceRole); + // Required + out.writeByteArray(mLeTemporaryKey); + // Optional + out.writeByteArray(mLeAppearance); + // Optional + out.writeInt(mLeFlags); } + // For Parcelable public static final @android.annotation.NonNull Parcelable.Creator<OobData> CREATOR = new Parcelable.Creator<OobData>() { public OobData createFromParcel(Parcel in) { @@ -108,4 +969,47 @@ public class OobData implements Parcelable { return new OobData[size]; } }; + + /** + * @return a {@link String} representation of the OobData object. + * + * @hide + */ + @Override + @NonNull + public String toString() { + return "OobData: \n\t" + // Both + + "Device Address With Type: " + toHexString(mDeviceAddressWithType) + "\n\t" + + "Confirmation: " + toHexString(mConfirmationHash) + "\n\t" + + "Randomizer: " + toHexString(mRandomizerHash) + "\n\t" + + "Device Name: " + toHexString(mDeviceName) + "\n\t" + // Classic + + "OobData Length: " + toHexString(mClassicLength) + "\n\t" + + "Class of Device: " + toHexString(mClassOfDevice) + "\n\t" + // LE + + "LE Device Role: " + toHexString(mLeDeviceRole) + "\n\t" + + "LE Temporary Key: " + toHexString(mLeTemporaryKey) + "\n\t" + + "LE Appearance: " + toHexString(mLeAppearance) + "\n\t" + + "LE Flags: " + toHexString(mLeFlags) + "\n\t"; + } + + @NonNull + private String toHexString(@NonNull int b) { + return toHexString(new byte[] {(byte) b}); + } + + @NonNull + private String toHexString(@NonNull byte b) { + return toHexString(new byte[] {b}); + } + + @NonNull + private String toHexString(@NonNull byte[] array) { + StringBuilder builder = new StringBuilder(array.length * 2); + for (byte b: array) { + builder.append(String.format("%02x", b)); + } + return builder.toString(); + } } diff --git a/core/java/android/bluetooth/le/ScanFilter.java b/core/java/android/bluetooth/le/ScanFilter.java index 7511fd051e41..86721502d409 100644 --- a/core/java/android/bluetooth/le/ScanFilter.java +++ b/core/java/android/bluetooth/le/ScanFilter.java @@ -16,15 +16,19 @@ package android.bluetooth.le; +import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SystemApi; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothDevice.AddressType; import android.os.Parcel; import android.os.ParcelUuid; import android.os.Parcelable; import com.android.internal.util.BitUtils; +import com.android.internal.util.Preconditions; import java.util.Arrays; import java.util.List; @@ -53,6 +57,11 @@ public final class ScanFilter implements Parcelable { @Nullable private final String mDeviceAddress; + private final @AddressType int mAddressType; + + @Nullable + private final byte[] mIrk; + @Nullable private final ParcelUuid mServiceUuid; @Nullable @@ -79,12 +88,12 @@ public final class ScanFilter implements Parcelable { /** @hide */ public static final ScanFilter EMPTY = new ScanFilter.Builder().build(); - private ScanFilter(String name, String deviceAddress, ParcelUuid uuid, ParcelUuid uuidMask, ParcelUuid solicitationUuid, ParcelUuid solicitationUuidMask, ParcelUuid serviceDataUuid, byte[] serviceData, byte[] serviceDataMask, - int manufacturerId, byte[] manufacturerData, byte[] manufacturerDataMask) { + int manufacturerId, byte[] manufacturerData, byte[] manufacturerDataMask, + @AddressType int addressType, @Nullable byte[] irk) { mDeviceName = name; mServiceUuid = uuid; mServiceUuidMask = uuidMask; @@ -97,6 +106,8 @@ public final class ScanFilter implements Parcelable { mManufacturerId = manufacturerId; mManufacturerData = manufacturerData; mManufacturerDataMask = manufacturerDataMask; + mAddressType = addressType; + mIrk = irk; } @Override @@ -280,6 +291,23 @@ public final class ScanFilter implements Parcelable { return mDeviceAddress; } + /** + * @hide + */ + @SystemApi + public @AddressType int getAddressType() { + return mAddressType; + } + + /** + * @hide + */ + @SystemApi + @Nullable + public byte[] getIrk() { + return mIrk; + } + @Nullable public byte[] getServiceData() { return mServiceData; @@ -516,8 +544,16 @@ public final class ScanFilter implements Parcelable { */ public static final class Builder { + /** + * @hide + */ + @SystemApi + public static final int LEN_IRK_OCTETS = 16; + private String mDeviceName; private String mDeviceAddress; + private @AddressType int mAddressType = BluetoothDevice.ADDRESS_TYPE_PUBLIC; + private byte[] mIrk; private ParcelUuid mServiceUuid; private ParcelUuid mUuidMask; @@ -546,14 +582,130 @@ public final class ScanFilter implements Parcelable { * * @param deviceAddress The device Bluetooth address for the filter. It needs to be in the * format of "01:02:03:AB:CD:EF". The device address can be validated using {@link - * BluetoothAdapter#checkBluetoothAddress}. + * BluetoothAdapter#checkBluetoothAddress}. The @AddressType is defaulted to {@link + * BluetoothDevice#ADDRESS_TYPE_PUBLIC} * @throws IllegalArgumentException If the {@code deviceAddress} is invalid. */ public Builder setDeviceAddress(String deviceAddress) { - if (deviceAddress != null && !BluetoothAdapter.checkBluetoothAddress(deviceAddress)) { + return setDeviceAddress(mDeviceAddress, BluetoothDevice.ADDRESS_TYPE_PUBLIC); + } + + /** + * Set filter on Address with AddressType + * + * <p>This key is used to resolve a private address from a public address. + * + * @param deviceAddress The device Bluetooth address for the filter. It needs to be in the + * format of "01:02:03:AB:CD:EF". The device address can be validated using {@link + * BluetoothAdapter#checkBluetoothAddress}. May be any type of address. + * @param addressType indication of the type of address + * e.g. {@link BluetoothDevice#ADDRESS_TYPE_PUBLIC} + * or {@link BluetoothDevice#ADDRESS_TYPE_RANDOM} + * + * @throws IllegalArgumentException If the {@code deviceAddress} is invalid. + * @throws IllegalArgumentException If the {@code addressType} is invalid length + * @throws NullPointerException if {@code deviceAddress} is null. + * + * @hide + */ + @NonNull + @SystemApi + public Builder setDeviceAddress(@NonNull String deviceAddress, + @AddressType int addressType) { + return setDeviceAddressInternal(deviceAddress, addressType, null); + } + + /** + * Set filter on Address with AddressType and the Identity Resolving Key (IRK). + * + * <p>The IRK is used to resolve a {@link BluetoothDevice#ADDRESS_TYPE_PUBLIC} from + * a PRIVATE_ADDRESS type. + * + * @param deviceAddress The device Bluetooth address for the filter. It needs to be in the + * format of "01:02:03:AB:CD:EF". The device address can be validated using {@link + * BluetoothAdapter#checkBluetoothAddress}. This Address type must only be PUBLIC OR RANDOM + * STATIC. + * @param addressType indication of the type of address + * e.g. {@link BluetoothDevice#ADDRESS_TYPE_PUBLIC} + * or {@link BluetoothDevice#ADDRESS_TYPE_RANDOM} + * @param irk non-null byte array representing the Identity Resolving Key + * + * @throws IllegalArgumentException If the {@code deviceAddress} is invalid. + * @throws IllegalArgumentException if the {@code irk} is invalid length. + * @throws IllegalArgumentException If the {@code addressType} is invalid length or is not + * PUBLIC or RANDOM STATIC when an IRK is present. + * @throws NullPointerException if {@code deviceAddress} or {@code irk} is null. + * + * @hide + */ + @NonNull + @SystemApi + public Builder setDeviceAddress(@NonNull String deviceAddress, + @AddressType int addressType, + @NonNull byte[] irk) { + Preconditions.checkNotNull(irk); + if (irk.length != LEN_IRK_OCTETS) { + throw new IllegalArgumentException("'irk' is invalid length!"); + } + return setDeviceAddressInternal(deviceAddress, addressType, irk); + } + + /** + * Set filter on Address with AddressType and the Identity Resolving Key (IRK). + * + * <p>Internal setter for the device address + * + * @param deviceAddress The device Bluetooth address for the filter. It needs to be in the + * format of "01:02:03:AB:CD:EF". The device address can be validated using {@link + * BluetoothAdapter#checkBluetoothAddress}. + * @param addressType indication of the type of address + * e.g. {@link BluetoothDevice#ADDRESS_TYPE_PUBLIC} + * @param irk non-null byte array representing the Identity Resolving Address; nullable + * internally. + * + * @throws IllegalArgumentException If the {@code deviceAddress} is invalid. + * @throws IllegalArgumentException If the {@code addressType} is invalid length. + * @throws NullPointerException if {@code deviceAddress} is null. + * + * @hide + */ + @NonNull + private Builder setDeviceAddressInternal(@NonNull String deviceAddress, + @AddressType int addressType, + @Nullable byte[] irk) { + + // Make sure our deviceAddress is valid! + Preconditions.checkNotNull(deviceAddress); + if (!BluetoothAdapter.checkBluetoothAddress(deviceAddress)) { throw new IllegalArgumentException("invalid device address " + deviceAddress); } + + // Verify type range + if (addressType < BluetoothDevice.ADDRESS_TYPE_PUBLIC + || addressType > BluetoothDevice.ADDRESS_TYPE_RANDOM) { + throw new IllegalArgumentException("'addressType' is invalid!"); + } + + // IRK can only be used for a PUBLIC or RANDOM (STATIC) Address. + if (addressType == BluetoothDevice.ADDRESS_TYPE_RANDOM) { + // Don't want a bad combination of address and irk! + if (irk != null) { + // Since there are 3 possible RANDOM subtypes we must check to make sure + // the correct type of address is used. + if (!BluetoothAdapter.isAddressRandomStatic(deviceAddress)) { + throw new IllegalArgumentException( + "Invalid combination: IRK requires either a PUBLIC or " + + "RANDOM (STATIC) Address"); + } + } + } + + // PUBLIC doesn't require extra work + // Without an IRK any address may be accepted + mDeviceAddress = deviceAddress; + mAddressType = addressType; + mIrk = irk; return this; } @@ -727,7 +879,8 @@ public final class ScanFilter implements Parcelable { mServiceUuid, mUuidMask, mServiceSolicitationUuid, mServiceSolicitationUuidMask, mServiceDataUuid, mServiceData, mServiceDataMask, - mManufacturerId, mManufacturerData, mManufacturerDataMask); + mManufacturerId, mManufacturerData, mManufacturerDataMask, + mAddressType, mIrk); } } } diff --git a/core/java/android/bluetooth/le/ScanSettings.java b/core/java/android/bluetooth/le/ScanSettings.java index 504118ec5da8..368d1eecade4 100644 --- a/core/java/android/bluetooth/le/ScanSettings.java +++ b/core/java/android/bluetooth/le/ScanSettings.java @@ -52,6 +52,16 @@ public final class ScanSettings implements Parcelable { public static final int SCAN_MODE_LOW_LATENCY = 2; /** + * Perform Bluetooth LE scan in ambient discovery mode. This mode has lower duty cycle and more + * aggressive scan interval than balanced mode that provides a good trade-off between scan + * latency and power consumption. + * + * @hide + */ + @SystemApi + public static final int SCAN_MODE_AMBIENT_DISCOVERY = 3; + + /** * Trigger a callback for every Bluetooth advertisement found that matches the filter criteria. * If no filter is active, all advertisement packets are reported. */ @@ -276,10 +286,17 @@ public final class ScanSettings implements Parcelable { * @throws IllegalArgumentException If the {@code scanMode} is invalid. */ public Builder setScanMode(int scanMode) { - if (scanMode < SCAN_MODE_OPPORTUNISTIC || scanMode > SCAN_MODE_LOW_LATENCY) { - throw new IllegalArgumentException("invalid scan mode " + scanMode); + switch (scanMode) { + case SCAN_MODE_OPPORTUNISTIC: + case SCAN_MODE_LOW_POWER: + case SCAN_MODE_BALANCED: + case SCAN_MODE_LOW_LATENCY: + case SCAN_MODE_AMBIENT_DISCOVERY: + mScanMode = scanMode; + break; + default: + throw new IllegalArgumentException("invalid scan mode " + scanMode); } - mScanMode = scanMode; return this; } diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java index 32aa0377cd5f..d21462e02d92 100644 --- a/core/java/android/content/ContentResolver.java +++ b/core/java/android/content/ContentResolver.java @@ -744,7 +744,7 @@ public abstract class ContentResolver implements ContentInterface { // Always log queries which take 500ms+; shorter queries are // sampled accordingly. private static final boolean ENABLE_CONTENT_SAMPLE = false; - private static final int SLOW_THRESHOLD_MILLIS = 500; + private static final int SLOW_THRESHOLD_MILLIS = 500 * Build.HW_TIMEOUT_MULTIPLIER; private final Random mRandom = new Random(); // guarded by itself /** @hide */ @@ -758,7 +758,8 @@ public abstract class ContentResolver implements ContentInterface { * before we decide it must be hung. * @hide */ - public static final int CONTENT_PROVIDER_PUBLISH_TIMEOUT_MILLIS = 10 * 1000; + public static final int CONTENT_PROVIDER_PUBLISH_TIMEOUT_MILLIS = + 10 * 1000 * Build.HW_TIMEOUT_MULTIPLIER; /** * How long we wait for an provider to be published. Should be longer than @@ -766,10 +767,11 @@ public abstract class ContentResolver implements ContentInterface { * @hide */ public static final int CONTENT_PROVIDER_READY_TIMEOUT_MILLIS = - CONTENT_PROVIDER_PUBLISH_TIMEOUT_MILLIS + 10 * 1000; + CONTENT_PROVIDER_PUBLISH_TIMEOUT_MILLIS + 10 * 1000 * Build.HW_TIMEOUT_MULTIPLIER; // Timeout given a ContentProvider that has already been started and connected to. - private static final int CONTENT_PROVIDER_TIMEOUT_MILLIS = 3 * 1000; + private static final int CONTENT_PROVIDER_TIMEOUT_MILLIS = + 3 * 1000 * Build.HW_TIMEOUT_MULTIPLIER; // Should be >= {@link #CONTENT_PROVIDER_WAIT_TIMEOUT_MILLIS}, because that's how // long ActivityManagerService is giving a content provider to get published if a new process diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index aa6127904400..fe9ed27a516f 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -4099,7 +4099,8 @@ public abstract class Context { * @see #getSystemService(String) * @hide */ - @TestApi public static final String TEST_NETWORK_SERVICE = "test_network"; + @TestApi @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public static final String TEST_NETWORK_SERVICE = "test_network"; /** * Use with {@link #getSystemService(String)} to retrieve a {@link diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java index 7f834afd7b30..933dee3a6470 100644 --- a/core/java/android/hardware/camera2/CameraManager.java +++ b/core/java/android/hardware/camera2/CameraManager.java @@ -2024,7 +2024,9 @@ public final class CameraManager { // Tell listeners that the cameras and torch modes are unavailable and schedule a // reconnection to camera service. When camera service is reconnected, the camera // and torch statuses will be updated. - for (int i = 0; i < mDeviceStatus.size(); i++) { + // Iterate from the end to the beginning befcause onStatusChangedLocked removes + // entries from the ArrayMap. + for (int i = mDeviceStatus.size() - 1; i >= 0; i--) { String cameraId = mDeviceStatus.keyAt(i); onStatusChangedLocked(ICameraServiceListener.STATUS_NOT_PRESENT, cameraId); } diff --git a/core/java/android/net/INetworkPolicyListener.aidl b/core/java/android/net/INetworkPolicyListener.aidl index dfb1e996c55a..00c691379187 100644 --- a/core/java/android/net/INetworkPolicyListener.aidl +++ b/core/java/android/net/INetworkPolicyListener.aidl @@ -25,4 +25,5 @@ oneway interface INetworkPolicyListener { void onUidPoliciesChanged(int uid, int uidPolicies); void onSubscriptionOverride(int subId, int overrideMask, int overrideValue, in int[] networkTypes); void onSubscriptionPlansChanged(int subId, in SubscriptionPlan[] plans); + void onBlockedReasonChanged(int uid, int oldBlockedReason, int newBlockedReason); } diff --git a/core/java/android/net/INetworkPolicyManager.aidl b/core/java/android/net/INetworkPolicyManager.aidl index 9bf791ba33e0..171c6a2c6a19 100644 --- a/core/java/android/net/INetworkPolicyManager.aidl +++ b/core/java/android/net/INetworkPolicyManager.aidl @@ -62,6 +62,7 @@ interface INetworkPolicyManager { 3 - enabled */ int getRestrictBackgroundByCaller(); + int getRestrictBackgroundStatus(int uid); void setDeviceIdleMode(boolean enabled); void setWifiMeteredOverride(String networkId, int meteredOverride); diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java index 1c56954a1c36..6152589516c9 100644 --- a/core/java/android/net/NetworkPolicyManager.java +++ b/core/java/android/net/NetworkPolicyManager.java @@ -23,6 +23,7 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; +import android.annotation.SystemApi; import android.annotation.SystemService; import android.annotation.TestApi; import android.app.ActivityManager; @@ -44,6 +45,8 @@ import android.util.DebugUtils; import android.util.Pair; import android.util.Range; +import com.android.internal.util.function.pooled.PooledLambda; + import com.google.android.collect.Sets; import java.lang.annotation.Retention; @@ -53,6 +56,7 @@ import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executor; /** * Manager for creating and modifying network policy rules. @@ -60,6 +64,7 @@ import java.util.concurrent.ConcurrentHashMap; * @hide */ @TestApi +@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) @SystemService(Context.NETWORK_POLICY_SERVICE) public class NetworkPolicyManager { @@ -198,12 +203,157 @@ public class NetworkPolicyManager { }) public @interface SubscriptionOverrideMask {} + /** + * Flag to indicate that an app is not subject to any restrictions that could result in its + * network access blocked. + * + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public static final int BLOCKED_REASON_NONE = 0; + + /** + * Flag to indicate that an app is subject to Battery saver restrictions that would + * result in its network access being blocked. + * + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public static final int BLOCKED_REASON_BATTERY_SAVER = 1 << 0; + + /** + * Flag to indicate that an app is subject to Doze restrictions that would + * result in its network access being blocked. + * + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public static final int BLOCKED_REASON_DOZE = 1 << 1; + + /** + * Flag to indicate that an app is subject to App Standby restrictions that would + * result in its network access being blocked. + * + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public static final int BLOCKED_REASON_APP_STANDBY = 1 << 2; + + /** + * Flag to indicate that an app is subject to Restricted mode restrictions that would + * result in its network access being blocked. + * + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public static final int BLOCKED_REASON_RESTRICTED_MODE = 1 << 3; + + /** + * Flag to indicate that an app is subject to Data saver restrictions that would + * result in its metered network access being blocked. + * + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public static final int BLOCKED_METERED_REASON_DATA_SAVER = 1 << 16; + + /** + * Flag to indicate that an app is subject to user restrictions that would + * result in its metered network access being blocked. + * + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public static final int BLOCKED_METERED_REASON_USER_RESTRICTED = 1 << 17; + + /** + * Flag to indicate that an app is subject to Device admin restrictions that would + * result in its metered network access being blocked. + * + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public static final int BLOCKED_METERED_REASON_ADMIN_DISABLED = 1 << 18; + + /** @hide */ + public static final int BLOCKED_METERED_REASON_MASK = 0xffff0000; + + /** + * Flag to indicate that app is not exempt from any network restrictions. + * + * @hide + */ + public static final int ALLOWED_REASON_NONE = 0; + /** + * Flag to indicate that app is exempt from certain network restrictions because of it being a + * system component. + * + * @hide + */ + public static final int ALLOWED_REASON_SYSTEM = 1 << 0; + /** + * Flag to indicate that app is exempt from certain network restrictions because of it being + * in the foreground. + * + * @hide + */ + public static final int ALLOWED_REASON_FOREGROUND = 1 << 1; + /** + * Flag to indicate that app is exempt from certain network restrictions because of it being + * in the {@code allow-in-power-save} list. + * + * @hide + */ + public static final int ALLOWED_REASON_POWER_SAVE_ALLOWLIST = 1 << 2; + /** + * Flag to indicate that app is exempt from certain network restrictions because of it being + * in the {@code allow-in-power-save-except-idle} list. + * + * @hide + */ + public static final int ALLOWED_REASON_POWER_SAVE_EXCEPT_IDLE_ALLOWLIST = 1 << 3; + /** + * Flag to indicate that app is exempt from certain network restrictions because of it holding + * certain privileged permissions. + * + * @hide + */ + public static final int ALLOWED_REASON_RESTRICTED_MODE_PERMISSIONS = 1 << 4; + /** + * Flag to indicate that app is exempt from certain metered network restrictions because user + * explicitly exempted it. + * + * @hide + */ + public static final int ALLOWED_METERED_REASON_USER_EXEMPTED = 1 << 16; + + /** @hide */ + public static final int ALLOWED_METERED_REASON_MASK = 0xffff0000; + + /** + * @hide + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(flag = true, prefix = {"BLOCKED_"}, value = { + BLOCKED_REASON_NONE, + BLOCKED_REASON_BATTERY_SAVER, + BLOCKED_REASON_DOZE, + BLOCKED_REASON_APP_STANDBY, + BLOCKED_REASON_RESTRICTED_MODE, + BLOCKED_METERED_REASON_DATA_SAVER, + BLOCKED_METERED_REASON_USER_RESTRICTED, + BLOCKED_METERED_REASON_ADMIN_DISABLED, + }) + public @interface BlockedReason {} + private final Context mContext; @UnsupportedAppUsage private INetworkPolicyManager mService; private final Map<SubscriptionCallback, SubscriptionCallbackProxy> - mCallbackMap = new ConcurrentHashMap<>(); + mSubscriptionCallbackMap = new ConcurrentHashMap<>(); + private final Map<NetworkPolicyCallback, NetworkPolicyCallbackProxy> + mNetworkPolicyCallbackMap = new ConcurrentHashMap<>(); /** @hide */ public NetworkPolicyManager(Context context, INetworkPolicyManager service) { @@ -318,7 +468,7 @@ public class NetworkPolicyManager { } final SubscriptionCallbackProxy callbackProxy = new SubscriptionCallbackProxy(callback); - if (null != mCallbackMap.putIfAbsent(callback, callbackProxy)) { + if (null != mSubscriptionCallbackMap.putIfAbsent(callback, callbackProxy)) { throw new IllegalArgumentException("Callback is already registered."); } registerListener(callbackProxy); @@ -331,7 +481,7 @@ public class NetworkPolicyManager { throw new NullPointerException("Callback cannot be null."); } - final SubscriptionCallbackProxy callbackProxy = mCallbackMap.remove(callback); + final SubscriptionCallbackProxy callbackProxy = mSubscriptionCallbackMap.remove(callback); if (callbackProxy == null) return; unregisterListener(callbackProxy); @@ -379,6 +529,26 @@ public class NetworkPolicyManager { } /** + * Determines if an UID is subject to metered network restrictions while running in background. + * + * @param uid The UID whose status needs to be checked. + * @return {@link ConnectivityManager#RESTRICT_BACKGROUND_STATUS_DISABLED}, + * {@link ConnectivityManager##RESTRICT_BACKGROUND_STATUS_ENABLED}, + * or {@link ConnectivityManager##RESTRICT_BACKGROUND_STATUS_WHITELISTED} to denote + * the current status of the UID. + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + @RequiresPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) + public int getRestrictBackgroundStatus(int uid) { + try { + return mService.getRestrictBackgroundStatus(uid); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * Override connections to be temporarily marked as either unmetered or congested, * along with automatic timeouts if desired. * @@ -460,9 +630,8 @@ public class NetworkPolicyManager { * @param meteredNetwork True if the network is metered. * @return true if networking is blocked for the given uid according to current networking * policies. - * - * @hide */ + @RequiresPermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY) public boolean isUidNetworkingBlocked(int uid, boolean meteredNetwork) { try { return mService.isUidNetworkingBlocked(uid, meteredNetwork); @@ -501,9 +670,8 @@ public class NetworkPolicyManager { * * @param uid The target uid. * @return true if the given uid is restricted from doing networking on metered networks. - * - * @hide */ + @RequiresPermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY) public boolean isUidRestrictedOnMeteredNetworks(int uid) { try { return mService.isUidRestrictedOnMeteredNetworks(uid); @@ -513,11 +681,15 @@ public class NetworkPolicyManager { } /** - * Get multipath preference for the given network. + * Gets a hint on whether it is desirable to use multipath data transfer on the given network. + * + * @return One of the ConnectivityManager.MULTIPATH_PREFERENCE_* constants. * * @hide */ - public int getMultipathPreference(Network network) { + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + @RequiresPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) + public int getMultipathPreference(@NonNull Network network) { try { return mService.getMultipathPreference(network); } catch (RemoteException e) { @@ -689,6 +861,142 @@ public class NetworkPolicyManager { return WifiInfo.sanitizeSsid(ssid); } + /** + * Returns whether network access of an UID is blocked or not based on {@code blockedReasons} + * corresponding to it. + * + * {@code blockedReasons} would be a bitwise {@code OR} combination of the + * {@code BLOCKED_REASON_*} and/or {@code BLOCKED_METERED_REASON_*} constants. + * + * @param blockedReasons Value indicating the reasons for why the network access of an UID is + * blocked. If the value is equal to {@link #BLOCKED_REASON_NONE}, then + * it indicates that an app's network access is not blocked. + * @param meteredNetwork Value indicating whether the network is metered or not. + * @return Whether network access is blocked or not. + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public static boolean isUidBlocked(@BlockedReason int blockedReasons, boolean meteredNetwork) { + if (blockedReasons == BLOCKED_REASON_NONE) { + return false; + } + final int blockedOnAllNetworksReason = (blockedReasons & ~BLOCKED_METERED_REASON_MASK); + if (blockedOnAllNetworksReason != BLOCKED_REASON_NONE) { + return true; + } + if (meteredNetwork) { + return blockedReasons != BLOCKED_REASON_NONE; + } + return false; + } + + /** + * Returns the {@code string} representation of {@code blockedReasons} argument. + * + * @param blockedReasons Value indicating the reasons for why the network access of an UID is + * blocked. + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + @NonNull + public static String blockedReasonsToString(@BlockedReason int blockedReasons) { + return DebugUtils.flagsToString(NetworkPolicyManager.class, "BLOCKED_", blockedReasons); + } + + /** + * Register a {@link NetworkPolicyCallback} to listen for changes to network blocked status + * of apps. + * + * Note that when a caller tries to register a new callback, it might replace a previously + * registered callback if it is considered equal to the new one, based on the + * {@link Object#equals(Object)} check. + * + * @param executor The {@link Executor} to run the callback on. + * @param callback The {@link NetworkPolicyCallback} to be registered. + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + @RequiresPermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY) + public void registerNetworkPolicyCallback(@Nullable Executor executor, + @NonNull NetworkPolicyCallback callback) { + if (callback == null) { + throw new NullPointerException("Callback cannot be null."); + } + + final NetworkPolicyCallbackProxy callbackProxy = new NetworkPolicyCallbackProxy( + executor, callback); + registerListener(callbackProxy); + mNetworkPolicyCallbackMap.put(callback, callbackProxy); + } + + /** + * Unregister a previously registered {@link NetworkPolicyCallback}. + * + * @param callback The {@link NetworkPolicyCallback} to be unregistered. + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + @RequiresPermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY) + public void unregisterNetworkPolicyCallback(@NonNull NetworkPolicyCallback callback) { + if (callback == null) { + throw new NullPointerException("Callback cannot be null."); + } + + final NetworkPolicyCallbackProxy callbackProxy = mNetworkPolicyCallbackMap.remove(callback); + if (callbackProxy == null) return; + unregisterListener(callbackProxy); + } + + /** + * Interface for the callback to listen for changes to network blocked status of apps. + * + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public interface NetworkPolicyCallback { + /** + * Called when the reason for why the network access of an UID is blocked changes. + * + * @param uid The UID for which the blocked status changed. + * @param blockedReasons Value indicating the reasons for why the network access of an + * UID is blocked. + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + default void onUidBlockedReasonChanged(int uid, @BlockedReason int blockedReasons) {} + } + + /** @hide */ + public static class NetworkPolicyCallbackProxy extends Listener { + private final Executor mExecutor; + private final NetworkPolicyCallback mCallback; + + NetworkPolicyCallbackProxy(@Nullable Executor executor, + @NonNull NetworkPolicyCallback callback) { + mExecutor = executor; + mCallback = callback; + } + + @Override + public void onBlockedReasonChanged(int uid, @BlockedReason int oldBlockedReasons, + @BlockedReason int newBlockedReasons) { + if (oldBlockedReasons != newBlockedReasons) { + dispatchOnUidBlockedReasonChanged(mExecutor, mCallback, uid, newBlockedReasons); + } + } + } + + private static void dispatchOnUidBlockedReasonChanged(@Nullable Executor executor, + @NonNull NetworkPolicyCallback callback, int uid, @BlockedReason int blockedReasons) { + if (executor == null) { + callback.onUidBlockedReasonChanged(uid, blockedReasons); + } else { + executor.execute(PooledLambda.obtainRunnable( + NetworkPolicyCallback::onUidBlockedReasonChanged, + callback, uid, blockedReasons).recycleOnUse()); + } + } + /** @hide */ public static class SubscriptionCallback { /** @@ -743,5 +1051,7 @@ public class NetworkPolicyManager { @Override public void onSubscriptionOverride(int subId, int overrideMask, int overrideValue, int[] networkTypes) { } @Override public void onSubscriptionPlansChanged(int subId, SubscriptionPlan[] plans) { } + @Override public void onBlockedReasonChanged(int uid, + int oldBlockedReasons, int newBlockedReasons) { } } } diff --git a/core/java/android/net/VpnManager.java b/core/java/android/net/VpnManager.java index 77754d1256a7..5f65d46f3b1e 100644 --- a/core/java/android/net/VpnManager.java +++ b/core/java/android/net/VpnManager.java @@ -86,13 +86,21 @@ public class VpnManager { public static final int TYPE_VPN_LEGACY = 3; /** + * An VPN created by OEM code through other means than {@link VpnService} or {@link VpnManager}. + * @hide + */ + @SystemApi(client = MODULE_LIBRARIES) + public static final int TYPE_VPN_OEM = 4; + + /** * Channel for VPN notifications. * @hide */ public static final String NOTIFICATION_CHANNEL_VPN = "VPN"; /** @hide */ - @IntDef(value = {TYPE_VPN_NONE, TYPE_VPN_SERVICE, TYPE_VPN_PLATFORM, TYPE_VPN_LEGACY}) + @IntDef(value = {TYPE_VPN_NONE, TYPE_VPN_SERVICE, TYPE_VPN_PLATFORM, TYPE_VPN_LEGACY, + TYPE_VPN_OEM}) @Retention(RetentionPolicy.SOURCE) public @interface VpnType {} diff --git a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java index 9f83b21f0d0c..d4e8e2dca296 100644 --- a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java +++ b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java @@ -52,13 +52,12 @@ import java.util.concurrent.TimeUnit; * Network}s. * * <p>A VCN connection based on this configuration will be brought up dynamically based on device - * settings, and filed NetworkRequests. Underlying networks will be selected based on the services - * required by this configuration (as represented by network capabilities), and must be part of the - * subscription group under which this configuration is registered (see {@link + * settings, and filed NetworkRequests. Underlying Networks must provide INTERNET connectivity, and + * must be part of the subscription group under which this configuration is registered (see {@link * VcnManager#setVcnConfig}). * - * <p>As an abstraction of a cellular network, services that can be provided by a VCN network, or - * required for underlying networks are limited to services provided by cellular networks: + * <p>As an abstraction of a cellular network, services that can be provided by a VCN network are + * limited to services provided by cellular networks: * * <ul> * <li>{@link NetworkCapabilities#NET_CAPABILITY_MMS} @@ -214,13 +213,6 @@ public final class VcnGatewayConnectionConfig { checkValidCapability(cap); } - Preconditions.checkArgument( - mUnderlyingCapabilities != null && !mUnderlyingCapabilities.isEmpty(), - "underlyingCapabilities was null or empty"); - for (Integer cap : getAllUnderlyingCapabilities()) { - checkValidCapability(cap); - } - Objects.requireNonNull(mRetryIntervalsMs, "retryIntervalsMs was null"); validateRetryInterval(mRetryIntervalsMs); @@ -295,7 +287,9 @@ public final class VcnGatewayConnectionConfig { * * @see Builder#addRequiredUnderlyingCapability(int) * @see Builder#removeRequiredUnderlyingCapability(int) + * @hide */ + // TODO(b/182219992): Remove, and add when per-transport capabilities are supported @NonNull public int[] getRequiredUnderlyingCapabilities() { // Sorted set guarantees ordering @@ -470,7 +464,9 @@ public final class VcnGatewayConnectionConfig { * @return this {@link Builder} instance, for chaining * @see VcnGatewayConnectionConfig for a list of capabilities may be required of underlying * networks + * @hide */ + // TODO(b/182219992): Remove, and add when per-transport capabilities are supported @NonNull public Builder addRequiredUnderlyingCapability( @VcnSupportedCapability int underlyingCapability) { @@ -492,7 +488,9 @@ public final class VcnGatewayConnectionConfig { * @return this {@link Builder} instance, for chaining * @see VcnGatewayConnectionConfig for a list of capabilities may be required of underlying * networks + * @hide */ + // TODO(b/182219992): Remove, and add when per-transport capabilities are supported @NonNull @SuppressLint("BuilderSetStyle") // For consistency with NetCaps.Builder add/removeCap public Builder removeRequiredUnderlyingCapability( diff --git a/core/java/android/net/vcn/VcnManager.java b/core/java/android/net/vcn/VcnManager.java index 062438c6e5db..b73fdbff8ef3 100644 --- a/core/java/android/net/vcn/VcnManager.java +++ b/core/java/android/net/vcn/VcnManager.java @@ -448,7 +448,7 @@ public class VcnManager { * @param networkCapabilities an array of NetworkCapabilities.NET_CAPABILITY_* capabilities * for the Gateway Connection that encountered the error, for identification purposes. * These will be a sorted list with no duplicates and will match {@link - * VcnGatewayConnectionConfig#getRequiredUnderlyingCapabilities()} for one of the {@link + * VcnGatewayConnectionConfig#getExposedCapabilities()} for one of the {@link * VcnGatewayConnectionConfig}s set in the {@link VcnConfig} for this subscription * group. * @param errorCode the code to indicate the error that occurred diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index d7d3e5881219..189a8ac55a10 100755 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -138,7 +138,7 @@ public class Build { */ @UnsupportedAppUsage @TestApi - public static final boolean IS_EMULATOR = getString("ro.kernel.qemu").equals("1"); + public static final boolean IS_EMULATOR = getString("ro.boot.qemu").equals("1"); /** * A hardware serial number, if available. Alphanumeric only, case-insensitive. @@ -1116,6 +1116,18 @@ public class Build { } /** + * A multiplier for various timeouts on the system. + * + * The intent is that products targeting software emulators that are orders of magnitude slower + * than real hardware may set this to a large number. On real devices and hardware-accelerated + * virtualized devices this should not be set. + * + * @hide + */ + public static final int HW_TIMEOUT_MULTIPLIER = + SystemProperties.getInt("ro.hw_timeout_multiplier", 1); + + /** * True if Treble is enabled and required for this device. * * @hide diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index 8c2ca6d3e509..9d16f18ab848 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -16,8 +16,11 @@ package android.os; +import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; + import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SystemApi; import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; import android.system.ErrnoException; @@ -104,6 +107,7 @@ public class Process { * @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @SystemApi(client = MODULE_LIBRARIES) public static final int VPN_UID = 1016; /** diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java index 9cb76c1ffb5d..753abea2cfe2 100644 --- a/core/java/android/provider/Telephony.java +++ b/core/java/android/provider/Telephony.java @@ -5284,7 +5284,8 @@ public final class Telephony { * which network types are allowed for * {@link TelephonyManager#ALLOWED_NETWORK_TYPES_REASON_USER}, * {@link TelephonyManager#ALLOWED_NETWORK_TYPES_REASON_POWER}, - * {@link TelephonyManager#ALLOWED_NETWORK_TYPES_REASON_CARRIER}. + * {@link TelephonyManager#ALLOWED_NETWORK_TYPES_REASON_CARRIER}, + * {@link TelephonyManager#ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G}. * <P>Type: TEXT </P> * * @hide diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java index 0ae5ed7bf726..bbb1d0caac6a 100644 --- a/core/java/android/telephony/PhoneStateListener.java +++ b/core/java/android/telephony/PhoneStateListener.java @@ -21,7 +21,6 @@ import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.TestApi; -import android.compat.annotation.ChangeId; import android.compat.annotation.UnsupportedAppUsage; import android.os.Binder; import android.os.Build; @@ -1265,6 +1264,8 @@ public class PhoneStateListener { // default implementation empty } + + /** * The callback methods need to be called on the handler thread where * this object was created. If the binder did that for us it'd be nice. @@ -1576,7 +1577,12 @@ public class PhoneStateListener { // default implementation empty } - public void onAllowedNetworkTypesChanged(Map allowedNetworkTypesList) { + public void onAllowedNetworkTypesChanged(int reason, long allowedNetworkType) { + // default implementation empty + } + + public void onLinkCapacityEstimateChanged( + List<LinkCapacityEstimate> linkCapacityEstimateList) { // default implementation empty } } diff --git a/core/java/android/telephony/TelephonyCallback.java b/core/java/android/telephony/TelephonyCallback.java index a2584cae1b9c..e49c82cfbd54 100644 --- a/core/java/android/telephony/TelephonyCallback.java +++ b/core/java/android/telephony/TelephonyCallback.java @@ -24,7 +24,6 @@ import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.compat.annotation.ChangeId; -import android.compat.annotation.UnsupportedAppUsage; import android.os.Binder; import android.os.Build; import android.telephony.emergency.EmergencyNumber; @@ -545,9 +544,6 @@ public class TelephonyCallback { /** * Event for changes to allowed network list based on all active subscriptions. * - * <p>Requires permission {@link android.Manifest.permission#READ_PHONE_STATE} or the calling - * app has carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges}). - * * @hide * @see AllowedNetworkTypesListener#onAllowedNetworkTypesChanged */ @@ -556,6 +552,33 @@ public class TelephonyCallback { public static final int EVENT_ALLOWED_NETWORK_TYPE_LIST_CHANGED = 35; /** + * Event for changes to the legacy call state changed listener implemented by + * {@link PhoneStateListener#onCallStateChanged(int, String)}. This listener variant is similar + * to the new {@link CallStateListener#onCallStateChanged(int)} with the important distinction + * that it CAN provide the phone number associated with a call. + * + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.READ_CALL_LOG) + public static final int EVENT_LEGACY_CALL_STATE_CHANGED = 36; + + + /** + * Event for changes to the link capacity estimate (LCE) + * + * <p>Requires permission {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE} + * + * @see LinkCapacityEstimateChangedListener#onLinkCapacityEstimateChanged + * + * @hide + */ + @SystemApi + @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE) + public static final int EVENT_LINK_CAPACITY_ESTIMATE_CHANGED = 37; + + + /** * @hide */ @IntDef(prefix = {"EVENT_"}, value = { @@ -593,7 +616,9 @@ public class TelephonyCallback { EVENT_BARRING_INFO_CHANGED, EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED, EVENT_DATA_ENABLED_CHANGED, - EVENT_ALLOWED_NETWORK_TYPE_LIST_CHANGED + EVENT_ALLOWED_NETWORK_TYPE_LIST_CHANGED, + EVENT_LEGACY_CALL_STATE_CHANGED, + EVENT_LINK_CAPACITY_ESTIMATE_CHANGED }) @Retention(RetentionPolicy.SOURCE) public @interface TelephonyEvent { @@ -1259,30 +1284,34 @@ public class TelephonyCallback { public interface AllowedNetworkTypesListener { /** * Callback invoked when the current allowed network type list has changed on the - * registered subscription. + * registered subscription for a specified reason. * Note, the registered subscription is associated with {@link TelephonyManager} object - * on which - * {@link TelephonyManager#registerTelephonyCallback(Executor, TelephonyCallback)} + * on which {@link TelephonyManager#registerTelephonyCallback(Executor, TelephonyCallback)} * was called. * If this TelephonyManager object was created with * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the * given subscription ID. Otherwise, this callback applies to * {@link SubscriptionManager#getDefaultSubscriptionId()}. * - * @param allowedNetworkTypesList Map associating all allowed network type reasons - * ({@link TelephonyManager#ALLOWED_NETWORK_TYPES_REASON_USER}, - * {@link TelephonyManager#ALLOWED_NETWORK_TYPES_REASON_POWER}, - * {@link TelephonyManager#ALLOWED_NETWORK_TYPES_REASON_CARRIER}, and - * {@link TelephonyManager#ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G}) with reason's allowed - * network type values. + * @param reason an allowed network type reasons. + * @see TelephonyManager#ALLOWED_NETWORK_TYPES_REASON_USER + * @see TelephonyManager#ALLOWED_NETWORK_TYPES_REASON_POWER + * @see TelephonyManager#ALLOWED_NETWORK_TYPES_REASON_CARRIER + * @see TelephonyManager#ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G + * + * @param allowedNetworkType an allowed network type bitmask value. (for example, + * the long bitmask value is {{@link TelephonyManager#NETWORK_TYPE_BITMASK_NR}| + * {@link TelephonyManager#NETWORK_TYPE_BITMASK_LTE}}) + * * For example: - * map{{TelephonyManager#ALLOWED_NETWORK_TYPES_REASON_USER, long type value}, - * {TelephonyManager#ALLOWED_NETWORK_TYPES_REASON_POWER, long type value}, - * {TelephonyManager#ALLOWED_NETWORK_TYPES_REASON_CARRIER, long type value}, - * {TelephonyManager#ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G, long type value}} + * If the latest allowed network type is changed by user, then the system + * notifies the {@link TelephonyManager#ALLOWED_NETWORK_TYPES_REASON_USER} and + * long type value}. */ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) - void onAllowedNetworkTypesChanged(@NonNull Map<Integer, Long> allowedNetworkTypesList); + void onAllowedNetworkTypesChanged( + @TelephonyManager.AllowedNetworkTypesReason int reason, + @TelephonyManager.NetworkTypeBitMask long allowedNetworkType); } /** @@ -1330,10 +1359,7 @@ public class TelephonyCallback { /** * Interface for current physical channel configuration listener. - * - * @hide */ - @SystemApi public interface PhysicalChannelConfigListener { /** * Callback invoked when the current physical channel configuration has changed @@ -1363,6 +1389,25 @@ public class TelephonyCallback { @TelephonyManager.DataEnabledReason int reason); } + /** + * Interface for link capacity estimate changed listener. + * + * @hide + */ + @SystemApi + public interface LinkCapacityEstimateChangedListener { + /** + * Callback invoked when the link capacity estimate (LCE) changes + * + * @param linkCapacityEstimateList a list of {@link LinkCapacityEstimate} + * The list size is at least 1. + * In case of a dual connected network, the list size could be 2. + * Use {@link LinkCapacityEstimate#getType()} to get the type of each element. + */ + @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE) + void onLinkCapacityEstimateChanged( + @NonNull List<LinkCapacityEstimate> linkCapacityEstimateList); + } /** * The callback methods need to be called on the handler thread where @@ -1697,14 +1742,26 @@ public class TelephonyCallback { enabled, reason))); } - public void onAllowedNetworkTypesChanged(Map allowedNetworkTypesList) { + public void onAllowedNetworkTypesChanged(int reason, long allowedNetworkType) { AllowedNetworkTypesListener listener = (AllowedNetworkTypesListener) mTelephonyCallbackWeakRef.get(); if (listener == null) return; Binder.withCleanCallingIdentity( () -> mExecutor.execute( - () -> listener.onAllowedNetworkTypesChanged(allowedNetworkTypesList))); + () -> listener.onAllowedNetworkTypesChanged(reason, + allowedNetworkType))); + } + + public void onLinkCapacityEstimateChanged( + List<LinkCapacityEstimate> linkCapacityEstimateList) { + LinkCapacityEstimateChangedListener listener = + (LinkCapacityEstimateChangedListener) mTelephonyCallbackWeakRef.get(); + if (listener == null) return; + + Binder.withCleanCallingIdentity( + () -> mExecutor.execute(() -> listener.onLinkCapacityEstimateChanged( + linkCapacityEstimateList))); } } } diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java index 15d1a595ff0e..b111ec339ed7 100644 --- a/core/java/android/telephony/TelephonyRegistryManager.java +++ b/core/java/android/telephony/TelephonyRegistryManager.java @@ -825,24 +825,40 @@ public class TelephonyRegistryManager { } /** - * Notify emergency number list changed on certain subscription. - * - * @param slotIndex for which emergency number list changed. Can be derived from subId except - * when subId is invalid. - * @param subId for which emergency number list changed. + * Notify the allowed network types has changed for a specific subscription and the specific + * reason. + * @param slotIndex for which allowed network types changed. + * @param subId for which allowed network types changed. + * @param reason an allowed network type reasons. + * @param allowedNetworkType an allowed network type bitmask value. */ public void notifyAllowedNetworkTypesChanged(int slotIndex, int subId, - Map<Integer, Long> allowedNetworkTypeList) { + int reason, long allowedNetworkType) { try { - sRegistry.notifyAllowedNetworkTypesChanged(slotIndex, subId, allowedNetworkTypeList); + sRegistry.notifyAllowedNetworkTypesChanged(slotIndex, subId, reason, + allowedNetworkType); } catch (RemoteException ex) { // system process is dead } } + /** + * Notify that the link capacity estimate has changed. + * @param slotIndex for the phone object that gets the updated link capacity estimate + * @param subId for subscription that gets the updated link capacity estimate + * @param linkCapacityEstimateList a list of {@link LinkCapacityEstimate} + */ + public void notifyLinkCapacityEstimateChanged(int slotIndex, int subId, + List<LinkCapacityEstimate> linkCapacityEstimateList) { + try { + sRegistry.notifyLinkCapacityEstimateChanged(slotIndex, subId, linkCapacityEstimateList); + } catch (RemoteException ex) { + // system server crash + } + } + public @NonNull Set<Integer> getEventsFromCallback( @NonNull TelephonyCallback telephonyCallback) { - Set<Integer> eventList = new ArraySet<>(); if (telephonyCallback instanceof TelephonyCallback.ServiceStateListener) { @@ -973,6 +989,10 @@ public class TelephonyRegistryManager { eventList.add(TelephonyCallback.EVENT_ALLOWED_NETWORK_TYPE_LIST_CHANGED); } + if (telephonyCallback instanceof TelephonyCallback.LinkCapacityEstimateChangedListener) { + eventList.add(TelephonyCallback.EVENT_LINK_CAPACITY_ESTIMATE_CHANGED); + } + return eventList; } diff --git a/core/java/android/widget/OWNERS b/core/java/android/widget/OWNERS index 718076b49f77..64570a8ad155 100644 --- a/core/java/android/widget/OWNERS +++ b/core/java/android/widget/OWNERS @@ -5,6 +5,8 @@ alanv@google.com adamp@google.com aurimas@google.com siyamed@google.com +mount@google.com +njawad@google.com per-file TextView.java, EditText.java, Editor.java = siyamed@google.com, nona@google.com, clarabayarri@google.com diff --git a/core/java/com/android/internal/app/OWNERS b/core/java/com/android/internal/app/OWNERS index 7ade05cc6de1..e6c911e5b41d 100644 --- a/core/java/com/android/internal/app/OWNERS +++ b/core/java/com/android/internal/app/OWNERS @@ -3,6 +3,9 @@ per-file *Resolver* = file:/packages/SystemUI/OWNERS per-file *Chooser* = file:/packages/SystemUI/OWNERS per-file SimpleIconFactory.java = file:/packages/SystemUI/OWNERS per-file NetInitiatedActivity.java = file:/location/java/android/location/OWNERS -per-file IVoice* = file:/core/java/android/service/voice/OWNERS -per-file *Hotword* = file:/core/java/android/service/voice/OWNERS per-file *BatteryStats* = file:/BATTERY_STATS_OWNERS + +# Voice Interaction +per-file *Assist* = file:/core/java/android/service/voice/OWNERS +per-file *Hotword* = file:/core/java/android/service/voice/OWNERS +per-file *Voice* = file:/core/java/android/service/voice/OWNERS diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java index c220428df58b..5fea76a7228e 100644 --- a/core/java/com/android/internal/os/ZygoteInit.java +++ b/core/java/com/android/internal/os/ZygoteInit.java @@ -41,7 +41,6 @@ import android.os.UserHandle; import android.os.ZygoteProcess; import android.os.storage.StorageManager; import android.provider.DeviceConfig; -import android.security.keystore.AndroidKeyStoreProvider; import android.system.ErrnoException; import android.system.Os; import android.system.OsConstants; @@ -74,7 +73,6 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.security.Provider; import java.security.Security; -import java.util.Optional; /** * Startup class for the zygote process. @@ -227,17 +225,7 @@ public class ZygoteInit { // AndroidKeyStoreProvider.install() manipulates the list of JCA providers to insert // preferred providers. Note this is not done via security.properties as the JCA providers // are not on the classpath in the case of, for example, raw dalvikvm runtimes. - // TODO b/171305684 This code is used to conditionally enable the installation of the - // Keystore 2.0 provider to enable teams adjusting to Keystore 2.0 at their own - // pace. This code will be removed when all calling code was adjusted to - // Keystore 2.0. - Optional<Boolean> keystore2_enabled = - android.sysprop.Keystore2Properties.keystore2_enabled(); - if (keystore2_enabled.isPresent() && keystore2_enabled.get()) { - android.security.keystore2.AndroidKeyStoreProvider.install(); - } else { - AndroidKeyStoreProvider.install(); - } + android.security.keystore2.AndroidKeyStoreProvider.install(); Log.i(TAG, "Installed AndroidKeyStoreProvider in " + (SystemClock.uptimeMillis() - startTime) + "ms."); Trace.traceEnd(Trace.TRACE_TAG_DALVIK); diff --git a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl index ee94ef8ddda3..b90722c620a1 100644 --- a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl +++ b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl @@ -21,6 +21,7 @@ import android.telephony.CallAttributes; import android.telephony.CellIdentity; import android.telephony.CellInfo; import android.telephony.DataConnectionRealTimeInfo; +import android.telephony.LinkCapacityEstimate; import android.telephony.TelephonyDisplayInfo; import android.telephony.PhoneCapability; import android.telephony.PhysicalChannelConfig; @@ -71,5 +72,6 @@ oneway interface IPhoneStateListener { void onBarringInfoChanged(in BarringInfo barringInfo); void onPhysicalChannelConfigChanged(in List<PhysicalChannelConfig> configs); void onDataEnabledChanged(boolean enabled, int reason); - void onAllowedNetworkTypesChanged(in Map allowedNetworkTypeList); + void onAllowedNetworkTypesChanged(in int reason, in long allowedNetworkType); + void onLinkCapacityEstimateChanged(in List<LinkCapacityEstimate> linkCapacityEstimateList); } diff --git a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl index 8d691586dfb1..0e35c84fa226 100644 --- a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl +++ b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl @@ -23,6 +23,7 @@ import android.telephony.BarringInfo; import android.telephony.CallQuality; import android.telephony.CellIdentity; import android.telephony.CellInfo; +import android.telephony.LinkCapacityEstimate; import android.telephony.TelephonyDisplayInfo; import android.telephony.ims.ImsReasonInfo; import android.telephony.PhoneCapability; @@ -94,5 +95,7 @@ interface ITelephonyRegistry { void notifyPhysicalChannelConfigForSubscriber(in int subId, in List<PhysicalChannelConfig> configs); void notifyDataEnabled(in int phoneId, int subId, boolean enabled, int reason); - void notifyAllowedNetworkTypesChanged(in int phoneId, in int subId, in Map allowedNetworkTypeList); + void notifyAllowedNetworkTypesChanged(in int phoneId, in int subId, in int reason, in long allowedNetworkType); + void notifyLinkCapacityEstimateChanged(in int phoneId, in int subId, + in List<LinkCapacityEstimate> linkCapacityEstimateList); } diff --git a/core/java/com/android/internal/util/LocationPermissionChecker.java b/core/java/com/android/internal/util/LocationPermissionChecker.java deleted file mode 100644 index d67bd7a853c8..000000000000 --- a/core/java/com/android/internal/util/LocationPermissionChecker.java +++ /dev/null @@ -1,303 +0,0 @@ -/* - * 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.internal.util; - -import android.Manifest; -import android.annotation.IntDef; -import android.annotation.Nullable; -import android.app.ActivityManager; -import android.app.AppOpsManager; -import android.content.Context; -import android.content.pm.PackageManager; -import android.location.LocationManager; -import android.net.NetworkStack; -import android.os.Binder; -import android.os.Build; -import android.os.UserHandle; -import android.util.Log; - -import com.android.internal.annotations.VisibleForTesting; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - - -/** - * The methods used for location permission and location mode checking. - * - * @hide - */ -public class LocationPermissionChecker { - - private static final String TAG = "LocationPermissionChecker"; - - @Retention(RetentionPolicy.SOURCE) - @IntDef(prefix = {"LOCATION_PERMISSION_CHECK_STATUS_"}, value = { - SUCCEEDED, - ERROR_LOCATION_MODE_OFF, - ERROR_LOCATION_PERMISSION_MISSING, - }) - public @interface LocationPermissionCheckStatus{} - - // The location permission check succeeded. - public static final int SUCCEEDED = 0; - // The location mode turns off for the caller. - public static final int ERROR_LOCATION_MODE_OFF = 1; - // The location permission isn't granted for the caller. - public static final int ERROR_LOCATION_PERMISSION_MISSING = 2; - - private final Context mContext; - private final AppOpsManager mAppOpsManager; - - public LocationPermissionChecker(Context context) { - mContext = context; - mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); - } - - /** - * Check location permission granted by the caller. - * - * This API check if the location mode enabled for the caller and the caller has - * ACCESS_COARSE_LOCATION permission is targetSDK<29, otherwise, has ACCESS_FINE_LOCATION. - * - * @param pkgName package name of the application requesting access - * @param featureId The feature in the package - * @param uid The uid of the package - * @param message A message describing why the permission was checked. Only needed if this is - * not inside of a two-way binder call from the data receiver - * - * @return {@code true} returns if the caller has location permission and the location mode is - * enabled. - */ - public boolean checkLocationPermission(String pkgName, @Nullable String featureId, - int uid, @Nullable String message) { - return checkLocationPermissionInternal(pkgName, featureId, uid, message) == SUCCEEDED; - } - - /** - * Check location permission granted by the caller. - * - * This API check if the location mode enabled for the caller and the caller has - * ACCESS_COARSE_LOCATION permission is targetSDK<29, otherwise, has ACCESS_FINE_LOCATION. - * Compared with {@link #checkLocationPermission(String, String, int, String)}, this API returns - * the detail information about the checking result, including the reason why it's failed and - * logs the error for the caller. - * - * @param pkgName package name of the application requesting access - * @param featureId The feature in the package - * @param uid The uid of the package - * @param message A message describing why the permission was checked. Only needed if this is - * not inside of a two-way binder call from the data receiver - * - * @return {@link LocationPermissionCheckStatus} the result of the location permission check. - */ - public @LocationPermissionCheckStatus int checkLocationPermissionWithDetailInfo( - String pkgName, @Nullable String featureId, int uid, @Nullable String message) { - final int result = checkLocationPermissionInternal(pkgName, featureId, uid, message); - switch (result) { - case ERROR_LOCATION_MODE_OFF: - Log.e(TAG, "Location mode is disabled for the device"); - break; - case ERROR_LOCATION_PERMISSION_MISSING: - Log.e(TAG, "UID " + uid + " has no location permission"); - break; - } - return result; - } - - /** - * Enforce the caller has location permission. - * - * This API determines if the location mode enabled for the caller and the caller has - * ACCESS_COARSE_LOCATION permission is targetSDK<29, otherwise, has ACCESS_FINE_LOCATION. - * SecurityException is thrown if the caller has no permission or the location mode is disabled. - * - * @param pkgName package name of the application requesting access - * @param featureId The feature in the package - * @param uid The uid of the package - * @param message A message describing why the permission was checked. Only needed if this is - * not inside of a two-way binder call from the data receiver - */ - public void enforceLocationPermission(String pkgName, @Nullable String featureId, int uid, - @Nullable String message) throws SecurityException { - final int result = checkLocationPermissionInternal(pkgName, featureId, uid, message); - - switch (result) { - case ERROR_LOCATION_MODE_OFF: - throw new SecurityException("Location mode is disabled for the device"); - case ERROR_LOCATION_PERMISSION_MISSING: - throw new SecurityException("UID " + uid + " has no location permission"); - } - } - - private int checkLocationPermissionInternal(String pkgName, @Nullable String featureId, - int uid, @Nullable String message) { - checkPackage(uid, pkgName); - - // Apps with NETWORK_SETTINGS, NETWORK_SETUP_WIZARD, NETWORK_STACK & MAINLINE_NETWORK_STACK - // are granted a bypass. - if (checkNetworkSettingsPermission(uid) || checkNetworkSetupWizardPermission(uid) - || checkNetworkStackPermission(uid) || checkMainlineNetworkStackPermission(uid)) { - return SUCCEEDED; - } - - // Location mode must be enabled - if (!isLocationModeEnabled()) { - return ERROR_LOCATION_MODE_OFF; - } - - // LocationAccess by App: caller must have Coarse/Fine Location permission to have access to - // location information. - if (!checkCallersLocationPermission(pkgName, featureId, uid, - true /* coarseForTargetSdkLessThanQ */, message)) { - return ERROR_LOCATION_PERMISSION_MISSING; - } - return SUCCEEDED; - } - - /** - * Checks that calling process has android.Manifest.permission.ACCESS_FINE_LOCATION or - * android.Manifest.permission.ACCESS_COARSE_LOCATION (depending on config/targetSDK level) - * and a corresponding app op is allowed for this package and uid. - * - * @param pkgName PackageName of the application requesting access - * @param featureId The feature in the package - * @param uid The uid of the package - * @param coarseForTargetSdkLessThanQ If true and the targetSDK < Q then will check for COARSE - * else (false or targetSDK >= Q) then will check for FINE - * @param message A message describing why the permission was checked. Only needed if this is - * not inside of a two-way binder call from the data receiver - */ - public boolean checkCallersLocationPermission(String pkgName, @Nullable String featureId, - int uid, boolean coarseForTargetSdkLessThanQ, @Nullable String message) { - - boolean isTargetSdkLessThanQ = isTargetSdkLessThan(pkgName, Build.VERSION_CODES.Q, uid); - - String permissionType = Manifest.permission.ACCESS_FINE_LOCATION; - if (coarseForTargetSdkLessThanQ && isTargetSdkLessThanQ) { - // Having FINE permission implies having COARSE permission (but not the reverse) - permissionType = Manifest.permission.ACCESS_COARSE_LOCATION; - } - if (getUidPermission(permissionType, uid) == PackageManager.PERMISSION_DENIED) { - return false; - } - - // Always checking FINE - even if will not enforce. This will record the request for FINE - // so that a location request by the app is surfaced to the user. - boolean isFineLocationAllowed = noteAppOpAllowed( - AppOpsManager.OPSTR_FINE_LOCATION, pkgName, featureId, uid, message); - if (isFineLocationAllowed) { - return true; - } - if (coarseForTargetSdkLessThanQ && isTargetSdkLessThanQ) { - return noteAppOpAllowed(AppOpsManager.OPSTR_COARSE_LOCATION, pkgName, featureId, uid, - message); - } - return false; - } - - /** - * Retrieves a handle to LocationManager (if not already done) and check if location is enabled. - */ - public boolean isLocationModeEnabled() { - final LocationManager LocationManager = - (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE); - try { - return LocationManager.isLocationEnabledForUser(UserHandle.of( - getCurrentUser())); - } catch (Exception e) { - Log.e(TAG, "Failure to get location mode via API, falling back to settings", e); - return false; - } - } - - private boolean isTargetSdkLessThan(String packageName, int versionCode, int callingUid) { - final long ident = Binder.clearCallingIdentity(); - try { - if (mContext.getPackageManager().getApplicationInfoAsUser( - packageName, 0, - UserHandle.getUserHandleForUid(callingUid)).targetSdkVersion - < versionCode) { - return true; - } - } catch (PackageManager.NameNotFoundException e) { - // In case of exception, assume unknown app (more strict checking) - // Note: This case will never happen since checkPackage is - // called to verify validity before checking App's version. - } finally { - Binder.restoreCallingIdentity(ident); - } - return false; - } - - private boolean noteAppOpAllowed(String op, String pkgName, @Nullable String featureId, - int uid, @Nullable String message) { - return mAppOpsManager.noteOp(op, uid, pkgName, featureId, message) - == AppOpsManager.MODE_ALLOWED; - } - - private void checkPackage(int uid, String pkgName) - throws SecurityException { - if (pkgName == null) { - throw new SecurityException("Checking UID " + uid + " but Package Name is Null"); - } - mAppOpsManager.checkPackage(uid, pkgName); - } - - @VisibleForTesting - protected int getCurrentUser() { - return ActivityManager.getCurrentUser(); - } - - private int getUidPermission(String permissionType, int uid) { - // We don't care about pid, pass in -1 - return mContext.checkPermission(permissionType, -1, uid); - } - - /** - * Returns true if the |uid| holds NETWORK_SETTINGS permission. - */ - public boolean checkNetworkSettingsPermission(int uid) { - return getUidPermission(android.Manifest.permission.NETWORK_SETTINGS, uid) - == PackageManager.PERMISSION_GRANTED; - } - - /** - * Returns true if the |uid| holds NETWORK_SETUP_WIZARD permission. - */ - public boolean checkNetworkSetupWizardPermission(int uid) { - return getUidPermission(android.Manifest.permission.NETWORK_SETUP_WIZARD, uid) - == PackageManager.PERMISSION_GRANTED; - } - - /** - * Returns true if the |uid| holds NETWORK_STACK permission. - */ - public boolean checkNetworkStackPermission(int uid) { - return getUidPermission(android.Manifest.permission.NETWORK_STACK, uid) - == PackageManager.PERMISSION_GRANTED; - } - - /** - * Returns true if the |uid| holds MAINLINE_NETWORK_STACK permission. - */ - public boolean checkMainlineNetworkStackPermission(int uid) { - return getUidPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, uid) - == PackageManager.PERMISSION_GRANTED; - } - -} diff --git a/core/java/com/android/internal/util/Protocol.java b/core/java/com/android/internal/util/Protocol.java index 276cad9f6d6d..bbd738bc9eb6 100644 --- a/core/java/com/android/internal/util/Protocol.java +++ b/core/java/com/android/internal/util/Protocol.java @@ -59,8 +59,6 @@ public class Protocol { public static final int BASE_TETHERING = 0x00050000; public static final int BASE_NSD_MANAGER = 0x00060000; public static final int BASE_NETWORK_STATE_TRACKER = 0x00070000; - public static final int BASE_CONNECTIVITY_MANAGER = 0x00080000; - public static final int BASE_NETWORK_AGENT = 0x00081000; public static final int BASE_NETWORK_FACTORY = 0x00083000; public static final int BASE_ETHERNET = 0x00084000; public static final int BASE_LOWPAN = 0x00085000; diff --git a/core/java/com/android/internal/view/inline/OWNERS b/core/java/com/android/internal/view/inline/OWNERS new file mode 100644 index 000000000000..edfb2112198a --- /dev/null +++ b/core/java/com/android/internal/view/inline/OWNERS @@ -0,0 +1 @@ +include /core/java/android/view/autofill/OWNERS diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp index 065c79b8601f..452f55a0ba97 100644 --- a/core/jni/android_media_AudioTrack.cpp +++ b/core/jni/android_media_AudioTrack.cpp @@ -1419,6 +1419,42 @@ static jint android_media_AudioTrack_getDualMonoMode(JNIEnv *env, jobject thiz, return nativeToJavaStatus(status); } +static jint android_media_AudioTrack_getStartThresholdInFrames(JNIEnv *env, jobject thiz) { + sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); + if (lpTrack == nullptr) { + jniThrowException(env, "java/lang/IllegalStateException", + "Unable to retrieve AudioTrack pointer for getStartThresholdInFrames()"); + return (jint)AUDIO_JAVA_ERROR; + } + const ssize_t result = lpTrack->getStartThresholdInFrames(); + if (result <= 0) { + jniThrowExceptionFmt(env, "java/lang/IllegalStateException", + "Internal error detected in getStartThresholdInFrames() = %zd", + result); + return (jint)AUDIO_JAVA_ERROR; + } + return (jint)result; // this should be a positive value. +} + +static jint android_media_AudioTrack_setStartThresholdInFrames(JNIEnv *env, jobject thiz, + jint startThresholdInFrames) { + sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); + if (lpTrack == nullptr) { + jniThrowException(env, "java/lang/IllegalStateException", + "Unable to retrieve AudioTrack pointer for setStartThresholdInFrames()"); + return (jint)AUDIO_JAVA_ERROR; + } + // non-positive values of startThresholdInFrames are not allowed by the Java layer. + const ssize_t result = lpTrack->setStartThresholdInFrames(startThresholdInFrames); + if (result <= 0) { + jniThrowExceptionFmt(env, "java/lang/IllegalStateException", + "Internal error detected in setStartThresholdInFrames() = %zd", + result); + return (jint)AUDIO_JAVA_ERROR; + } + return (jint)result; // this should be a positive value. +} + // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- static const JNINativeMethod gMethods[] = { @@ -1496,6 +1532,10 @@ static const JNINativeMethod gMethods[] = { (void *)android_media_AudioTrack_getAudioDescriptionMixLeveldB}, {"native_set_dual_mono_mode", "(I)I", (void *)android_media_AudioTrack_setDualMonoMode}, {"native_get_dual_mono_mode", "([I)I", (void *)android_media_AudioTrack_getDualMonoMode}, + {"native_setStartThresholdInFrames", "(I)I", + (void *)android_media_AudioTrack_setStartThresholdInFrames}, + {"native_getStartThresholdInFrames", "()I", + (void *)android_media_AudioTrack_getStartThresholdInFrames}, }; // field names found in android/media/AudioTrack.java diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp index 04faebc7beff..63743051bc40 100644 --- a/core/jni/android_util_Process.cpp +++ b/core/jni/android_util_Process.cpp @@ -52,6 +52,7 @@ #include <string.h> #include <sys/epoll.h> #include <sys/errno.h> +#include <sys/pidfd.h> #include <sys/resource.h> #include <sys/stat.h> #include <sys/syscall.h> @@ -1290,14 +1291,8 @@ void android_os_Process_removeAllProcessGroups(JNIEnv* env, jobject clazz) return removeAllProcessGroups(); } -// Wrapper function to the syscall pidfd_open, which creates a file -// descriptor that refers to the process whose PID is specified in pid. -static inline int sys_pidfd_open(pid_t pid, unsigned int flags) { - return syscall(__NR_pidfd_open, pid, flags); -} - static jint android_os_Process_nativePidFdOpen(JNIEnv* env, jobject, jint pid, jint flags) { - int fd = sys_pidfd_open(pid, flags); + int fd = pidfd_open(pid, flags); if (fd < 0) { jniThrowErrnoException(env, "nativePidFdOpen", errno); return -1; diff --git a/core/proto/android/net/networkcapabilities.proto b/core/proto/android/net/networkcapabilities.proto new file mode 100644 index 000000000000..edb6c0400062 --- /dev/null +++ b/core/proto/android/net/networkcapabilities.proto @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2017 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. + */ + +syntax = "proto2"; + +package android.net; + +option java_multiple_files = true; + +import "frameworks/base/core/proto/android/privacy.proto"; +import "frameworks/proto_logging/stats/enums/net/enums.proto"; + +/** + * An android.net.NetworkCapabilities object. + */ +message NetworkCapabilitiesProto { + option (.android.msg_privacy).dest = DEST_AUTOMATIC; + + repeated Transport transports = 1; + + enum NetCapability { + // Indicates this is a network that has the ability to reach the + // carrier's MMSC for sending and receiving MMS messages. + NET_CAPABILITY_MMS = 0; + // Indicates this is a network that has the ability to reach the + // carrier's SUPL server, used to retrieve GPS information. + NET_CAPABILITY_SUPL = 1; + // Indicates this is a network that has the ability to reach the + // carrier's DUN or tethering gateway. + NET_CAPABILITY_DUN = 2; + // Indicates this is a network that has the ability to reach the + // carrier's FOTA portal, used for over the air updates. + NET_CAPABILITY_FOTA = 3; + // Indicates this is a network that has the ability to reach the + // carrier's IMS servers, used for network registration and signaling. + NET_CAPABILITY_IMS = 4; + // Indicates this is a network that has the ability to reach the + // carrier's CBS servers, used for carrier specific services. + NET_CAPABILITY_CBS = 5; + // Indicates this is a network that has the ability to reach a Wi-Fi + // direct peer. + NET_CAPABILITY_WIFI_P2P = 6; + // Indicates this is a network that has the ability to reach a carrier's + // Initial Attach servers. + NET_CAPABILITY_IA = 7; + // Indicates this is a network that has the ability to reach a carrier's + // RCS servers, used for Rich Communication Services. + NET_CAPABILITY_RCS = 8; + // Indicates this is a network that has the ability to reach a carrier's + // XCAP servers, used for configuration and control. + NET_CAPABILITY_XCAP = 9; + // Indicates this is a network that has the ability to reach a carrier's + // Emergency IMS servers or other services, used for network signaling + // during emergency calls. + NET_CAPABILITY_EIMS = 10; + // Indicates that this network is unmetered. + NET_CAPABILITY_NOT_METERED = 11; + // Indicates that this network should be able to reach the internet. + NET_CAPABILITY_INTERNET = 12; + // Indicates that this network is available for general use. If this is + // not set applications should not attempt to communicate on this + // network. Note that this is simply informative and not enforcement - + // enforcement is handled via other means. Set by default. + NET_CAPABILITY_NOT_RESTRICTED = 13; + // Indicates that the user has indicated implicit trust of this network. + // This generally means it's a sim-selected carrier, a plugged in + // ethernet, a paired BT device or a wifi the user asked to connect to. + // Untrusted networks are probably limited to unknown wifi AP. Set by + // default. + NET_CAPABILITY_TRUSTED = 14; + // Indicates that this network is not a VPN. This capability is set by + // default and should be explicitly cleared for VPN networks. + NET_CAPABILITY_NOT_VPN = 15; + // Indicates that connectivity on this network was successfully + // validated. For example, for a network with NET_CAPABILITY_INTERNET, + // it means that Internet connectivity was successfully detected. + NET_CAPABILITY_VALIDATED = 16; + // Indicates that this network was found to have a captive portal in + // place last time it was probed. + NET_CAPABILITY_CAPTIVE_PORTAL = 17; + // Indicates that this network is not roaming. + NET_CAPABILITY_NOT_ROAMING = 18; + // Indicates that this network is available for use by apps, and not a + // network that is being kept up in the background to facilitate fast + // network switching. + NET_CAPABILITY_FOREGROUND = 19; + } + repeated NetCapability capabilities = 2; + + // Passive link bandwidth. This is a rough guide of the expected peak + // bandwidth for the first hop on the given transport. It is not measured, + // but may take into account link parameters (Radio technology, allocated + // channels, etc). + optional int32 link_up_bandwidth_kbps = 3; + optional int32 link_down_bandwidth_kbps = 4; + + optional string network_specifier = 5 [ (.android.privacy).dest = DEST_EXPLICIT ]; + + // True if this object specifies a signal strength. + optional bool can_report_signal_strength = 6; + // This is a signed integer, and higher values indicate better signal. The + // exact units are bearer-dependent. For example, Wi-Fi uses RSSI. + // Only valid if can_report_signal_strength is true. + optional sint32 signal_strength = 7; +} diff --git a/core/proto/android/net/networkrequest.proto b/core/proto/android/net/networkrequest.proto index 0041f199b448..57b9f7162e67 100644 --- a/core/proto/android/net/networkrequest.proto +++ b/core/proto/android/net/networkrequest.proto @@ -20,8 +20,8 @@ package android.net; option java_multiple_files = true; +import "frameworks/base/core/proto/android/net/networkcapabilities.proto"; import "frameworks/base/core/proto/android/privacy.proto"; -import "frameworks/proto_logging/stats/enums/net/networkcapabilities.proto"; /** * An android.net.NetworkRequest object. diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto index e97b1a8770ed..64cf75d51c3d 100644 --- a/core/proto/android/os/incident.proto +++ b/core/proto/android/os/incident.proto @@ -55,13 +55,13 @@ import "frameworks/base/core/proto/android/service/print.proto"; import "frameworks/base/core/proto/android/service/procstats.proto"; import "frameworks/base/core/proto/android/service/restricted_image.proto"; import "frameworks/base/core/proto/android/service/sensor_service.proto"; +import "frameworks/base/core/proto/android/service/usb.proto"; import "frameworks/base/core/proto/android/util/event_log_tags.proto"; import "frameworks/base/core/proto/android/util/log.proto"; import "frameworks/base/core/proto/android/util/textdump.proto"; import "frameworks/base/core/proto/android/privacy.proto"; import "frameworks/base/core/proto/android/section.proto"; import "frameworks/base/proto/src/ipconnectivity.proto"; -import "frameworks/proto_logging/stats/enums/service/usb.proto"; package android.os; diff --git a/core/proto/android/service/enums.proto b/core/proto/android/service/enums.proto deleted file mode 100644 index b64e685104b7..000000000000 --- a/core/proto/android/service/enums.proto +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -syntax = "proto2"; -package android.service; - -option java_outer_classname = "ServiceProtoEnums"; -option java_multiple_files = true; - -enum UsbEndPointType { - USB_ENDPOINT_TYPE_XFER_CONTROL = 0; - USB_ENDPOINT_TYPE_XFER_ISOC = 1; - USB_ENDPOINT_TYPE_XFER_BULK = 2; - USB_ENDPOINT_TYPE_XFER_INT = 3; -} - -enum UsbEndPointDirection { - USB_ENDPOINT_DIR_OUT = 0; - USB_ENDPOINT_DIR_IN = 0x80; -} - -enum UsbConnectionRecordMode { - USB_CONNECTION_RECORD_MODE_CONNECT = 0; - USB_CONNECTION_RECORD_MODE_CONNECT_BADPARSE = 1; - USB_CONNECTION_RECORD_MODE_CONNECT_BADDEVICE = 2; - USB_CONNECTION_RECORD_MODE_DISCONNECT = -1; -}
\ No newline at end of file diff --git a/core/proto/android/service/usb.proto b/core/proto/android/service/usb.proto new file mode 100644 index 000000000000..dd313aa81726 --- /dev/null +++ b/core/proto/android/service/usb.proto @@ -0,0 +1,431 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +syntax = "proto2"; +package android.service.usb; + +option java_multiple_files = true; +option java_outer_classname = "UsbServiceProto"; + +import "frameworks/base/core/proto/android/content/component_name.proto"; +import "frameworks/base/core/proto/android/privacy.proto"; +import "frameworks/proto_logging/stats/enums/service/enums.proto"; + +message UsbServiceDumpProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional UsbDeviceManagerProto device_manager = 1; + optional UsbHostManagerProto host_manager = 2; + optional UsbPortManagerProto port_manager = 3; + optional UsbAlsaManagerProto alsa_manager = 4; + optional UsbSettingsManagerProto settings_manager = 5; + optional UsbPermissionsManagerProto permissions_manager = 6; +} + +message UsbDeviceManagerProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional UsbHandlerProto handler = 1; + optional UsbDebuggingManagerProto debugging_manager = 2; +} + +message UsbHandlerProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + /* Same as android.hardware.usb.gadget.V1_0.GadgetFunction.* */ + enum Function { + FUNCTION_ADB = 1; + FUNCTION_ACCESSORY = 2; + FUNCTION_MTP = 4; + FUNCTION_MIDI = 8; + FUNCTION_PTP = 16; + FUNCTION_RNDIS = 32; + FUNCTION_AUDIO_SOURCE = 64; + } + + repeated Function current_functions = 1; + optional bool current_functions_applied = 2; + repeated Function screen_unlocked_functions = 3; + optional bool screen_locked = 4; + optional bool connected = 5; + optional bool configured = 6; + optional UsbAccessoryProto current_accessory = 7; + optional bool host_connected = 8; + optional bool source_power = 9; + optional bool sink_power = 10; + optional bool usb_charging = 11; + optional bool hide_usb_notification = 12; + optional bool audio_accessory_connected = 13; + optional bool adb_enabled = 14; + optional string kernel_state = 15; + optional string kernel_function_list = 16; +} + +message UsbAccessoryProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional string manufacturer = 1; + optional string model = 2; + // For "classical" USB-accessories the manufacturer bakes this into the + // firmware of the device. If an Android phone is configured as accessory, the + // app that sets up the accessory side of the connection set this. Either way, + // these are part of the detection protocol, and so they cannot be user set or + // unique. + optional string description = 3; + optional string version = 4; + optional string uri = 5 [ (android.privacy).dest = DEST_EXPLICIT ]; + // Non-resettable hardware ID. + optional string serial = 6 [ (android.privacy).dest = DEST_LOCAL ]; +} + +message UsbDebuggingManagerProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional bool connected_to_adb = 1; + // A workstation that connects to the phone for debugging is identified by + // this key. + optional string last_key_received = 2 [ (android.privacy).dest = DEST_EXPLICIT ]; + optional string user_keys = 3 [ (android.privacy).dest = DEST_LOCAL ]; + optional string system_keys = 4 [ (android.privacy).dest = DEST_LOCAL ]; +} + +message UsbHostManagerProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional android.content.ComponentNameProto default_usb_host_connection_handler = 1; + repeated UsbDeviceProto devices = 2; + optional int32 num_connects = 3; + repeated UsbConnectionRecordProto connections = 4; +} + +message UsbDeviceProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + // Generic USB name, not user-provided. + optional string name = 1; + // ID specific to the vendor, not the device. + optional int32 vendor_id = 2; + // ID of this product type: Each vendor gives each product a unique ID. E.g. + // all mice of the same model would have the same ID. + optional int32 product_id = 3; + optional int32 class = 4; + optional int32 subclass = 5; + optional int32 protocol = 6; + optional string manufacturer_name = 7; + optional string product_name = 8; + optional string version = 9; + // Non-resettable hardware ID. + optional string serial_number = 10 [ (android.privacy).dest = DEST_LOCAL ]; + repeated UsbConfigurationProto configurations = 11; +} + +message UsbConfigurationProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + // A single USB device can have several configurations and the app accessing + // the USB device can switch between them. At any time only one can be active. + // Each configuration can present completely different interfaces end + // endpoints, i.e. a completely different behavior. + optional int32 id = 1; + // Hardware-defined name, not set by the user. + optional string name = 2; + optional uint32 attributes = 3; + optional int32 max_power = 4; + repeated UsbInterfaceProto interfaces = 5; +} + +message UsbInterfaceProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + // Hardware defined. This is the id used by the app to identify the interface. + optional int32 id = 1; + optional int32 alternate_settings = 2; + optional string name = 3; + optional int32 class = 4; + optional int32 subclass = 5; + optional int32 protocol = 6; + repeated UsbEndPointProto endpoints = 7; +} + +message UsbEndPointProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional int32 endpoint_number = 1; + optional android.service.UsbEndPointDirection direction = 2; + // The address of the endpoint. Needed to read and write to the endpoint. + optional int32 address = 3; + optional android.service.UsbEndPointType type = 4; + optional uint32 attributes = 5; + optional int32 max_packet_size = 6; + optional int32 interval = 7; +} + +message UsbConnectionRecordProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + // usb device's address, e.g. 001/002, nothing about the phone + optional string device_address = 1; + optional android.service.UsbConnectionRecordMode mode = 2; + optional int64 timestamp = 3; + optional int32 manufacturer = 4; + optional int32 product = 5; + optional UsbIsHeadsetProto is_headset = 6; +} + +message UsbIsHeadsetProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional bool in = 1; + optional bool out = 2; +} + +message UsbPortManagerProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional bool is_simulation_active = 1; + repeated UsbPortInfoProto usb_ports = 2; +} + +message UsbPortInfoProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional UsbPortProto port = 1; + optional UsbPortStatusProto status = 2; + optional bool can_change_mode = 3; + optional bool can_change_power_role = 4; + optional bool can_change_data_role = 5; + optional int64 connected_at_millis = 6; + optional int64 last_connect_duration_millis = 7; +} + +message UsbPortProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + /* Same as android.hardware.usb.V1_1.Constants.PortMode_1_1 */ + enum Mode { + MODE_NONE = 0; + MODE_UFP = 1; + MODE_DFP = 2; + MODE_DRP = 3; + MODE_AUDIO_ACCESSORY = 4; + MODE_DEBUG_ACCESSORY = 8; + } + + // ID of the port. A device (eg: Chromebooks) might have multiple ports. + optional string id = 1; + repeated Mode supported_modes = 2; +} + +message UsbPortStatusProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + /* Same as android.hardware.usb.V1_0.Constants.PortPowerRole */ + enum PowerRole { + POWER_ROLE_NONE = 0; + POWER_ROLE_SOURCE = 1; + POWER_ROLE_SINK = 2; + } + + /* Same as android.hardware.usb.V1_0.Constants.PortDataRole */ + enum DataRole { + DATA_ROLE_NONE = 0; + DATA_ROLE_HOST = 1; + DATA_ROLE_DEVICE = 2; + } + + optional bool connected = 1; + optional UsbPortProto.Mode current_mode = 2; + optional PowerRole power_role = 3; + optional DataRole data_role = 4; + repeated UsbPortStatusRoleCombinationProto role_combinations = 5; + optional android.service.ContaminantPresenceStatus contaminant_presence_status = 6; +} + +message UsbPortStatusRoleCombinationProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional UsbPortStatusProto.PowerRole power_role = 1; + optional UsbPortStatusProto.DataRole data_role = 2; +} + +message UsbAlsaManagerProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional int32 cards_parser = 1; + repeated UsbAlsaDeviceProto alsa_devices = 2; + repeated UsbMidiDeviceProto midi_devices = 3; +} + +message UsbAlsaDeviceProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional int32 card = 1; + optional int32 device = 2; + optional string name = 3; + optional bool has_playback = 4; + optional bool has_capture = 5; + // usb device's address, e.g. 001/002, nothing about the phone + optional string address = 6; +} + +message UsbMidiDeviceProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional int32 card = 1; + optional int32 device = 2; + // usb device's address, e.g. 001/002, nothing about the phone + optional string device_address = 3; +} + +message UsbSettingsManagerProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + repeated UsbUserSettingsManagerProto user_settings = 1; + repeated UsbProfileGroupSettingsManagerProto profile_group_settings = 2; +} + +message UsbUserSettingsManagerProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional int32 user_id = 1; + reserved 2; // previously device_permissions, now unused + reserved 3; // previously accessory_permissions, now unused + repeated UsbDeviceAttachedActivities device_attached_activities = 4; + repeated UsbAccessoryAttachedActivities accessory_attached_activities = 5; +} + +message UsbProfileGroupSettingsManagerProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + // The user id of the personal profile if the device has a work profile. + optional int32 parent_user_id = 1; + repeated UsbSettingsDevicePreferenceProto device_preferences = 2; + repeated UsbSettingsAccessoryPreferenceProto accessory_preferences = 3; +} + +message UsbSettingsDevicePreferenceProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional UsbDeviceFilterProto filter = 1; + optional UserPackageProto user_package = 2; +} + +message UsbPermissionsManagerProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + repeated UsbUserPermissionsManagerProto user_permissions = 1; +} + +message UsbUserPermissionsManagerProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional int32 user_id = 1; + + repeated UsbDevicePermissionProto device_permissions = 2; + repeated UsbAccessoryPermissionProto accessory_permissions = 3; + + repeated UsbDevicePersistentPermissionProto device_persistent_permissions = 4; + repeated UsbAccessoryPersistentPermissionProto accessory_persistent_permissions = 5; +} + +message UsbDevicePermissionProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + // Name of device set by manufacturer + // All devices of the same model have the same name + optional string device_name = 1; + repeated int32 uids = 2; +} + +message UsbAccessoryPermissionProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + // Description of accessory set by manufacturer + // All accessories of the same model have the same description + optional string accessory_description = 1; + repeated int32 uids = 2; +} + +message UsbDevicePersistentPermissionProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional UsbDeviceFilterProto device_filter = 1; + repeated UsbUidPermissionProto permission_values = 2; +} + +message UsbAccessoryPersistentPermissionProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional UsbAccessoryFilterProto accessory_filter = 1; + repeated UsbUidPermissionProto permission_values = 2; +} + +message UsbUidPermissionProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional int32 uid = 1; + optional bool is_granted = 2; +} + +message UsbDeviceFilterProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + // Mirrors the vendor_id of UsbDeviceProto. + optional int32 vendor_id = 1; + optional int32 product_id = 2; + optional int32 class = 3; + optional int32 subclass = 4; + optional int32 protocol = 5; + optional string manufacturer_name = 6; + optional string product_name = 7; + optional string serial_number = 8 [ (android.privacy).dest = DEST_EXPLICIT ]; +} + +message UserPackageProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional int32 user_id = 1; + optional string package_name =2; +} + +message UsbSettingsAccessoryPreferenceProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional UsbAccessoryFilterProto filter = 1; + optional UserPackageProto user_package = 2; +} + +message UsbAccessoryFilterProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional string manufacturer = 1; + optional string model = 2; + optional string version = 3; +} + +message UsbDeviceAttachedActivities { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional android.content.ComponentNameProto activity = 1; + repeated UsbDeviceFilterProto filters = 2; +} + +message UsbAccessoryAttachedActivities { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional android.content.ComponentNameProto activity = 1; + repeated UsbAccessoryFilterProto filters = 2; +} diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 2f352e955d29..61e7d0ad9a73 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -5172,6 +5172,10 @@ <permission android:name="android.permission.INPUT_CONSUMER" android:protectionLevel="signature" /> + <!-- @hide @SystemApi Allows an application to manage app hibernation state. --> + <permission android:name="android.permission.MANAGE_APP_HIBERNATION" + android:protectionLevel="signature|installer" /> + <!-- Attribution for Country Detector. --> <attribution android:tag="CountryDetector" android:label="@string/country_detector"/> <!-- Attribution for Location service. --> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 22a79ed12c24..0f6f15de6458 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -327,9 +327,6 @@ <item>"0,1"</item> </string-array> - <!-- The maximum duration (in milliseconds) we expect a network transition to take --> - <integer name="config_networkTransitionTimeout">60000</integer> - <!-- Whether/how to notify the user on network switches. See LingerMonitor.java. --> <integer translatable="false" name="config_networkNotifySwitchType">0</integer> @@ -342,16 +339,6 @@ Settings.Global.NETWORK_AVOID_BAD_WIFI. This is the default value of that setting. --> <integer translatable="false" name="config_networkAvoidBadWifi">1</integer> - <!-- Configuration hook for the URL returned by ConnectivityManager#getCaptivePortalServerUrl. - If empty, the returned value is controlled by Settings.Global.CAPTIVE_PORTAL_HTTP_URL, - and if that value is empty, the framework will use a hard-coded default. - This is *NOT* a URL that will always be used by the system network validation to detect - captive portals: NetworkMonitor may use different strategies and will not necessarily use - this URL. NetworkMonitor behaviour should be configured with NetworkStack resource overlays - instead. --> - <!--suppress CheckTagEmptyBody --> - <string translatable="false" name="config_networkCaptivePortalServerUrl"></string> - <!-- If the hardware supports specially marking packets that caused a wakeup of the main CPU, set this value to the mark used. --> <integer name="config_networkWakeupPacketMark">0</integer> @@ -459,14 +446,6 @@ apps requested it. --> <bool name="config_vehicleInternalNetworkAlwaysRequested">false</bool> - <!-- Configuration of network interfaces that support WakeOnLAN --> - <string-array translatable="false" name="config_wakeonlan_supported_interfaces"> - <!-- - <item>wlan0</item> - <item>eth0</item> - --> - </string-array> - <!-- This setting is deprecated, please use com.android.networkstack.tethering.R.array.config_mobile_hotspot_provision_app instead. --> <string-array translatable="false" name="config_mobile_hotspot_provision_app"> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index fc75463a44fa..ad24b79779d4 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -685,7 +685,6 @@ <java-symbol type="string" name="not_checked" /> <java-symbol type="array" name="config_ethernet_interfaces" /> <java-symbol type="bool" name="config_vehicleInternalNetworkAlwaysRequested" /> - <java-symbol type="array" name="config_wakeonlan_supported_interfaces" /> <java-symbol type="string" name="config_forceVoiceInteractionServicePackage" /> <java-symbol type="string" name="config_mms_user_agent" /> <java-symbol type="string" name="config_mms_user_agent_profile_url" /> @@ -1951,11 +1950,9 @@ <java-symbol type="integer" name="config_lowBatteryCloseWarningBump" /> <java-symbol type="integer" name="config_lowBatteryWarningLevel" /> <java-symbol type="integer" name="config_networkPolicyDefaultWarning" /> - <java-symbol type="integer" name="config_networkTransitionTimeout" /> <java-symbol type="integer" name="config_networkNotifySwitchType" /> <java-symbol type="array" name="config_networkNotifySwitches" /> <java-symbol type="integer" name="config_networkAvoidBadWifi" /> - <java-symbol type="string" name="config_networkCaptivePortalServerUrl" /> <java-symbol type="integer" name="config_networkWakeupPacketMark" /> <java-symbol type="integer" name="config_networkWakeupPacketMask" /> <java-symbol type="bool" name="config_apfDrop802_3Frames" /> diff --git a/core/tests/utiltests/src/com/android/internal/util/LocationPermissionCheckerTest.java b/core/tests/utiltests/src/com/android/internal/util/LocationPermissionCheckerTest.java deleted file mode 100644 index 7175f562d7ef..000000000000 --- a/core/tests/utiltests/src/com/android/internal/util/LocationPermissionCheckerTest.java +++ /dev/null @@ -1,296 +0,0 @@ -/* - * 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.internal.util; - -import static android.Manifest.permission.NETWORK_SETTINGS; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.ArgumentMatchers.nullable; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.Manifest; -import android.app.ActivityManager; -import android.app.AppOpsManager; -import android.content.Context; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; -import android.location.LocationManager; -import android.os.Binder; -import android.os.Build; -import android.os.UserHandle; -import android.os.UserManager; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; - -import java.util.HashMap; - -/** Unit tests for {@link LocationPermissionChecker}. */ -public class LocationPermissionCheckerTest { - - public static final String TAG = "ConnectivityUtilTest"; - - // Mock objects for testing - @Mock private Context mMockContext; - @Mock private PackageManager mMockPkgMgr; - @Mock private ApplicationInfo mMockApplInfo; - @Mock private AppOpsManager mMockAppOps; - @Mock private UserManager mMockUserManager; - @Mock private LocationManager mLocationManager; - - private static final String TEST_PKG_NAME = "com.google.somePackage"; - private static final String TEST_FEATURE_ID = "com.google.someFeature"; - private static final int MANAGED_PROFILE_UID = 1100000; - private static final int OTHER_USER_UID = 1200000; - - private final String mInteractAcrossUsersFullPermission = - "android.permission.INTERACT_ACROSS_USERS_FULL"; - private final String mManifestStringCoarse = - Manifest.permission.ACCESS_COARSE_LOCATION; - private final String mManifestStringFine = - Manifest.permission.ACCESS_FINE_LOCATION; - - // Test variables - private int mWifiScanAllowApps; - private int mUid; - private int mCoarseLocationPermission; - private int mAllowCoarseLocationApps; - private int mFineLocationPermission; - private int mAllowFineLocationApps; - private int mNetworkSettingsPermission; - private int mCurrentUser; - private boolean mIsLocationEnabled; - private boolean mThrowSecurityException; - private Answer<Integer> mReturnPermission; - private HashMap<String, Integer> mPermissionsList = new HashMap<String, Integer>(); - private LocationPermissionChecker mChecker; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - initTestVars(); - } - - private void setupMocks() throws Exception { - when(mMockPkgMgr.getApplicationInfoAsUser(eq(TEST_PKG_NAME), eq(0), any())) - .thenReturn(mMockApplInfo); - when(mMockContext.getPackageManager()).thenReturn(mMockPkgMgr); - when(mMockAppOps.noteOp(AppOpsManager.OPSTR_WIFI_SCAN, mUid, TEST_PKG_NAME, - TEST_FEATURE_ID, null)).thenReturn(mWifiScanAllowApps); - when(mMockAppOps.noteOp(eq(AppOpsManager.OPSTR_COARSE_LOCATION), eq(mUid), - eq(TEST_PKG_NAME), eq(TEST_FEATURE_ID), nullable(String.class))) - .thenReturn(mAllowCoarseLocationApps); - when(mMockAppOps.noteOp(eq(AppOpsManager.OPSTR_FINE_LOCATION), eq(mUid), - eq(TEST_PKG_NAME), eq(TEST_FEATURE_ID), nullable(String.class))) - .thenReturn(mAllowFineLocationApps); - if (mThrowSecurityException) { - doThrow(new SecurityException("Package " + TEST_PKG_NAME + " doesn't belong" - + " to application bound to user " + mUid)) - .when(mMockAppOps).checkPackage(mUid, TEST_PKG_NAME); - } - when(mMockContext.getSystemService(Context.APP_OPS_SERVICE)) - .thenReturn(mMockAppOps); - when(mMockContext.getSystemService(Context.USER_SERVICE)) - .thenReturn(mMockUserManager); - when(mMockContext.getSystemService(Context.LOCATION_SERVICE)).thenReturn(mLocationManager); - } - - private void setupTestCase() throws Exception { - setupMocks(); - setupMockInterface(); - mChecker = new LocationPermissionChecker(mMockContext); - } - - private void initTestVars() { - mPermissionsList.clear(); - mReturnPermission = createPermissionAnswer(); - mWifiScanAllowApps = AppOpsManager.MODE_ERRORED; - mUid = OTHER_USER_UID; - mThrowSecurityException = true; - mMockApplInfo.targetSdkVersion = Build.VERSION_CODES.M; - mIsLocationEnabled = false; - mCurrentUser = ActivityManager.getCurrentUser(); - mCoarseLocationPermission = PackageManager.PERMISSION_DENIED; - mFineLocationPermission = PackageManager.PERMISSION_DENIED; - mAllowCoarseLocationApps = AppOpsManager.MODE_ERRORED; - mAllowFineLocationApps = AppOpsManager.MODE_ERRORED; - mNetworkSettingsPermission = PackageManager.PERMISSION_DENIED; - } - - private void setupMockInterface() { - Binder.restoreCallingIdentity((((long) mUid) << 32) | Binder.getCallingPid()); - doAnswer(mReturnPermission).when(mMockContext).checkPermission( - anyString(), anyInt(), anyInt()); - when(mMockUserManager.isSameProfileGroup(UserHandle.SYSTEM, - UserHandle.getUserHandleForUid(MANAGED_PROFILE_UID))) - .thenReturn(true); - when(mMockContext.checkPermission(mManifestStringCoarse, -1, mUid)) - .thenReturn(mCoarseLocationPermission); - when(mMockContext.checkPermission(mManifestStringFine, -1, mUid)) - .thenReturn(mFineLocationPermission); - when(mMockContext.checkPermission(NETWORK_SETTINGS, -1, mUid)) - .thenReturn(mNetworkSettingsPermission); - when(mLocationManager.isLocationEnabledForUser(any())).thenReturn(mIsLocationEnabled); - } - - private Answer<Integer> createPermissionAnswer() { - return new Answer<Integer>() { - @Override - public Integer answer(InvocationOnMock invocation) { - int myUid = (int) invocation.getArguments()[1]; - String myPermission = (String) invocation.getArguments()[0]; - mPermissionsList.get(myPermission); - if (mPermissionsList.containsKey(myPermission)) { - int uid = mPermissionsList.get(myPermission); - if (myUid == uid) { - return PackageManager.PERMISSION_GRANTED; - } - } - return PackageManager.PERMISSION_DENIED; - } - }; - } - - @Test - public void testEnforceLocationPermission_HasAllPermissions_BeforeQ() throws Exception { - mIsLocationEnabled = true; - mThrowSecurityException = false; - mCoarseLocationPermission = PackageManager.PERMISSION_GRANTED; - mAllowCoarseLocationApps = AppOpsManager.MODE_ALLOWED; - mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; - mUid = mCurrentUser; - setupTestCase(); - - final int result = - mChecker.checkLocationPermissionWithDetailInfo( - TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null); - assertEquals(LocationPermissionChecker.SUCCEEDED, result); - } - - @Test - public void testEnforceLocationPermission_HasAllPermissions_AfterQ() throws Exception { - mMockApplInfo.targetSdkVersion = Build.VERSION_CODES.Q; - mIsLocationEnabled = true; - mThrowSecurityException = false; - mUid = mCurrentUser; - mFineLocationPermission = PackageManager.PERMISSION_GRANTED; - mAllowFineLocationApps = AppOpsManager.MODE_ALLOWED; - mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; - setupTestCase(); - - final int result = - mChecker.checkLocationPermissionWithDetailInfo( - TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null); - assertEquals(LocationPermissionChecker.SUCCEEDED, result); - } - - @Test - public void testEnforceLocationPermission_PkgNameAndUidMismatch() throws Exception { - mThrowSecurityException = true; - mIsLocationEnabled = true; - mFineLocationPermission = PackageManager.PERMISSION_GRANTED; - mAllowFineLocationApps = AppOpsManager.MODE_ALLOWED; - mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; - setupTestCase(); - - assertThrows(SecurityException.class, - () -> mChecker.checkLocationPermissionWithDetailInfo( - TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null)); - } - - @Test - public void testenforceCanAccessScanResults_NoCoarseLocationPermission() throws Exception { - mThrowSecurityException = false; - mIsLocationEnabled = true; - setupTestCase(); - - final int result = - mChecker.checkLocationPermissionWithDetailInfo( - TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null); - assertEquals(LocationPermissionChecker.ERROR_LOCATION_PERMISSION_MISSING, result); - } - - @Test - public void testenforceCanAccessScanResults_NoFineLocationPermission() throws Exception { - mThrowSecurityException = false; - mMockApplInfo.targetSdkVersion = Build.VERSION_CODES.Q; - mIsLocationEnabled = true; - mCoarseLocationPermission = PackageManager.PERMISSION_GRANTED; - mAllowFineLocationApps = AppOpsManager.MODE_ERRORED; - mUid = MANAGED_PROFILE_UID; - setupTestCase(); - - final int result = - mChecker.checkLocationPermissionWithDetailInfo( - TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null); - assertEquals(LocationPermissionChecker.ERROR_LOCATION_PERMISSION_MISSING, result); - verify(mMockAppOps, never()).noteOp(anyInt(), anyInt(), anyString()); - } - - @Test - public void testenforceCanAccessScanResults_LocationModeDisabled() throws Exception { - mThrowSecurityException = false; - mUid = MANAGED_PROFILE_UID; - mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; - mPermissionsList.put(mInteractAcrossUsersFullPermission, mUid); - mIsLocationEnabled = false; - - setupTestCase(); - - final int result = - mChecker.checkLocationPermissionWithDetailInfo( - TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null); - assertEquals(LocationPermissionChecker.ERROR_LOCATION_MODE_OFF, result); - } - - @Test - public void testenforceCanAccessScanResults_LocationModeDisabledHasNetworkSettings() - throws Exception { - mThrowSecurityException = false; - mIsLocationEnabled = false; - mNetworkSettingsPermission = PackageManager.PERMISSION_GRANTED; - setupTestCase(); - - final int result = - mChecker.checkLocationPermissionWithDetailInfo( - TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null); - assertEquals(LocationPermissionChecker.SUCCEEDED, result); - } - - - private static void assertThrows(Class<? extends Exception> exceptionClass, Runnable r) { - try { - r.run(); - Assert.fail("Expected " + exceptionClass + " to be thrown."); - } catch (Exception exception) { - assertTrue(exceptionClass.isInstance(exception)); - } - } -} diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml index 354d83c293e6..653e690506bc 100644 --- a/data/etc/privapp-permissions-platform.xml +++ b/data/etc/privapp-permissions-platform.xml @@ -451,6 +451,7 @@ applications that come with the platform <permission name="android.permission.MANAGE_SOUND_TRIGGER" /> <permission name="android.permission.CAPTURE_AUDIO_HOTWORD" /> <permission name="android.permission.MODIFY_QUIET_MODE" /> + <permission name="android.permission.MANAGE_APP_HIBERNATION"/> </privapp-permissions> <privapp-permissions package="com.android.statementservice"> diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java index 937f01ce3767..a08f390c9fd3 100644 --- a/keystore/java/android/security/KeyStore.java +++ b/keystore/java/android/security/KeyStore.java @@ -207,7 +207,7 @@ public class KeyStore { case UserState.LSKF_LOCKED: return KeyStore.State.LOCKED; default: - throw new AssertionError(KeyStore.VALUE_CORRUPTED); + throw new AssertionError(userState); } } ret = mBinder.getState(userId); diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java b/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java index 2ee952cbc5fb..9d8a5effc2d7 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java @@ -123,8 +123,9 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor throws InvalidKeyException { resetAll(); - if (!(key instanceof AndroidKeyStorePrivateKey - || key instanceof AndroidKeyStoreSecretKey)) { + // Public key operations get diverted to the default provider. + if (!(key instanceof AndroidKeyStorePrivateKey) + && (key instanceof PrivateKey || key instanceof PublicKey)) { try { mCipher = Cipher.getInstance(getTransform()); String transform = getTransform(); @@ -184,8 +185,9 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException { resetAll(); - if (!(key instanceof AndroidKeyStorePrivateKey - || key instanceof AndroidKeyStoreSecretKey)) { + // Public key operations get diverted to the default provider. + if (!(key instanceof AndroidKeyStorePrivateKey) + && (key instanceof PrivateKey || key instanceof PublicKey)) { try { mCipher = Cipher.getInstance(getTransform()); mCipher.init(opmode, key, params, random); @@ -213,8 +215,9 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException { resetAll(); - if (!(key instanceof AndroidKeyStorePrivateKey - || key instanceof AndroidKeyStoreSecretKey)) { + // Public key operations get diverted to the default provider. + if (!(key instanceof AndroidKeyStorePrivateKey) + && (key instanceof PrivateKey || key instanceof PublicKey)) { try { mCipher = Cipher.getInstance(getTransform()); mCipher.init(opmode, key, params, random); diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java b/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java index fa852e33a1d8..ba6d22f681ce 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java @@ -145,23 +145,15 @@ public class AndroidKeyStoreProvider extends Provider { sInstalled = true; Security.addProvider(new AndroidKeyStoreProvider()); - Security.addProvider( - new android.security.keystore.AndroidKeyStoreProvider( - "AndroidKeyStoreLegacy")); Provider workaroundProvider = new AndroidKeyStoreBCWorkaroundProvider(); - Provider legacyWorkaroundProvider = - new android.security.keystore.AndroidKeyStoreBCWorkaroundProvider( - "AndroidKeyStoreBCWorkaroundLegacy"); if (bcProviderIndex != -1) { // Bouncy Castle provider found -- install the workaround provider above it. // insertProviderAt uses 1-based positions. - Security.insertProviderAt(legacyWorkaroundProvider, bcProviderIndex + 1); Security.insertProviderAt(workaroundProvider, bcProviderIndex + 1); } else { // Bouncy Castle provider not found -- install the workaround provider at lowest // priority. Security.addProvider(workaroundProvider); - Security.addProvider(legacyWorkaroundProvider); } } diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp index 446e81e65bb8..c6ab1194cf66 100644 --- a/libs/hwui/Properties.cpp +++ b/libs/hwui/Properties.cpp @@ -124,7 +124,7 @@ bool Properties::load() { SkAndroidFrameworkTraceUtil::setEnableTracing( base::GetBoolProperty(PROPERTY_SKIA_ATRACE_ENABLED, false)); - runningInEmulator = base::GetBoolProperty(PROPERTY_QEMU_KERNEL, false); + runningInEmulator = base::GetBoolProperty(PROPERTY_IS_EMULATOR, false); defaultRenderAhead = std::max(-1, std::min(2, base::GetIntProperty(PROPERTY_RENDERAHEAD, render_ahead().value_or(0)))); diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h index d3ecb54d94f6..6ea208e933f2 100644 --- a/libs/hwui/Properties.h +++ b/libs/hwui/Properties.h @@ -160,7 +160,7 @@ enum DebugLevel { /** * Property for whether this is running in the emulator. */ -#define PROPERTY_QEMU_KERNEL "ro.kernel.qemu" +#define PROPERTY_IS_EMULATOR "ro.boot.qemu" #define PROPERTY_RENDERAHEAD "debug.hwui.render_ahead" diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java index 1b05c3b57256..b265ebfc02a0 100644 --- a/media/java/android/media/AudioTrack.java +++ b/media/java/android/media/AudioTrack.java @@ -2077,6 +2077,65 @@ public class AudioTrack extends PlayerBase } /** + * Sets the streaming start threshold for an <code>AudioTrack</code>. + * <p> The streaming start threshold is the buffer level that the written audio + * data must reach for audio streaming to start after {@link #play()} is called. + * <p> For compressed streams, the size of a frame is considered to be exactly one byte. + * + * @param startThresholdInFrames the desired start threshold. + * @return the actual start threshold in frames value. This is + * an integer between 1 to the buffer capacity + * (see {@link #getBufferCapacityInFrames()}), + * and might change if the output sink changes after track creation. + * @throws IllegalStateException if the track is not initialized or the + * track transfer mode is not {@link #MODE_STREAM}. + * @throws IllegalArgumentException if startThresholdInFrames is not positive. + * @see #getStartThresholdInFrames() + */ + public @IntRange(from = 1) int setStartThresholdInFrames( + @IntRange (from = 1) int startThresholdInFrames) { + if (mState != STATE_INITIALIZED) { + throw new IllegalStateException("AudioTrack is not initialized"); + } + if (mDataLoadMode != MODE_STREAM) { + throw new IllegalStateException("AudioTrack must be a streaming track"); + } + if (startThresholdInFrames < 1) { + throw new IllegalArgumentException("startThresholdInFrames " + + startThresholdInFrames + " must be positive"); + } + return native_setStartThresholdInFrames(startThresholdInFrames); + } + + /** + * Returns the streaming start threshold of the <code>AudioTrack</code>. + * <p> The streaming start threshold is the buffer level that the written audio + * data must reach for audio streaming to start after {@link #play()} is called. + * When an <code>AudioTrack</code> is created, the streaming start threshold + * is the buffer capacity in frames. If the buffer size in frames is reduced + * by {@link #setBufferSizeInFrames(int)} to a value smaller than the start threshold + * then that value will be used instead for the streaming start threshold. + * <p> For compressed streams, the size of a frame is considered to be exactly one byte. + * + * @return the current start threshold in frames value. This is + * an integer between 1 to the buffer capacity + * (see {@link #getBufferCapacityInFrames()}), + * and might change if the output sink changes after track creation. + * @throws IllegalStateException if the track is not initialized or the + * track is not {@link #MODE_STREAM}. + * @see #setStartThresholdInFrames(int) + */ + public @IntRange (from = 1) int getStartThresholdInFrames() { + if (mState != STATE_INITIALIZED) { + throw new IllegalStateException("AudioTrack is not initialized"); + } + if (mDataLoadMode != MODE_STREAM) { + throw new IllegalStateException("AudioTrack must be a streaming track"); + } + return native_getStartThresholdInFrames(); + } + + /** * Returns the frame count of the native <code>AudioTrack</code> buffer. * @return current size in frames of the <code>AudioTrack</code> buffer. * @throws IllegalStateException @@ -4179,6 +4238,8 @@ public class AudioTrack extends PlayerBase private native int native_get_audio_description_mix_level_db(float[] level); private native int native_set_dual_mono_mode(int dualMonoMode); private native int native_get_dual_mono_mode(int[] dualMonoMode); + private native int native_setStartThresholdInFrames(int startThresholdInFrames); + private native int native_getStartThresholdInFrames(); //--------------------------------------------------------- // Utility methods diff --git a/media/jni/Android.bp b/media/jni/Android.bp index f65dfddef008..517e192e00af 100644 --- a/media/jni/Android.bp +++ b/media/jni/Android.bp @@ -19,6 +19,7 @@ cc_library_shared { name: "libmedia_jni", defaults: ["libcodec2-internal-defaults"], + min_sdk_version: "", srcs: [ "android_media_ImageWriter.cpp", diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp index 694b93919cde..3976086ea495 100644 --- a/media/jni/android_media_tv_Tuner.cpp +++ b/media/jni/android_media_tv_Tuner.cpp @@ -287,7 +287,10 @@ Dvr::~Dvr() { jint Dvr::close() { Result r = mDvrSp->close(); if (r == Result::SUCCESS) { - EventFlag::deleteEventFlag(&mDvrMQEventFlag); + if (mDvrMQEventFlag != nullptr) { + EventFlag::deleteEventFlag(&mDvrMQEventFlag); + } + mDvrMQ = nullptr; } return (jint) r; } @@ -723,13 +726,15 @@ Filter::~Filter() { env->DeleteWeakGlobalRef(mFilterObj); mFilterObj = NULL; - EventFlag::deleteEventFlag(&mFilterMQEventFlag); } int Filter::close() { Result r = mFilterSp->close(); if (r == Result::SUCCESS) { - EventFlag::deleteEventFlag(&mFilterMQEventFlag); + if (mFilterMQEventFlag != nullptr) { + EventFlag::deleteEventFlag(&mFilterMQEventFlag); + } + mFilterMQ = nullptr; } return (int)r; } @@ -3050,6 +3055,9 @@ static jint android_media_tv_Tuner_configure_filter( filterSp->mFilterMQ = std::make_unique<MQ>(filterMQDesc, true); EventFlag::createEventFlag( filterSp->mFilterMQ->getEventFlagWord(), &(filterSp->mFilterMQEventFlag)); + } else { + filterSp->mFilterMQ = nullptr; + filterSp->mFilterMQEventFlag = nullptr; } } return (jint) getQueueDescResult; @@ -3137,13 +3145,12 @@ static jint android_media_tv_Tuner_read_filter_fmq( } static jint android_media_tv_Tuner_close_filter(JNIEnv *env, jobject filter) { - sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter(); - if (iFilterSp == NULL) { + sp<Filter> filterSp = getFilter(env, filter); + if (filterSp == NULL) { ALOGD("Failed to close filter: filter not found"); return (jint) Result::NOT_INITIALIZED; } - Result r = iFilterSp->close(); - return (jint) r; + return filterSp->close(); } static sp<TimeFilter> getTimeFilter(JNIEnv *env, jobject filter) { diff --git a/media/jni/soundpool/StreamManager.cpp b/media/jni/soundpool/StreamManager.cpp index 8b84bf3eb8d8..309d71cfd062 100644 --- a/media/jni/soundpool/StreamManager.cpp +++ b/media/jni/soundpool/StreamManager.cpp @@ -43,6 +43,14 @@ static constexpr bool kPlayOnCallingThread = true; // Amount of time for a StreamManager thread to wait before closing. static constexpr int64_t kWaitTimeBeforeCloseNs = 9 * NANOS_PER_SECOND; +// Debug flag: +// kForceLockStreamManagerStop is set to true to force lock the StreamManager +// worker thread during stop. This limits concurrency of Stream processing. +// Normally we lock the StreamManager worker thread during stop ONLY +// for SoundPools configured with a single Stream. +// +static constexpr bool kForceLockStreamManagerStop = false; + //////////// StreamMap::StreamMap(int32_t streams) { @@ -103,6 +111,7 @@ StreamManager::StreamManager( : StreamMap(streams) , mAttributes(*attributes) , mOpPackageName(std::move(opPackageName)) + , mLockStreamManagerStop(streams == 1 || kForceLockStreamManagerStop) { ALOGV("%s(%d, %zu, ...)", __func__, streams, threads); forEach([this](Stream *stream) { @@ -113,7 +122,8 @@ StreamManager::StreamManager( }); mThreadPool = std::make_unique<ThreadPool>( - std::min(threads, (size_t)std::thread::hardware_concurrency()), + std::min((size_t)streams, // do not make more threads than streams to play + std::min(threads, (size_t)std::thread::hardware_concurrency())), "SoundPool_"); } @@ -348,14 +358,14 @@ void StreamManager::addToActiveQueue_l(Stream *stream) { void StreamManager::run(int32_t id) { ALOGV("%s(%d) entering", __func__, id); - int64_t waitTimeNs = kWaitTimeBeforeCloseNs; + int64_t waitTimeNs = 0; // on thread start, mRestartStreams can be non-empty. std::unique_lock lock(mStreamManagerLock); while (!mQuit) { - if (mRestartStreams.empty()) { // on thread start, mRestartStreams can be non-empty. + if (waitTimeNs > 0) { mStreamManagerCondition.wait_for( lock, std::chrono::duration<int64_t, std::nano>(waitTimeNs)); } - ALOGV("%s(%d) awake", __func__, id); + ALOGV("%s(%d) awake lock waitTimeNs:%lld", __func__, id, (long long)waitTimeNs); sanityCheckQueue_l(); @@ -375,12 +385,12 @@ void StreamManager::run(int32_t id) } mRestartStreams.erase(it); mProcessingStreams.emplace(stream); - lock.unlock(); + if (!mLockStreamManagerStop) lock.unlock(); stream->stop(); ALOGV("%s(%d) stopping streamID:%d", __func__, id, stream->getStreamID()); if (Stream* nextStream = stream->playPairStream()) { ALOGV("%s(%d) starting streamID:%d", __func__, id, nextStream->getStreamID()); - lock.lock(); + if (!mLockStreamManagerStop) lock.lock(); if (nextStream->getStopTimeNs() > 0) { // the next stream was stopped before we can move it to the active queue. ALOGV("%s(%d) stopping started streamID:%d", @@ -390,7 +400,7 @@ void StreamManager::run(int32_t id) addToActiveQueue_l(nextStream); } } else { - lock.lock(); + if (!mLockStreamManagerStop) lock.lock(); mAvailableStreams.insert(stream); } mProcessingStreams.erase(stream); diff --git a/media/jni/soundpool/StreamManager.h b/media/jni/soundpool/StreamManager.h index 81ac69eb4358..85b468cd2cbc 100644 --- a/media/jni/soundpool/StreamManager.h +++ b/media/jni/soundpool/StreamManager.h @@ -437,6 +437,14 @@ private: void sanityCheckQueue_l() const REQUIRES(mStreamManagerLock); const audio_attributes_t mAttributes; + const std::string mOpPackageName; + + // For legacy compatibility, we lock the stream manager on stop when + // there is only one stream. This allows a play to be called immediately + // after stopping, otherwise it is possible that the play might be discarded + // (returns 0) because that stream may be in the worker thread call to stop. + const bool mLockStreamManagerStop; + std::unique_ptr<ThreadPool> mThreadPool; // locked internally // mStreamManagerLock is used to lock access for transitions between the @@ -477,8 +485,6 @@ private: // The paired stream may be active or restarting. // No particular order. std::unordered_set<Stream*> mProcessingStreams GUARDED_BY(mStreamManagerLock); - - const std::string mOpPackageName; }; } // namespace android::soundpool diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java index 6fab9e4641b6..550e324733d9 100644 --- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java +++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java @@ -86,7 +86,7 @@ public class CaptivePortalLoginActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - mCm = ConnectivityManager.from(this); + mCm = getSystemService(ConnectivityManager.class); mUrl = getUrlForCaptivePortal(); if (mUrl == null) { done(false); @@ -161,7 +161,6 @@ public class CaptivePortalLoginActivity extends Activity { if (network != null) { network = network.getPrivateDnsBypassingCopy(); mCm.bindProcessToNetwork(network); - mCm.setProcessDefaultNetworkForHostResolution(network); } mNetwork = network; } diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/ProvisionObserver.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/ProvisionObserver.java index 78a02d71fc9f..43ca7393abfc 100644 --- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/ProvisionObserver.java +++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/ProvisionObserver.java @@ -49,7 +49,7 @@ public class ProvisionObserver extends JobService { case PROVISION_OBSERVER_REEVALUATION_JOB_ID: if (isProvisioned(this)) { Log.d(TAG, "device provisioned, force network re-evaluation"); - final ConnectivityManager connMgr = ConnectivityManager.from(this); + final ConnectivityManager connMgr = getSystemService(ConnectivityManager.class); Network[] info = connMgr.getAllNetworks(); for (Network nw : info) { final NetworkCapabilities nc = connMgr.getNetworkCapabilities(nw); diff --git a/packages/Connectivity/framework/Android.bp b/packages/Connectivity/framework/Android.bp index 9da27d271169..017ff51f366d 100644 --- a/packages/Connectivity/framework/Android.bp +++ b/packages/Connectivity/framework/Android.bp @@ -23,7 +23,25 @@ package { default_applicable_licenses: ["frameworks_base_license"], } -// TODO: use a java_library in the bootclasspath instead +java_library { + name: "framework-connectivity-protos", + proto: { + type: "nano", + }, + srcs: [ + // TODO: consider moving relevant .proto files directly to the module directory + ":framework-javastream-protos", + ], + apex_available: [ + "//apex_available:platform", + "com.android.tethering", + ], + jarjar_rules: "jarjar-rules-proto.txt", + visibility: [ + "//visibility:private", + ], +} + filegroup { name: "framework-connectivity-internal-sources", srcs: [ @@ -84,3 +102,39 @@ java_sdk_library { ], permitted_packages: ["android.net", "com.android.connectivity.aidl"], } + +java_library { + name: "framework-connectivity.impl", + // Instead of building against private API (framework.jar), + // build against core_platform + framework-minus-apex + module + // stub libs. This allows framework.jar to depend on this library, + // so it can be part of the private API until all clients have been migrated. + // TODO: just build against module_api, and remove this jar from + // the private API. + sdk_version: "core_platform", + srcs: [ + ":framework-connectivity-sources", + ], + aidl: { + include_dirs: [ + "frameworks/base/core/java", // For framework parcelables + "frameworks/native/aidl/binder", // For PersistableBundle.aidl + ], + }, + libs: [ + "framework-minus-apex", + // TODO: just framework-tethering, framework-wifi when building against module_api + "framework-tethering.stubs.module_lib", + "framework-wifi.stubs.module_lib", + "unsupportedappusage", + "ServiceConnectivityResources", + ], + static_libs: [ + "framework-connectivity-protos", + "net-utils-device-common", + ], + jarjar_rules: "jarjar-rules.txt", + apex_available: ["com.android.tethering"], + installable: true, + permitted_packages: ["android.net", "com.android.connectivity.aidl"], +} diff --git a/packages/Connectivity/framework/aidl-export/android/net/NetworkScore.aidl b/packages/Connectivity/framework/aidl-export/android/net/NetworkScore.aidl new file mode 100644 index 000000000000..af12dcf7f17a --- /dev/null +++ b/packages/Connectivity/framework/aidl-export/android/net/NetworkScore.aidl @@ -0,0 +1,20 @@ +/** + * Copyright (c) 2021, 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; + +parcelable NetworkScore; + diff --git a/packages/Connectivity/framework/api/current.txt b/packages/Connectivity/framework/api/current.txt index 243e4ca4295a..e415e01fea3a 100644 --- a/packages/Connectivity/framework/api/current.txt +++ b/packages/Connectivity/framework/api/current.txt @@ -87,6 +87,7 @@ package android.net { method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public boolean isActiveNetworkMetered(); method public boolean isDefaultNetworkActive(); method @Deprecated public static boolean isNetworkTypeValid(int); + method public void registerBestMatchingNetworkCallback(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler); method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback); method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler); method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerNetworkCallback(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback); @@ -290,6 +291,7 @@ package android.net { ctor public NetworkCapabilities(); ctor public NetworkCapabilities(android.net.NetworkCapabilities); method public int describeContents(); + method @NonNull public int[] getCapabilities(); method public int getLinkDownstreamBandwidthKbps(); method public int getLinkUpstreamBandwidthKbps(); method @Nullable public android.net.NetworkSpecifier getNetworkSpecifier(); diff --git a/packages/Connectivity/framework/api/module-lib-current.txt b/packages/Connectivity/framework/api/module-lib-current.txt index 4b3336644ef9..aa7a0ac46598 100644 --- a/packages/Connectivity/framework/api/module-lib-current.txt +++ b/packages/Connectivity/framework/api/module-lib-current.txt @@ -6,11 +6,26 @@ package android.net { } public class ConnectivityManager { + method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void factoryReset(); method @NonNull @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public java.util.List<android.net.NetworkStateSnapshot> getAllNetworkStateSnapshot(); + method @Nullable public android.net.ProxyInfo getGlobalProxy(); method @NonNull public static android.util.Range<java.lang.Integer> getIpSecNetIdRange(); + method @NonNull public static String getPrivateDnsMode(@NonNull android.content.Context); method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void registerSystemDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler); method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void requestBackgroundNetwork(@NonNull android.net.NetworkRequest, @NonNull android.os.Handler, @NonNull android.net.ConnectivityManager.NetworkCallback); + method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void setAcceptPartialConnectivity(@NonNull android.net.Network, boolean, boolean); + method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void setAcceptUnvalidated(@NonNull android.net.Network, boolean, boolean); + method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void setAvoidUnvalidated(@NonNull android.net.Network); + method @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public void setGlobalProxy(@Nullable android.net.ProxyInfo); + method @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public void setProfileNetworkPreference(@NonNull android.os.UserHandle, int, @Nullable java.util.concurrent.Executor, @Nullable Runnable); method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_TEST_NETWORKS, android.Manifest.permission.NETWORK_STACK}) public void simulateDataStall(int, long, @NonNull android.net.Network, @NonNull android.os.PersistableBundle); + method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void startCaptivePortalApp(@NonNull android.net.Network); + method public void systemReady(); + field public static final String PRIVATE_DNS_MODE_OFF = "off"; + field public static final String PRIVATE_DNS_MODE_OPPORTUNISTIC = "opportunistic"; + field public static final String PRIVATE_DNS_MODE_PROVIDER_HOSTNAME = "hostname"; + field public static final int PROFILE_NETWORK_PREFERENCE_DEFAULT = 0; // 0x0 + field public static final int PROFILE_NETWORK_PREFERENCE_ENTERPRISE = 1; // 0x1 } public final class NetworkAgentConfig implements android.os.Parcelable { @@ -22,9 +37,29 @@ package android.net { } public final class NetworkCapabilities implements android.os.Parcelable { + ctor public NetworkCapabilities(@Nullable android.net.NetworkCapabilities, long); + method @Nullable public java.util.Set<android.util.Range<java.lang.Integer>> getUids(); + field public static final long REDACT_ALL = -1L; // 0xffffffffffffffffL + field public static final long REDACT_FOR_ACCESS_FINE_LOCATION = 1L; // 0x1L + field public static final long REDACT_FOR_LOCAL_MAC_ADDRESS = 2L; // 0x2L + field public static final long REDACT_FOR_NETWORK_SETTINGS = 4L; // 0x4L + field public static final long REDACT_NONE = 0L; // 0x0L field public static final int TRANSPORT_TEST = 7; // 0x7 } + public static final class NetworkCapabilities.Builder { + method @NonNull public android.net.NetworkCapabilities.Builder setUids(@Nullable java.util.Set<android.util.Range<java.lang.Integer>>); + } + + public static class NetworkRequest.Builder { + method @NonNull public android.net.NetworkRequest.Builder setUids(@Nullable java.util.Set<android.util.Range<java.lang.Integer>>); + } + + public class ParseException extends java.lang.RuntimeException { + ctor public ParseException(@NonNull String); + ctor public ParseException(@NonNull String, @NonNull Throwable); + } + public final class TcpRepairWindow { ctor public TcpRepairWindow(int, int, int, int, int, int); field public final int maxWindow; @@ -60,6 +95,11 @@ package android.net { field @NonNull public static final android.os.Parcelable.Creator<android.net.TestNetworkSpecifier> CREATOR; } + public interface TransportInfo { + method public default long getApplicableRedactions(); + method @NonNull public default android.net.TransportInfo makeCopy(long); + } + public final class VpnTransportInfo implements android.os.Parcelable android.net.TransportInfo { ctor public VpnTransportInfo(int); method public int describeContents(); diff --git a/packages/Connectivity/framework/api/system-current.txt b/packages/Connectivity/framework/api/system-current.txt index a98f14ea9408..703fca408f7a 100644 --- a/packages/Connectivity/framework/api/system-current.txt +++ b/packages/Connectivity/framework/api/system-current.txt @@ -18,7 +18,7 @@ package android.net { method public long getRefreshTimeMillis(); method @Nullable public android.net.Uri getUserPortalUrl(); method public int getUserPortalUrlSource(); - method @Nullable public String getVenueFriendlyName(); + method @Nullable public CharSequence getVenueFriendlyName(); method @Nullable public android.net.Uri getVenueInfoUrl(); method public int getVenueInfoUrlSource(); method public boolean isCaptive(); @@ -40,7 +40,7 @@ package android.net { method @NonNull public android.net.CaptivePortalData.Builder setSessionExtendable(boolean); method @NonNull public android.net.CaptivePortalData.Builder setUserPortalUrl(@Nullable android.net.Uri); method @NonNull public android.net.CaptivePortalData.Builder setUserPortalUrl(@Nullable android.net.Uri, int); - method @NonNull public android.net.CaptivePortalData.Builder setVenueFriendlyName(@Nullable String); + method @NonNull public android.net.CaptivePortalData.Builder setVenueFriendlyName(@Nullable CharSequence); method @NonNull public android.net.CaptivePortalData.Builder setVenueInfoUrl(@Nullable android.net.Uri); method @NonNull public android.net.CaptivePortalData.Builder setVenueInfoUrl(@Nullable android.net.Uri, int); } @@ -52,11 +52,11 @@ package android.net { method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void getLatestTetheringEntitlementResult(int, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityManager.OnTetheringEntitlementResultListener); method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public boolean isTetheringSupported(); method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_FACTORY}) public int registerNetworkProvider(@NonNull android.net.NetworkProvider); - method public void registerQosCallback(@NonNull android.net.QosSocketInfo, @NonNull android.net.QosCallback, @NonNull java.util.concurrent.Executor); + method public void registerQosCallback(@NonNull android.net.QosSocketInfo, @NonNull java.util.concurrent.Executor, @NonNull android.net.QosCallback); method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void registerTetheringEventCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityManager.OnTetheringEventCallback); method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void requestNetwork(@NonNull android.net.NetworkRequest, int, int, @NonNull android.os.Handler, @NonNull android.net.ConnectivityManager.NetworkCallback); method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_AIRPLANE_MODE, android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK}) public void setAirplaneMode(boolean); - method @RequiresPermission(android.Manifest.permission.CONTROL_OEM_PAID_NETWORK_PREFERENCE) public void setOemNetworkPreference(@NonNull android.net.OemNetworkPreferences, @Nullable java.util.concurrent.Executor, @Nullable android.net.ConnectivityManager.OnSetOemNetworkPreferenceListener); + method @RequiresPermission(android.Manifest.permission.CONTROL_OEM_PAID_NETWORK_PREFERENCE) public void setOemNetworkPreference(@NonNull android.net.OemNetworkPreferences, @Nullable java.util.concurrent.Executor, @Nullable Runnable); method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public boolean shouldAvoidBadWifi(); method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void startCaptivePortalApp(@NonNull android.net.Network, @NonNull android.os.Bundle); method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback); @@ -78,10 +78,6 @@ package android.net { field @Deprecated public static final int TYPE_WIFI_P2P = 13; // 0xd } - public static interface ConnectivityManager.OnSetOemNetworkPreferenceListener { - method public void onComplete(); - } - @Deprecated public abstract static class ConnectivityManager.OnStartTetheringCallback { ctor @Deprecated public ConnectivityManager.OnStartTetheringCallback(); method @Deprecated public void onTetheringFailed(); @@ -265,7 +261,6 @@ package android.net { } public final class NetworkCapabilities implements android.os.Parcelable { - ctor public NetworkCapabilities(@Nullable android.net.NetworkCapabilities, boolean); method @NonNull public int[] getAdministratorUids(); method @Nullable public String getSsid(); method @NonNull public int[] getTransportTypes(); @@ -439,11 +434,6 @@ package android.net { field public final int tcpWindowScale; } - public interface TransportInfo { - method public default boolean hasLocationSensitiveFields(); - method @NonNull public default android.net.TransportInfo makeCopy(boolean); - } - } package android.net.apf { diff --git a/packages/Connectivity/framework/jarjar-rules-proto.txt b/packages/Connectivity/framework/jarjar-rules-proto.txt new file mode 100644 index 000000000000..37b4dec1c331 --- /dev/null +++ b/packages/Connectivity/framework/jarjar-rules-proto.txt @@ -0,0 +1,3 @@ +keep android.net.NetworkCapabilitiesProto +keep android.net.NetworkProto +keep android.net.NetworkRequestProto diff --git a/packages/Connectivity/framework/jarjar-rules.txt b/packages/Connectivity/framework/jarjar-rules.txt new file mode 100644 index 000000000000..0959840f2dd2 --- /dev/null +++ b/packages/Connectivity/framework/jarjar-rules.txt @@ -0,0 +1,10 @@ +rule com.android.net.module.util.** android.net.connectivity.framework.util.@1 + +# TODO (b/149403767): remove the annotations from net-utils-device-common instead of here +zap android.annotation.** +zap com.android.net.module.annotation.** +zap com.android.internal.annotations.** + +rule android.net.NetworkCapabilitiesProto* android.net.connectivity.proto.NetworkCapabilitiesProto@1 +rule android.net.NetworkProto* android.net.connectivity.proto.NetworkProto@1 +rule android.net.NetworkRequestProto* android.net.connectivity.proto.NetworkRequestProto@1 diff --git a/packages/Connectivity/framework/src/android/net/CaptivePortalData.java b/packages/Connectivity/framework/src/android/net/CaptivePortalData.java index eafda4d2d694..82dbd0fb1f87 100644 --- a/packages/Connectivity/framework/src/android/net/CaptivePortalData.java +++ b/packages/Connectivity/framework/src/android/net/CaptivePortalData.java @@ -42,7 +42,7 @@ public final class CaptivePortalData implements Parcelable { private final long mByteLimit; private final long mExpiryTimeMillis; private final boolean mCaptive; - private final String mVenueFriendlyName; + private final CharSequence mVenueFriendlyName; private final int mVenueInfoUrlSource; private final int mUserPortalUrlSource; @@ -65,7 +65,7 @@ public final class CaptivePortalData implements Parcelable { private CaptivePortalData(long refreshTimeMillis, Uri userPortalUrl, Uri venueInfoUrl, boolean isSessionExtendable, long byteLimit, long expiryTimeMillis, boolean captive, - String venueFriendlyName, int venueInfoUrlSource, int userPortalUrlSource) { + CharSequence venueFriendlyName, int venueInfoUrlSource, int userPortalUrlSource) { mRefreshTimeMillis = refreshTimeMillis; mUserPortalUrl = userPortalUrl; mVenueInfoUrl = venueInfoUrl; @@ -80,7 +80,7 @@ public final class CaptivePortalData implements Parcelable { private CaptivePortalData(Parcel p) { this(p.readLong(), p.readParcelable(null), p.readParcelable(null), p.readBoolean(), - p.readLong(), p.readLong(), p.readBoolean(), p.readString(), p.readInt(), + p.readLong(), p.readLong(), p.readBoolean(), p.readCharSequence(), p.readInt(), p.readInt()); } @@ -98,7 +98,7 @@ public final class CaptivePortalData implements Parcelable { dest.writeLong(mByteLimit); dest.writeLong(mExpiryTimeMillis); dest.writeBoolean(mCaptive); - dest.writeString(mVenueFriendlyName); + dest.writeCharSequence(mVenueFriendlyName); dest.writeInt(mVenueInfoUrlSource); dest.writeInt(mUserPortalUrlSource); } @@ -114,7 +114,7 @@ public final class CaptivePortalData implements Parcelable { private long mBytesRemaining = -1; private long mExpiryTime = -1; private boolean mCaptive; - private String mVenueFriendlyName; + private CharSequence mVenueFriendlyName; private @CaptivePortalDataSource int mVenueInfoUrlSource = CAPTIVE_PORTAL_DATA_SOURCE_OTHER; private @CaptivePortalDataSource int mUserPortalUrlSource = CAPTIVE_PORTAL_DATA_SOURCE_OTHER; @@ -228,7 +228,7 @@ public final class CaptivePortalData implements Parcelable { * Set the venue friendly name. */ @NonNull - public Builder setVenueFriendlyName(@Nullable String venueFriendlyName) { + public Builder setVenueFriendlyName(@Nullable CharSequence venueFriendlyName) { mVenueFriendlyName = venueFriendlyName; return this; } @@ -321,7 +321,7 @@ public final class CaptivePortalData implements Parcelable { * Get the venue friendly name */ @Nullable - public String getVenueFriendlyName() { + public CharSequence getVenueFriendlyName() { return mVenueFriendlyName; } diff --git a/packages/Connectivity/framework/src/android/net/ConnectivityManager.java b/packages/Connectivity/framework/src/android/net/ConnectivityManager.java index 8c66db9a205a..e23747e27a05 100644 --- a/packages/Connectivity/framework/src/android/net/ConnectivityManager.java +++ b/packages/Connectivity/framework/src/android/net/ConnectivityManager.java @@ -16,10 +16,12 @@ package android.net; import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; +import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_DEFAULT_MODE; +import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE; import static android.net.NetworkRequest.Type.BACKGROUND_REQUEST; import static android.net.NetworkRequest.Type.LISTEN; +import static android.net.NetworkRequest.Type.LISTEN_FOR_BEST; import static android.net.NetworkRequest.Type.REQUEST; -import static android.net.NetworkRequest.Type.TRACK_BEST; import static android.net.NetworkRequest.Type.TRACK_DEFAULT; import static android.net.NetworkRequest.Type.TRACK_SYSTEM_DEFAULT; import static android.net.QosCallback.QosCallbackRegistrationException; @@ -31,11 +33,13 @@ import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; +import android.annotation.StringDef; import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.annotation.SystemService; import android.app.PendingIntent; import android.compat.annotation.UnsupportedAppUsage; +import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.net.IpSecManager.UdpEncapsulationSocket; @@ -58,20 +62,19 @@ import android.os.PersistableBundle; import android.os.Process; import android.os.RemoteException; import android.os.ResultReceiver; -import android.os.ServiceManager; import android.os.ServiceSpecificException; +import android.os.UserHandle; import android.provider.Settings; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; +import android.text.TextUtils; import android.util.ArrayMap; import android.util.Log; import android.util.Range; import android.util.SparseIntArray; -import com.android.connectivity.aidl.INetworkAgent; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.Preconditions; -import com.android.internal.util.Protocol; import libcore.net.event.NetworkEventDispatcher; @@ -802,24 +805,27 @@ public class ConnectivityManager { /** * @hide */ + @SystemApi(client = MODULE_LIBRARIES) public static final String PRIVATE_DNS_MODE_OFF = "off"; /** * @hide */ + @SystemApi(client = MODULE_LIBRARIES) public static final String PRIVATE_DNS_MODE_OPPORTUNISTIC = "opportunistic"; /** * @hide */ + @SystemApi(client = MODULE_LIBRARIES) public static final String PRIVATE_DNS_MODE_PROVIDER_HOSTNAME = "hostname"; - /** - * The default Private DNS mode. - * - * This may change from release to release or may become dependent upon - * the capabilities of the underlying platform. - * - * @hide - */ - public static final String PRIVATE_DNS_DEFAULT_MODE_FALLBACK = PRIVATE_DNS_MODE_OPPORTUNISTIC; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @StringDef(value = { + PRIVATE_DNS_MODE_OFF, + PRIVATE_DNS_MODE_OPPORTUNISTIC, + PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, + }) + public @interface PrivateDnsMode {} @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562) private final IConnectivityManager mService; @@ -834,7 +840,6 @@ public class ConnectivityManager { private final Context mContext; - private INetworkPolicyManager mNPManager; private final TetheringManager mTetheringManager; /** @@ -907,8 +912,8 @@ public class ConnectivityManager { /** * @hide - * TODO: Expose for SystemServer when becomes a module. */ + @SystemApi(client = MODULE_LIBRARIES) public void systemReady() { try { mService.systemReady(); @@ -963,6 +968,33 @@ public class ConnectivityManager { } /** + * Preference for {@link #setNetworkPreferenceForUser(UserHandle, int, Executor, Runnable)}. + * Specify that the traffic for this user should by follow the default rules. + * @hide + */ + @SystemApi(client = MODULE_LIBRARIES) + public static final int PROFILE_NETWORK_PREFERENCE_DEFAULT = 0; + + /** + * Preference for {@link #setNetworkPreferenceForUser(UserHandle, int, Executor, Runnable)}. + * Specify that the traffic for this user should by default go on a network with + * {@link NetworkCapabilities#NET_CAPABILITY_ENTERPRISE}, and on the system default network + * if no such network is available. + * @hide + */ + @SystemApi(client = MODULE_LIBRARIES) + public static final int PROFILE_NETWORK_PREFERENCE_ENTERPRISE = 1; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = { + PROFILE_NETWORK_PREFERENCE_DEFAULT, + PROFILE_NETWORK_PREFERENCE_ENTERPRISE + }) + public @interface ProfileNetworkPreference { + } + + /** * Specifies the preferred network type. When the device has more * than one type available the preferred network type will be used. * @@ -3003,8 +3035,9 @@ public class ConnectivityManager { * HTTP proxy. A {@code null} value will clear the global HTTP proxy. * @hide */ + @SystemApi(client = MODULE_LIBRARIES) @RequiresPermission(android.Manifest.permission.NETWORK_STACK) - public void setGlobalProxy(ProxyInfo p) { + public void setGlobalProxy(@Nullable ProxyInfo p) { try { mService.setGlobalProxy(p); } catch (RemoteException e) { @@ -3019,6 +3052,8 @@ public class ConnectivityManager { * if no global HTTP proxy is set. * @hide */ + @SystemApi(client = MODULE_LIBRARIES) + @Nullable public ProxyInfo getGlobalProxy() { try { return mService.getGlobalProxy(); @@ -3205,23 +3240,6 @@ public class ConnectivityManager { } } - // TODO : remove this method. It is a stopgap measure to help sheperding a number - // of dependent changes that would conflict throughout the automerger graph. Having this - // temporarily helps with the process of going through with all these dependent changes across - // the entire tree. - /** - * @hide - * Register a NetworkAgent with ConnectivityService. - * @return Network corresponding to NetworkAgent. - */ - @RequiresPermission(anyOf = { - NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, - android.Manifest.permission.NETWORK_FACTORY}) - public Network registerNetworkAgent(INetworkAgent na, NetworkInfo ni, LinkProperties lp, - NetworkCapabilities nc, int score, NetworkAgentConfig config) { - return registerNetworkAgent(na, ni, lp, nc, score, config, NetworkProvider.ID_NONE); - } - /** * @hide * Register a NetworkAgent with ConnectivityService. @@ -3231,7 +3249,8 @@ public class ConnectivityManager { NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_FACTORY}) public Network registerNetworkAgent(INetworkAgent na, NetworkInfo ni, LinkProperties lp, - NetworkCapabilities nc, int score, NetworkAgentConfig config, int providerId) { + NetworkCapabilities nc, @NonNull NetworkScore score, NetworkAgentConfig config, + int providerId) { try { return mService.registerNetworkAgent(na, ni, lp, nc, score, config, providerId); } catch (RemoteException e) { @@ -3531,29 +3550,28 @@ public class ConnectivityManager { } } - private static final int BASE = Protocol.BASE_CONNECTIVITY_MANAGER; /** @hide */ - public static final int CALLBACK_PRECHECK = BASE + 1; + public static final int CALLBACK_PRECHECK = 1; /** @hide */ - public static final int CALLBACK_AVAILABLE = BASE + 2; + public static final int CALLBACK_AVAILABLE = 2; /** @hide arg1 = TTL */ - public static final int CALLBACK_LOSING = BASE + 3; + public static final int CALLBACK_LOSING = 3; /** @hide */ - public static final int CALLBACK_LOST = BASE + 4; + public static final int CALLBACK_LOST = 4; /** @hide */ - public static final int CALLBACK_UNAVAIL = BASE + 5; + public static final int CALLBACK_UNAVAIL = 5; /** @hide */ - public static final int CALLBACK_CAP_CHANGED = BASE + 6; + public static final int CALLBACK_CAP_CHANGED = 6; /** @hide */ - public static final int CALLBACK_IP_CHANGED = BASE + 7; + public static final int CALLBACK_IP_CHANGED = 7; /** @hide obj = NetworkCapabilities, arg1 = seq number */ - private static final int EXPIRE_LEGACY_REQUEST = BASE + 8; + private static final int EXPIRE_LEGACY_REQUEST = 8; /** @hide */ - public static final int CALLBACK_SUSPENDED = BASE + 9; + public static final int CALLBACK_SUSPENDED = 9; /** @hide */ - public static final int CALLBACK_RESUMED = BASE + 10; + public static final int CALLBACK_RESUMED = 10; /** @hide */ - public static final int CALLBACK_BLK_CHANGED = BASE + 11; + public static final int CALLBACK_BLK_CHANGED = 11; /** @hide */ public static String getCallbackName(int whichCallback) { @@ -4249,15 +4267,33 @@ public class ConnectivityManager { } /** - * @hide + * Registers to receive notifications about the best matching network which satisfy the given + * {@link NetworkRequest}. The callbacks will continue to be called until + * either the application exits or {@link #unregisterNetworkCallback(NetworkCallback)} is + * called. + * + * <p>To avoid performance issues due to apps leaking callbacks, the system will limit the + * number of outstanding requests to 100 per app (identified by their UID), shared with + * {@link #registerNetworkCallback} and its variants and {@link #requestNetwork} as well as + * {@link ConnectivityDiagnosticsManager#registerConnectivityDiagnosticsCallback}. + * Requesting a network with this method will count toward this limit. If this limit is + * exceeded, an exception will be thrown. To avoid hitting this issue and to conserve resources, + * make sure to unregister the callbacks with + * {@link #unregisterNetworkCallback(NetworkCallback)}. + * + * + * @param request {@link NetworkRequest} describing this request. + * @param networkCallback The {@link NetworkCallback} that the system will call as suitable + * networks change state. + * @param handler {@link Handler} to specify the thread upon which the callback will be invoked. + * @throws RuntimeException if the app already has too many callbacks registered. */ - // TODO: Make it public api. @SuppressLint("ExecutorRegistration") public void registerBestMatchingNetworkCallback(@NonNull NetworkRequest request, @NonNull NetworkCallback networkCallback, @NonNull Handler handler) { final NetworkCapabilities nc = request.networkCapabilities; final CallbackHandler cbHandler = new CallbackHandler(handler); - sendRequestForNetwork(nc, networkCallback, 0, TRACK_BEST, TYPE_NONE, cbHandler); + sendRequestForNetwork(nc, networkCallback, 0, LISTEN_FOR_BEST, TYPE_NONE, cbHandler); } /** @@ -4352,8 +4388,13 @@ public class ConnectivityManager { * * @hide */ - @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) - public void setAcceptUnvalidated(Network network, boolean accept, boolean always) { + @SystemApi(client = MODULE_LIBRARIES) + @RequiresPermission(anyOf = { + android.Manifest.permission.NETWORK_SETTINGS, + android.Manifest.permission.NETWORK_SETUP_WIZARD, + android.Manifest.permission.NETWORK_STACK, + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) + public void setAcceptUnvalidated(@NonNull Network network, boolean accept, boolean always) { try { mService.setAcceptUnvalidated(network, accept, always); } catch (RemoteException e) { @@ -4375,8 +4416,14 @@ public class ConnectivityManager { * * @hide */ - @RequiresPermission(android.Manifest.permission.NETWORK_STACK) - public void setAcceptPartialConnectivity(Network network, boolean accept, boolean always) { + @SystemApi(client = MODULE_LIBRARIES) + @RequiresPermission(anyOf = { + android.Manifest.permission.NETWORK_SETTINGS, + android.Manifest.permission.NETWORK_SETUP_WIZARD, + android.Manifest.permission.NETWORK_STACK, + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) + public void setAcceptPartialConnectivity(@NonNull Network network, boolean accept, + boolean always) { try { mService.setAcceptPartialConnectivity(network, accept, always); } catch (RemoteException e) { @@ -4394,8 +4441,13 @@ public class ConnectivityManager { * * @hide */ - @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) - public void setAvoidUnvalidated(Network network) { + @SystemApi(client = MODULE_LIBRARIES) + @RequiresPermission(anyOf = { + android.Manifest.permission.NETWORK_SETTINGS, + android.Manifest.permission.NETWORK_SETUP_WIZARD, + android.Manifest.permission.NETWORK_STACK, + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) + public void setAvoidUnvalidated(@NonNull Network network) { try { mService.setAvoidUnvalidated(network); } catch (RemoteException e) { @@ -4406,12 +4458,20 @@ public class ConnectivityManager { /** * Requests that the system open the captive portal app on the specified network. * + * <p>This is to be used on networks where a captive portal was detected, as per + * {@link NetworkCapabilities#NET_CAPABILITY_CAPTIVE_PORTAL}. + * * @param network The network to log into. * * @hide */ - @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) - public void startCaptivePortalApp(Network network) { + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + @RequiresPermission(anyOf = { + android.Manifest.permission.NETWORK_SETTINGS, + android.Manifest.permission.NETWORK_STACK, + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK + }) + public void startCaptivePortalApp(@NonNull Network network) { try { mService.startCaptivePortalApp(network); } catch (RemoteException e) { @@ -4525,7 +4585,10 @@ public class ConnectivityManager { * Resets all connectivity manager settings back to factory defaults. * @hide */ - @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) + @SystemApi(client = MODULE_LIBRARIES) + @RequiresPermission(anyOf = { + android.Manifest.permission.NETWORK_SETTINGS, + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void factoryReset() { try { mService.factoryReset(); @@ -4603,7 +4666,7 @@ public class ConnectivityManager { Log.e(TAG, "Can't set proxy properties", e); } // Must flush DNS cache as new network may have different DNS resolutions. - InetAddress.clearDnsCache(); + InetAddressCompat.clearDnsCache(); // Must flush socket pool as idle sockets will be bound to previous network and may // cause subsequent fetches to be performed on old network. NetworkEventDispatcher.getInstance().onNetworkConfigurationChanged(); @@ -4728,17 +4791,6 @@ public class ConnectivityManager { public @interface RestrictBackgroundStatus { } - private INetworkPolicyManager getNetworkPolicyManager() { - synchronized (this) { - if (mNPManager != null) { - return mNPManager; - } - mNPManager = INetworkPolicyManager.Stub.asInterface(ServiceManager - .getService(Context.NETWORK_POLICY_SERVICE)); - return mNPManager; - } - } - /** * Determines if the calling application is subject to metered network restrictions while * running on background. @@ -4749,7 +4801,7 @@ public class ConnectivityManager { */ public @RestrictBackgroundStatus int getRestrictBackgroundStatus() { try { - return getNetworkPolicyManager().getRestrictBackgroundByCaller(); + return mService.getRestrictBackgroundStatusByCaller(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -4879,20 +4931,20 @@ public class ConnectivityManager { * {@link QosCallback#onError(QosCallbackException)}. see: {@link QosCallbackException}. * * @param socketInfo the socket information used to match QoS events - * @param callback receives qos events that satisfy socketInfo * @param executor The executor on which the callback will be invoked. The provided * {@link Executor} must run callback sequentially, otherwise the order of - * callbacks cannot be guaranteed. + * callbacks cannot be guaranteed.onQosCallbackRegistered + * @param callback receives qos events that satisfy socketInfo * * @hide */ @SystemApi public void registerQosCallback(@NonNull final QosSocketInfo socketInfo, - @NonNull final QosCallback callback, - @CallbackExecutor @NonNull final Executor executor) { + @CallbackExecutor @NonNull final Executor executor, + @NonNull final QosCallback callback) { Objects.requireNonNull(socketInfo, "socketInfo must be non-null"); - Objects.requireNonNull(callback, "callback must be non-null"); Objects.requireNonNull(executor, "executor must be non-null"); + Objects.requireNonNull(callback, "callback must be non-null"); try { synchronized (mQosCallbackConnections) { @@ -5057,19 +5109,6 @@ public class ConnectivityManager { } /** - * Listener for {@link #setOemNetworkPreference(OemNetworkPreferences, Executor, - * OnSetOemNetworkPreferenceListener)}. - * @hide - */ - @SystemApi - public interface OnSetOemNetworkPreferenceListener { - /** - * Called when setOemNetworkPreference() successfully completes. - */ - void onComplete(); - } - - /** * Used by automotive devices to set the network preferences used to direct traffic at an * application level as per the given OemNetworkPreferences. An example use-case would be an * automotive OEM wanting to provide connectivity for applications critical to the usage of a @@ -5091,16 +5130,16 @@ public class ConnectivityManager { @RequiresPermission(android.Manifest.permission.CONTROL_OEM_PAID_NETWORK_PREFERENCE) public void setOemNetworkPreference(@NonNull final OemNetworkPreferences preference, @Nullable @CallbackExecutor final Executor executor, - @Nullable final OnSetOemNetworkPreferenceListener listener) { + @Nullable final Runnable listener) { Objects.requireNonNull(preference, "OemNetworkPreferences must be non-null"); if (null != listener) { Objects.requireNonNull(executor, "Executor must be non-null"); } - final IOnSetOemNetworkPreferenceListener listenerInternal = listener == null ? null : - new IOnSetOemNetworkPreferenceListener.Stub() { + final IOnCompleteListener listenerInternal = listener == null ? null : + new IOnCompleteListener.Stub() { @Override public void onComplete() { - executor.execute(listener::onComplete); + executor.execute(listener::run); } }; @@ -5112,10 +5151,56 @@ public class ConnectivityManager { } } + /** + * Request that a user profile is put by default on a network matching a given preference. + * + * See the documentation for the individual preferences for a description of the supported + * behaviors. + * + * @param profile the profile concerned. + * @param preference the preference for this profile. + * @param executor an executor to execute the listener on. Optional if listener is null. + * @param listener an optional listener to listen for completion of the operation. + * @throws IllegalArgumentException if {@code profile} is not a valid user profile. + * @throws SecurityException if missing the appropriate permissions. + * @hide + */ + // This function is for establishing per-profile default networking and can only be called by + // the device policy manager, running as the system server. It would make no sense to call it + // on a context for a user because it does not establish a setting on behalf of a user, rather + // it establishes a setting for a user on behalf of the DPM. + @SuppressLint({"UserHandle"}) + @SystemApi(client = MODULE_LIBRARIES) + @RequiresPermission(android.Manifest.permission.NETWORK_STACK) + public void setProfileNetworkPreference(@NonNull final UserHandle profile, + @ProfileNetworkPreference final int preference, + @Nullable @CallbackExecutor final Executor executor, + @Nullable final Runnable listener) { + if (null != listener) { + Objects.requireNonNull(executor, "Pass a non-null executor, or a null listener"); + } + final IOnCompleteListener proxy; + if (null == listener) { + proxy = null; + } else { + proxy = new IOnCompleteListener.Stub() { + @Override + public void onComplete() { + executor.execute(listener::run); + } + }; + } + try { + mService.setProfileNetworkPreference(profile, preference, proxy); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + // The first network ID of IPSec tunnel interface. - private static final int TUN_INTF_NETID_START = 0xFC00; + private static final int TUN_INTF_NETID_START = 0xFC00; // 0xFC00 = 64512 // The network ID range of IPSec tunnel interface. - private static final int TUN_INTF_NETID_RANGE = 0x0400; + private static final int TUN_INTF_NETID_RANGE = 0x0400; // 0x0400 = 1024 /** * Get the network ID range reserved for IPSec tunnel interfaces. @@ -5128,4 +5213,25 @@ public class ConnectivityManager { public static Range<Integer> getIpSecNetIdRange() { return new Range(TUN_INTF_NETID_START, TUN_INTF_NETID_START + TUN_INTF_NETID_RANGE - 1); } + + /** + * Get private DNS mode from settings. + * + * @param context The Context to query the private DNS mode from settings. + * @return A string of private DNS mode as one of the PRIVATE_DNS_MODE_* constants. + * + * @hide + */ + @SystemApi(client = MODULE_LIBRARIES) + @NonNull + @PrivateDnsMode + public static String getPrivateDnsMode(@NonNull Context context) { + final ContentResolver cr = context.getContentResolver(); + String mode = Settings.Global.getString(cr, PRIVATE_DNS_MODE); + if (TextUtils.isEmpty(mode)) mode = Settings.Global.getString(cr, PRIVATE_DNS_DEFAULT_MODE); + // If both PRIVATE_DNS_MODE and PRIVATE_DNS_DEFAULT_MODE are not set, choose + // PRIVATE_DNS_MODE_OPPORTUNISTIC as default mode. + if (TextUtils.isEmpty(mode)) mode = PRIVATE_DNS_MODE_OPPORTUNISTIC; + return mode; + } } diff --git a/packages/Connectivity/framework/src/android/net/ConnectivityResources.java b/packages/Connectivity/framework/src/android/net/ConnectivityResources.java new file mode 100644 index 000000000000..18f0de0cc9a1 --- /dev/null +++ b/packages/Connectivity/framework/src/android/net/ConnectivityResources.java @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2021 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.content.pm.PackageManager.MATCH_SYSTEM_ONLY; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.content.res.Resources; +import android.util.Log; + +import com.android.internal.annotations.VisibleForTesting; + +import java.util.List; + +/** + * Utility to obtain the {@link com.android.server.ConnectivityService} {@link Resources}, in the + * ServiceConnectivityResources APK. + * @hide + */ +public class ConnectivityResources { + private static final String RESOURCES_APK_INTENT = + "com.android.server.connectivity.intent.action.SERVICE_CONNECTIVITY_RESOURCES_APK"; + private static final String RES_PKG_DIR = "/apex/com.android.tethering/"; + + @NonNull + private final Context mContext; + + @Nullable + private Context mResourcesContext = null; + + @Nullable + private static Context sTestResourcesContext = null; + + public ConnectivityResources(Context context) { + mContext = context; + } + + /** + * Convenience method to mock all resources for the duration of a test. + * + * Call with a null context to reset after the test. + */ + @VisibleForTesting + public static void setResourcesContextForTest(@Nullable Context testContext) { + sTestResourcesContext = testContext; + } + + /** + * Get the {@link Context} of the resources package. + */ + public synchronized Context getResourcesContext() { + if (sTestResourcesContext != null) { + return sTestResourcesContext; + } + + if (mResourcesContext != null) { + return mResourcesContext; + } + + final List<ResolveInfo> pkgs = mContext.getPackageManager() + .queryIntentActivities(new Intent(RESOURCES_APK_INTENT), MATCH_SYSTEM_ONLY); + pkgs.removeIf(pkg -> !pkg.activityInfo.applicationInfo.sourceDir.startsWith(RES_PKG_DIR)); + if (pkgs.size() > 1) { + Log.wtf(ConnectivityResources.class.getSimpleName(), + "More than one package found: " + pkgs); + } + if (pkgs.isEmpty()) { + throw new IllegalStateException("No connectivity resource package found"); + } + + final Context pkgContext; + try { + pkgContext = mContext.createPackageContext( + pkgs.get(0).activityInfo.applicationInfo.packageName, 0 /* flags */); + } catch (PackageManager.NameNotFoundException e) { + throw new IllegalStateException("Resolved package not found", e); + } + + mResourcesContext = pkgContext; + return pkgContext; + } + + /** + * Get the {@link Resources} of the ServiceConnectivityResources APK. + */ + public Resources get() { + return getResourcesContext().getResources(); + } +} diff --git a/packages/Connectivity/framework/src/android/net/ConnectivitySettingsManager.java b/packages/Connectivity/framework/src/android/net/ConnectivitySettingsManager.java new file mode 100644 index 000000000000..bbd83931ee0d --- /dev/null +++ b/packages/Connectivity/framework/src/android/net/ConnectivitySettingsManager.java @@ -0,0 +1,241 @@ +/* + * Copyright (C) 2021 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.annotation.IntDef; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * A manager class for connectivity module settings. + * + * @hide + */ +public class ConnectivitySettingsManager { + + private ConnectivitySettingsManager() {} + + /** Data activity timeout settings */ + + /** + * Inactivity timeout to track mobile data activity. + * + * If set to a positive integer, it indicates the inactivity timeout value in seconds to + * infer the data activity of mobile network. After a period of no activity on mobile + * networks with length specified by the timeout, an {@code ACTION_DATA_ACTIVITY_CHANGE} + * intent is fired to indicate a transition of network status from "active" to "idle". Any + * subsequent activity on mobile networks triggers the firing of {@code + * ACTION_DATA_ACTIVITY_CHANGE} intent indicating transition from "idle" to "active". + * + * Network activity refers to transmitting or receiving data on the network interfaces. + * + * Tracking is disabled if set to zero or negative value. + */ + public static final String DATA_ACTIVITY_TIMEOUT_MOBILE = "data_activity_timeout_mobile"; + + /** + * Timeout to tracking Wifi data activity. Same as {@code DATA_ACTIVITY_TIMEOUT_MOBILE} + * but for Wifi network. + */ + public static final String DATA_ACTIVITY_TIMEOUT_WIFI = "data_activity_timeout_wifi"; + + /** Dns resolver settings */ + + /** + * Sample validity in seconds to configure for the system DNS resolver. + */ + public static final String DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS = + "dns_resolver_sample_validity_seconds"; + + /** + * Success threshold in percent for use with the system DNS resolver. + */ + public static final String DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT = + "dns_resolver_success_threshold_percent"; + + /** + * Minimum number of samples needed for statistics to be considered meaningful in the + * system DNS resolver. + */ + public static final String DNS_RESOLVER_MIN_SAMPLES = "dns_resolver_min_samples"; + + /** + * Maximum number taken into account for statistics purposes in the system DNS resolver. + */ + public static final String DNS_RESOLVER_MAX_SAMPLES = "dns_resolver_max_samples"; + + /** Network switch notification settings */ + + /** + * The maximum number of notifications shown in 24 hours when switching networks. + */ + public static final String NETWORK_SWITCH_NOTIFICATION_DAILY_LIMIT = + "network_switch_notification_daily_limit"; + + /** + * The minimum time in milliseconds between notifications when switching networks. + */ + public static final String NETWORK_SWITCH_NOTIFICATION_RATE_LIMIT_MILLIS = + "network_switch_notification_rate_limit_millis"; + + /** Captive portal settings */ + + /** + * The URL used for HTTP captive portal detection upon a new connection. + * A 204 response code from the server is used for validation. + */ + public static final String CAPTIVE_PORTAL_HTTP_URL = "captive_portal_http_url"; + + /** + * What to do when connecting a network that presents a captive portal. + * Must be one of the CAPTIVE_PORTAL_MODE_* constants above. + * + * The default for this setting is CAPTIVE_PORTAL_MODE_PROMPT. + */ + public static final String CAPTIVE_PORTAL_MODE = "captive_portal_mode"; + + /** + * Don't attempt to detect captive portals. + */ + public static final int CAPTIVE_PORTAL_MODE_IGNORE = 0; + + /** + * When detecting a captive portal, display a notification that + * prompts the user to sign in. + */ + public static final int CAPTIVE_PORTAL_MODE_PROMPT = 1; + + /** + * When detecting a captive portal, immediately disconnect from the + * network and do not reconnect to that network in the future. + */ + public static final int CAPTIVE_PORTAL_MODE_AVOID = 2; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = { + CAPTIVE_PORTAL_MODE_IGNORE, + CAPTIVE_PORTAL_MODE_PROMPT, + CAPTIVE_PORTAL_MODE_AVOID, + }) + public @interface CaptivePortalMode {} + + /** Global http proxy settings */ + + /** + * Host name for global http proxy. Set via ConnectivityManager. + */ + public static final String GLOBAL_HTTP_PROXY_HOST = "global_http_proxy_host"; + + /** + * Integer host port for global http proxy. Set via ConnectivityManager. + */ + public static final String GLOBAL_HTTP_PROXY_PORT = "global_http_proxy_port"; + + /** + * Exclusion list for global proxy. This string contains a list of + * comma-separated domains where the global proxy does not apply. + * Domains should be listed in a comma- separated list. Example of + * acceptable formats: ".domain1.com,my.domain2.com" Use + * ConnectivityManager to set/get. + */ + public static final String GLOBAL_HTTP_PROXY_EXCLUSION_LIST = + "global_http_proxy_exclusion_list"; + + /** + * The location PAC File for the proxy. + */ + public static final String GLOBAL_HTTP_PROXY_PAC = "global_proxy_pac_url"; + + /** Private dns settings */ + + /** + * The requested Private DNS mode (string), and an accompanying specifier (string). + * + * Currently, the specifier holds the chosen provider name when the mode requests + * a specific provider. It may be used to store the provider name even when the + * mode changes so that temporarily disabling and re-enabling the specific + * provider mode does not necessitate retyping the provider hostname. + */ + public static final String PRIVATE_DNS_MODE = "private_dns_mode"; + + /** + * The specific Private DNS provider name. + */ + public static final String PRIVATE_DNS_SPECIFIER = "private_dns_specifier"; + + /** + * Forced override of the default mode (hardcoded as "automatic", nee "opportunistic"). + * This allows changing the default mode without effectively disabling other modes, + * all of which require explicit user action to enable/configure. See also b/79719289. + * + * Value is a string, suitable for assignment to PRIVATE_DNS_MODE above. + */ + public static final String PRIVATE_DNS_DEFAULT_MODE = "private_dns_default_mode"; + + /** Other settings */ + + /** + * The number of milliseconds to hold on to a PendingIntent based request. This delay gives + * the receivers of the PendingIntent an opportunity to make a new network request before + * the Network satisfying the request is potentially removed. + */ + public static final String CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS = + "connectivity_release_pending_intent_delay_ms"; + + /** + * Whether the mobile data connection should remain active even when higher + * priority networks like WiFi are active, to help make network switching faster. + * + * See ConnectivityService for more info. + * + * (0 = disabled, 1 = enabled) + */ + public static final String MOBILE_DATA_ALWAYS_ON = "mobile_data_always_on"; + + /** + * Whether the wifi data connection should remain active even when higher + * priority networks like Ethernet are active, to keep both networks. + * In the case where higher priority networks are connected, wifi will be + * unused unless an application explicitly requests to use it. + * + * See ConnectivityService for more info. + * + * (0 = disabled, 1 = enabled) + */ + public static final String WIFI_ALWAYS_REQUESTED = "wifi_always_requested"; + + /** + * Whether to automatically switch away from wifi networks that lose Internet access. + * Only meaningful if config_networkAvoidBadWifi is set to 0, otherwise the system always + * avoids such networks. Valid values are: + * + * 0: Don't avoid bad wifi, don't prompt the user. Get stuck on bad wifi like it's 2013. + * null: Ask the user whether to switch away from bad wifi. + * 1: Avoid bad wifi. + */ + public static final String NETWORK_AVOID_BAD_WIFI = "network_avoid_bad_wifi"; + + /** + * User setting for ConnectivityManager.getMeteredMultipathPreference(). This value may be + * overridden by the system based on device or application state. If null, the value + * specified by config_networkMeteredMultipathPreference is used. + */ + public static final String NETWORK_METERED_MULTIPATH_PREFERENCE = + "network_metered_multipath_preference"; +} diff --git a/packages/Connectivity/framework/src/android/net/IConnectivityManager.aidl b/packages/Connectivity/framework/src/android/net/IConnectivityManager.aidl index f9393e315b83..3300fa8fd12a 100644 --- a/packages/Connectivity/framework/src/android/net/IConnectivityManager.aidl +++ b/packages/Connectivity/framework/src/android/net/IConnectivityManager.aidl @@ -20,7 +20,8 @@ import android.app.PendingIntent; import android.net.ConnectionInfo; import android.net.ConnectivityDiagnosticsManager; import android.net.IConnectivityDiagnosticsCallback; -import android.net.IOnSetOemNetworkPreferenceListener; +import android.net.INetworkAgent; +import android.net.IOnCompleteListener; import android.net.INetworkActivityListener; import android.net.IQosCallback; import android.net.ISocketKeepaliveCallback; @@ -30,6 +31,7 @@ import android.net.NetworkAgentConfig; import android.net.NetworkCapabilities; import android.net.NetworkInfo; import android.net.NetworkRequest; +import android.net.NetworkScore; import android.net.NetworkState; import android.net.NetworkStateSnapshot; import android.net.OemNetworkPreferences; @@ -42,8 +44,7 @@ import android.os.Messenger; import android.os.ParcelFileDescriptor; import android.os.PersistableBundle; import android.os.ResultReceiver; - -import com.android.connectivity.aidl.INetworkAgent; +import android.os.UserHandle; /** * Interface that answers queries about, and allows changing, the @@ -138,7 +139,7 @@ interface IConnectivityManager void declareNetworkRequestUnfulfillable(in NetworkRequest request); Network registerNetworkAgent(in INetworkAgent na, in NetworkInfo ni, in LinkProperties lp, - in NetworkCapabilities nc, int score, in NetworkAgentConfig config, + in NetworkCapabilities nc, in NetworkScore score, in NetworkAgentConfig config, in int factorySerialNumber); NetworkRequest requestNetwork(in NetworkCapabilities networkCapabilities, int reqType, @@ -214,5 +215,10 @@ interface IConnectivityManager void unregisterQosCallback(in IQosCallback callback); void setOemNetworkPreference(in OemNetworkPreferences preference, - in IOnSetOemNetworkPreferenceListener listener); + in IOnCompleteListener listener); + + void setProfileNetworkPreference(in UserHandle profile, int preference, + in IOnCompleteListener listener); + + int getRestrictBackgroundStatusByCaller(); } diff --git a/packages/Connectivity/framework/src/com/android/connectivity/aidl/INetworkAgent.aidl b/packages/Connectivity/framework/src/android/net/INetworkAgent.aidl index 64b556720cd2..1f66e18717d8 100644 --- a/packages/Connectivity/framework/src/com/android/connectivity/aidl/INetworkAgent.aidl +++ b/packages/Connectivity/framework/src/android/net/INetworkAgent.aidl @@ -13,13 +13,13 @@ * See the License for the specific language governing perNmissions and * limitations under the License. */ -package com.android.connectivity.aidl; +package android.net; import android.net.NattKeepalivePacketData; import android.net.QosFilterParcelable; import android.net.TcpKeepalivePacketData; -import com.android.connectivity.aidl.INetworkAgentRegistry; +import android.net.INetworkAgentRegistry; /** * Interface to notify NetworkAgent of connectivity events. diff --git a/packages/Connectivity/framework/src/com/android/connectivity/aidl/INetworkAgentRegistry.aidl b/packages/Connectivity/framework/src/android/net/INetworkAgentRegistry.aidl index f0193db5c2e2..c5464d32412b 100644 --- a/packages/Connectivity/framework/src/com/android/connectivity/aidl/INetworkAgentRegistry.aidl +++ b/packages/Connectivity/framework/src/android/net/INetworkAgentRegistry.aidl @@ -13,17 +13,18 @@ * See the License for the specific language governing perNmissions and * limitations under the License. */ -package com.android.connectivity.aidl; +package android.net; import android.net.LinkProperties; import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkInfo; +import android.net.NetworkScore; import android.net.QosSession; import android.telephony.data.EpsBearerQosSessionAttributes; /** - * Interface for NetworkAgents to send network network properties. + * Interface for NetworkAgents to send network properties. * @hide */ oneway interface INetworkAgentRegistry { @@ -31,7 +32,7 @@ oneway interface INetworkAgentRegistry { void sendLinkProperties(in LinkProperties lp); // TODO: consider replacing this by "markConnected()" and removing void sendNetworkInfo(in NetworkInfo info); - void sendScore(int score); + void sendScore(in NetworkScore score); void sendExplicitlySelected(boolean explicitlySelected, boolean acceptPartial); void sendSocketKeepaliveEvent(int slot, int reason); void sendUnderlyingNetworks(in @nullable List<Network> networks); diff --git a/packages/Connectivity/framework/src/android/net/IOnSetOemNetworkPreferenceListener.aidl b/packages/Connectivity/framework/src/android/net/IOnCompleteListener.aidl index 7979afc54f90..4bb89f6c89e4 100644 --- a/packages/Connectivity/framework/src/android/net/IOnSetOemNetworkPreferenceListener.aidl +++ b/packages/Connectivity/framework/src/android/net/IOnCompleteListener.aidl @@ -18,6 +18,6 @@ package android.net; /** @hide */ -oneway interface IOnSetOemNetworkPreferenceListener { +oneway interface IOnCompleteListener { void onComplete(); } diff --git a/packages/Connectivity/framework/src/android/net/InetAddressCompat.java b/packages/Connectivity/framework/src/android/net/InetAddressCompat.java new file mode 100644 index 000000000000..6b7e75c75359 --- /dev/null +++ b/packages/Connectivity/framework/src/android/net/InetAddressCompat.java @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2021 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.util.Log; + +import java.lang.reflect.InvocationTargetException; +import java.net.InetAddress; +import java.net.UnknownHostException; + +/** + * Compatibility utility for InetAddress core platform APIs. + * + * Connectivity has access to such APIs, but they are not part of the module_current stubs yet + * (only core_current). Most stable core platform APIs are included manually in the connectivity + * build rules, but because InetAddress is also part of the base java SDK that is earlier on the + * classpath, the extra core platform APIs are not seen. + * + * TODO (b/183097033): remove this utility as soon as core_current is part of module_current + * @hide + */ +public class InetAddressCompat { + + /** + * @see InetAddress#clearDnsCache() + */ + public static void clearDnsCache() { + try { + InetAddress.class.getMethod("clearDnsCache").invoke(null); + } catch (InvocationTargetException e) { + if (e.getCause() instanceof RuntimeException) { + throw (RuntimeException) e.getCause(); + } + throw new IllegalStateException("Unknown InvocationTargetException", e.getCause()); + } catch (IllegalAccessException | NoSuchMethodException e) { + Log.wtf(InetAddressCompat.class.getSimpleName(), "Error clearing DNS cache", e); + } + } + + /** + * @see InetAddress#getAllByNameOnNet(String, int) + */ + public static InetAddress[] getAllByNameOnNet(String host, int netId) throws + UnknownHostException { + return (InetAddress[]) callGetByNameMethod("getAllByNameOnNet", host, netId); + } + + /** + * @see InetAddress#getByNameOnNet(String, int) + */ + public static InetAddress getByNameOnNet(String host, int netId) throws + UnknownHostException { + return (InetAddress) callGetByNameMethod("getByNameOnNet", host, netId); + } + + private static Object callGetByNameMethod(String method, String host, int netId) + throws UnknownHostException { + try { + return InetAddress.class.getMethod(method, String.class, int.class) + .invoke(null, host, netId); + } catch (InvocationTargetException e) { + if (e.getCause() instanceof UnknownHostException) { + throw (UnknownHostException) e.getCause(); + } + if (e.getCause() instanceof RuntimeException) { + throw (RuntimeException) e.getCause(); + } + throw new IllegalStateException("Unknown InvocationTargetException", e.getCause()); + } catch (IllegalAccessException | NoSuchMethodException e) { + Log.wtf(InetAddressCompat.class.getSimpleName(), "Error calling " + method, e); + throw new IllegalStateException("Error querying via " + method, e); + } + } +} diff --git a/packages/Connectivity/framework/src/android/net/Network.java b/packages/Connectivity/framework/src/android/net/Network.java index 46141e0d0c1e..0741414ab3aa 100644 --- a/packages/Connectivity/framework/src/android/net/Network.java +++ b/packages/Connectivity/framework/src/android/net/Network.java @@ -30,10 +30,10 @@ 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; import libcore.io.IoUtils; +import libcore.net.http.Dns; +import libcore.net.http.HttpURLConnectionFactory; import java.io.FileDescriptor; import java.io.IOException; @@ -142,7 +142,7 @@ public class Network implements Parcelable { * @throws UnknownHostException if the address lookup fails. */ public InetAddress[] getAllByName(String host) throws UnknownHostException { - return InetAddress.getAllByNameOnNet(host, getNetIdForResolv()); + return InetAddressCompat.getAllByNameOnNet(host, getNetIdForResolv()); } /** @@ -155,7 +155,7 @@ public class Network implements Parcelable { * if the address lookup fails. */ public InetAddress getByName(String host) throws UnknownHostException { - return InetAddress.getByNameOnNet(host, getNetIdForResolv()); + return InetAddressCompat.getByNameOnNet(host, getNetIdForResolv()); } /** @@ -299,7 +299,7 @@ public class Network implements Parcelable { // 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(); + HttpURLConnectionFactory urlConnectionFactory = HttpURLConnectionFactory.createInstance(); urlConnectionFactory.setDns(dnsLookup); // Let traffic go via dnsLookup // A private connection pool just for this Network. urlConnectionFactory.setNewConnectionPool(httpMaxConnections, diff --git a/packages/Connectivity/framework/src/android/net/NetworkAgent.java b/packages/Connectivity/framework/src/android/net/NetworkAgent.java index 27aa15d1e1e4..3863ed1113f3 100644 --- a/packages/Connectivity/framework/src/android/net/NetworkAgent.java +++ b/packages/Connectivity/framework/src/android/net/NetworkAgent.java @@ -34,10 +34,7 @@ import android.os.RemoteException; import android.telephony.data.EpsBearerQosSessionAttributes; import android.util.Log; -import com.android.connectivity.aidl.INetworkAgent; -import com.android.connectivity.aidl.INetworkAgentRegistry; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.Protocol; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -125,7 +122,10 @@ public abstract class NetworkAgent { */ public final int providerId; - private static final int BASE = Protocol.BASE_NETWORK_AGENT; + // ConnectivityService parses message constants from itself and NetworkAgent with MessageUtils + // for debugging purposes, and crashes if some messages have the same values. + // TODO: have ConnectivityService store message names in different maps and remove this base + private static final int BASE = 200; /** * Sent by ConnectivityService to the NetworkAgent to inform it of @@ -371,6 +371,14 @@ public abstract class NetworkAgent { return ni; } + // Temporary backward compatibility constructor + public NetworkAgent(@NonNull Context context, @NonNull Looper looper, @NonNull String logTag, + @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, int score, + @NonNull NetworkAgentConfig config, @Nullable NetworkProvider provider) { + this(context, looper, logTag, nc, lp, + new NetworkScore.Builder().setLegacyInt(score).build(), config, provider); + } + /** * Create a new network agent. * @param context a {@link Context} to get system services from. @@ -382,10 +390,12 @@ public abstract class NetworkAgent { * @param score the initial score of this network. Update with sendNetworkScore. * @param config an immutable {@link NetworkAgentConfig} for this agent. * @param provider the {@link NetworkProvider} managing this agent. + * @hide TODO : unhide when impl is complete */ public NetworkAgent(@NonNull Context context, @NonNull Looper looper, @NonNull String logTag, - @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, int score, - @NonNull NetworkAgentConfig config, @Nullable NetworkProvider provider) { + @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, + @NonNull NetworkScore score, @NonNull NetworkAgentConfig config, + @Nullable NetworkProvider provider) { this(looper, context, logTag, nc, lp, score, config, provider == null ? NetworkProvider.ID_NONE : provider.getProviderId(), getLegacyNetworkInfo(config)); @@ -395,12 +405,12 @@ public abstract class NetworkAgent { public final Context context; public final NetworkCapabilities capabilities; public final LinkProperties properties; - public final int score; + public final NetworkScore score; public final NetworkAgentConfig config; public final NetworkInfo info; InitialConfiguration(@NonNull Context context, @NonNull NetworkCapabilities capabilities, - @NonNull LinkProperties properties, int score, @NonNull NetworkAgentConfig config, - @NonNull NetworkInfo info) { + @NonNull LinkProperties properties, @NonNull NetworkScore score, + @NonNull NetworkAgentConfig config, @NonNull NetworkInfo info) { this.context = context; this.capabilities = capabilities; this.properties = properties; @@ -412,8 +422,9 @@ public abstract class NetworkAgent { private volatile InitialConfiguration mInitialConfiguration; private NetworkAgent(@NonNull Looper looper, @NonNull Context context, @NonNull String logTag, - @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, int score, - @NonNull NetworkAgentConfig config, int providerId, @NonNull NetworkInfo ni) { + @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, + @NonNull NetworkScore score, @NonNull NetworkAgentConfig config, int providerId, + @NonNull NetworkInfo ni) { mHandler = new NetworkAgentHandler(looper); LOG_TAG = logTag; mNetworkInfo = new NetworkInfo(ni); @@ -423,7 +434,7 @@ public abstract class NetworkAgent { } mInitialConfiguration = new InitialConfiguration(context, - new NetworkCapabilities(nc, /* parcelLocationSensitiveFields */ true), + new NetworkCapabilities(nc, NetworkCapabilities.REDACT_NONE), new LinkProperties(lp), score, config, ni); } @@ -867,21 +878,29 @@ public abstract class NetworkAgent { mBandwidthUpdatePending.set(false); mLastBwRefreshTime = System.currentTimeMillis(); final NetworkCapabilities nc = - new NetworkCapabilities(networkCapabilities, - /* parcelLocationSensitiveFields */ true); + new NetworkCapabilities(networkCapabilities, NetworkCapabilities.REDACT_NONE); queueOrSendMessage(reg -> reg.sendNetworkCapabilities(nc)); } /** * Must be called by the agent to update the score of this network. * + * @param score the new score. + * @hide TODO : unhide when impl is complete + */ + public final void sendNetworkScore(@NonNull NetworkScore score) { + Objects.requireNonNull(score); + queueOrSendMessage(reg -> reg.sendScore(score)); + } + + /** + * Must be called by the agent to update the score of this network. + * * @param score the new score, between 0 and 99. + * deprecated use sendNetworkScore(NetworkScore) TODO : remove in S. */ public final void sendNetworkScore(@IntRange(from = 0, to = 99) int score) { - if (score < 0) { - throw new IllegalArgumentException("Score must be >= 0"); - } - queueOrSendMessage(reg -> reg.sendScore(score)); + sendNetworkScore(new NetworkScore.Builder().setLegacyInt(score).build()); } /** diff --git a/packages/Connectivity/framework/src/android/net/NetworkAgentConfig.java b/packages/Connectivity/framework/src/android/net/NetworkAgentConfig.java index 664c2650ff0c..5e50a6404acb 100644 --- a/packages/Connectivity/framework/src/android/net/NetworkAgentConfig.java +++ b/packages/Connectivity/framework/src/android/net/NetworkAgentConfig.java @@ -50,7 +50,8 @@ public final class NetworkAgentConfig implements Parcelable { * ap in the wifi settings to trigger a connection is explicit. A 3rd party app asking to * connect to a particular access point is also explicit, though this may change in the future * as we want apps to use the multinetwork apis. - * + * TODO : this is a bad name, because it sounds like the user just tapped on the network. + * It's not necessarily the case ; auto-reconnection to WiFi has this true for example. * @hide */ public boolean explicitlySelected; diff --git a/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java b/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java index 058f3c999dd7..790d52d54e48 100644 --- a/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java +++ b/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java @@ -19,9 +19,11 @@ package android.net; import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE; import android.annotation.IntDef; +import android.annotation.LongDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; +import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; import android.net.ConnectivityManager.NetworkCallback; @@ -32,6 +34,7 @@ import android.os.Parcelable; import android.os.Process; import android.text.TextUtils; import android.util.ArraySet; +import android.util.Range; import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.VisibleForTesting; @@ -63,6 +66,68 @@ import java.util.StringJoiner; public final class NetworkCapabilities implements Parcelable { private static final String TAG = "NetworkCapabilities"; + /** + * Mechanism to support redaction of fields in NetworkCapabilities that are guarded by specific + * app permissions. + **/ + /** + * Don't redact any fields since the receiving app holds all the necessary permissions. + * + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public static final long REDACT_NONE = 0; + + /** + * Redact any fields that need {@link android.Manifest.permission#ACCESS_FINE_LOCATION} + * permission since the receiving app does not hold this permission or the location toggle + * is off. + * + * @see android.Manifest.permission#ACCESS_FINE_LOCATION + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public static final long REDACT_FOR_ACCESS_FINE_LOCATION = 1 << 0; + + /** + * Redact any fields that need {@link android.Manifest.permission#LOCAL_MAC_ADDRESS} + * permission since the receiving app does not hold this permission. + * + * @see android.Manifest.permission#LOCAL_MAC_ADDRESS + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public static final long REDACT_FOR_LOCAL_MAC_ADDRESS = 1 << 1; + + /** + * + * Redact any fields that need {@link android.Manifest.permission#NETWORK_SETTINGS} + * permission since the receiving app does not hold this permission. + * + * @see android.Manifest.permission#NETWORK_SETTINGS + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public static final long REDACT_FOR_NETWORK_SETTINGS = 1 << 2; + + /** + * Redact all fields in this object that require any relevant permission. + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public static final long REDACT_ALL = -1L; + + /** @hide */ + @LongDef(flag = true, prefix = { "REDACT_" }, value = { + REDACT_NONE, + REDACT_FOR_ACCESS_FINE_LOCATION, + REDACT_FOR_LOCAL_MAC_ADDRESS, + REDACT_FOR_NETWORK_SETTINGS, + REDACT_ALL + }) + @Retention(RetentionPolicy.SOURCE) + public @interface RedactionType {} + // Set to true when private DNS is broken. private boolean mPrivateDnsBroken; @@ -77,32 +142,31 @@ public final class NetworkCapabilities implements Parcelable { private String mRequestorPackageName; /** - * Indicates whether parceling should preserve fields that are set based on permissions of - * the process receiving the {@link NetworkCapabilities}. + * Indicates what fields should be redacted from this instance. */ - private final boolean mParcelLocationSensitiveFields; + private final @RedactionType long mRedactions; public NetworkCapabilities() { - mParcelLocationSensitiveFields = false; + mRedactions = REDACT_ALL; clearAll(); mNetworkCapabilities = DEFAULT_CAPABILITIES; } public NetworkCapabilities(NetworkCapabilities nc) { - this(nc, false /* parcelLocationSensitiveFields */); + this(nc, REDACT_ALL); } /** * Make a copy of NetworkCapabilities. * * @param nc Original NetworkCapabilities - * @param parcelLocationSensitiveFields Whether to parcel location sensitive data or not. + * @param redactions bitmask of redactions that needs to be performed on this new instance of + * {@link NetworkCapabilities}. * @hide */ - @SystemApi - public NetworkCapabilities( - @Nullable NetworkCapabilities nc, boolean parcelLocationSensitiveFields) { - mParcelLocationSensitiveFields = parcelLocationSensitiveFields; + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public NetworkCapabilities(@Nullable NetworkCapabilities nc, @RedactionType long redactions) { + mRedactions = redactions; if (nc != null) { set(nc); } @@ -114,11 +178,13 @@ public final class NetworkCapabilities implements Parcelable { * @hide */ public void clearAll() { - // Ensures that the internal copies maintained by the connectivity stack does not set - // this bit. - if (mParcelLocationSensitiveFields) { + // Ensures that the internal copies maintained by the connectivity stack does not set it to + // anything other than |REDACT_ALL|. + if (mRedactions != REDACT_ALL) { + // This is needed because the current redaction mechanism relies on redaction while + // parceling. throw new UnsupportedOperationException( - "Cannot clear NetworkCapabilities when parcelLocationSensitiveFields is set"); + "Cannot clear NetworkCapabilities when mRedactions is set"); } mNetworkCapabilities = mTransportTypes = mUnwantedNetworkCapabilities = 0; mLinkUpBandwidthKbps = mLinkDownBandwidthKbps = LINK_BANDWIDTH_UNSPECIFIED; @@ -148,12 +214,12 @@ public final class NetworkCapabilities implements Parcelable { mLinkDownBandwidthKbps = nc.mLinkDownBandwidthKbps; mNetworkSpecifier = nc.mNetworkSpecifier; if (nc.getTransportInfo() != null) { - setTransportInfo(nc.getTransportInfo().makeCopy(mParcelLocationSensitiveFields)); + setTransportInfo(nc.getTransportInfo().makeCopy(mRedactions)); } else { setTransportInfo(null); } mSignalStrength = nc.mSignalStrength; - setUids(nc.mUids); // Will make the defensive copy + mUids = (nc.mUids == null) ? null : new ArraySet<>(nc.mUids); setAdministratorUids(nc.getAdministratorUids()); mOwnerUid = nc.mOwnerUid; mUnwantedNetworkCapabilities = nc.mUnwantedNetworkCapabilities; @@ -609,10 +675,8 @@ public final class NetworkCapabilities implements Parcelable { * Gets all the capabilities set on this {@code NetworkCapability} instance. * * @return an array of capability values for this instance. - * @hide */ - @UnsupportedAppUsage - public @NetCapability int[] getCapabilities() { + public @NonNull @NetCapability int[] getCapabilities() { return NetworkCapabilitiesUtils.unpackBits(mNetworkCapabilities); } @@ -1458,9 +1522,8 @@ public final class NetworkCapabilities implements Parcelable { * @hide */ public @NonNull NetworkCapabilities setSingleUid(int uid) { - final ArraySet<UidRange> identity = new ArraySet<>(1); - identity.add(new UidRange(uid, uid)); - setUids(identity); + mUids = new ArraySet<>(1); + mUids.add(new UidRange(uid, uid)); return this; } @@ -1469,22 +1532,34 @@ public final class NetworkCapabilities implements Parcelable { * This makes a copy of the set so that callers can't modify it after the call. * @hide */ - public @NonNull NetworkCapabilities setUids(Set<UidRange> uids) { - if (null == uids) { - mUids = null; - } else { - mUids = new ArraySet<>(uids); - } + public @NonNull NetworkCapabilities setUids(@Nullable Set<Range<Integer>> uids) { + mUids = UidRange.fromIntRanges(uids); return this; } /** * Get the list of UIDs this network applies to. * This returns a copy of the set so that callers can't modify the original object. + * + * @return the list of UIDs this network applies to. If {@code null}, then the network applies + * to all UIDs. * @hide */ - public @Nullable Set<UidRange> getUids() { - return null == mUids ? null : new ArraySet<>(mUids); + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + @SuppressLint("NullableCollection") + public @Nullable Set<Range<Integer>> getUids() { + return UidRange.toIntRanges(mUids); + } + + /** + * Get the list of UIDs this network applies to. + * This returns a copy of the set so that callers can't modify the original object. + * @hide + */ + public @Nullable Set<UidRange> getUidRanges() { + if (mUids == null) return null; + + return new ArraySet<>(mUids); } /** @@ -2338,6 +2413,23 @@ public final class NetworkCapabilities implements Parcelable { } /** + * Returns a bitmask of all the applicable redactions (based on the permissions held by the + * receiving app) to be performed on this object. + * + * @return bitmask of redactions applicable on this instance. + * @hide + */ + public @RedactionType long getApplicableRedactions() { + // Currently, there are no fields redacted in NetworkCapabilities itself, so we just + // passthrough the redactions required by the embedded TransportInfo. If this changes + // in the future, modify this method. + if (mTransportInfo == null) { + return NetworkCapabilities.REDACT_NONE; + } + return mTransportInfo.getApplicableRedactions(); + } + + /** * Builder class for NetworkCapabilities. * * This class is mainly for for {@link NetworkAgent} instances to use. Many fields in @@ -2655,6 +2747,21 @@ public final class NetworkCapabilities implements Parcelable { } /** + * Set the list of UIDs this network applies to. + * + * @param uids the list of UIDs this network applies to, or {@code null} if this network + * applies to all UIDs. + * @return this builder + * @hide + */ + @NonNull + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public Builder setUids(@Nullable Set<Range<Integer>> uids) { + mCaps.setUids(uids); + return this; + } + + /** * Builds the instance of the capabilities. * * @return the built instance of NetworkCapabilities. diff --git a/packages/Connectivity/framework/src/android/net/NetworkRequest.java b/packages/Connectivity/framework/src/android/net/NetworkRequest.java index 3fd95ee58df2..cf131f0df607 100644 --- a/packages/Connectivity/framework/src/android/net/NetworkRequest.java +++ b/packages/Connectivity/framework/src/android/net/NetworkRequest.java @@ -36,6 +36,7 @@ import static android.net.NetworkCapabilities.TRANSPORT_TEST; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; +import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; import android.net.NetworkCapabilities.NetCapability; @@ -45,6 +46,7 @@ import android.os.Parcel; import android.os.Parcelable; import android.os.Process; import android.text.TextUtils; +import android.util.Range; import android.util.proto.ProtoOutputStream; import java.util.Arrays; @@ -140,7 +142,7 @@ public class NetworkRequest implements Parcelable { REQUEST, BACKGROUND_REQUEST, TRACK_SYSTEM_DEFAULT, - TRACK_BEST, + LISTEN_FOR_BEST, }; /** @@ -277,11 +279,14 @@ public class NetworkRequest implements Parcelable { * Set the watched UIDs for this request. This will be reset and wiped out unless * the calling app holds the CHANGE_NETWORK_STATE permission. * - * @param uids The watched UIDs as a set of UidRanges, or null for everything. + * @param uids The watched UIDs as a set of {@code Range<Integer>}, or null for everything. * @return The builder to facilitate chaining. * @hide */ - public Builder setUids(Set<UidRange> uids) { + @NonNull + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + @SuppressLint("MissingGetterMatchingBuilder") + public Builder setUids(@Nullable Set<Range<Integer>> uids) { mNetworkCapabilities.setUids(uids); return this; } @@ -514,6 +519,15 @@ public class NetworkRequest implements Parcelable { } /** + * Returns true iff. this NetworkRequest is of type LISTEN_FOR_BEST. + * + * @hide + */ + public boolean isListenForBest() { + return type == Type.LISTEN_FOR_BEST; + } + + /** * Returns true iff. the contained NetworkRequest is one that: * * - should be associated with at most one satisfying network diff --git a/packages/Connectivity/framework/src/android/net/NetworkScore.java b/packages/Connectivity/framework/src/android/net/NetworkScore.java new file mode 100644 index 000000000000..eadcb2d0a7f4 --- /dev/null +++ b/packages/Connectivity/framework/src/android/net/NetworkScore.java @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2021 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.annotation.NonNull; +import android.os.Parcel; +import android.os.Parcelable; + +import com.android.internal.annotations.VisibleForTesting; + +/** + * Object representing the quality of a network as perceived by the user. + * + * A NetworkScore object represents the characteristics of a network that affects how good the + * network is considered for a particular use. + * @hide + */ +// TODO : @SystemApi when the implementation is complete +public final class NetworkScore implements Parcelable { + // This will be removed soon. Do *NOT* depend on it for any new code that is not part of + // a migration. + private final int mLegacyInt; + + // Agent-managed policies + // TODO : add them here, starting from 1 + /** @hide */ + public static final int MIN_AGENT_MANAGED_POLICY = 0; + /** @hide */ + public static final int MAX_AGENT_MANAGED_POLICY = -1; + + // Bitmask of all the policies applied to this score. + private final long mPolicies; + + /** @hide */ + NetworkScore(final int legacyInt, final long policies) { + mLegacyInt = legacyInt; + mPolicies = policies; + } + + private NetworkScore(@NonNull final Parcel in) { + mLegacyInt = in.readInt(); + mPolicies = in.readLong(); + } + + public int getLegacyInt() { + return mLegacyInt; + } + + /** + * @return whether this score has a particular policy. + */ + @VisibleForTesting + public boolean hasPolicy(final int policy) { + return 0 != (mPolicies & (1L << policy)); + } + + @Override + public String toString() { + return "Score(" + mLegacyInt + ")"; + } + + @Override + public void writeToParcel(@NonNull final Parcel dest, final int flags) { + dest.writeInt(mLegacyInt); + dest.writeLong(mPolicies); + } + + @Override + public int describeContents() { + return 0; + } + + @NonNull public static final Creator<NetworkScore> CREATOR = new Creator<>() { + @Override + @NonNull + public NetworkScore createFromParcel(@NonNull final Parcel in) { + return new NetworkScore(in); + } + + @Override + @NonNull + public NetworkScore[] newArray(int size) { + return new NetworkScore[size]; + } + }; + + /** + * A builder for NetworkScore. + */ + public static final class Builder { + private static final long POLICY_NONE = 0L; + private static final int INVALID_LEGACY_INT = Integer.MIN_VALUE; + private int mLegacyInt = INVALID_LEGACY_INT; + + /** + * Sets the legacy int for this score. + * + * Do not rely on this. It will be gone by the time S is released. + * + * @param score the legacy int + * @return this + */ + @NonNull + public Builder setLegacyInt(final int score) { + mLegacyInt = score; + return this; + } + + /** + * Builds this NetworkScore. + * @return The built NetworkScore object. + */ + @NonNull + public NetworkScore build() { + return new NetworkScore(mLegacyInt, POLICY_NONE); + } + } +} diff --git a/packages/Connectivity/framework/src/android/net/OemNetworkPreferences.java b/packages/Connectivity/framework/src/android/net/OemNetworkPreferences.java index 48bd29769f83..5a76cd6d6b0f 100644 --- a/packages/Connectivity/framework/src/android/net/OemNetworkPreferences.java +++ b/packages/Connectivity/framework/src/android/net/OemNetworkPreferences.java @@ -73,6 +73,14 @@ public final class OemNetworkPreferences implements Parcelable { private final Bundle mNetworkMappings; /** + * Return whether this object is empty. + * @hide + */ + public boolean isEmpty() { + return mNetworkMappings.keySet().size() == 0; + } + + /** * Return the currently built application package name to {@link OemNetworkPreference} mappings. * @return the current network preferences map. */ diff --git a/packages/Connectivity/framework/src/android/net/ParseException.java b/packages/Connectivity/framework/src/android/net/ParseException.java index bcfdd7ef09cc..ca6d012dfe7c 100644 --- a/packages/Connectivity/framework/src/android/net/ParseException.java +++ b/packages/Connectivity/framework/src/android/net/ParseException.java @@ -17,6 +17,7 @@ package android.net; import android.annotation.NonNull; +import android.annotation.SystemApi; /** * Thrown when parsing failed. @@ -25,12 +26,16 @@ import android.annotation.NonNull; public class ParseException extends RuntimeException { public String response; - ParseException(@NonNull String response) { + /** @hide */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public ParseException(@NonNull String response) { super(response); this.response = response; } - ParseException(@NonNull String response, @NonNull Throwable cause) { + /** @hide */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public ParseException(@NonNull String response, @NonNull Throwable cause) { super(response, cause); this.response = response; } diff --git a/packages/Connectivity/framework/src/android/net/TransportInfo.java b/packages/Connectivity/framework/src/android/net/TransportInfo.java index aa4bbb051179..fa889eabb842 100644 --- a/packages/Connectivity/framework/src/android/net/TransportInfo.java +++ b/packages/Connectivity/framework/src/android/net/TransportInfo.java @@ -29,35 +29,47 @@ import android.annotation.SystemApi; public interface TransportInfo { /** - * Create a copy of a {@link TransportInfo} that will preserve location sensitive fields that - * were set based on the permissions of the process that originally received it. + * Create a copy of a {@link TransportInfo} with some fields redacted based on the permissions + * held by the receiving app. * - * <p>By default {@link TransportInfo} does not preserve such fields during parceling, as - * they should not be shared outside of the process that receives them without appropriate - * checks. + * <p> + * Usage by connectivity stack: + * <ul> + * <li> Connectivity stack will invoke {@link #getApplicableRedactions()} to find the list + * of redactions that are required by this {@link TransportInfo} instance.</li> + * <li> Connectivity stack then loops through each bit in the bitmask returned and checks if the + * receiving app holds the corresponding permission. + * <ul> + * <li> If the app holds the corresponding permission, the bit is cleared from the + * |redactions| bitmask. </li> + * <li> If the app does not hold the corresponding permission, the bit is retained in the + * |redactions| bitmask. </li> + * </ul> + * <li> Connectivity stack then invokes {@link #makeCopy(long)} with the necessary |redactions| + * to create a copy to send to the corresponding app. </li> + * </ul> + * </p> * - * @param parcelLocationSensitiveFields Whether the location sensitive fields should be kept - * when parceling - * @return Copy of this instance. + * @param redactions bitmask of redactions that needs to be performed on this instance. + * @return Copy of this instance with the necessary redactions. * @hide */ - @SystemApi + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) @NonNull - default TransportInfo makeCopy(boolean parcelLocationSensitiveFields) { + default TransportInfo makeCopy(@NetworkCapabilities.RedactionType long redactions) { return this; } /** - * Returns whether this TransportInfo type has location sensitive fields or not (helps - * to determine whether to perform a location permission check or not before sending to - * apps). + * Returns a bitmask of all the applicable redactions (based on the permissions held by the + * receiving app) to be performed on this TransportInfo. * - * @return {@code true} if this instance contains location sensitive info, {@code false} - * otherwise. + * @return bitmask of redactions applicable on this instance. + * @see #makeCopy(long) * @hide */ - @SystemApi - default boolean hasLocationSensitiveFields() { - return false; + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + default @NetworkCapabilities.RedactionType long getApplicableRedactions() { + return NetworkCapabilities.REDACT_NONE; } } diff --git a/packages/Connectivity/framework/src/android/net/UidRange.java b/packages/Connectivity/framework/src/android/net/UidRange.java index 26518d32edcb..bc67c745c98f 100644 --- a/packages/Connectivity/framework/src/android/net/UidRange.java +++ b/packages/Connectivity/framework/src/android/net/UidRange.java @@ -20,8 +20,11 @@ import android.annotation.Nullable; import android.os.Parcel; import android.os.Parcelable; import android.os.UserHandle; +import android.util.ArraySet; +import android.util.Range; import java.util.Collection; +import java.util.Set; /** * An inclusive range of UIDs. @@ -149,4 +152,32 @@ public final class UidRange implements Parcelable { } return false; } + + /** + * Convert a set of {@code Range<Integer>} to a set of {@link UidRange}. + */ + @Nullable + public static ArraySet<UidRange> fromIntRanges(@Nullable Set<Range<Integer>> ranges) { + if (null == ranges) return null; + + final ArraySet<UidRange> uids = new ArraySet<>(); + for (Range<Integer> range : ranges) { + uids.add(new UidRange(range.getLower(), range.getUpper())); + } + return uids; + } + + /** + * Convert a set of {@link UidRange} to a set of {@code Range<Integer>}. + */ + @Nullable + public static ArraySet<Range<Integer>> toIntRanges(@Nullable Set<UidRange> ranges) { + if (null == ranges) return null; + + final ArraySet<Range<Integer>> uids = new ArraySet<>(); + for (UidRange range : ranges) { + uids.add(new Range<Integer>(range.start, range.stop)); + } + return uids; + } } diff --git a/packages/Connectivity/framework/src/android/net/VpnTransportInfo.java b/packages/Connectivity/framework/src/android/net/VpnTransportInfo.java index c5100794899a..cd8f4c06de65 100644 --- a/packages/Connectivity/framework/src/android/net/VpnTransportInfo.java +++ b/packages/Connectivity/framework/src/android/net/VpnTransportInfo.java @@ -22,9 +22,6 @@ import android.annotation.NonNull; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; -import android.util.SparseArray; - -import com.android.internal.util.MessageUtils; import java.util.Objects; @@ -38,9 +35,6 @@ import java.util.Objects; */ @SystemApi(client = MODULE_LIBRARIES) public final class VpnTransportInfo implements TransportInfo, Parcelable { - private static final SparseArray<String> sTypeToString = - MessageUtils.findMessageNames(new Class[]{VpnManager.class}, new String[]{"TYPE_VPN_"}); - /** Type of this VPN. */ public final int type; @@ -63,8 +57,7 @@ public final class VpnTransportInfo implements TransportInfo, Parcelable { @Override public String toString() { - final String typeString = sTypeToString.get(type, "VPN_TYPE_???"); - return String.format("VpnTransportInfo{%s}", typeString); + return String.format("VpnTransportInfo{type=%d}", type); } @Override diff --git a/packages/Connectivity/framework/src/android/net/apf/ApfCapabilities.java b/packages/Connectivity/framework/src/android/net/apf/ApfCapabilities.java index bf5b26e278f9..85b24713f256 100644 --- a/packages/Connectivity/framework/src/android/net/apf/ApfCapabilities.java +++ b/packages/Connectivity/framework/src/android/net/apf/ApfCapabilities.java @@ -19,12 +19,12 @@ package android.net.apf; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; +import android.content.Context; import android.content.res.Resources; +import android.net.ConnectivityResources; import android.os.Parcel; import android.os.Parcelable; -import com.android.internal.R; - /** * APF program support capabilities. APF stands for Android Packet Filtering and it is a flexible * way to drop unwanted network packets to save power. @@ -36,6 +36,8 @@ import com.android.internal.R; */ @SystemApi public final class ApfCapabilities implements Parcelable { + private static ConnectivityResources sResources; + /** * Version of APF instruction set supported for packet filtering. 0 indicates no support for * packet filtering using APF programs. @@ -65,6 +67,14 @@ public final class ApfCapabilities implements Parcelable { apfPacketFormat = in.readInt(); } + @NonNull + private static synchronized ConnectivityResources getResources(@NonNull Context ctx) { + if (sResources == null) { + sResources = new ConnectivityResources(ctx); + } + return sResources; + } + @Override public int describeContents() { @@ -121,13 +131,43 @@ public final class ApfCapabilities implements Parcelable { * @return Whether the APF Filter in the device should filter out IEEE 802.3 Frames. */ public static boolean getApfDrop8023Frames() { - return Resources.getSystem().getBoolean(R.bool.config_apfDrop802_3Frames); + // TODO(b/183076074): remove reading resources from system resources + final Resources systemRes = Resources.getSystem(); + final int id = systemRes.getIdentifier("config_apfDrop802_3Frames", "bool", "android"); + return systemRes.getBoolean(id); + } + + /** + * @return Whether the APF Filter in the device should filter out IEEE 802.3 Frames. + * @hide + */ + public static boolean getApfDrop8023Frames(@NonNull Context context) { + final ConnectivityResources res = getResources(context); + // TODO(b/183076074): use R.bool.config_apfDrop802_3Frames directly + final int id = res.get().getIdentifier("config_apfDrop802_3Frames", "bool", + res.getResourcesContext().getPackageName()); + return res.get().getBoolean(id); } /** * @return An array of denylisted EtherType, packets with EtherTypes within it will be dropped. */ public static @NonNull int[] getApfEtherTypeBlackList() { - return Resources.getSystem().getIntArray(R.array.config_apfEthTypeBlackList); + // TODO(b/183076074): remove reading resources from system resources + final Resources systemRes = Resources.getSystem(); + final int id = systemRes.getIdentifier("config_apfEthTypeBlackList", "array", "android"); + return systemRes.getIntArray(id); + } + + /** + * @return An array of denylisted EtherType, packets with EtherTypes within it will be dropped. + * @hide + */ + public static @NonNull int[] getApfEtherTypeDenyList(@NonNull Context context) { + final ConnectivityResources res = getResources(context); + // TODO(b/183076074): use R.array.config_apfEthTypeDenyList directly + final int id = res.get().getIdentifier("config_apfEthTypeDenyList", "array", + res.getResourcesContext().getPackageName()); + return res.get().getIntArray(id); } } diff --git a/packages/Connectivity/framework/src/android/net/util/KeepaliveUtils.java b/packages/Connectivity/framework/src/android/net/util/KeepaliveUtils.java index bfc4563fbf8f..8d7a0b3d02ed 100644 --- a/packages/Connectivity/framework/src/android/net/util/KeepaliveUtils.java +++ b/packages/Connectivity/framework/src/android/net/util/KeepaliveUtils.java @@ -19,12 +19,11 @@ package android.net.util; import android.annotation.NonNull; import android.content.Context; import android.content.res.Resources; +import android.net.ConnectivityResources; import android.net.NetworkCapabilities; import android.text.TextUtils; import android.util.AndroidRuntimeException; -import com.android.internal.R; - /** * Collection of utilities for socket keepalive offload. * @@ -52,8 +51,11 @@ public final class KeepaliveUtils { public static int[] getSupportedKeepalives(@NonNull Context context) { String[] res = null; try { - res = context.getResources().getStringArray( - R.array.config_networkSupportedKeepaliveCount); + final ConnectivityResources connRes = new ConnectivityResources(context); + // TODO: use R.id.config_networkSupportedKeepaliveCount directly + final int id = connRes.get().getIdentifier("config_networkSupportedKeepaliveCount", + "array", connRes.getResourcesContext().getPackageName()); + res = new ConnectivityResources(context).get().getStringArray(id); } catch (Resources.NotFoundException unused) { } if (res == null) throw new KeepaliveDeviceConfigurationException("invalid resource"); diff --git a/packages/Connectivity/framework/src/android/net/util/MultinetworkPolicyTracker.java b/packages/Connectivity/framework/src/android/net/util/MultinetworkPolicyTracker.java index 739ddada50b4..0b42a0036925 100644 --- a/packages/Connectivity/framework/src/android/net/util/MultinetworkPolicyTracker.java +++ b/packages/Connectivity/framework/src/android/net/util/MultinetworkPolicyTracker.java @@ -16,8 +16,8 @@ package android.net.util; -import static android.provider.Settings.Global.NETWORK_AVOID_BAD_WIFI; -import static android.provider.Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE; +import static android.net.ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI; +import static android.net.ConnectivitySettingsManager.NETWORK_METERED_MULTIPATH_PREFERENCE; import android.annotation.NonNull; import android.content.BroadcastReceiver; @@ -27,6 +27,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.res.Resources; import android.database.ContentObserver; +import android.net.ConnectivityResources; import android.net.Uri; import android.os.Handler; import android.provider.Settings; @@ -35,7 +36,6 @@ import android.telephony.TelephonyCallback; import android.telephony.TelephonyManager; import android.util.Log; -import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import java.util.Arrays; @@ -64,6 +64,7 @@ public class MultinetworkPolicyTracker { private static String TAG = MultinetworkPolicyTracker.class.getSimpleName(); private final Context mContext; + private final ConnectivityResources mResources; private final Handler mHandler; private final Runnable mAvoidBadWifiCallback; private final List<Uri> mSettingsUris; @@ -107,11 +108,12 @@ public class MultinetworkPolicyTracker { public MultinetworkPolicyTracker(Context ctx, Handler handler, Runnable avoidBadWifiCallback) { mContext = ctx; + mResources = new ConnectivityResources(ctx); mHandler = handler; mAvoidBadWifiCallback = avoidBadWifiCallback; mSettingsUris = Arrays.asList( - Settings.Global.getUriFor(NETWORK_AVOID_BAD_WIFI), - Settings.Global.getUriFor(NETWORK_METERED_MULTIPATH_PREFERENCE)); + Settings.Global.getUriFor(NETWORK_AVOID_BAD_WIFI), + Settings.Global.getUriFor(NETWORK_METERED_MULTIPATH_PREFERENCE)); mResolver = mContext.getContentResolver(); mSettingObserver = new SettingObserver(); mBroadcastReceiver = new BroadcastReceiver() { @@ -160,12 +162,16 @@ public class MultinetworkPolicyTracker { * Whether the device or carrier configuration disables avoiding bad wifi by default. */ public boolean configRestrictsAvoidBadWifi() { - return (getResourcesForActiveSubId().getInteger(R.integer.config_networkAvoidBadWifi) == 0); + // TODO: use R.integer.config_networkAvoidBadWifi directly + final int id = mResources.get().getIdentifier("config_networkAvoidBadWifi", + "integer", mResources.getResourcesContext().getPackageName()); + return (getResourcesForActiveSubId().getInteger(id) == 0); } @NonNull private Resources getResourcesForActiveSubId() { - return SubscriptionManager.getResourcesForSubId(mContext, mActiveSubId); + return SubscriptionManager.getResourcesForSubId( + mResources.getResourcesContext(), mActiveSubId); } /** @@ -205,8 +211,10 @@ public class MultinetworkPolicyTracker { * The default (device and carrier-dependent) value for metered multipath preference. */ public int configMeteredMultipathPreference() { - return mContext.getResources().getInteger( - R.integer.config_networkMeteredMultipathPreference); + // TODO: use R.integer.config_networkMeteredMultipathPreference directly + final int id = mResources.get().getIdentifier("config_networkMeteredMultipathPreference", + "integer", mResources.getResourcesContext().getPackageName()); + return mResources.get().getInteger(id); } public void updateMeteredMultipathPreference() { diff --git a/packages/Connectivity/service/Android.bp b/packages/Connectivity/service/Android.bp index 856f3b85333a..1330e719e774 100644 --- a/packages/Connectivity/service/Android.bp +++ b/packages/Connectivity/service/Android.bp @@ -60,6 +60,7 @@ java_library { "services.core", "services.net", "unsupportedappusage", + "ServiceConnectivityResources", ], static_libs: [ "modules-utils-os", @@ -67,6 +68,7 @@ java_library { "net-utils-framework-common", "netd-client", "PlatformProperties", + "service-connectivity-protos", ], apex_available: [ "//apex_available:platform", @@ -75,6 +77,21 @@ java_library { } java_library { + name: "service-connectivity-protos", + proto: { + type: "nano", + }, + srcs: [ + ":system-messages-proto-src", + ], + libs: ["libprotobuf-java-nano"], + apex_available: [ + "//apex_available:platform", + "com.android.tethering", + ], +} + +java_library { name: "service-connectivity", installable: true, static_libs: [ diff --git a/packages/Connectivity/service/ServiceConnectivityResources/Android.bp b/packages/Connectivity/service/ServiceConnectivityResources/Android.bp new file mode 100644 index 000000000000..fa4501ac7f29 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/Android.bp @@ -0,0 +1,35 @@ +// +// Copyright (C) 2021 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. +// + +// APK to hold all the wifi overlayable resources. +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +android_app { + name: "ServiceConnectivityResources", + sdk_version: "module_current", + resource_dirs: [ + "res", + ], + privileged: true, + export_package_resources: true, + apex_available: [ + "com.android.tethering", + ], + // TODO: use a dedicated cert once generated + certificate: "platform", +} diff --git a/packages/Connectivity/service/ServiceConnectivityResources/AndroidManifest.xml b/packages/Connectivity/service/ServiceConnectivityResources/AndroidManifest.xml new file mode 100644 index 000000000000..2c303026158e --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/AndroidManifest.xml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * Copyright (C) 2021 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 for connectivity resources APK --> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.connectivity.resources" + coreApp="true" + android:versionCode="1" + android:versionName="S-initial"> + <application + android:label="@string/connectivityResourcesAppLabel" + android:defaultToDeviceProtectedStorage="true" + android:directBootAware="true"> + <!-- This is only used to identify this app by resolving the action. + The activity is never actually triggered. --> + <activity android:name="android.app.Activity" android:exported="true" android:enabled="true"> + <intent-filter> + <action android:name="com.android.server.connectivity.intent.action.SERVICE_CONNECTIVITY_RESOURCES_APK" /> + </intent-filter> + </activity> + </application> +</manifest> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/drawable-hdpi/stat_notify_rssi_in_range.png b/packages/Connectivity/service/ServiceConnectivityResources/res/drawable-hdpi/stat_notify_rssi_in_range.png Binary files differnew file mode 100644 index 000000000000..74977e6aefff --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/drawable-hdpi/stat_notify_rssi_in_range.png diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/drawable-mdpi/stat_notify_rssi_in_range.png b/packages/Connectivity/service/ServiceConnectivityResources/res/drawable-mdpi/stat_notify_rssi_in_range.png Binary files differnew file mode 100644 index 000000000000..62e4fe94a35c --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/drawable-mdpi/stat_notify_rssi_in_range.png diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/drawable-xhdpi/stat_notify_rssi_in_range.png b/packages/Connectivity/service/ServiceConnectivityResources/res/drawable-xhdpi/stat_notify_rssi_in_range.png Binary files differnew file mode 100644 index 000000000000..c0586d8bc21e --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/drawable-xhdpi/stat_notify_rssi_in_range.png diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/drawable-xxhdpi/stat_notify_rssi_in_range.png b/packages/Connectivity/service/ServiceConnectivityResources/res/drawable-xxhdpi/stat_notify_rssi_in_range.png Binary files differnew file mode 100644 index 000000000000..86c34ed18d73 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/drawable-xxhdpi/stat_notify_rssi_in_range.png diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/drawable/stat_notify_wifi_in_range.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/drawable/stat_notify_wifi_in_range.xml new file mode 100644 index 000000000000..a271ca5224c7 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/drawable/stat_notify_wifi_in_range.xml @@ -0,0 +1,27 @@ +<!-- +Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="26.0dp" + android:height="24.0dp" + android:viewportWidth="26.0" + android:viewportHeight="24.0"> + <path + android:fillColor="#4DFFFFFF" + android:pathData="M19.1,14l-3.4,0l0,-1.5c0,-1.8 0.8,-2.8 1.5,-3.4C18.1,8.3 19.200001,8 20.6,8c1.2,0 2.3,0.3 3.1,0.8l1.9,-2.3C25.1,6.1 20.299999,2.1 13,2.1S0.9,6.1 0.4,6.5L13,22l0,0l0,0l0,0l0,0l6.5,-8.1L19.1,14z"/> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M19.5,17.799999c0,-0.8 0.1,-1.3 0.2,-1.6c0.2,-0.3 0.5,-0.7 1.1,-1.2c0.4,-0.4 0.7,-0.8 1,-1.1s0.4,-0.8 0.4,-1.2c0,-0.5 -0.1,-0.9 -0.4,-1.2c-0.3,-0.3 -0.7,-0.4 -1.2,-0.4c-0.4,0 -0.8,0.1 -1.1,0.3c-0.3,0.2 -0.4,0.6 -0.4,1.1l-1.9,0c0,-1 0.3,-1.7 1,-2.2c0.6,-0.5 1.5,-0.8 2.5,-0.8c1.1,0 2,0.3 2.6,0.8c0.6,0.5 0.9,1.3 0.9,2.3c0,0.7 -0.2,1.3 -0.6,1.8c-0.4,0.6 -0.9,1.1 -1.5,1.6c-0.3,0.3 -0.5,0.5 -0.6,0.7c-0.1,0.2 -0.1,0.6 -0.1,1L19.5,17.700001zM21.4,21l-1.9,0l0,-1.8l1.9,0L21.4,21z"/> +</vector> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-af/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-af/strings.xml new file mode 100644 index 000000000000..68720d5d27cd --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-af/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Meld aan by Wi-Fi-netwerk"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Meld by netwerk aan"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> het geen internettoegang nie"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Tik vir opsies"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"Selnetwerk het nie internettoegang nie"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"Netwerk het nie internettoegang nie"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Daar kan nie by private DNS-bediener ingegaan word nie"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> het beperkte konnektiwiteit"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Tik om in elk geval te koppel"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"Het oorgeskakel na <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"Toestel gebruik <xliff:g id="NEW_NETWORK">%1$s</xliff:g> wanneer <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> geen internettoegang het nie. Heffings kan geld."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"Het oorgeskakel van <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> na <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"\'n onbekende netwerktipe"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"mobiele data"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-am/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-am/strings.xml new file mode 100644 index 000000000000..78d928351d35 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-am/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"ወደ Wi-Fi አውታረ መረብ በመለያ ግባ"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"ወደ አውታረ መረብ በመለያ ይግቡ"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> ምንም የበይነ መረብ መዳረሻ የለም"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"ለአማራጮች መታ ያድርጉ"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"የተንቀሳቃሽ ስልክ አውታረ መረብ የበይነመረብ መዳረሻ የለውም"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"አውታረ መረብ የበይነመረብ መዳረሻ የለውም"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"የግል ዲኤንኤስ አገልጋይ ሊደረስበት አይችልም"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> የተገደበ ግንኙነት አለው"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"ለማንኛውም ለማገናኘት መታ ያድርጉ"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"ወደ <xliff:g id="NETWORK_TYPE">%1$s</xliff:g> ተቀይሯል"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> ምንም ዓይነት የበይነመረብ ግንኙነት በማይኖረው ጊዜ መሣሪያዎች <xliff:g id="NEW_NETWORK">%1$s</xliff:g>ን ይጠቀማሉ። ክፍያዎች ተፈጻሚ ሊሆኑ ይችላሉ።"</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"ከ<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> ወደ <xliff:g id="NEW_NETWORK">%2$s</xliff:g> ተቀይሯል"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"አንድ ያልታወቀ አውታረ መረብ ዓይነት"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"የተንቀሳቃሽ ስልክ ውሂብ"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"ብሉቱዝ"</item> + <item msgid="1616528372438698248">"ኤተርኔት"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ar/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ar/strings.xml new file mode 100644 index 000000000000..8698a7e6e127 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ar/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"تسجيل الدخول إلى شبكة Wi-Fi"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"تسجيل الدخول إلى الشبكة"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"لا يتوفّر في <xliff:g id="NETWORK_SSID">%1$s</xliff:g> إمكانية الاتصال بالإنترنت."</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"انقر للحصول على الخيارات."</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"شبكة الجوّال هذه غير متصلة بالإنترنت"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"الشبكة غير متصلة بالإنترنت"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"لا يمكن الوصول إلى خادم أسماء نظام نطاقات خاص"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"إمكانية اتصال <xliff:g id="NETWORK_SSID">%1$s</xliff:g> محدودة."</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"يمكنك النقر للاتصال على أي حال."</string> + <string name="network_switch_metered" msgid="1531869544142283384">"تم التبديل إلى <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"يستخدم الجهاز <xliff:g id="NEW_NETWORK">%1$s</xliff:g> عندما لا يتوفر اتصال بالإنترنت في شبكة <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g>، ويمكن أن يتم فرض رسوم مقابل ذلك."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"تم التبديل من <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> إلى <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"نوع شبكة غير معروف"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"بيانات الجوّال"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"بلوتوث"</item> + <item msgid="1616528372438698248">"إيثرنت"</item> + <item msgid="9177085807664964627">"شبكة افتراضية خاصة (VPN)"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-as/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-as/strings.xml new file mode 100644 index 000000000000..10b234adced6 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-as/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"ৱাই-ফাই নেটৱৰ্কত ছাইন ইন কৰক"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"নেটৱৰ্কত ছাইন ইন কৰক"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g>ৰ ইণ্টাৰনেটৰ এক্সেছ নাই"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"অধিক বিকল্পৰ বাবে টিপক"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"ম’বাইল নেটৱৰ্কৰ কোনো ইণ্টাৰনেটৰ এক্সেছ নাই"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"নেটৱৰ্কৰ কোনো ইণ্টাৰনেটৰ এক্সেছ নাই"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"ব্যক্তিগত DNS ছাৰ্ভাৰ এক্সেছ কৰিব নোৱাৰি"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g>ৰ সকলো সেৱাৰ এক্সেছ নাই"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"যিকোনো প্ৰকাৰে সংযোগ কৰিবলৈ টিপক"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g>লৈ সলনি কৰা হ’ল"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"যেতিয়া <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g>ত ইণ্টাৰনেট নাথাকে, তেতিয়া ডিভাইচে <xliff:g id="NEW_NETWORK">%1$s</xliff:g>ক ব্যৱহাৰ কৰে। মাচুল প্ৰযোজ্য হ\'ব পাৰে।"</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g>ৰ পৰা <xliff:g id="NEW_NETWORK">%2$s</xliff:g> লৈ সলনি কৰা হ’ল"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"অজ্ঞাত প্ৰকাৰৰ নেটৱৰ্ক"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"ম’বাইল ডেটা"</item> + <item msgid="5520925862115353992">"ৱাই-ফাই"</item> + <item msgid="1055487873974272842">"ব্লুটুথ"</item> + <item msgid="1616528372438698248">"ইথাৰনেট"</item> + <item msgid="9177085807664964627">"ভিপিএন"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-az/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-az/strings.xml new file mode 100644 index 000000000000..d75a20460c85 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-az/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Wi-Fi şəbəkəsinə daxil ol"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Şəbəkəyə daxil olun"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> üçün internet girişi əlçatan deyil"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Seçimlər üçün tıklayın"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"Mobil şəbəkənin internetə girişi yoxdur"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"Şəbəkənin internetə girişi yoxdur"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Özəl DNS serverinə giriş mümkün deyil"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> bağlantını məhdudlaşdırdı"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"İstənilən halda klikləyin"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> şəbəkə növünə keçirildi"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> şəbəkəsinin internetə girişi olmadıqda, cihaz <xliff:g id="NEW_NETWORK">%1$s</xliff:g> şəbəkəsini istifadə edir. Xidmət haqqı tutula bilər."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> şəbəkəsindən <xliff:g id="NEW_NETWORK">%2$s</xliff:g> şəbəkəsinə keçirildi"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"naməlum şəbəkə növü"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"mobil data"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-b+sr+Latn/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-b+sr+Latn/strings.xml new file mode 100644 index 000000000000..11e4957a7b4b --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-b+sr+Latn/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Prijavljivanje na WiFi mrežu"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Prijavite se na mrežu"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> nema pristup internetu"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Dodirnite za opcije"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"Mobilna mreža nema pristup internetu"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"Mreža nema pristup internetu"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Pristup privatnom DNS serveru nije uspeo"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> ima ograničenu vezu"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Dodirnite da biste se ipak povezali"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"Prešli ste na tip mreže <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"Uređaj koristi tip mreže <xliff:g id="NEW_NETWORK">%1$s</xliff:g> kada tip mreže <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> nema pristup internetu. Možda će se naplaćivati troškovi."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"Prešli ste sa tipa mreže <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> na tip mreže <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"nepoznat tip mreže"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"mobilni podaci"</item> + <item msgid="5520925862115353992">"WiFi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Eternet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-be/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-be/strings.xml new file mode 100644 index 000000000000..6b0b1f1130e8 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-be/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Уваход у сетку Wi-Fi"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Увайдзіце ў сетку"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> не мае доступу ў інтэрнэт"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Дакраніцеся, каб убачыць параметры"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"Мабільная сетка не мае доступу ў інтэрнэт"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"Сетка не мае доступу ў інтэрнэт"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Не ўдалося атрымаць доступ да прыватнага DNS-сервера"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> мае абмежаваную магчымасць падключэння"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Націсніце, каб падключыцца"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"Выкананы пераход да <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"Прылада выкарыстоўвае сетку <xliff:g id="NEW_NETWORK">%1$s</xliff:g>, калі ў сетцы <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> няма доступу да інтэрнэту. Можа спаганяцца плата."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"Выкананы пераход з <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> да <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"невядомы тып сеткі"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"мабільная перадача даных"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-bg/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-bg/strings.xml new file mode 100644 index 000000000000..6427bd09cf69 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-bg/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Влизане в Wi-Fi мрежа"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Вход в мрежата"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> няма достъп до интернет"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Докоснете за опции"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"Мобилната мрежа няма достъп до интернет"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"Мрежата няма достъп до интернет"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Не може да се осъществи достъп до частния DNS сървър"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> има ограничена свързаност"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Докоснете, за да се свържете въпреки това"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"Превключи се към <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"Устройството използва <xliff:g id="NEW_NETWORK">%1$s</xliff:g>, когато <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> няма достъп до интернет. Възможно е да бъдете таксувани."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"Превключи се от <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> към <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"неизвестен тип мрежа"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"мобилни данни"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"виртуална частна мрежа (VPN)"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-bn/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-bn/strings.xml new file mode 100644 index 000000000000..74d4cd6d7e25 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-bn/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"ওয়াই-ফাই নেটওয়ার্কে সাইন-ইন করুন"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"নেটওয়ার্কে সাইন-ইন করুন"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g>-এর ইন্টারনেটে অ্যাক্সেস নেই"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"বিকল্পগুলির জন্য আলতো চাপুন"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"মোবাইল নেটওয়ার্কে কোনও ইন্টারনেট অ্যাক্সেস নেই"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"নেটওয়ার্কে কোনও ইন্টারনেট অ্যাক্সেস নেই"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"ব্যক্তিগত ডিএনএস সার্ভার অ্যাক্সেস করা যাবে না"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g>-এর সীমিত কানেক্টিভিটি আছে"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"তবুও কানেক্ট করতে ট্যাপ করুন"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> এ পাল্টানো হয়েছে"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> এ ইন্টারনেট অ্যাক্সেস না থাকলে <xliff:g id="NEW_NETWORK">%1$s</xliff:g> ব্যবহার করা হয়৷ ডেটা চার্জ প্রযোজ্য৷"</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> থেকে <xliff:g id="NEW_NETWORK">%2$s</xliff:g> এ পাল্টানো হয়েছে"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"এই নেটওয়ার্কের প্রকার অজানা"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"মোবাইল ডেটা"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"ব্লুটুথ"</item> + <item msgid="1616528372438698248">"ইথারনেট"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-bs/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-bs/strings.xml new file mode 100644 index 000000000000..19f6e1a3f5e8 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-bs/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Prijavljivanje na WiFi mrežu"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Prijava na mrežu"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"Mreža <xliff:g id="NETWORK_SSID">%1$s</xliff:g> nema pristup internetu"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Dodirnite za opcije"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"Mobilna mreža nema pristup internetu"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"Mreža nema pristup internetu"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Nije moguće pristupiti privatnom DNS serveru"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"Mreža <xliff:g id="NETWORK_SSID">%1$s</xliff:g> ima ograničenu povezivost"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Dodirnite da se ipak povežete"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"Prebačeno na: <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"Kada <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> nema pristup internetu, uređaj koristi mrežu <xliff:g id="NEW_NETWORK">%1$s</xliff:g>. Moguća je naplata usluge."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"Prebačeno iz mreže <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> u <xliff:g id="NEW_NETWORK">%2$s</xliff:g> mrežu"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"nepoznata vrsta mreže"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"prijenos podataka na mobilnoj mreži"</item> + <item msgid="5520925862115353992">"WiFi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ca/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ca/strings.xml new file mode 100644 index 000000000000..c55684d6e03d --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ca/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Inicia la sessió a la xarxa Wi-Fi"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Inicia la sessió a la xarxa"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> no té accés a Internet"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Toca per veure les opcions"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"La xarxa mòbil no té accés a Internet"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"La xarxa no té accés a Internet"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"No es pot accedir al servidor DNS privat"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> té una connectivitat limitada"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Toca per connectar igualment"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"Actualment en ús: <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"El dispositiu utilitza <xliff:g id="NEW_NETWORK">%1$s</xliff:g> en cas que <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> no tingui accés a Internet. És possible que s\'hi apliquin càrrecs."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"Abans es feia servir la xarxa <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g>; ara s\'utilitza <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"una tipus de xarxa desconegut"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"dades mòbils"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-cs/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-cs/strings.xml new file mode 100644 index 000000000000..fa8c411e48f9 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-cs/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Přihlásit se k síti Wi-Fi"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Přihlásit se k síti"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"Síť <xliff:g id="NETWORK_SSID">%1$s</xliff:g> nemá přístup k internetu"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Klepnutím zobrazíte možnosti"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"Mobilní síť nemá přístup k internetu"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"Síť nemá přístup k internetu"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Nelze získat přístup k soukromému serveru DNS"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"Síť <xliff:g id="NETWORK_SSID">%1$s</xliff:g> umožňuje jen omezené připojení"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Klepnutím se i přesto připojíte"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"Přechod na síť <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"Když síť <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> nebude mít přístup k internetu, zařízení použije síť <xliff:g id="NEW_NETWORK">%1$s</xliff:g>. Mohou být účtovány poplatky."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"Přechod ze sítě <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> na síť <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"neznámý typ sítě"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"mobilní data"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-da/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-da/strings.xml new file mode 100644 index 000000000000..f7be6df981b6 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-da/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Log ind på Wi-Fi-netværk"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Log ind på netværk"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> har ingen internetforbindelse"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Tryk for at se valgmuligheder"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"Mobilnetværket har ingen internetadgang"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"Netværket har ingen internetadgang"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Der er ikke adgang til den private DNS-server"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> har begrænset forbindelse"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Tryk for at oprette forbindelse alligevel"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"Der blev skiftet til <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"Enheden benytter <xliff:g id="NEW_NETWORK">%1$s</xliff:g>, når der ikke er internetadgang via <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g>. Der opkræves muligvis betaling."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"Der blev skiftet fra <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> til <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"en ukendt netværkstype"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"mobildata"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-de/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-de/strings.xml new file mode 100644 index 000000000000..1e7b80c8f638 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-de/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"In WLAN anmelden"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Im Netzwerk anmelden"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> hat keinen Internetzugriff"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Für Optionen tippen"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"Mobiles Netzwerk hat keinen Internetzugriff"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"Netzwerk hat keinen Internetzugriff"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Auf den privaten DNS-Server kann nicht zugegriffen werden"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"Schlechte Verbindung mit <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Tippen, um die Verbindung trotzdem herzustellen"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"Zu <xliff:g id="NETWORK_TYPE">%1$s</xliff:g> gewechselt"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"Auf dem Gerät werden <xliff:g id="NEW_NETWORK">%1$s</xliff:g> genutzt, wenn über <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> kein Internet verfügbar ist. Eventuell fallen Gebühren an."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"Von \"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g>\" zu \"<xliff:g id="NEW_NETWORK">%2$s</xliff:g>\" gewechselt"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"ein unbekannter Netzwerktyp"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"Mobile Daten"</item> + <item msgid="5520925862115353992">"WLAN"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-el/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-el/strings.xml new file mode 100644 index 000000000000..89647fdb1ef3 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-el/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Συνδεθείτε στο δίκτυο Wi-Fi"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Σύνδεση στο δίκτυο"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"Η εφαρμογή <xliff:g id="NETWORK_SSID">%1$s</xliff:g> δεν έχει πρόσβαση στο διαδίκτυο"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Πατήστε για να δείτε τις επιλογές"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"Το δίκτυο κινητής τηλεφωνίας δεν έχει πρόσβαση στο διαδίκτυο."</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"Το δίκτυο δεν έχει πρόσβαση στο διαδίκτυο."</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Δεν είναι δυνατή η πρόσβαση στον ιδιωτικό διακομιστή DNS."</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"Το δίκτυο <xliff:g id="NETWORK_SSID">%1$s</xliff:g> έχει περιορισμένη συνδεσιμότητα"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Πατήστε για σύνδεση ούτως ή άλλως"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"Μετάβαση σε δίκτυο <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"Η συσκευή χρησιμοποιεί το δίκτυο <xliff:g id="NEW_NETWORK">%1$s</xliff:g> όταν το δίκτυο <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> δεν έχει πρόσβαση στο διαδίκτυο. Μπορεί να ισχύουν χρεώσεις."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"Μετάβαση από το δίκτυο <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> στο δίκτυο <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"άγνωστος τύπος δικτύου"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"δεδομένα κινητής τηλεφωνίας"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-en-rAU/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-en-rAU/strings.xml new file mode 100644 index 000000000000..d29e2ec9f3a3 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-en-rAU/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Sign in to a Wi-Fi network"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Sign in to network"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> has no Internet access"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Tap for options"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"Mobile network has no Internet access"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"Network has no Internet access"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Private DNS server cannot be accessed"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> has limited connectivity"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Tap to connect anyway"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"Switched to <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"Device uses <xliff:g id="NEW_NETWORK">%1$s</xliff:g> when <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> has no Internet access. Charges may apply."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"Switched from <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> to <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"an unknown network type"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"mobile data"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-en-rCA/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-en-rCA/strings.xml new file mode 100644 index 000000000000..d29e2ec9f3a3 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-en-rCA/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Sign in to a Wi-Fi network"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Sign in to network"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> has no Internet access"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Tap for options"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"Mobile network has no Internet access"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"Network has no Internet access"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Private DNS server cannot be accessed"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> has limited connectivity"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Tap to connect anyway"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"Switched to <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"Device uses <xliff:g id="NEW_NETWORK">%1$s</xliff:g> when <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> has no Internet access. Charges may apply."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"Switched from <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> to <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"an unknown network type"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"mobile data"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-en-rGB/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-en-rGB/strings.xml new file mode 100644 index 000000000000..d29e2ec9f3a3 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-en-rGB/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Sign in to a Wi-Fi network"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Sign in to network"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> has no Internet access"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Tap for options"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"Mobile network has no Internet access"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"Network has no Internet access"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Private DNS server cannot be accessed"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> has limited connectivity"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Tap to connect anyway"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"Switched to <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"Device uses <xliff:g id="NEW_NETWORK">%1$s</xliff:g> when <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> has no Internet access. Charges may apply."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"Switched from <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> to <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"an unknown network type"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"mobile data"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-en-rIN/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-en-rIN/strings.xml new file mode 100644 index 000000000000..d29e2ec9f3a3 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-en-rIN/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Sign in to a Wi-Fi network"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Sign in to network"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> has no Internet access"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Tap for options"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"Mobile network has no Internet access"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"Network has no Internet access"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Private DNS server cannot be accessed"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> has limited connectivity"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Tap to connect anyway"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"Switched to <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"Device uses <xliff:g id="NEW_NETWORK">%1$s</xliff:g> when <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> has no Internet access. Charges may apply."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"Switched from <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> to <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"an unknown network type"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"mobile data"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-en-rXC/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-en-rXC/strings.xml new file mode 100644 index 000000000000..cd69133966f2 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-en-rXC/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Sign in to Wi-Fi network"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Sign in to network"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> has no internet access"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Tap for options"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"Mobile network has no internet access"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"Network has no internet access"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Private DNS server cannot be accessed"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> has limited connectivity"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Tap to connect anyway"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"Switched to <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"Device uses <xliff:g id="NEW_NETWORK">%1$s</xliff:g> when <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> has no internet access. Charges may apply."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"Switched from <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> to <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"an unknown network type"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"mobile data"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-es-rUS/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-es-rUS/strings.xml new file mode 100644 index 000000000000..9102dc019a2d --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-es-rUS/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Accede a una red Wi-Fi."</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Acceder a la red"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g>no tiene acceso a Internet"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Presiona para ver opciones"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"La red móvil no tiene acceso a Internet"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"La red no tiene acceso a Internet"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"No se puede acceder al servidor DNS privado"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> tiene conectividad limitada"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Presiona para conectarte de todas formas"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"Se cambió a <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"El dispositivo usa <xliff:g id="NEW_NETWORK">%1$s</xliff:g> cuando <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> no tiene acceso a Internet. Es posible que se apliquen cargos."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"Se cambió de <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> a <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"un tipo de red desconocido"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"Datos móviles"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-es/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-es/strings.xml new file mode 100644 index 000000000000..4c15566a7397 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-es/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Iniciar sesión en red Wi-Fi"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Iniciar sesión en la red"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> no tiene acceso a Internet"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Toca para ver opciones"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"La red móvil no tiene acceso a Internet"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"La red no tiene acceso a Internet"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"No se ha podido acceder al servidor DNS privado"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> tiene una conectividad limitada"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Toca para conectarte de todas formas"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"Se ha cambiado a <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"El dispositivo utiliza <xliff:g id="NEW_NETWORK">%1$s</xliff:g> cuando <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> no tiene acceso a Internet. Es posible que se apliquen cargos."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"Se ha cambiado de <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> a <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"tipo de red desconocido"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"datos móviles"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-et/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-et/strings.xml new file mode 100644 index 000000000000..398223a341c6 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-et/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Logi sisse WiFi-võrku"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Võrku sisselogimine"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"Võrgul <xliff:g id="NETWORK_SSID">%1$s</xliff:g> puudub Interneti-ühendus"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Puudutage valikute nägemiseks"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"Mobiilsidevõrgul puudub Interneti-ühendus"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"Võrgul puudub Interneti-ühendus"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Privaatsele DNS-serverile ei pääse juurde"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"Võrgu <xliff:g id="NETWORK_SSID">%1$s</xliff:g> ühendus on piiratud"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Puudutage, kui soovite siiski ühenduse luua"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"Lülitati võrgule <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"Seade kasutab võrku <xliff:g id="NEW_NETWORK">%1$s</xliff:g>, kui võrgul <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> puudub juurdepääs Internetile. Rakenduda võivad tasud."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"Lülitati võrgult <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> võrgule <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"tundmatu võrgutüüp"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"mobiilne andmeside"</item> + <item msgid="5520925862115353992">"WiFi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-eu/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-eu/strings.xml new file mode 100644 index 000000000000..dd70316f6959 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-eu/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Hasi saioa Wi-Fi sarean"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Hasi saioa sarean"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"Ezin da konektatu Internetera <xliff:g id="NETWORK_SSID">%1$s</xliff:g> sarearen bidez"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Sakatu aukerak ikusteko"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"Sare mugikorra ezin da konektatu Internetera"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"Sarea ezin da konektatu Internetera"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Ezin da atzitu DNS zerbitzari pribatua"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> sareak konektagarritasun murriztua du"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Sakatu hala ere konektatzeko"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> erabiltzen ari zara orain"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> Internetera konektatzeko gauza ez denean, <xliff:g id="NEW_NETWORK">%1$s</xliff:g> erabiltzen du gailuak. Agian kostuak ordaindu beharko dituzu."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> erabiltzen ari zinen, baina <xliff:g id="NEW_NETWORK">%2$s</xliff:g> erabiltzen ari zara orain"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"sare mota ezezaguna"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"datu-konexioa"</item> + <item msgid="5520925862115353992">"Wifia"</item> + <item msgid="1055487873974272842">"Bluetooth-a"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-fa/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-fa/strings.xml new file mode 100644 index 000000000000..46a946c50b0e --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-fa/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"ورود به شبکه Wi-Fi"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"ورود به سیستم شبکه"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> به اینترنت دسترسی ندارد"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"برای گزینهها ضربه بزنید"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"شبکه تلفن همراه به اینترنت دسترسی ندارد"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"شبکه به اینترنت دسترسی ندارد"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"سرور DNS خصوصی قابل دسترسی نیست"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> اتصال محدودی دارد"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"بههرصورت، برای اتصال ضربه بزنید"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"به <xliff:g id="NETWORK_TYPE">%1$s</xliff:g> تغییر کرد"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"وقتی <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> به اینترنت دسترسی نداشته باشد، دستگاه از <xliff:g id="NEW_NETWORK">%1$s</xliff:g> استفاده میکند. ممکن است هزینههایی اعمال شود."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"از <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> به <xliff:g id="NEW_NETWORK">%2$s</xliff:g> تغییر کرد"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"نوع شبکه نامشخص"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"داده تلفن همراه"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"بلوتوث"</item> + <item msgid="1616528372438698248">"اترنت"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-fi/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-fi/strings.xml new file mode 100644 index 000000000000..dd944415c9de --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-fi/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Kirjaudu Wi-Fi-verkkoon"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Kirjaudu verkkoon"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> ei ole yhteydessä internetiin"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Näytä vaihtoehdot napauttamalla."</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"Mobiiliverkko ei ole yhteydessä internetiin"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"Verkko ei ole yhteydessä internetiin"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Ei pääsyä yksityiselle DNS-palvelimelle"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> toimii rajoitetulla yhteydellä"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Yhdistä napauttamalla"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> otettiin käyttöön"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"<xliff:g id="NEW_NETWORK">%1$s</xliff:g> otetaan käyttöön, kun <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> ei voi muodostaa yhteyttä internetiin. Veloitukset ovat mahdollisia."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> poistettiin käytöstä ja <xliff:g id="NEW_NETWORK">%2$s</xliff:g> otettiin käyttöön."</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"tuntematon verkon tyyppi"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"mobiilidata"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-fr-rCA/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-fr-rCA/strings.xml new file mode 100644 index 000000000000..02ef50b2c175 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-fr-rCA/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Connectez-vous au réseau Wi-Fi"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Connectez-vous au réseau"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"Le réseau <xliff:g id="NETWORK_SSID">%1$s</xliff:g> n\'offre aucun accès à Internet"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Touchez pour afficher les options"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"Le réseau cellulaire n\'offre aucun accès à Internet"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"Le réseau n\'offre aucun accès à Internet"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Impossible d\'accéder au serveur DNS privé"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"Le réseau <xliff:g id="NETWORK_SSID">%1$s</xliff:g> offre une connectivité limitée"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Touchez pour vous connecter quand même"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"Passé au réseau <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"L\'appareil utilise <xliff:g id="NEW_NETWORK">%1$s</xliff:g> quand <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> n\'a pas d\'accès à Internet. Des frais peuvent s\'appliquer."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"Passé du réseau <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> au <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"un type de réseau inconnu"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"données cellulaires"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"RPV"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-fr/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-fr/strings.xml new file mode 100644 index 000000000000..08c9d8157a11 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-fr/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Connectez-vous au réseau Wi-Fi"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Se connecter au réseau"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"Aucune connexion à Internet pour <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Appuyez ici pour afficher des options."</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"Le réseau mobile ne dispose d\'aucun accès à Internet"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"Le réseau ne dispose d\'aucun accès à Internet"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Impossible d\'accéder au serveur DNS privé"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"La connectivité de <xliff:g id="NETWORK_SSID">%1$s</xliff:g> est limitée"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Appuyer pour se connecter quand même"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"Nouveau réseau : <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"L\'appareil utilise <xliff:g id="NEW_NETWORK">%1$s</xliff:g> lorsque <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> n\'a pas de connexion Internet. Des frais peuvent s\'appliquer."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"Ancien réseau : <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g>. Nouveau réseau : <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"type de réseau inconnu"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"données mobiles"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-gl/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-gl/strings.xml new file mode 100644 index 000000000000..9f98055ab962 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-gl/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Inicia sesión na rede wifi"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Inicia sesión na rede"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> non ten acceso a Internet"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Toca para ver opcións."</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"A rede de telefonía móbil non ten acceso a Internet"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"A rede non ten acceso a Internet"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Non se puido acceder ao servidor DNS privado"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"A conectividade de <xliff:g id="NETWORK_SSID">%1$s</xliff:g> é limitada"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Toca para conectarte de todas formas"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"Cambiouse a: <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"O dispositivo utiliza <xliff:g id="NEW_NETWORK">%1$s</xliff:g> cando <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> non ten acceso a Internet. Pódense aplicar cargos."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"Cambiouse de <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> a <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"un tipo de rede descoñecido"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"datos móbiles"</item> + <item msgid="5520925862115353992">"wifi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-gu/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-gu/strings.xml new file mode 100644 index 000000000000..4ae5a2c45faf --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-gu/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"વાઇ-ફાઇ નેટવર્ક પર સાઇન ઇન કરો"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"નેટવર્ક પર સાઇન ઇન કરો"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> ઇન્ટરનેટ ઍક્સેસ ધરાવતું નથી"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"વિકલ્પો માટે ટૅપ કરો"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"મોબાઇલ નેટવર્ક કોઈ ઇન્ટરનેટ ઍક્સેસ ધરાવતું નથી"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"નેટવર્ક કોઈ ઇન્ટરનેટ ઍક્સેસ ધરાવતું નથી"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"ખાનગી DNS સર્વર ઍક્સેસ કરી શકાતા નથી"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> મર્યાદિત કનેક્ટિવિટી ધરાવે છે"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"છતાં કનેક્ટ કરવા માટે ટૅપ કરો"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> પર સ્વિચ કર્યું"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"જ્યારે <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> પાસે કોઈ ઇન્ટરનેટ ઍક્સેસ ન હોય ત્યારે ઉપકરણ <xliff:g id="NEW_NETWORK">%1$s</xliff:g>નો ઉપયોગ કરે છે. શુલ્ક લાગુ થઈ શકે છે."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> પરથી <xliff:g id="NEW_NETWORK">%2$s</xliff:g> પર સ્વિચ કર્યું"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"અજાણ્યો નેટવર્ક પ્રકાર"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"મોબાઇલ ડેટા"</item> + <item msgid="5520925862115353992">"વાઇ-ફાઇ"</item> + <item msgid="1055487873974272842">"બ્લૂટૂથ"</item> + <item msgid="1616528372438698248">"ઇથરનેટ"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-hi/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-hi/strings.xml new file mode 100644 index 000000000000..eff1b600e487 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-hi/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"वाई-फ़ाई नेटवर्क में साइन इन करें"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"नेटवर्क में साइन इन करें"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> का इंटरनेट नहीं चल रहा है"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"विकल्पों के लिए टैप करें"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"मोबाइल नेटवर्क पर इंटरनेट ऐक्सेस नहीं है"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"इस नेटवर्क पर इंटरनेट ऐक्सेस नहीं है"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"निजी डीएनएस सर्वर को ऐक्सेस नहीं किया जा सकता"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> की कनेक्टिविटी सीमित है"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"फिर भी कनेक्ट करने के लिए टैप करें"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> पर ले जाया गया"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> में इंटरनेट की सुविधा नहीं होने पर डिवाइस <xliff:g id="NEW_NETWORK">%1$s</xliff:g> का इस्तेमाल करता है. इसके लिए शुल्क लिया जा सकता है."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> से <xliff:g id="NEW_NETWORK">%2$s</xliff:g> पर ले जाया गया"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"अज्ञात नेटवर्क प्रकार"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"मोबाइल डेटा"</item> + <item msgid="5520925862115353992">"वाई-फ़ाई"</item> + <item msgid="1055487873974272842">"ब्लूटूथ"</item> + <item msgid="1616528372438698248">"ईथरनेट"</item> + <item msgid="9177085807664964627">"वीपीएन"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-hr/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-hr/strings.xml new file mode 100644 index 000000000000..52bfb936ba08 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-hr/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Prijava na Wi-Fi mrežu"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Prijava na mrežu"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> nema pristup internetu"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Dodirnite za opcije"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"Mobilna mreža nema pristup internetu"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"Mreža nema pristup internetu"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Nije moguće pristupiti privatnom DNS poslužitelju"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> ima ograničenu povezivost"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Dodirnite da biste se ipak povezali"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"Prelazak na drugu mrežu: <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"Kada <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> nema pristup internetu, na uređaju se upotrebljava <xliff:g id="NEW_NETWORK">%1$s</xliff:g>. Moguća je naplata naknade."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"Mreža je promijenjena: <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> > <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"nepoznata vrsta mreže"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"mobilni podaci"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-hu/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-hu/strings.xml new file mode 100644 index 000000000000..2ff59b51733e --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-hu/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Bejelentkezés Wi-Fi hálózatba"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Bejelentkezés a hálózatba"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"A(z) <xliff:g id="NETWORK_SSID">%1$s</xliff:g> hálózaton nincs internet-hozzáférés"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Koppintson a beállítások megjelenítéséhez"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"A mobilhálózaton nincs internet-hozzáférés"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"A hálózaton nincs internet-hozzáférés"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"A privát DNS-kiszolgálóhoz nem lehet hozzáférni"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"A(z) <xliff:g id="NETWORK_SSID">%1$s</xliff:g> hálózat korlátozott kapcsolatot biztosít"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Koppintson, ha mindenképpen csatlakozni szeretne"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"Átváltva erre: <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"<xliff:g id="NEW_NETWORK">%1$s</xliff:g> használata, ha nincs internet-hozzáférés <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g>-kapcsolaton keresztül. A szolgáltató díjat számíthat fel."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"Átváltva <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g>-hálózatról erre: <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"ismeretlen hálózati típus"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"mobiladatok"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-hy/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-hy/strings.xml new file mode 100644 index 000000000000..b35d31c7b681 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-hy/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Մուտք գործեք Wi-Fi ցանց"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Մուտք գործեք ցանց"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> ցանցը չունի մուտք ինտերնետին"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Հպեք՝ ընտրանքները տեսնելու համար"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"Բջջային ցանցը չի ապահովում ինտերնետ կապ"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"Ցանցը միացված չէ ինտերնետին"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Մասնավոր DNS սերվերն անհասանելի է"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> ցանցի կապը սահմանափակ է"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Հպեք՝ միանալու համար"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"Անցել է <xliff:g id="NETWORK_TYPE">%1$s</xliff:g> ցանցի"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"Երբ <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> ցանցում ինտերնետ կապ չի լինում, սարքն անցնում է <xliff:g id="NEW_NETWORK">%1$s</xliff:g> ցանցի: Նման դեպքում կարող են վճարներ գանձվել:"</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> ցանցից անցել է <xliff:g id="NEW_NETWORK">%2$s</xliff:g> ցանցի"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"ցանցի անհայտ տեսակ"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"բջջային ինտերնետ"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-in/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-in/strings.xml new file mode 100644 index 000000000000..27d7d89601b1 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-in/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Login ke jaringan Wi-Fi"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Login ke jaringan"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> tidak memiliki akses internet"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Ketuk untuk melihat opsi"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"Jaringan seluler tidak memiliki akses internet"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"Jaringan tidak memiliki akses internet"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Server DNS pribadi tidak dapat diakses"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> memiliki konektivitas terbatas"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Ketuk untuk tetap menyambungkan"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"Dialihkan ke <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"Perangkat menggunakan <xliff:g id="NEW_NETWORK">%1$s</xliff:g> jika <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> tidak memiliki akses internet. Tarif mungkin berlaku."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"Dialihkan dari <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> ke <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"jenis jaringan yang tidak dikenal"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"data seluler"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-is/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-is/strings.xml new file mode 100644 index 000000000000..97f42dcf07f2 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-is/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Skrá inn á Wi-Fi net"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Skrá inn á net"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> er ekki með internetaðgang"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Ýttu til að sjá valkosti"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"Farsímakerfið er ekki tengt við internetið"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"Netkerfið er ekki tengt við internetið"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Ekki næst í DNS-einkaþjón"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"Tengigeta <xliff:g id="NETWORK_SSID">%1$s</xliff:g> er takmörkuð"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Ýttu til að tengjast samt"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"Skipt yfir á <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"Tækið notar <xliff:g id="NEW_NETWORK">%1$s</xliff:g> þegar <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> er ekki með internetaðgang. Gjöld kunna að eiga við."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"Skipt úr <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> yfir í <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"óþekkt tegund netkerfis"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"farsímagögn"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-it/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-it/strings.xml new file mode 100644 index 000000000000..7836101137fe --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-it/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Accedi a rete Wi-Fi"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Accedi alla rete"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> non ha accesso a Internet"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Tocca per le opzioni"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"La rete mobile non ha accesso a Internet"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"La rete non ha accesso a Internet"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Non è possibile accedere al server DNS privato"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> ha una connettività limitata"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Tocca per connettere comunque"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"Passato a <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"Il dispositivo utilizza <xliff:g id="NEW_NETWORK">%1$s</xliff:g> quando <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> non ha accesso a Internet. Potrebbero essere applicati costi."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"Passato da <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> a <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"tipo di rete sconosciuto"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"dati mobili"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-iw/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-iw/strings.xml new file mode 100644 index 000000000000..f322b995470e --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-iw/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"היכנס לרשת Wi-Fi"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"היכנס לרשת"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"ל-<xliff:g id="NETWORK_SSID">%1$s</xliff:g> אין גישה לאינטרנט"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"הקש לקבלת אפשרויות"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"לרשת הסלולרית אין גישה לאינטרנט"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"לרשת אין גישה לאינטרנט"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"לא ניתן לגשת לשרת DNS הפרטי"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"הקישוריות של <xliff:g id="NETWORK_SSID">%1$s</xliff:g> מוגבלת"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"כדי להתחבר למרות זאת יש להקיש"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"מעבר אל <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"המכשיר משתמש ברשת <xliff:g id="NEW_NETWORK">%1$s</xliff:g> כשלרשת <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> אין גישה לאינטרנט. עשויים לחול חיובים."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"עבר מרשת <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> לרשת <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"סוג רשת לא מזוהה"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"חבילת גלישה"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ja/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ja/strings.xml new file mode 100644 index 000000000000..1aa3216fbcdb --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ja/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Wi-Fiネットワークにログイン"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"ネットワークにログインしてください"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> はインターネットにアクセスできません"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"タップしてその他のオプションを表示"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"モバイル ネットワークがインターネットに接続されていません"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"ネットワークがインターネットに接続されていません"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"プライベート DNS サーバーにアクセスできません"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> の接続が制限されています"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"接続するにはタップしてください"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"「<xliff:g id="NETWORK_TYPE">%1$s</xliff:g>」に切り替えました"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"デバイスで「<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g>」によるインターネット接続ができない場合に「<xliff:g id="NEW_NETWORK">%1$s</xliff:g>」を使用します。通信料が発生することがあります。"</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"「<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g>」から「<xliff:g id="NEW_NETWORK">%2$s</xliff:g>」に切り替えました"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"不明なネットワーク タイプ"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"モバイルデータ"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"イーサネット"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ka/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ka/strings.xml new file mode 100644 index 000000000000..61d21b55a059 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ka/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Wi-Fi ქსელთან დაკავშირება"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"ქსელში შესვლა"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g>-ს არ აქვს ინტერნეტზე წვდომა"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"შეეხეთ ვარიანტების სანახავად"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"მობილურ ქსელს არ აქვს ინტერნეტზე წვდომა"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"ქსელს არ აქვს ინტერნეტზე წვდომა"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"პირად DNS სერვერზე წვდომა შეუძლებელია"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g>-ის კავშირები შეზღუდულია"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"შეეხეთ, თუ მაინც გსურთ დაკავშირება"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"ახლა გამოიყენება <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"თუ <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> ინტერნეტთან კავშირს დაკარგავს, მოწყობილობის მიერ <xliff:g id="NEW_NETWORK">%1$s</xliff:g> იქნება გამოყენებული, რამაც შეიძლება დამატებითი ხარჯები გამოიწვიოს."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"ახლა გამოიყენება <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> (გამოიყენებოდა <xliff:g id="NEW_NETWORK">%2$s</xliff:g>)"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"უცნობი ტიპის ქსელი"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"მობილური ინტერნეტი"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-kk/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-kk/strings.xml new file mode 100644 index 000000000000..969aaef52217 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-kk/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Wi-Fi желісіне кіру"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Желіге кіру"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> желісінің интернетті пайдалану мүмкіндігі шектеулі."</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Опциялар үшін түртіңіз"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"Мобильдік желі интернетке қосылмаған."</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"Желі интернетке қосылмаған."</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Жеке DNS серверіне кіру мүмкін емес."</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> желісінің қосылу мүмкіндігі шектеулі."</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Бәрібір жалғау үшін түртіңіз."</string> + <string name="network_switch_metered" msgid="1531869544142283384">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> желісіне ауысты"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"Құрылғы <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> желісінде интернетпен байланыс жоғалған жағдайда <xliff:g id="NEW_NETWORK">%1$s</xliff:g> желісін пайдаланады. Деректер ақысы алынуы мүмкін."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> желісінен <xliff:g id="NEW_NETWORK">%2$s</xliff:g> желісіне ауысты"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"желі түрі белгісіз"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"мобильдік деректер"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-km/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-km/strings.xml new file mode 100644 index 000000000000..da3c3378601b --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-km/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"ចូលបណ្ដាញវ៉ាយហ្វាយ"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"ចូលទៅបណ្តាញ"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> មិនមានការតភ្ជាប់អ៊ីនធឺណិតទេ"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"ប៉ះសម្រាប់ជម្រើស"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"បណ្ដាញទូរសព្ទចល័តមិនមានការតភ្ជាប់អ៊ីនធឺណិតទេ"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"បណ្ដាញមិនមានការតភ្ជាប់អ៊ីនធឺណិតទេ"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"មិនអាចចូលប្រើម៉ាស៊ីនមេ DNS ឯកជនបានទេ"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> មានការតភ្ជាប់មានកម្រិត"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"មិនអីទេ ចុចភ្ជាប់ចុះ"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"បានប្តូរទៅ <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"ឧបករណ៍ប្រើ <xliff:g id="NEW_NETWORK">%1$s</xliff:g> នៅពេលដែល <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> មិនមានការតភ្ជាប់អ៊ីនធឺណិត។ អាចគិតថ្លៃលើការប្រើប្រាស់ទិន្នន័យ។"</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"បានប្តូរពី <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> ទៅ <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"ប្រភេទបណ្តាញមិនស្គាល់"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"ទិន្នន័យទូរសព្ទចល័ត"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"ប៊្លូធូស"</item> + <item msgid="1616528372438698248">"អ៊ីសឺរណិត"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-kn/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-kn/strings.xml new file mode 100644 index 000000000000..3b5e04773151 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-kn/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"ವೈ-ಫೈ ನೆಟ್ವರ್ಕ್ಗೆ ಸೈನ್ ಇನ್ ಮಾಡಿ"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"ನೆಟ್ವರ್ಕ್ಗೆ ಸೈನ್ ಇನ್ ಮಾಡಿ"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> ಯಾವುದೇ ಇಂಟರ್ನೆಟ್ ಸಂಪರ್ಕವನ್ನು ಹೊಂದಿಲ್ಲ"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"ಆಯ್ಕೆಗಳಿಗೆ ಟ್ಯಾಪ್ ಮಾಡಿ"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"ಮೊಬೈಲ್ ನೆಟ್ವರ್ಕ್ ಯಾವುದೇ ಇಂಟರ್ನೆಟ್ ಪ್ರವೇಶವನ್ನು ಹೊಂದಿಲ್ಲ"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"ನೆಟ್ವರ್ಕ್ ಇಂಟರ್ನೆಟ್ ಪ್ರವೇಶವನ್ನು ಹೊಂದಿಲ್ಲ"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"ಖಾಸಗಿ DNS ಸರ್ವರ್ ಅನ್ನು ಪ್ರವೇಶಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> ಸೀಮಿತ ಸಂಪರ್ಕ ಕಲ್ಪಿಸುವಿಕೆಯನ್ನು ಹೊಂದಿದೆ"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"ಹೇಗಾದರೂ ಸಂಪರ್ಕಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> ಗೆ ಬದಲಾಯಿಸಲಾಗಿದೆ"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> ಇಂಟರ್ನೆಟ್ ಪ್ರವೇಶ ಹೊಂದಿಲ್ಲದಿರುವಾಗ, ಸಾಧನವು <xliff:g id="NEW_NETWORK">%1$s</xliff:g> ಬಳಸುತ್ತದೆ. ಶುಲ್ಕಗಳು ಅನ್ವಯವಾಗಬಹುದು."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> ರಿಂದ <xliff:g id="NEW_NETWORK">%2$s</xliff:g> ಗೆ ಬದಲಾಯಿಸಲಾಗಿದೆ"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"ಅಪರಿಚಿತ ನೆಟ್ವರ್ಕ್ ಪ್ರಕಾರ"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"ಮೊಬೈಲ್ ಡೇಟಾ"</item> + <item msgid="5520925862115353992">"ವೈ-ಫೈ"</item> + <item msgid="1055487873974272842">"ಬ್ಲೂಟೂತ್"</item> + <item msgid="1616528372438698248">"ಇಥರ್ನೆಟ್"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ko/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ko/strings.xml new file mode 100644 index 000000000000..874bd7597049 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ko/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Wi-Fi 네트워크에 로그인"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"네트워크에 로그인"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g>이(가) 인터넷에 액세스할 수 없습니다."</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"탭하여 옵션 보기"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"모바일 네트워크에 인터넷이 연결되어 있지 않습니다."</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"네트워크에 인터넷이 연결되어 있지 않습니다."</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"비공개 DNS 서버에 액세스할 수 없습니다."</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g>에서 연결을 제한했습니다."</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"계속 연결하려면 탭하세요."</string> + <string name="network_switch_metered" msgid="1531869544142283384">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g>(으)로 전환"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g>(으)로 인터넷에 연결할 수 없는 경우 기기에서 <xliff:g id="NEW_NETWORK">%1$s</xliff:g>이(가) 사용됩니다. 요금이 부과될 수 있습니다."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g>에서 <xliff:g id="NEW_NETWORK">%2$s</xliff:g>(으)로 전환"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"알 수 없는 네트워크 유형"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"모바일 데이터"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"블루투스"</item> + <item msgid="1616528372438698248">"이더넷"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ky/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ky/strings.xml new file mode 100644 index 000000000000..1ace4dc8ecf5 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ky/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Wi-Fi түйүнүнө кирүү"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Тармакка кирүү"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> Интернетке туташуусу жок"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Параметрлерди ачуу үчүн таптап коюңуз"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"Мобилдик Интернет жок"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"Тармактын Интернет жок"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Жеке DNS сервери жеткиликсиз"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> байланышы чектелген"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Баары бир туташуу үчүн таптаңыз"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> тармагына которуштурулду"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> тармагы Интернетке туташпай турганда, түзмөгүңүз <xliff:g id="NEW_NETWORK">%1$s</xliff:g> тармагын колдонот. Акы алынышы мүмкүн."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> дегенден <xliff:g id="NEW_NETWORK">%2$s</xliff:g> тармагына которуштурулду"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"белгисиз тармак түрү"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"мобилдик трафик"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-lo/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-lo/strings.xml new file mode 100644 index 000000000000..3db497ef4588 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-lo/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"ເຂົ້າສູ່ລະບົບເຄືອຂ່າຍ Wi-Fi"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"ລົງຊື່ເຂົ້າເຄືອຂ່າຍ"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> ບໍ່ມີການເຊື່ອມຕໍ່ອິນເຕີເນັດ"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"ແຕະເພື່ອເບິ່ງຕົວເລືອກ"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"ເຄືອຂ່າຍມືຖືບໍ່ສາມາດເຂົ້າເຖິງອິນເຕີເນັດໄດ້"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"ເຄືອຂ່າຍບໍ່ສາມາດເຂົ້າເຖິງອິນເຕີເນັດໄດ້"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"ບໍ່ສາມາດເຂົ້າເຖິງເຊີບເວີ DNS ສ່ວນຕົວໄດ້"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> ມີການເຊື່ອມຕໍ່ທີ່ຈຳກັດ"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"ແຕະເພື່ອຢືນຢັນການເຊື່ອມຕໍ່"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"ສະຫຼັບໄປໃຊ້ <xliff:g id="NETWORK_TYPE">%1$s</xliff:g> ແລ້ວ"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"ອຸປະກອນຈະໃຊ້ <xliff:g id="NEW_NETWORK">%1$s</xliff:g> ເມື່ອ <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> ບໍ່ມີການເຊື່ອມຕໍ່ອິນເຕີເນັດ. ອາດມີການຮຽກເກັບຄ່າບໍລິການ."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"ສະຫຼັບຈາກ <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> ໄປໃຊ້ <xliff:g id="NEW_NETWORK">%2$s</xliff:g> ແລ້ວ"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"ບໍ່ຮູ້ຈັກປະເພດເຄືອຂ່າຍ"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"ອິນເຕີເນັດມືຖື"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"ອີເທີເນັດ"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-lt/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-lt/strings.xml new file mode 100644 index 000000000000..c639c1f1a5d6 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-lt/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Prisijungti prie „Wi-Fi“ tinklo"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Prisijungti prie tinklo"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"„<xliff:g id="NETWORK_SSID">%1$s</xliff:g>“ negali pasiekti interneto"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Palieskite, kad būtų rodomos parinktys."</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"Mobiliojo ryšio tinkle nėra prieigos prie interneto"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"Tinkle nėra prieigos prie interneto"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Privataus DNS serverio negalima pasiekti"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"„<xliff:g id="NETWORK_SSID">%1$s</xliff:g>“ ryšys apribotas"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Palieskite, jei vis tiek norite prisijungti"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"Perjungta į tinklą <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"Įrenginyje naudojamas kitas tinklas (<xliff:g id="NEW_NETWORK">%1$s</xliff:g>), kai dabartiniame tinkle (<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g>) nėra interneto ryšio. Gali būti taikomi mokesčiai."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"Perjungta iš tinklo <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> į tinklą <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"nežinomas tinklo tipas"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"mobiliojo ryšio duomenys"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Eternetas"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-lv/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-lv/strings.xml new file mode 100644 index 000000000000..5774603bf50f --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-lv/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Pierakstieties Wi-Fi tīklā"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Pierakstīšanās tīklā"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"Tīklā <xliff:g id="NETWORK_SSID">%1$s</xliff:g> nav piekļuves internetam"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Pieskarieties, lai skatītu iespējas."</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"Mobilajā tīklā nav piekļuves internetam."</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"Tīklā nav piekļuves internetam."</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Nevar piekļūt privātam DNS serverim."</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"Tīklā <xliff:g id="NETWORK_SSID">%1$s</xliff:g> ir ierobežota savienojamība"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Lai tik un tā izveidotu savienojumu, pieskarieties"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"Pārslēdzās uz tīklu <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"Kad vienā tīklā (<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g>) nav piekļuves internetam, ierīcē tiek izmantots cits tīkls (<xliff:g id="NEW_NETWORK">%1$s</xliff:g>). Var tikt piemērota maksa."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"Pārslēdzās no tīkla <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> uz tīklu <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"nezināms tīkla veids"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"mobilie dati"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-mcc204-mnc04/config.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-mcc204-mnc04/config.xml new file mode 100644 index 000000000000..7e7025fb042f --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-mcc204-mnc04/config.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<!-- Configuration values for ConnectivityService + DO NOT EDIT THIS FILE for specific device configuration; instead, use a Runtime Resources + Overlay package following the overlayable.xml configuration in the same directory: + https://source.android.com/devices/architecture/rros --> +<resources> + <!-- Whether the device should automatically switch away from Wi-Fi networks that lose + Internet access. Actual device behaviour is controlled by + Settings.Global.NETWORK_AVOID_BAD_WIFI. This is the default value of that setting. --> + <integer translatable="false" name="config_networkAvoidBadWifi">0</integer> +</resources>
\ No newline at end of file diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-mcc310-mnc004/config.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-mcc310-mnc004/config.xml new file mode 100644 index 000000000000..7e7025fb042f --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-mcc310-mnc004/config.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<!-- Configuration values for ConnectivityService + DO NOT EDIT THIS FILE for specific device configuration; instead, use a Runtime Resources + Overlay package following the overlayable.xml configuration in the same directory: + https://source.android.com/devices/architecture/rros --> +<resources> + <!-- Whether the device should automatically switch away from Wi-Fi networks that lose + Internet access. Actual device behaviour is controlled by + Settings.Global.NETWORK_AVOID_BAD_WIFI. This is the default value of that setting. --> + <integer translatable="false" name="config_networkAvoidBadWifi">0</integer> +</resources>
\ No newline at end of file diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-mcc311-mnc480/config.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-mcc311-mnc480/config.xml new file mode 100644 index 000000000000..7e7025fb042f --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-mcc311-mnc480/config.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<!-- Configuration values for ConnectivityService + DO NOT EDIT THIS FILE for specific device configuration; instead, use a Runtime Resources + Overlay package following the overlayable.xml configuration in the same directory: + https://source.android.com/devices/architecture/rros --> +<resources> + <!-- Whether the device should automatically switch away from Wi-Fi networks that lose + Internet access. Actual device behaviour is controlled by + Settings.Global.NETWORK_AVOID_BAD_WIFI. This is the default value of that setting. --> + <integer translatable="false" name="config_networkAvoidBadWifi">0</integer> +</resources>
\ No newline at end of file diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-mk/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-mk/strings.xml new file mode 100644 index 000000000000..053c7cf93bf2 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-mk/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Најавете се на мрежа на Wi-Fi"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Најавете се на мрежа"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> нема интернет-пристап"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Допрете за опции"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"Мобилната мрежа нема интернет-пристап"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"Мрежата нема интернет-пристап"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Не може да се пристапи до приватниот DNS-сервер"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> има ограничена поврзливост"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Допрете за да се поврзете и покрај тоа"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"Префрлено на <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"Уредот користи <xliff:g id="NEW_NETWORK">%1$s</xliff:g> кога <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> нема пристап до интернет. Може да се наплатат трошоци."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"Префрлено од <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> на <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"непознат тип мрежа"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"мобилен интернет"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Етернет"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ml/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ml/strings.xml new file mode 100644 index 000000000000..3e80cf1cd72b --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ml/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"വൈഫൈ നെറ്റ്വർക്കിലേക്ക് സൈൻ ഇൻ ചെയ്യുക"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"നെറ്റ്വർക്കിലേക്ക് സൈൻ ഇൻ ചെയ്യുക"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> എന്നതിന് ഇന്റർനെറ്റ് ആക്സസ് ഇല്ല"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"ഓപ്ഷനുകൾക്ക് ടാപ്പുചെയ്യുക"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"മൊബെെൽ നെറ്റ്വർക്കിന് ഇന്റർനെറ്റ് ആക്സസ് ഇല്ല"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"നെറ്റ്വർക്കിന് ഇന്റർനെറ്റ് ആക്സസ് ഇല്ല"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"സ്വകാര്യ DNS സെർവർ ആക്സസ് ചെയ്യാനാവില്ല"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> എന്നതിന് പരിമിതമായ കണക്റ്റിവിറ്റി ഉണ്ട്"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"ഏതുവിധേനയും കണക്റ്റ് ചെയ്യാൻ ടാപ്പ് ചെയ്യുക"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> എന്നതിലേക്ക് മാറി"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g>-ന് ഇന്റർനെറ്റ് ആക്സസ് ഇല്ലാത്തപ്പോൾ ഉപകരണം <xliff:g id="NEW_NETWORK">%1$s</xliff:g> ഉപയോഗിക്കുന്നു. നിരക്കുകൾ ബാധകമായേക്കാം."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> നെറ്റ്വർക്കിൽ നിന്ന് <xliff:g id="NEW_NETWORK">%2$s</xliff:g> നെറ്റ്വർക്കിലേക്ക് മാറി"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"തിരിച്ചറിയാനാകാത്ത ഒരു നെറ്റ്വർക്ക് തരം"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"മൊബൈൽ ഡാറ്റ"</item> + <item msgid="5520925862115353992">"വൈഫൈ"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"ഇതര്നെറ്റ്"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-mn/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-mn/strings.xml new file mode 100644 index 000000000000..214fc0c1dd83 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-mn/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Wi-Fi сүлжээнд нэвтэрнэ үү"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Сүлжээнд нэвтэрнэ үү"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g>-д интернэтийн хандалт алга"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Сонголт хийхийн тулд товшино уу"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"Мобайл сүлжээнд интернэт хандалт байхгүй байна"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"Сүлжээнд интернэт хандалт байхгүй байна"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Хувийн DNS серверт хандах боломжгүй байна"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> зарим үйлчилгээнд хандах боломжгүй байна"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Ямар ч тохиолдолд холбогдохын тулд товших"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> руу шилжүүлсэн"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> интернет холболтгүй үед төхөөрөмж <xliff:g id="NEW_NETWORK">%1$s</xliff:g>-г ашигладаг. Төлбөр гарч болзошгүй."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g>-с <xliff:g id="NEW_NETWORK">%2$s</xliff:g> руу шилжүүлсэн"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"сүлжээний тодорхойгүй төрөл"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"мобайл дата"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Этернэт"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-mr/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-mr/strings.xml new file mode 100644 index 000000000000..c4b19989fc7e --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-mr/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"वाय-फाय नेटवर्कमध्ये साइन इन करा"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"नेटवर्कवर साइन इन करा"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> ला इंटरनेट अॅक्सेस नाही"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"पर्यायांसाठी टॅप करा"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"मोबाइल नेटवर्कला इंटरनेट ॲक्सेस नाही"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"नेटवर्कला इंटरनेट ॲक्सेस नाही"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"खाजगी DNS सर्व्हर ॲक्सेस करू शकत नाही"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> ला मर्यादित कनेक्टिव्हिटी आहे"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"तरीही कनेक्ट करण्यासाठी टॅप करा"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> वर स्विच केले"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> कडे इंटरनेटचा अॅक्सेस नसताना डिव्हाइस <xliff:g id="NEW_NETWORK">%1$s</xliff:g> वापरते. शुल्क लागू शकते."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> वरून <xliff:g id="NEW_NETWORK">%2$s</xliff:g> वर स्विच केले"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"अज्ञात नेटवर्क प्रकार"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"मोबाइल डेटा"</item> + <item msgid="5520925862115353992">"वाय-फाय"</item> + <item msgid="1055487873974272842">"ब्लूटूथ"</item> + <item msgid="1616528372438698248">"इथरनेट"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ms/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ms/strings.xml new file mode 100644 index 000000000000..529d0bd466af --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ms/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Log masuk ke rangkaian Wi-Fi"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Log masuk ke rangkaian"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> tiada akses Internet"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Ketik untuk mendapatkan pilihan"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"Rangkaian mudah alih tiada akses Internet"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"Rangkaian tiada akses Internet"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Pelayan DNS peribadi tidak boleh diakses"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> mempunyai kesambungan terhad"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Ketik untuk menyambung juga"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"Beralih kepada <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"Peranti menggunakan <xliff:g id="NEW_NETWORK">%1$s</xliff:g> apabila <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> tiada akses Internet. Bayaran mungkin dikenakan."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"Beralih daripada <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> kepada <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"jenis rangkaian tidak diketahui"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"data mudah alih"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-my/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-my/strings.xml new file mode 100644 index 000000000000..50590fa3fc3e --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-my/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"ဝိုင်ဖိုင်ကွန်ရက်သို့ လက်မှတ်ထိုးဝင်ပါ"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"ကွန်ယက်သို့ လက်မှတ်ထိုးဝင်ရန်"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> တွင် အင်တာနက်အသုံးပြုခွင့် မရှိပါ"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"အခြားရွေးချယ်စရာများကိုကြည့်ရန် တို့ပါ"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"မိုဘိုင်းကွန်ရက်တွင် အင်တာနက်ချိတ်ဆက်မှု မရှိပါ"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"ကွန်ရက်တွင် အင်တာနက်အသုံးပြုခွင့် မရှိပါ"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"သီးသန့် ဒီအန်အက်စ် (DNS) ဆာဗာကို သုံး၍မရပါ။"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> တွင် ချိတ်ဆက်မှုကို ကန့်သတ်ထားသည်"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"မည်သို့ပင်ဖြစ်စေ ချိတ်ဆက်ရန် တို့ပါ"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> သို့ ပြောင်းလိုက်ပြီ"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> ဖြင့် အင်တာနက် အသုံးမပြုနိုင်သည့်အချိန်တွင် စက်ပစ္စည်းသည် <xliff:g id="NEW_NETWORK">%1$s</xliff:g> ကို သုံးပါသည်။ ဒေတာသုံးစွဲခ ကျသင့်နိုင်ပါသည်။"</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> မှ <xliff:g id="NEW_NETWORK">%2$s</xliff:g> သို့ ပြောင်းလိုက်ပြီ"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"အမည်မသိကွန်ရက်အမျိုးအစား"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"မိုဘိုင်းဒေတာ"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"ဘလူးတုသ်"</item> + <item msgid="1616528372438698248">"အီသာနက်"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-nb/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-nb/strings.xml new file mode 100644 index 000000000000..b89d198f380d --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-nb/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Logg på Wi-Fi-nettverket"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Logg på nettverk"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> har ingen internettilkobling"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Trykk for å få alternativer"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"Mobilnettverket har ingen internettilgang"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"Nettverket har ingen internettilgang"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Den private DNS-tjeneren kan ikke nås"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> har begrenset tilkobling"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Trykk for å koble til likevel"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"Byttet til <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"Enheten bruker <xliff:g id="NEW_NETWORK">%1$s</xliff:g> når <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> ikke har Internett-tilgang. Avgifter kan påløpe."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"Byttet fra <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> til <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"en ukjent nettverkstype"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"mobildata"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ne/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ne/strings.xml new file mode 100644 index 000000000000..bdcfa3bfc41b --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ne/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Wi-Fi नेटवर्कमा साइन इन गर्नुहोस्"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"सञ्जालमा साइन इन गर्नुहोस्"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> को इन्टरनेटमाथि पहुँच छैन"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"विकल्पहरूका लागि ट्याप गर्नुहोस्"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"मोबाइल नेटवर्कको इन्टरनेटमाथि पहुँच छैन"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"नेटवर्कको इन्टरनेटमाथि पहुँच छैन"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"निजी DNS सर्भरमाथि पहुँच प्राप्त गर्न सकिँदैन"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> को जडान सीमित छ"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"जसरी भए पनि जडान गर्न ट्याप गर्नुहोस्"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> मा बदल्नुहोस्"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> मार्फत इन्टरनेटमाथि पहुँच राख्न नसकेको अवस्थामा यन्त्रले <xliff:g id="NEW_NETWORK">%1$s</xliff:g> प्रयोग गर्दछ। शुल्क लाग्न सक्छ।"</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> बाट <xliff:g id="NEW_NETWORK">%2$s</xliff:g> मा परिवर्तन गरियो"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"नेटवर्कको कुनै अज्ञात प्रकार"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"मोबाइल डेटा"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"ब्लुटुथ"</item> + <item msgid="1616528372438698248">"इथरनेट"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-nl/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-nl/strings.xml new file mode 100644 index 000000000000..8ecff6e3b540 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-nl/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Inloggen bij wifi-netwerk"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Inloggen bij netwerk"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> heeft geen internettoegang"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Tik voor opties"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"Mobiel netwerk heeft geen internettoegang"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"Netwerk heeft geen internettoegang"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Geen toegang tot privé-DNS-server"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> heeft beperkte connectiviteit"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Tik om toch verbinding te maken"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"Overgeschakeld naar <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"Apparaat gebruikt <xliff:g id="NEW_NETWORK">%1$s</xliff:g> wanneer <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> geen internetverbinding heeft. Er kunnen kosten in rekening worden gebracht."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"Overgeschakeld van <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> naar <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"een onbekend netwerktype"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"mobiele data"</item> + <item msgid="5520925862115353992">"Wifi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-or/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-or/strings.xml new file mode 100644 index 000000000000..6ec1f9d3e42f --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-or/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"ୱାଇ-ଫାଇ ନେଟୱର୍କରେ ସାଇନ୍-ଇନ୍ କରନ୍ତୁ"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"ନେଟ୍ୱର୍କରେ ସାଇନ୍ ଇନ୍ କରନ୍ତୁ"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g>ର ଇଣ୍ଟର୍ନେଟ୍ ଆକ୍ସେସ୍ ନାହିଁ"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"ବିକଳ୍ପ ପାଇଁ ଟାପ୍ କରନ୍ତୁ"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"ମୋବାଇଲ୍ ନେଟ୍ୱାର୍କରେ ଇଣ୍ଟର୍ନେଟ୍ ଆକ୍ସେସ୍ ନାହିଁ"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"ନେଟ୍ୱାର୍କରେ ଇଣ୍ଟର୍ନେଟ୍ ଆକ୍ସେସ୍ ନାହିଁ"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"ବ୍ୟକ୍ତିଗତ DNS ସର୍ଭର୍ ଆକ୍ସେସ୍ କରିହେବ ନାହିଁ"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g>ର ସୀମିତ ସଂଯୋଗ ଅଛି"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"ତଥାପି ଯୋଗାଯୋଗ କରିବାକୁ ଟାପ୍ କରନ୍ତୁ"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g>କୁ ବଦଳାଗଲା"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g>ର ଇଣ୍ଟରନେଟ୍ ଆକ୍ସେସ୍ ନଥିବାବେଳେ ଡିଭାଇସ୍ <xliff:g id="NEW_NETWORK">%1$s</xliff:g> ବ୍ୟବହାର କରିଥାଏ। ଶୁଳ୍କ ଲାଗୁ ହୋଇପାରେ।"</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> ରୁ <xliff:g id="NEW_NETWORK">%2$s</xliff:g>କୁ ବଦଳାଗଲା"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"ଏକ ଅଜଣା ନେଟ୍ୱର୍କ ପ୍ରକାର"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"ମୋବାଇଲ୍ ଡାଟା"</item> + <item msgid="5520925862115353992">"ୱାଇ-ଫାଇ"</item> + <item msgid="1055487873974272842">"ବ୍ଲୁଟୁଥ"</item> + <item msgid="1616528372438698248">"ଇଥରନେଟ୍"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-pa/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-pa/strings.xml new file mode 100644 index 000000000000..e9481932d6c6 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-pa/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕ \'ਤੇ ਸਾਈਨ-ਇਨ ਕਰੋ"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"ਨੈੱਟਵਰਕ \'ਤੇ ਸਾਈਨ-ਇਨ ਕਰੋ"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> ਕੋਲ ਇੰਟਰਨੈੱਟ ਪਹੁੰਚ ਨਹੀਂ ਹੈ"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"ਵਿਕਲਪਾਂ ਲਈ ਟੈਪ ਕਰੋ"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"ਮੋਬਾਈਲ ਨੈੱਟਵਰਕ ਕੋਲ ਇੰਟਰਨੈੱਟ ਤੱਕ ਪਹੁੰਚ ਨਹੀਂ ਹੈ"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"ਨੈੱਟਵਰਕ ਕੋਲ ਇੰਟਰਨੈੱਟ ਤੱਕ ਪਹੁੰਚ ਨਹੀਂ ਹੈ"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"ਨਿੱਜੀ ਡੋਮੇਨ ਨਾਮ ਪ੍ਰਣਾਲੀ (DNS) ਸਰਵਰ \'ਤੇ ਪਹੁੰਚ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕੀ"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> ਕੋਲ ਸੀਮਤ ਕਨੈਕਟੀਵਿਟੀ ਹੈ"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"ਫਿਰ ਵੀ ਕਨੈਕਟ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"ਬਦਲਕੇ <xliff:g id="NETWORK_TYPE">%1$s</xliff:g> ਲਿਆਂਦਾ ਗਿਆ"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> ਦੀ ਇੰਟਰਨੈੱਟ \'ਤੇ ਪਹੁੰਚ ਨਾ ਹੋਣ \'ਤੇ ਡੀਵਾਈਸ <xliff:g id="NEW_NETWORK">%1$s</xliff:g> ਦੀ ਵਰਤੋਂ ਕਰਦਾ ਹੈ। ਖਰਚੇ ਲਾਗੂ ਹੋ ਸਕਦੇ ਹਨ।"</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> ਤੋਂ ਬਦਲਕੇ <xliff:g id="NEW_NETWORK">%2$s</xliff:g> \'ਤੇ ਕੀਤਾ ਗਿਆ"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"ਇੱਕ ਅਗਿਆਤ ਨੈੱਟਵਰਕ ਕਿਸਮ"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"ਮੋਬਾਈਲ ਡਾਟਾ"</item> + <item msgid="5520925862115353992">"ਵਾਈ-ਫਾਈ"</item> + <item msgid="1055487873974272842">"ਬਲੂਟੁੱਥ"</item> + <item msgid="1616528372438698248">"ਈਥਰਨੈੱਟ"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-pl/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-pl/strings.xml new file mode 100644 index 000000000000..038328f0fc8f --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-pl/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Zaloguj się w sieci Wi-Fi"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Zaloguj się do sieci"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> nie ma dostępu do internetu"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Kliknij, by wyświetlić opcje"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"Sieć komórkowa nie ma dostępu do internetu"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"Sieć nie ma dostępu do internetu"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Brak dostępu do prywatnego serwera DNS"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> ma ograniczoną łączność"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Kliknij, by mimo to nawiązać połączenie"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"Zmieniono na połączenie typu <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"Urządzenie korzysta z połączenia typu <xliff:g id="NEW_NETWORK">%1$s</xliff:g>, gdy <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> nie dostępu do internetu. Mogą zostać naliczone opłaty."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"Przełączono z połączenia typu <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> na <xliff:g id="NEW_NETWORK">%2$s</xliff:g>."</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"nieznany typ sieci"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"mobilna transmisja danych"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-pt-rBR/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-pt-rBR/strings.xml new file mode 100644 index 000000000000..fe37405ebe0d --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-pt-rBR/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Fazer login na rede Wi-Fi"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Fazer login na rede"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> não tem acesso à Internet"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Toque para ver opções"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"A rede móvel não tem acesso à Internet"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"A rede não tem acesso à Internet"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Não é possível acessar o servidor DNS privado"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> tem conectividade limitada"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Toque para conectar mesmo assim"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"Alternado para <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"O dispositivo usa <xliff:g id="NEW_NETWORK">%1$s</xliff:g> quando <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> não tem acesso à Internet. Esse serviço pode ser cobrado."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"Alternado de <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> para <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"um tipo de rede desconhecido"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"dados móveis"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-pt-rPT/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-pt-rPT/strings.xml new file mode 100644 index 000000000000..69060f726683 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-pt-rPT/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Iniciar sessão na rede Wi-Fi"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Início de sessão na rede"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> não tem acesso à Internet"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Toque para obter mais opções"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"A rede móvel não tem acesso à Internet"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"A rede não tem acesso à Internet"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Não é possível aceder ao servidor DNS."</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> tem conetividade limitada."</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Toque para ligar mesmo assim."</string> + <string name="network_switch_metered" msgid="1531869544142283384">"Mudou para <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"O dispositivo utiliza <xliff:g id="NEW_NETWORK">%1$s</xliff:g> quando <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> não tem acesso à Internet. Podem aplicar-se custos."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"Mudou de <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> para <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"um tipo de rede desconhecido"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"dados móveis"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-pt/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-pt/strings.xml new file mode 100644 index 000000000000..fe37405ebe0d --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-pt/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Fazer login na rede Wi-Fi"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Fazer login na rede"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> não tem acesso à Internet"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Toque para ver opções"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"A rede móvel não tem acesso à Internet"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"A rede não tem acesso à Internet"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Não é possível acessar o servidor DNS privado"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> tem conectividade limitada"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Toque para conectar mesmo assim"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"Alternado para <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"O dispositivo usa <xliff:g id="NEW_NETWORK">%1$s</xliff:g> quando <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> não tem acesso à Internet. Esse serviço pode ser cobrado."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"Alternado de <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> para <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"um tipo de rede desconhecido"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"dados móveis"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ro/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ro/strings.xml new file mode 100644 index 000000000000..227b7bed706d --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ro/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Conectați-vă la rețeaua Wi-Fi"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Conectați-vă la rețea"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> nu are acces la internet"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Atingeți pentru opțiuni"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"Rețeaua mobilă nu are acces la internet"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"Rețeaua nu are acces la internet"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Serverul DNS privat nu poate fi accesat"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> are conectivitate limitată"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Atingeți pentru a vă conecta oricum"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"S-a comutat la <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"Dispozitivul folosește <xliff:g id="NEW_NETWORK">%1$s</xliff:g> când <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> nu are acces la internet. Se pot aplica taxe."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"S-a comutat de la <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> la <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"un tip de rețea necunoscut"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"date mobile"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ru/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ru/strings.xml new file mode 100644 index 000000000000..18acf81537a7 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ru/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Подключение к Wi-Fi"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Регистрация в сети"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"Сеть \"<xliff:g id="NETWORK_SSID">%1$s</xliff:g>\" не подключена к Интернету"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Нажмите, чтобы показать варианты."</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"Мобильная сеть не подключена к Интернету"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"Сеть не подключена к Интернету"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Доступа к частному DNS-серверу нет."</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"Подключение к сети \"<xliff:g id="NETWORK_SSID">%1$s</xliff:g>\" ограничено"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Нажмите, чтобы подключиться"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"Новое подключение: <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"Устройство использует <xliff:g id="NEW_NETWORK">%1$s</xliff:g>, если подключение к сети <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> недоступно. Может взиматься плата за передачу данных."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"Устройство отключено от сети <xliff:g id="NEW_NETWORK">%2$s</xliff:g> и теперь использует <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"неизвестный тип сети"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"мобильный Интернет"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-si/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-si/strings.xml new file mode 100644 index 000000000000..6307c2b01bdd --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-si/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Wi-Fi ජාලයට පුරනය වන්න"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"ජාලයට පුරනය වන්න"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> හට අන්තර්ජාල ප්රවේශය නැත"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"විකල්ප සඳහා තට්ටු කරන්න"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"ජංගම ජාලවලට අන්තර්ජාල ප්රවේශය නැත"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"ජාලයට අන්තර්ජාල ප්රවේශය නැත"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"පුද්ගලික DNS සේවාදායකයට ප්රවේශ වීමට නොහැකිය"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> හට සීමිත සබැඳුම් හැකියාවක් ඇත"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"කෙසේ වෙතත් ඉදිරියට යාමට තට්ටු කරන්න"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> වෙත මාරු විය"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"උපාංගය <xliff:g id="NEW_NETWORK">%1$s</xliff:g> <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> සඳහා අන්තර්ජාල ප්රවේශය නැති විට භාවිත කරයි. ගාස්තු අදාළ විය හැකිය."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> සිට <xliff:g id="NEW_NETWORK">%2$s</xliff:g> වෙත මාරු විය"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"නොදන්නා ජාල වර්ගයකි"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"ජංගම දත්ත"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"බ්ලූටූත්"</item> + <item msgid="1616528372438698248">"ඊතර්නෙට්"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-sk/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-sk/strings.xml new file mode 100644 index 000000000000..e894fefcf49e --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-sk/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Prihlásiť sa do siete Wi‑Fi"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Prihlásenie do siete"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> nemá prístup k internetu"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Klepnutím získate možnosti"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"Mobilná sieť nemá prístup k internetu"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"Sieť nemá prístup k internetu"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"K súkromnému serveru DNS sa nepodarilo získať prístup"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> má obmedzené pripojenie"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Ak sa chcete aj napriek tomu pripojiť, klepnite"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"Prepnuté na sieť: <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"Keď <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> nemá prístup k internetu, zariadenie používa <xliff:g id="NEW_NETWORK">%1$s</xliff:g>. Môžu sa účtovať poplatky."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"Prepnuté zo siete <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> na sieť <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"neznámy typ siete"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"mobilné dáta"</item> + <item msgid="5520925862115353992">"Wi‑Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-sl/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-sl/strings.xml new file mode 100644 index 000000000000..954b32480eb6 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-sl/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Prijavite se v omrežje Wi-Fi"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Prijava v omrežje"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"Omrežje <xliff:g id="NETWORK_SSID">%1$s</xliff:g> nima dostopa do interneta"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Dotaknite se za možnosti"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"Mobilno omrežje nima dostopa do interneta"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"Omrežje nima dostopa do interneta"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Do zasebnega strežnika DNS ni mogoče dostopati"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"Povezljivost omrežja <xliff:g id="NETWORK_SSID">%1$s</xliff:g> je omejena"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Dotaknite se, da kljub temu vzpostavite povezavo"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"Preklopljeno na omrežje vrste <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"Naprava uporabi omrežje vrste <xliff:g id="NEW_NETWORK">%1$s</xliff:g>, ko omrežje vrste <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> nima dostopa do interneta. Prenos podatkov se lahko zaračuna."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"Preklopljeno z omrežja vrste <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> na omrežje vrste <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"neznana vrsta omrežja"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"prenos podatkov v mobilnem omrežju"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-sq/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-sq/strings.xml new file mode 100644 index 000000000000..bd5d05203452 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-sq/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Identifikohu në rrjetin Wi-Fi"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Identifikohu në rrjet"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> nuk ka qasje në internet"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Trokit për opsionet"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"Rrjeti celular nuk ka qasje në internet"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"Rrjeti nuk ka qasje në internet"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Serveri privat DNS nuk mund të qaset"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> ka lidhshmëri të kufizuar"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Trokit për t\'u lidhur gjithsesi"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"Kaloi te <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"Pajisja përdor <xliff:g id="NEW_NETWORK">%1$s</xliff:g> kur <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> nuk ka qasje në internet. Mund të zbatohen tarifa."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"Kaloi nga <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> te <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"një lloj rrjeti i panjohur"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"të dhënat celulare"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Eternet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-sr/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-sr/strings.xml new file mode 100644 index 000000000000..8bedbffec9a3 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-sr/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Пријављивање на WiFi мрежу"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Пријавите се на мрежу"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> нема приступ интернету"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Додирните за опције"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"Мобилна мрежа нема приступ интернету"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"Мрежа нема приступ интернету"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Приступ приватном DNS серверу није успео"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> има ограничену везу"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Додирните да бисте се ипак повезали"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"Прешли сте на тип мреже <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"Уређај користи тип мреже <xliff:g id="NEW_NETWORK">%1$s</xliff:g> када тип мреже <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> нема приступ интернету. Можда ће се наплаћивати трошкови."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"Прешли сте са типа мреже <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> на тип мреже <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"непознат тип мреже"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"мобилни подаци"</item> + <item msgid="5520925862115353992">"WiFi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Етернет"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-sv/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-sv/strings.xml new file mode 100644 index 000000000000..b3f17630437d --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-sv/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Logga in på ett Wi-Fi-nätverk"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Logga in på nätverket"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> har ingen internetanslutning"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Tryck för alternativ"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"Mobilnätverket har ingen internetanslutning"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"Nätverket har ingen internetanslutning"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Det går inte att komma åt den privata DNS-servern."</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> har begränsad anslutning"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Tryck för att ansluta ändå"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"Byte av nätverk till <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"<xliff:g id="NEW_NETWORK">%1$s</xliff:g> används på enheten när det inte finns internetåtkomst via <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g>. Avgifter kan tillkomma."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"Byte av nätverk från <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> till <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"en okänd nätverkstyp"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"mobildata"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-sw/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-sw/strings.xml new file mode 100644 index 000000000000..9674654c6967 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-sw/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Ingia kwa mtandao wa Wi-Fi"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Ingia katika mtandao"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> haina uwezo wa kufikia intaneti"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Gusa ili upate chaguo"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"Mtandao wa simu hauna uwezo wa kufikia intaneti"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"Mtandao hauna uwezo wa kufikia intaneti"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Seva ya faragha ya DNS haiwezi kufikiwa"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> ina muunganisho unaofikia huduma chache."</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Gusa ili uunganishe tu"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"Sasa inatumia <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"Kifaa hutumia <xliff:g id="NEW_NETWORK">%1$s</xliff:g> wakati <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> haina intaneti. Huenda ukalipishwa."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"Imebadilisha mtandao kutoka <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> na sasa inatumia <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"aina ya mtandao isiyojulikana"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"data ya simu"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethaneti"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ta/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ta/strings.xml new file mode 100644 index 000000000000..12604cbf1c8d --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ta/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"வைஃபை நெட்வொர்க்கில் உள்நுழையவும்"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"நெட்வொர்க்கில் உள்நுழையவும்"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> நெட்வொர்க்கிற்கு இணைய அணுகல் இல்லை"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"விருப்பங்களுக்கு, தட்டவும்"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"மொபைல் நெட்வொர்க்கிற்கு இணைய அணுகல் இல்லை"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"நெட்வொர்க்கிற்கு இணைய அணுகல் இல்லை"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"தனிப்பட்ட DNS சேவையகத்தை அணுக இயலாது"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> வரம்பிற்கு உட்பட்ட இணைப்புநிலையைக் கொண்டுள்ளது"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"எப்படியேனும் இணைப்பதற்குத் தட்டவும்"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g>க்கு மாற்றப்பட்டது"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> நெட்வொர்க்கில் இண்டர்நெட் அணுகல் இல்லாததால், சாதனமானது <xliff:g id="NEW_NETWORK">%1$s</xliff:g> நெட்வொர்க்கைப் பயன்படுத்துகிறது. கட்டணங்கள் விதிக்கப்படலாம்."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> இலிருந்து <xliff:g id="NEW_NETWORK">%2$s</xliff:g>க்கு மாற்றப்பட்டது"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"தெரியாத நெட்வொர்க் வகை"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"மொபைல் டேட்டா"</item> + <item msgid="5520925862115353992">"வைஃபை"</item> + <item msgid="1055487873974272842">"புளூடூத்"</item> + <item msgid="1616528372438698248">"ஈத்தர்நெட்"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-te/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-te/strings.xml new file mode 100644 index 000000000000..84a8640b0727 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-te/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Wi-Fi నెట్వర్క్కి సైన్ ఇన్ చేయండి"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"నెట్వర్క్కి సైన్ ఇన్ చేయండి"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g>కి ఇంటర్నెట్ యాక్సెస్ లేదు"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"ఎంపికల కోసం నొక్కండి"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"మొబైల్ నెట్వర్క్కు ఇంటర్నెట్ యాక్సెస్ లేదు"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"నెట్వర్క్కు ఇంటర్నెట్ యాక్సెస్ లేదు"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"ప్రైవేట్ DNS సర్వర్ను యాక్సెస్ చేయడం సాధ్యపడదు"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> పరిమిత కనెక్టివిటీని కలిగి ఉంది"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"ఏదేమైనా కనెక్ట్ చేయడానికి నొక్కండి"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g>కి మార్చబడింది"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"పరికరం <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g>కి ఇంటర్నెట్ యాక్సెస్ లేనప్పుడు <xliff:g id="NEW_NETWORK">%1$s</xliff:g>ని ఉపయోగిస్తుంది. ఛార్జీలు వర్తించవచ్చు."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> నుండి <xliff:g id="NEW_NETWORK">%2$s</xliff:g>కి మార్చబడింది"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"తెలియని నెట్వర్క్ రకం"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"మొబైల్ డేటా"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"బ్లూటూత్"</item> + <item msgid="1616528372438698248">"ఈథర్నెట్"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-th/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-th/strings.xml new file mode 100644 index 000000000000..1616e5151d3b --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-th/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"ลงชื่อเข้าใช้เครือข่าย WiFi"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"ลงชื่อเข้าใช้เครือข่าย"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> เข้าถึงอินเทอร์เน็ตไม่ได้"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"แตะเพื่อดูตัวเลือก"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"เครือข่ายมือถือไม่มีการเข้าถึงอินเทอร์เน็ต"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"เครือข่ายไม่มีการเข้าถึงอินเทอร์เน็ต"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"เข้าถึงเซิร์ฟเวอร์ DNS ไม่ได้"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> มีการเชื่อมต่อจำกัด"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"แตะเพื่อเชื่อมต่อ"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"เปลี่ยนเป็น <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"อุปกรณ์จะใช้ <xliff:g id="NEW_NETWORK">%1$s</xliff:g> เมื่อ <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> เข้าถึงอินเทอร์เน็ตไม่ได้ โดยอาจมีค่าบริการ"</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"เปลี่ยนจาก <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> เป็น <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"ประเภทเครือข่ายที่ไม่รู้จัก"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"เน็ตมือถือ"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"บลูทูธ"</item> + <item msgid="1616528372438698248">"อีเทอร์เน็ต"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-tl/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-tl/strings.xml new file mode 100644 index 000000000000..3bf1ce494aba --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-tl/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Mag-sign in sa Wi-Fi network"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Mag-sign in sa network"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"Walang access sa internet ang <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"I-tap para sa mga opsyon"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"Walang access sa internet ang mobile network"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"Walang access sa internet ang network"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Hindi ma-access ang pribadong DNS server"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"Limitado ang koneksyon ng <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"I-tap para kumonekta pa rin"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"Lumipat sa <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"Ginagamit ng device ang <xliff:g id="NEW_NETWORK">%1$s</xliff:g> kapag walang access sa internet ang <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g>. Maaaring may mga malapat na singilin."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"Lumipat sa <xliff:g id="NEW_NETWORK">%2$s</xliff:g> mula sa <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"isang hindi kilalang uri ng network"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"mobile data"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-tr/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-tr/strings.xml new file mode 100644 index 000000000000..5c326e5eeec7 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-tr/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Kablosuz ağda oturum açın"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Ağda oturum açın"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> ağının internet bağlantısı yok"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Seçenekler için dokunun"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"Mobil ağın internet bağlantısı yok"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"Ağın internet bağlantısı yok"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Gizli DNS sunucusuna erişilemiyor"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> sınırlı bağlantıya sahip"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Yine de bağlanmak için dokunun"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> ağına geçildi"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> ağının internet erişimi olmadığında cihaz <xliff:g id="NEW_NETWORK">%1$s</xliff:g> ağını kullanır. Bunun için ödeme alınabilir."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> ağından <xliff:g id="NEW_NETWORK">%2$s</xliff:g> ağına geçildi"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"bilinmeyen ağ türü"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"mobil veri"</item> + <item msgid="5520925862115353992">"Kablosuz"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-uk/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-uk/strings.xml new file mode 100644 index 000000000000..d1382da924af --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-uk/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Вхід у мережу Wi-Fi"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Вхід у мережу"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"Мережа <xliff:g id="NETWORK_SSID">%1$s</xliff:g> не має доступу до Інтернету"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Торкніться, щоб відкрити опції"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"Мобільна мережа не має доступу до Інтернету"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"Мережа не має доступу до Інтернету"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Немає доступу до приватного DNS-сервера"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"Підключення до мережі <xliff:g id="NETWORK_SSID">%1$s</xliff:g> обмежено"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Натисніть, щоб усе одно підключитися"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"Пристрій перейшов на мережу <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"Коли мережа <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> не має доступу до Інтернету, використовується <xliff:g id="NEW_NETWORK">%1$s</xliff:g>. Може стягуватися плата."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"Пристрій перейшов з мережі <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> на мережу <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"невідомий тип мережі"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"мобільне передавання даних"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"Мережа VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ur/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ur/strings.xml new file mode 100644 index 000000000000..3c031ad31877 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ur/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Wi-Fi نیٹ ورک میں سائن ان کریں"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"نیٹ ورک میں سائن ان کریں"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> کو انٹرنیٹ تک رسائی حاصل نہیں ہے"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"اختیارات کیلئے تھپتھپائیں"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"موبائل نیٹ ورک کو انٹرنیٹ تک رسائی حاصل نہیں ہے"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"نیٹ ورک کو انٹرنیٹ تک رسائی حاصل نہیں ہے"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"نجی DNS سرور تک رسائی حاصل نہیں کی جا سکی"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> کی کنیکٹوٹی محدود ہے"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"بہر حال منسلک کرنے کے لیے تھپتھپائیں"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> پر سوئچ ہو گیا"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"جب <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> کو انٹرنیٹ تک رسائی نہیں ہوتی ہے تو آلہ <xliff:g id="NEW_NETWORK">%1$s</xliff:g> کا استعمال کرتا ہے۔ چارجز لاگو ہو سکتے ہیں۔"</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> سے <xliff:g id="NEW_NETWORK">%2$s</xliff:g> پر سوئچ ہو گیا"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"نیٹ ورک کی نامعلوم قسم"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"موبائل ڈیٹا"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"بلوٹوتھ"</item> + <item msgid="1616528372438698248">"ایتھرنیٹ"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-uz/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-uz/strings.xml new file mode 100644 index 000000000000..7518db3a7b8c --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-uz/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Wi-Fi tarmoqqa kirish"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Tarmoqqa kirish"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> nomli tarmoqda internetga ruxsati yoʻq"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Variantlarni ko‘rsatish uchun bosing"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"Mobil tarmoq internetga ulanmagan"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"Tarmoq internetga ulanmagan"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Xususiy DNS server ishlamayapti"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> nomli tarmoqda aloqa cheklangan"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Baribir ulash uchun bosing"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"Yangi ulanish: <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"Agar <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> tarmoqda internet uzilsa, qurilma <xliff:g id="NEW_NETWORK">%1$s</xliff:g>ga ulanadi. Sarflangan trafik uchun haq olinishi mumkin."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> tarmog‘idan <xliff:g id="NEW_NETWORK">%2$s</xliff:g> tarmog‘iga o‘tildi"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"noma’lum tarmoq turi"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"mobil internet"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-vi/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-vi/strings.xml new file mode 100644 index 000000000000..d2284d49051b --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-vi/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Đăng nhập vào mạng Wi-Fi"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Đăng nhập vào mạng"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> không có quyền truy cập Internet"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Nhấn để biết tùy chọn"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"Mạng di động không có quyền truy cập Internet"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"Mạng không có quyền truy cập Internet"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Không thể truy cập máy chủ DNS riêng tư"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> có khả năng kết nối giới hạn"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Nhấn để tiếp tục kết nối"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"Đã chuyển sang <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"Thiết bị sử dụng <xliff:g id="NEW_NETWORK">%1$s</xliff:g> khi <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> không có quyền truy cập Internet. Bạn có thể phải trả phí."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"Đã chuyển từ <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> sang <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"loại mạng không xác định"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"dữ liệu di động"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"Bluetooth"</item> + <item msgid="1616528372438698248">"Ethernet"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-zh-rCN/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-zh-rCN/strings.xml new file mode 100644 index 000000000000..813482b4999b --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-zh-rCN/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"登录到WLAN网络"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"登录到网络"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> 无法访问互联网"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"点按即可查看相关选项"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"此移动网络无法访问互联网"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"此网络无法访问互联网"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"无法访问私人 DNS 服务器"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> 的连接受限"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"点按即可继续连接"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"已切换至<xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"设备会在<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g>无法访问互联网时使用<xliff:g id="NEW_NETWORK">%1$s</xliff:g>(可能需要支付相应的费用)。"</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"已从<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g>切换至<xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"未知网络类型"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"移动数据"</item> + <item msgid="5520925862115353992">"WLAN"</item> + <item msgid="1055487873974272842">"蓝牙"</item> + <item msgid="1616528372438698248">"以太网"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-zh-rHK/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-zh-rHK/strings.xml new file mode 100644 index 000000000000..676404fe2ce0 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-zh-rHK/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"登入 Wi-Fi 網絡"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"登入網絡"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g>未有連接至互聯網"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"輕按即可查看選項"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"流動網絡並未連接互聯網"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"網絡並未連接互聯網"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"無法存取私人 DNS 伺服器"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g>連線受限"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"仍要輕按以連結至此網絡"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"已切換至<xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"裝置會在 <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> 無法連線至互聯網時使用<xliff:g id="NEW_NETWORK">%1$s</xliff:g> (可能需要支付相關費用)。"</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"已從<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g>切換至<xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"不明網絡類型"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"流動數據"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"藍牙"</item> + <item msgid="1616528372438698248">"以太網"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-zh-rTW/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-zh-rTW/strings.xml new file mode 100644 index 000000000000..f355138bd6a4 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-zh-rTW/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"登入 Wi-Fi 網路"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"登入網路"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> 沒有網際網路連線"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"輕觸即可查看選項"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"這個行動網路沒有網際網路連線"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"這個網路沒有網際網路連線"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"無法存取私人 DNS 伺服器"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> 的連線能力受限"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"輕觸即可繼續連線"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"已切換至<xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"裝置會在無法連上「<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g>」時切換至「<xliff:g id="NEW_NETWORK">%1$s</xliff:g>」(可能需要支付相關費用)。"</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"已從 <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> 切換至<xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"不明的網路類型"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"行動數據"</item> + <item msgid="5520925862115353992">"Wi-Fi"</item> + <item msgid="1055487873974272842">"藍牙"</item> + <item msgid="1616528372438698248">"乙太網路"</item> + <item msgid="9177085807664964627">"VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-zu/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-zu/strings.xml new file mode 100644 index 000000000000..55fefb793998 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-zu/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_available_sign_in" msgid="381054692557675237">"Ngena ngemvume kunethiwekhi ye-Wi-Fi"</string> + <string name="network_available_sign_in" msgid="1520342291829283114">"Ngena ngemvume kunethiwekhi"</string> + <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) --> + <string name="wifi_no_internet" msgid="1386911698276448061">"I-<xliff:g id="NETWORK_SSID">%1$s</xliff:g> ayinakho ukufinyelela kwe-inthanethi"</string> + <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Thepha ukuze uthole izinketho"</string> + <string name="mobile_no_internet" msgid="4014455157529909781">"Inethiwekhi yeselula ayinakho ukufinyelela kwe-inthanethi"</string> + <string name="other_networks_no_internet" msgid="6698711684200067033">"Inethiwekhi ayinakho ukufinyelela kwenethiwekhi"</string> + <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Iseva eyimfihlo ye-DNS ayikwazi ukufinyelelwa"</string> + <string name="network_partial_connectivity" msgid="4791024923851432291">"I-<xliff:g id="NETWORK_SSID">%1$s</xliff:g> inokuxhumeka okukhawulelwe"</string> + <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Thepha ukuze uxhume noma kunjalo"</string> + <string name="network_switch_metered" msgid="1531869544142283384">"Kushintshelwe ku-<xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> + <string name="network_switch_metered_detail" msgid="1358296010128405906">"Idivayisi isebenzisa i-<xliff:g id="NEW_NETWORK">%1$s</xliff:g> uma i-<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> inganakho ukufinyelela kwe-inthanethi. Kungasebenza izindleko."</string> + <string name="network_switch_metered_toast" msgid="501662047275723743">"Kushintshelewe kusuka ku-<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> kuya ku-<xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> + <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"uhlobo olungaziwa lwenethiwekhi"</string> + <string-array name="network_switch_type_name"> + <item msgid="2255670471736226365">"idatha yeselula"</item> + <item msgid="5520925862115353992">"I-Wi-Fi"</item> + <item msgid="1055487873974272842">"I-Bluetooth"</item> + <item msgid="1616528372438698248">"I-Ethernet"</item> + <item msgid="9177085807664964627">"I-VPN"</item> + </string-array> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values/config.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values/config.xml new file mode 100644 index 000000000000..71674e4dc606 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values/config.xml @@ -0,0 +1,92 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<!-- Configuration values for ConnectivityService + DO NOT EDIT THIS FILE for specific device configuration; instead, use a Runtime Resources + Overlay package following the overlayable.xml configuration in the same directory: + https://source.android.com/devices/architecture/rros --> +<resources> + + <!-- Configuration hook for the URL returned by ConnectivityManager#getCaptivePortalServerUrl. + If empty, the returned value is controlled by Settings.Global.CAPTIVE_PORTAL_HTTP_URL, + and if that value is empty, the framework will use a hard-coded default. + This is *NOT* a URL that will always be used by the system network validation to detect + captive portals: NetworkMonitor may use different strategies and will not necessarily use + this URL. NetworkMonitor behaviour should be configured with NetworkStack resource overlays + instead. --> + <!--suppress CheckTagEmptyBody --> + <string translatable="false" name="config_networkCaptivePortalServerUrl"></string> + + <!-- The maximum duration (in milliseconds) we expect a network transition to take --> + <integer name="config_networkTransitionTimeout">60000</integer> + + <!-- Configuration of network interfaces that support WakeOnLAN --> + <string-array translatable="false" name="config_wakeonlan_supported_interfaces"> + <!-- + <item>wlan0</item> + <item>eth0</item> + --> + </string-array> + + <string-array translatable="false" name="config_legacy_networktype_restore_timers"> + <item>2,60000</item><!-- mobile_mms --> + <item>3,60000</item><!-- mobile_supl --> + <item>4,60000</item><!-- mobile_dun --> + <item>5,60000</item><!-- mobile_hipri --> + <item>10,60000</item><!-- mobile_fota --> + <item>11,60000</item><!-- mobile_ims --> + <item>12,60000</item><!-- mobile_cbs --> + </string-array> + + <!-- Whether the APF Filter in the device should filter out IEEE 802.3 Frames + Those frames are identified by the field Eth-type having values + less than 0x600 --> + <bool translatable="false" name="config_apfDrop802_3Frames">true</bool> + + <!-- An array of Denylisted EtherType, packets with EtherTypes within this array + will be dropped + TODO: need to put proper values, these are for testing purposes only --> + <integer-array translatable="false" name="config_apfEthTypeDenyList"> + <item>0x88A2</item> + <item>0x88A4</item> + <item>0x88B8</item> + <item>0x88CD</item> + <item>0x88E3</item> + </integer-array> + + <!-- Default supported concurrent socket keepalive slots per transport type, used by + ConnectivityManager.createSocketKeepalive() for calculating the number of keepalive + offload slots that should be reserved for privileged access. This string array should be + overridden by the device to present the capability of creating socket keepalives. --> + <!-- An Array of "[NetworkCapabilities.TRANSPORT_*],[supported keepalives] --> + <string-array translatable="false" name="config_networkSupportedKeepaliveCount"> + <item>0,1</item> + <item>1,3</item> + </string-array> + + + <!-- Default value for ConnectivityManager.getMultipathPreference() on metered networks. Actual + device behaviour is controlled by the metered multipath preference in + ConnectivitySettingsManager. This is the default value of that setting. --> + <integer translatable="false" name="config_networkMeteredMultipathPreference">0</integer> + + <!-- Whether the device should automatically switch away from Wi-Fi networks that lose + Internet access. Actual device behaviour is controlled by + Settings.Global.NETWORK_AVOID_BAD_WIFI. This is the default value of that setting. --> + <integer translatable="false" name="config_networkAvoidBadWifi">1</integer> + +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values/overlayable.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values/overlayable.xml new file mode 100644 index 000000000000..25e19cedbbba --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values/overlayable.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8" ?> +<!-- Copyright (C) 2021 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<resources xmlns:android="http://schemas.android.com/apk/res/android"> + <overlayable name="ServiceConnectivityResourcesConfig"> + <policy type="product|system|vendor"> + <!-- Configuration values for ConnectivityService --> + <item type="array" name="config_legacy_networktype_restore_timers"/> + <item type="string" name="config_networkCaptivePortalServerUrl"/> + <item type="integer" name="config_networkTransitionTimeout"/> + <item type="array" name="config_wakeonlan_supported_interfaces"/> + <item type="bool" name="config_apfDrop802_3Frames"/> + <item type="array" name="config_apfEthTypeDenyList"/> + <item type="integer" name="config_networkMeteredMultipathPreference"/> + <item type="array" name="config_networkSupportedKeepaliveCount"/> + <item type="integer" name="config_networkAvoidBadWifi"/> + + </policy> + </overlayable> +</resources> diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values/strings.xml new file mode 100644 index 000000000000..b2fa5f5b4129 --- /dev/null +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values/strings.xml @@ -0,0 +1,74 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <!-- The System Connectivity Resources package is an internal system package that provides + configuration values for system networking that were pre-configured in the device. This + is the name of the package to display in the list of system apps. [CHAR LIMIT=40] --> + <string name="connectivityResourcesAppLabel">System Connectivity Resources</string> + + <!-- A notification is shown when a wifi captive portal network is detected. This is the notification's title. --> + <string name="wifi_available_sign_in">Sign in to Wi-Fi network</string> + + <!-- A notification is shown when a captive portal network is detected. This is the notification's title. --> + <string name="network_available_sign_in">Sign in to network</string> + + <!-- A notification is shown when a captive portal network is detected. This is the notification's message. --> + <string name="network_available_sign_in_detailed"><xliff:g id="network_ssid">%1$s</xliff:g></string> + + <!-- A notification is shown when the user connects to a Wi-Fi network and the system detects that that network has no Internet access. This is the notification's title. --> + <string name="wifi_no_internet"><xliff:g id="network_ssid" example="GoogleGuest">%1$s</xliff:g> has no internet access</string> + + <!-- A notification is shown when the user connects to a Wi-Fi network and the system detects that that network has no Internet access. This is the notification's message. --> + <string name="wifi_no_internet_detailed">Tap for options</string> + + <!-- A notification is shown when the user connects to a mobile network without internet access. This is the notification's title. --> + <string name="mobile_no_internet">Mobile network has no internet access</string> + + <!-- A notification is shown when the user connects to a non-mobile and non-wifi network without internet access. This is the notification's title. --> + <string name="other_networks_no_internet">Network has no internet access</string> + + <!-- A notification is shown when connected network without internet due to private dns validation failed. This is the notification's message. [CHAR LIMIT=NONE] --> + <string name="private_dns_broken_detailed">Private DNS server cannot be accessed</string> + + <!-- A notification is shown when the user connects to a network that doesn't have access to some services (e.g. Push notifications may not work). This is the notification's title. [CHAR LIMIT=50] --> + <string name="network_partial_connectivity"><xliff:g id="network_ssid" example="GoogleGuest">%1$s</xliff:g> has limited connectivity</string> + + <!-- A notification is shown when the user connects to a network that doesn't have access to some services (e.g. Push notifications may not work). This is the notification's message. [CHAR LIMIT=50] --> + <string name="network_partial_connectivity_detailed">Tap to connect anyway</string> + + <!-- A notification might be shown if the device switches to another network type (e.g., mobile data) because it detects that the network it was using (e.g., Wi-Fi) has lost Internet connectivity. This is the notification's title. %1$s is the network type that the device switched to, e.g., cellular data. It is one of the strings in the network_switch_type_name array. --> + <string name="network_switch_metered">Switched to <xliff:g id="network_type">%1$s</xliff:g></string> + + <!-- A notification might be shown if the device switches to another network type (e.g., mobile data) because it detects that the network it was using (e.g., Wi-Fi) has lost Internet connectivity. This is the notification's message. %1$s is the network that the device switched to, e.g., cellular data. %2$s is the network type the device switched from, e.g., Wi-Fi. Both are strings in the network_switch_type_name array. --> + <string name="network_switch_metered_detail">Device uses <xliff:g id="new_network">%1$s</xliff:g> when <xliff:g id="previous_network">%2$s</xliff:g> has no internet access. Charges may apply.</string> + + <!-- A toast might be shown if the device switches to another network type (e.g., mobile data) because it detects that the network it was using (e.g., Wi-Fi) has lost Internet connectivity. This is the text of the toast. %1$s is the network that the device switched from, e.g., Wi-Fi. %2$s is the network type the device switched from, e.g., cellular data. Both are strings in the network_switch_type_name array. --> + <string name="network_switch_metered_toast">Switched from <xliff:g id="previous_network">%1$s</xliff:g> to <xliff:g id="new_network">%2$s</xliff:g></string> + + <!-- Network type names used in the network_switch_metered and network_switch_metered_detail strings. These must be kept in the sync with the values NetworkCapabilities.TRANSPORT_xxx values, and in the same order. --> + <string-array name="network_switch_type_name"> + <item>mobile data</item> + <item>Wi-Fi</item> + <item>Bluetooth</item> + <item>Ethernet</item> + <item>VPN</item> + </string-array> + + <!-- Network type name displayed if one of the types is not found in network_switch_type_name. --> + <string name="network_switch_type_name_unknown">an unknown network type</string> + +</resources> diff --git a/packages/Connectivity/service/jarjar-rules.txt b/packages/Connectivity/service/jarjar-rules.txt index a7b419b020b5..5caa11b11ae4 100644 --- a/packages/Connectivity/service/jarjar-rules.txt +++ b/packages/Connectivity/service/jarjar-rules.txt @@ -12,3 +12,6 @@ rule android.util.LocalLog* com.android.connectivity.util.LocalLog@1 # the one in com.android.internal.util rule android.util.IndentingPrintWriter* android.connectivity.util.IndentingPrintWriter@1 rule com.android.internal.util.** com.android.connectivity.util.@1 + +rule com.android.internal.messages.** com.android.connectivity.messages.@1 +rule com.google.protobuf.** com.android.connectivity.protobuf.@1 diff --git a/packages/Connectivity/service/proto/connectivityproto.proto b/packages/Connectivity/service/proto/connectivityproto.proto new file mode 100644 index 000000000000..a992d7c26368 --- /dev/null +++ b/packages/Connectivity/service/proto/connectivityproto.proto @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2021 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. + */ + +syntax = "proto2"; + +// Connectivity protos can be created in this directory. Note this file must be included before +// building system-messages-proto, otherwise it will not build by itself. diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java index ad459a4c3b93..40a457f3f626 100644 --- a/packages/SettingsLib/src/com/android/settingslib/Utils.java +++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java @@ -22,7 +22,6 @@ import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.location.LocationManager; import android.media.AudioManager; -import android.net.ConnectivityManager; import android.net.TetheringManager; import android.os.BatteryManager; import android.os.SystemProperties; @@ -33,6 +32,7 @@ import android.provider.Settings; import android.telephony.AccessNetworkConstants; import android.telephony.NetworkRegistrationInfo; import android.telephony.ServiceState; +import android.telephony.TelephonyManager; import androidx.annotation.NonNull; import androidx.core.graphics.drawable.RoundedBitmapDrawable; @@ -435,8 +435,7 @@ public class Utils { } public static boolean isWifiOnly(Context context) { - return !context.getSystemService(ConnectivityManager.class) - .isNetworkSupported(ConnectivityManager.TYPE_MOBILE); + return !context.getSystemService(TelephonyManager.class).isDataCapable(); } /** Returns if the automatic storage management feature is turned on or not. **/ diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractIpAddressPreferenceController.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractIpAddressPreferenceController.java index 3bb3a0c412a5..7f12cc8e6911 100644 --- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractIpAddressPreferenceController.java +++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractIpAddressPreferenceController.java @@ -18,6 +18,7 @@ package com.android.settingslib.deviceinfo; import android.content.Context; import android.net.ConnectivityManager; +import android.net.LinkAddress; import android.net.LinkProperties; import android.net.wifi.WifiManager; @@ -28,7 +29,6 @@ import androidx.preference.PreferenceScreen; import com.android.settingslib.R; import com.android.settingslib.core.lifecycle.Lifecycle; -import java.net.InetAddress; import java.util.Iterator; /** @@ -93,19 +93,19 @@ public abstract class AbstractIpAddressPreferenceController * @return the formatted and newline-separated IP addresses, or null if none. */ private static String getDefaultIpAddresses(ConnectivityManager cm) { - LinkProperties prop = cm.getActiveLinkProperties(); + LinkProperties prop = cm.getLinkProperties(cm.getActiveNetwork()); return formatIpAddresses(prop); } private static String formatIpAddresses(LinkProperties prop) { if (prop == null) return null; - Iterator<InetAddress> iter = prop.getAllAddresses().iterator(); + Iterator<LinkAddress> iter = prop.getAllLinkAddresses().iterator(); // If there are no entries, return null if (!iter.hasNext()) return null; // Concatenate all available addresses, newline separated StringBuilder addresses = new StringBuilder(); while (iter.hasNext()) { - addresses.append(iter.next().getHostAddress()); + addresses.append(iter.next().getAddress().getHostAddress()); if (iter.hasNext()) addresses.append("\n"); } return addresses.toString(); diff --git a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java index 092cbf3c7c12..60bcf37304a5 100644 --- a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java +++ b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java @@ -16,7 +16,6 @@ package com.android.settingslib.net; -import static android.net.ConnectivityManager.TYPE_MOBILE; import static android.net.NetworkStatsHistory.FIELD_RX_BYTES; import static android.net.NetworkStatsHistory.FIELD_TX_BYTES; import static android.net.TrafficStats.MB_IN_BYTES; @@ -59,7 +58,6 @@ public class DataUsageController { PERIOD_BUILDER, Locale.getDefault()); private final Context mContext; - private final ConnectivityManager mConnectivityManager; private final INetworkStatsService mStatsService; private final NetworkPolicyManager mPolicyManager; private final NetworkStatsManager mNetworkStatsManager; @@ -71,7 +69,6 @@ public class DataUsageController { public DataUsageController(Context context) { mContext = context; - mConnectivityManager = ConnectivityManager.from(context); mStatsService = INetworkStatsService.Stub.asInterface( ServiceManager.getService(Context.NETWORK_STATS_SERVICE)); mPolicyManager = NetworkPolicyManager.from(mContext); @@ -236,7 +233,7 @@ public class DataUsageController { public boolean isMobileDataSupported() { // require both supported network and ready SIM - return mConnectivityManager.isNetworkSupported(TYPE_MOBILE) + return getTelephonyManager().isDataCapable() && getTelephonyManager().getSimState() == SIM_STATE_READY; } diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java index 6568bffddecc..268603fa8b0d 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java @@ -2445,8 +2445,8 @@ class DatabaseHelper extends SQLiteOpenHelper { R.bool.def_auto_time_zone); // Sync timezone to NITZ loadSetting(stmt, Settings.Global.STAY_ON_WHILE_PLUGGED_IN, - ("1".equals(SystemProperties.get("ro.kernel.qemu")) || - res.getBoolean(R.bool.def_stay_on_while_plugged_in)) + ("1".equals(SystemProperties.get("ro.boot.qemu")) + || res.getBoolean(R.bool.def_stay_on_while_plugged_in)) ? 1 : 0); loadIntegerSetting(stmt, Settings.Global.WIFI_SLEEP_POLICY, diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index 3fed29ac3ce2..b7ce2a30931b 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -367,6 +367,7 @@ <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" /> <uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" /> <uses-permission android:name="android.permission.BIND_RESUME_ON_REBOOT_SERVICE" /> + <uses-permission android:name="android.permission.MANAGE_APP_HIBERNATION"/> <application android:label="@string/app_label" android:theme="@android:style/Theme.DeviceDefault.DayNight" diff --git a/services/core/Android.bp b/services/core/Android.bp index f1ab2aa8b5ec..c40afbfe4f97 100644 --- a/services/core/Android.bp +++ b/services/core/Android.bp @@ -81,9 +81,18 @@ genrule { out: ["services.core.protolog.json"], } +genrule { + name: "statslog-art-java-gen", + tools: ["stats-log-api-gen"], + cmd: "$(location stats-log-api-gen) --java $(out) --module art" + + " --javaPackage com.android.internal.art --javaClass ArtStatsLog --worksource", + out: ["com/android/internal/art/ArtStatsLog.java"], +} + java_library_static { name: "services.core.unboosted", srcs: [ + ":statslog-art-java-gen", ":services.core.protologsrc", ":dumpstate_aidl", ":framework_native_aidl", diff --git a/services/core/java/com/android/server/BluetoothDeviceConfigListener.java b/services/core/java/com/android/server/BluetoothDeviceConfigListener.java index 2dcf82ff9410..611a37de70f4 100644 --- a/services/core/java/com/android/server/BluetoothDeviceConfigListener.java +++ b/services/core/java/com/android/server/BluetoothDeviceConfigListener.java @@ -17,6 +17,9 @@ package com.android.server; import android.provider.DeviceConfig; +import android.util.Slog; + +import java.util.ArrayList; /** * The BluetoothDeviceConfigListener handles system device config change callback and checks @@ -30,10 +33,12 @@ import android.provider.DeviceConfig; class BluetoothDeviceConfigListener { private static final String TAG = "BluetoothDeviceConfigListener"; - BluetoothManagerService mService; + private final BluetoothManagerService mService; + private final boolean mLogDebug; - BluetoothDeviceConfigListener(BluetoothManagerService service) { + BluetoothDeviceConfigListener(BluetoothManagerService service, boolean logDebug) { mService = service; + mLogDebug = logDebug; DeviceConfig.addOnPropertiesChangedListener( DeviceConfig.NAMESPACE_BLUETOOTH, (Runnable r) -> r.run(), @@ -47,6 +52,13 @@ class BluetoothDeviceConfigListener { if (!properties.getNamespace().equals(DeviceConfig.NAMESPACE_BLUETOOTH)) { return; } + if (mLogDebug) { + ArrayList<String> flags = new ArrayList<>(); + for (String name : properties.getKeyset()) { + flags.add(name + "='" + properties.getString(name, "") + "'"); + } + Slog.d(TAG, "onPropertiesChanged: " + String.join(",", flags)); + } boolean foundInit = false; for (String name : properties.getKeyset()) { if (name.startsWith("INIT_")) { diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java index aab05532e2b7..992ef2657a65 100644 --- a/services/core/java/com/android/server/BluetoothManagerService.java +++ b/services/core/java/com/android/server/BluetoothManagerService.java @@ -453,6 +453,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (mHandler.hasMessages(MESSAGE_INIT_FLAGS_CHANGED) && state == BluetoothProfile.STATE_DISCONNECTED && !mBluetoothModeChangeHelper.isA2dpOrHearingAidConnected()) { + Slog.i(TAG, "Device disconnected, reactivating pending flag changes"); onInitFlagsChanged(); } } @@ -810,6 +811,35 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return enabledProfiles; } + private boolean isDeviceProvisioned() { + return Settings.Global.getInt(mContentResolver, Settings.Global.DEVICE_PROVISIONED, + 0) != 0; + } + + // Monitor change of BLE scan only mode settings. + private void registerForProvisioningStateChange() { + ContentObserver contentObserver = new ContentObserver(null) { + @Override + public void onChange(boolean selfChange) { + if (!isDeviceProvisioned()) { + if (DBG) { + Slog.d(TAG, "DEVICE_PROVISIONED setting changed, but device is not " + + "provisioned"); + } + return; + } + if (mHandler.hasMessages(MESSAGE_INIT_FLAGS_CHANGED)) { + Slog.i(TAG, "Device provisioned, reactivating pending flag changes"); + onInitFlagsChanged(); + } + } + }; + + mContentResolver.registerContentObserver( + Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED), false, + contentObserver); + } + // Monitor change of BLE scan only mode settings. private void registerForBleScanModeChange() { ContentObserver contentObserver = new ContentObserver(null) { @@ -1375,7 +1405,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (mBluetoothAirplaneModeListener != null) { mBluetoothAirplaneModeListener.start(mBluetoothModeChangeHelper); } - mBluetoothDeviceConfigListener = new BluetoothDeviceConfigListener(this); + registerForProvisioningStateChange(); + mBluetoothDeviceConfigListener = new BluetoothDeviceConfigListener(this, DBG); } /** @@ -2219,12 +2250,25 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } mHandler.removeMessages(MESSAGE_INIT_FLAGS_CHANGED); if (mBluetoothModeChangeHelper.isA2dpOrHearingAidConnected()) { + Slog.i(TAG, "Delaying MESSAGE_INIT_FLAGS_CHANGED by " + + DELAY_FOR_RETRY_INIT_FLAG_CHECK_MS + + " ms due to existing connections"); + mHandler.sendEmptyMessageDelayed( + MESSAGE_INIT_FLAGS_CHANGED, + DELAY_FOR_RETRY_INIT_FLAG_CHECK_MS); + break; + } + if (!isDeviceProvisioned()) { + Slog.i(TAG, "Delaying MESSAGE_INIT_FLAGS_CHANGED by " + + DELAY_FOR_RETRY_INIT_FLAG_CHECK_MS + + "ms because device is not provisioned"); mHandler.sendEmptyMessageDelayed( MESSAGE_INIT_FLAGS_CHANGED, DELAY_FOR_RETRY_INIT_FLAG_CHECK_MS); break; } if (mBluetooth != null && isEnabled()) { + Slog.i(TAG, "Restarting Bluetooth due to init flag change"); restartForReason( BluetoothProtoEnums.ENABLE_DISABLE_REASON_INIT_FLAGS_CHANGED); } diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index eac9f4de5ae7..39230630966c 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -17,6 +17,10 @@ package com.android.server; import static android.Manifest.permission.RECEIVE_DATA_ACTIVITY_CHANGE; +import static android.content.pm.PackageManager.FEATURE_BLUETOOTH; +import static android.content.pm.PackageManager.FEATURE_WATCH; +import static android.content.pm.PackageManager.FEATURE_WIFI; +import static android.content.pm.PackageManager.FEATURE_WIFI_DIRECT; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport.KEY_NETWORK_PROBES_ATTEMPTED_BITMASK; import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport.KEY_NETWORK_PROBES_SUCCEEDED_BITMASK; @@ -28,15 +32,30 @@ import static android.net.ConnectivityDiagnosticsManager.DataStallReport.KEY_TCP import static android.net.ConnectivityDiagnosticsManager.DataStallReport.KEY_TCP_PACKET_FAIL_RATE; import static android.net.ConnectivityManager.CONNECTIVITY_ACTION; import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC; +import static android.net.ConnectivityManager.TYPE_BLUETOOTH; import static android.net.ConnectivityManager.TYPE_ETHERNET; +import static android.net.ConnectivityManager.TYPE_MOBILE; +import static android.net.ConnectivityManager.TYPE_MOBILE_CBS; +import static android.net.ConnectivityManager.TYPE_MOBILE_DUN; +import static android.net.ConnectivityManager.TYPE_MOBILE_EMERGENCY; +import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA; +import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI; +import static android.net.ConnectivityManager.TYPE_MOBILE_IA; +import static android.net.ConnectivityManager.TYPE_MOBILE_IMS; +import static android.net.ConnectivityManager.TYPE_MOBILE_MMS; +import static android.net.ConnectivityManager.TYPE_MOBILE_SUPL; import static android.net.ConnectivityManager.TYPE_NONE; +import static android.net.ConnectivityManager.TYPE_PROXY; import static android.net.ConnectivityManager.TYPE_VPN; +import static android.net.ConnectivityManager.TYPE_WIFI; +import static android.net.ConnectivityManager.TYPE_WIFI_P2P; import static android.net.ConnectivityManager.getNetworkTypeName; import static android.net.ConnectivityManager.isNetworkTypeValid; import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_PRIVDNS; import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_PARTIAL; import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_VALID; import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL; +import static android.net.NetworkCapabilities.NET_CAPABILITY_ENTERPRISE; import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND; import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED; @@ -50,11 +69,15 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PAID; import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE; import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY; import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; +import static android.net.NetworkCapabilities.REDACT_FOR_ACCESS_FINE_LOCATION; +import static android.net.NetworkCapabilities.REDACT_FOR_LOCAL_MAC_ADDRESS; +import static android.net.NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS; 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; +import static android.net.NetworkPolicyManager.BLOCKED_REASON_NONE; +import static android.net.NetworkPolicyManager.blockedReasonsToString; +import static android.net.NetworkRequest.Type.LISTEN_FOR_BEST; import static android.net.shared.NetworkMonitorUtils.isPrivateDnsValidationRequired; import static android.os.Process.INVALID_UID; import static android.os.Process.VPN_UID; @@ -86,6 +109,9 @@ import android.net.ConnectivityDiagnosticsManager.ConnectivityReport; import android.net.ConnectivityDiagnosticsManager.DataStallReport; import android.net.ConnectivityManager; import android.net.ConnectivityManager.NetworkCallback; +import android.net.ConnectivityManager.RestrictBackgroundStatus; +import android.net.ConnectivityResources; +import android.net.ConnectivitySettingsManager; import android.net.DataStallReportParcelable; import android.net.DnsResolverServiceManager; import android.net.ICaptivePortal; @@ -94,10 +120,10 @@ import android.net.IConnectivityManager; import android.net.IDnsResolver; import android.net.INetd; import android.net.INetworkActivityListener; +import android.net.INetworkAgent; import android.net.INetworkMonitor; import android.net.INetworkMonitorCallbacks; -import android.net.INetworkPolicyListener; -import android.net.IOnSetOemNetworkPreferenceListener; +import android.net.IOnCompleteListener; import android.net.IQosCallback; import android.net.ISocketKeepaliveCallback; import android.net.InetAddresses; @@ -110,13 +136,14 @@ import android.net.Network; import android.net.NetworkAgent; import android.net.NetworkAgentConfig; import android.net.NetworkCapabilities; -import android.net.NetworkConfig; import android.net.NetworkInfo; import android.net.NetworkInfo.DetailedState; import android.net.NetworkMonitorManager; import android.net.NetworkPolicyManager; +import android.net.NetworkPolicyManager.NetworkPolicyCallback; import android.net.NetworkProvider; import android.net.NetworkRequest; +import android.net.NetworkScore; import android.net.NetworkSpecifier; import android.net.NetworkStack; import android.net.NetworkStackClient; @@ -187,18 +214,16 @@ import android.util.Pair; import android.util.SparseArray; import android.util.SparseIntArray; -import com.android.connectivity.aidl.INetworkAgent; -import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.IndentingPrintWriter; -import com.android.internal.util.LocationPermissionChecker; import com.android.internal.util.MessageUtils; import com.android.modules.utils.BasicShellCommandHandler; import com.android.net.module.util.BaseNetdUnsolicitedEventListener; import com.android.net.module.util.CollectionUtils; import com.android.net.module.util.LinkPropertiesUtils.CompareOrUpdateResult; import com.android.net.module.util.LinkPropertiesUtils.CompareResult; +import com.android.net.module.util.LocationPermissionChecker; import com.android.net.module.util.NetworkCapabilitiesUtils; import com.android.net.module.util.PermissionUtils; import com.android.server.connectivity.AutodestructReference; @@ -213,9 +238,9 @@ import com.android.server.connectivity.NetworkNotificationManager; import com.android.server.connectivity.NetworkNotificationManager.NotificationType; import com.android.server.connectivity.NetworkRanker; import com.android.server.connectivity.PermissionMonitor; +import com.android.server.connectivity.ProfileNetworkPreferences; import com.android.server.connectivity.ProxyTracker; import com.android.server.connectivity.QosCallbackTracker; -import com.android.server.net.NetworkPolicyManagerInternal; import libcore.io.IoUtils; @@ -263,7 +288,7 @@ public class ConnectivityService extends IConnectivityManager.Stub /** * Default URL to use for {@link #getCaptivePortalServerUrl()}. This should not be changed * by OEMs for configuration purposes, as this value is overridden by - * Settings.Global.CAPTIVE_PORTAL_HTTP_URL. + * ConnectivitySettingsManager.CAPTIVE_PORTAL_HTTP_URL. * R.string.config_networkCaptivePortalServerUrl should be overridden instead for this purpose * (preferably via runtime resource overlays). */ @@ -296,7 +321,7 @@ public class ConnectivityService extends IConnectivityManager.Stub protected int mNascentDelayMs; // How long to delay to removal of a pending intent based request. - // See Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS + // See ConnectivitySettingsManager.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS private final int mReleasePendingIntentDelayMs; private MockableSystemProperties mSystemProperties; @@ -309,14 +334,13 @@ public class ConnectivityService extends IConnectivityManager.Stub private volatile boolean mLockdownEnabled; /** - * Stale copy of uid rules provided by NPMS. As long as they are accessed only in internal - * handler thread, they don't need a lock. + * Stale copy of uid blocked reasons provided by NPMS. As long as they are accessed only in + * internal handler thread, they don't need a lock. */ - private SparseIntArray mUidRules = new SparseIntArray(); - /** Flag indicating if background data is restricted. */ - private boolean mRestrictBackground; + private SparseIntArray mUidBlockedReasons = new SparseIntArray(); private final Context mContext; + private final ConnectivityResources mResources; // The Context is created for UserHandle.ALL. private final Context mUserAllContext; private final Dependencies mDeps; @@ -329,7 +353,6 @@ public class ConnectivityService extends IConnectivityManager.Stub protected INetd mNetd; private NetworkStatsManager mStatsManager; private NetworkPolicyManager mPolicyManager; - private NetworkPolicyManagerInternal mPolicyManagerInternal; private final NetdCallback mNetdCallback; /** @@ -487,16 +510,6 @@ public class ConnectivityService extends IConnectivityManager.Stub // Handle private DNS validation status updates. private static final int EVENT_PRIVATE_DNS_VALIDATION_UPDATE = 38; - /** - * Used to handle onUidRulesChanged event from NetworkPolicyManagerService. - */ - private static final int EVENT_UID_RULES_CHANGED = 39; - - /** - * Used to handle onRestrictBackgroundChanged event from NetworkPolicyManagerService. - */ - private static final int EVENT_DATA_SAVER_CHANGED = 40; - /** * Event for NetworkMonitor/NetworkAgentInfo to inform ConnectivityService that the network has * been tested. @@ -556,8 +569,8 @@ public class ConnectivityService extends IConnectivityManager.Stub private static final int EVENT_SET_REQUIRE_VPN_FOR_UIDS = 47; /** - * used internally when setting the default networks for OemNetworkPreferences. - * obj = OemNetworkPreferences + * Used internally when setting the default networks for OemNetworkPreferences. + * obj = Pair<OemNetworkPreferences, listener> */ private static final int EVENT_SET_OEM_NETWORK_PREFERENCE = 48; @@ -567,6 +580,19 @@ public class ConnectivityService extends IConnectivityManager.Stub private static final int EVENT_REPORT_NETWORK_ACTIVITY = 49; /** + * Used internally when setting a network preference for a user profile. + * obj = Pair<ProfileNetworkPreference, Listener> + */ + private static final int EVENT_SET_PROFILE_NETWORK_PREFERENCE = 50; + + /** + * Event to specify that reasons for why an uid is blocked changed. + * arg1 = uid + * arg2 = blockedReasons + */ + private static final int EVENT_UID_BLOCKED_REASON_CHANGED = 51; + + /** * Argument for {@link #EVENT_PROVISIONING_NOTIFICATION} to indicate that the notification * should be shown. */ @@ -604,7 +630,6 @@ public class ConnectivityService extends IConnectivityManager.Stub private Intent mInitialBroadcast; private PowerManager.WakeLock mNetTransitionWakeLock; - private int mNetTransitionWakeLockTimeout; private final PowerManager.WakeLock mPendingIntentWakeLock; // A helper object to track the current default HTTP proxy. ConnectivityService needs to tell @@ -616,11 +641,8 @@ public class ConnectivityService extends IConnectivityManager.Stub private UserManager mUserManager; - private NetworkConfig[] mNetConfigs; - private int mNetworksDefined; - // the set of network types that can only be enabled by system/sig apps - private List mProtectedNetworks; + private List<Integer> mProtectedNetworks; private Set<String> mWolSupportedInterfaces; @@ -710,18 +732,63 @@ public class ConnectivityService extends IConnectivityManager.Stub * They are therefore not thread-safe with respect to each other. * - getNetworkForType() can be called at any time on binder threads. It is synchronized * on mTypeLists to be thread-safe with respect to a concurrent remove call. + * - getRestoreTimerForType(type) is also synchronized on mTypeLists. * - dump is thread-safe with respect to concurrent add and remove calls. */ private final ArrayList<NetworkAgentInfo> mTypeLists[]; @NonNull private final ConnectivityService mService; + // Restore timers for requestNetworkForFeature (network type -> timer in ms). Types without + // an entry have no timer (equivalent to -1). Lazily loaded. + @NonNull + private ArrayMap<Integer, Integer> mRestoreTimers = new ArrayMap<>(); + LegacyTypeTracker(@NonNull ConnectivityService service) { mService = service; mTypeLists = new ArrayList[ConnectivityManager.MAX_NETWORK_TYPE + 1]; } - public void addSupportedType(int type) { + public void loadSupportedTypes(@NonNull Context ctx, @NonNull TelephonyManager tm) { + final PackageManager pm = ctx.getPackageManager(); + if (pm.hasSystemFeature(FEATURE_WIFI)) { + addSupportedType(TYPE_WIFI); + } + if (pm.hasSystemFeature(FEATURE_WIFI_DIRECT)) { + addSupportedType(TYPE_WIFI_P2P); + } + if (tm.isDataCapable()) { + // Telephony does not have granular support for these types: they are either all + // supported, or none is supported + addSupportedType(TYPE_MOBILE); + addSupportedType(TYPE_MOBILE_MMS); + addSupportedType(TYPE_MOBILE_SUPL); + addSupportedType(TYPE_MOBILE_DUN); + addSupportedType(TYPE_MOBILE_HIPRI); + addSupportedType(TYPE_MOBILE_FOTA); + addSupportedType(TYPE_MOBILE_IMS); + addSupportedType(TYPE_MOBILE_CBS); + addSupportedType(TYPE_MOBILE_IA); + addSupportedType(TYPE_MOBILE_EMERGENCY); + } + if (pm.hasSystemFeature(FEATURE_BLUETOOTH)) { + addSupportedType(TYPE_BLUETOOTH); + } + if (pm.hasSystemFeature(FEATURE_WATCH)) { + // TYPE_PROXY is only used on Wear + addSupportedType(TYPE_PROXY); + } + // Ethernet is often not specified in the configs, although many devices can use it via + // USB host adapters. Add it as long as the ethernet service is here. + if (ctx.getSystemService(Context.ETHERNET_SERVICE) != null) { + addSupportedType(TYPE_ETHERNET); + } + + // Always add TYPE_VPN as a supported type + addSupportedType(TYPE_VPN); + } + + private void addSupportedType(int type) { if (mTypeLists[type] != null) { throw new IllegalStateException( "legacy list for type " + type + "already initialized"); @@ -742,6 +809,35 @@ public class ConnectivityService extends IConnectivityManager.Stub return null; } + public int getRestoreTimerForType(int type) { + synchronized (mTypeLists) { + if (mRestoreTimers == null) { + mRestoreTimers = loadRestoreTimers(); + } + return mRestoreTimers.getOrDefault(type, -1); + } + } + + private ArrayMap<Integer, Integer> loadRestoreTimers() { + final String[] configs = mService.mResources.get().getStringArray( + com.android.connectivity.resources.R.array + .config_legacy_networktype_restore_timers); + final ArrayMap<Integer, Integer> ret = new ArrayMap<>(configs.length); + for (final String config : configs) { + final String[] splits = TextUtils.split(config, ","); + if (splits.length != 2) { + logwtf("Invalid restore timer token count: " + config); + continue; + } + try { + ret.put(Integer.parseInt(splits[0]), Integer.parseInt(splits[1])); + } catch (NumberFormatException e) { + logwtf("Invalid restore timer number format: " + config, e); + } + } + return ret; + } + private void maybeLogBroadcast(NetworkAgentInfo nai, DetailedState state, int type, boolean isDefaultNetwork) { if (DBG) { @@ -1012,6 +1108,13 @@ public class ConnectivityService extends IConnectivityManager.Stub } /** + * Get the {@link ConnectivityResources} to use in ConnectivityService. + */ + public ConnectivityResources getResources(@NonNull Context ctx) { + return new ConnectivityResources(ctx); + } + + /** * Create a HandlerThread to use in ConnectivityService. */ public HandlerThread makeHandlerThread() { @@ -1093,6 +1196,7 @@ public class ConnectivityService extends IConnectivityManager.Stub mSystemProperties = mDeps.getSystemProperties(); mNetIdManager = mDeps.makeNetIdManager(); mContext = Objects.requireNonNull(context, "missing Context"); + mResources = deps.getResources(mContext); mNetworkRequestCounter = new PerUidCounter(MAX_NETWORK_REQUESTS_PER_UID); mMetricsLog = logger; @@ -1127,7 +1231,7 @@ public class ConnectivityService extends IConnectivityManager.Stub new ConnectivityDiagnosticsHandler(mHandlerThread.getLooper()); mReleasePendingIntentDelayMs = Settings.Secure.getInt(context.getContentResolver(), - Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS, 5_000); + ConnectivitySettingsManager.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS, 5_000); mLingerDelayMs = mSystemProperties.getInt(LINGER_DELAY_PROPERTY, DEFAULT_LINGER_DELAY_MS); // TODO: Consider making the timer customizable. @@ -1135,9 +1239,6 @@ public class ConnectivityService extends IConnectivityManager.Stub mStatsManager = mContext.getSystemService(NetworkStatsManager.class); mPolicyManager = mContext.getSystemService(NetworkPolicyManager.class); - mPolicyManagerInternal = Objects.requireNonNull( - LocalServices.getService(NetworkPolicyManagerInternal.class), - "missing NetworkPolicyManagerInternal"); mDnsResolver = Objects.requireNonNull(dnsresolver, "missing IDnsResolver"); mProxyTracker = mDeps.makeProxyTracker(mContext, mHandler); @@ -1146,86 +1247,28 @@ public class ConnectivityService extends IConnectivityManager.Stub mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); mLocationPermissionChecker = new LocationPermissionChecker(mContext); - // To ensure uid rules are synchronized with Network Policy, register for + // To ensure uid state is synchronized with Network Policy, register for // NetworkPolicyManagerService events must happen prior to NetworkPolicyManagerService // reading existing policy from disk. - mPolicyManager.registerListener(mPolicyListener); + mPolicyManager.registerNetworkPolicyCallback(null, mPolicyCallback); final PowerManager powerManager = (PowerManager) context.getSystemService( Context.POWER_SERVICE); mNetTransitionWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); - mNetTransitionWakeLockTimeout = mContext.getResources().getInteger( - com.android.internal.R.integer.config_networkTransitionTimeout); mPendingIntentWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); - mNetConfigs = new NetworkConfig[ConnectivityManager.MAX_NETWORK_TYPE+1]; - - // TODO: What is the "correct" way to do determine if this is a wifi only device? - boolean wifiOnly = mSystemProperties.getBoolean("ro.radio.noril", false); - log("wifiOnly=" + wifiOnly); - String[] naStrings = context.getResources().getStringArray( - com.android.internal.R.array.networkAttributes); - for (String naString : naStrings) { - try { - NetworkConfig n = new NetworkConfig(naString); - if (VDBG) log("naString=" + naString + " config=" + n); - if (n.type > ConnectivityManager.MAX_NETWORK_TYPE) { - loge("Error in networkAttributes - ignoring attempt to define type " + - n.type); - continue; - } - if (wifiOnly && ConnectivityManager.isNetworkTypeMobile(n.type)) { - log("networkAttributes - ignoring mobile as this dev is wifiOnly " + - n.type); - continue; - } - if (mNetConfigs[n.type] != null) { - loge("Error in networkAttributes - ignoring attempt to redefine type " + - n.type); - continue; - } - mLegacyTypeTracker.addSupportedType(n.type); - - mNetConfigs[n.type] = n; - mNetworksDefined++; - } catch(Exception e) { - // ignore it - leave the entry null - } - } - - // Forcibly add TYPE_VPN as a supported type, if it has not already been added via config. - if (mNetConfigs[TYPE_VPN] == null) { - // mNetConfigs is used only for "restore time", which isn't applicable to VPNs, so we - // don't need to add TYPE_VPN to mNetConfigs. - mLegacyTypeTracker.addSupportedType(TYPE_VPN); - mNetworksDefined++; // used only in the log() statement below. - } - - // Do the same for Ethernet, since it's often not specified in the configs, although many - // devices can use it via USB host adapters. - if (mNetConfigs[TYPE_ETHERNET] == null - && mContext.getSystemService(Context.ETHERNET_SERVICE) != null) { - mLegacyTypeTracker.addSupportedType(TYPE_ETHERNET); - mNetworksDefined++; - } - - if (VDBG) log("mNetworksDefined=" + mNetworksDefined); - - mProtectedNetworks = new ArrayList<Integer>(); + mLegacyTypeTracker.loadSupportedTypes(mContext, mTelephonyManager); + mProtectedNetworks = new ArrayList<>(); int[] protectedNetworks = context.getResources().getIntArray( com.android.internal.R.array.config_protectedNetworks); for (int p : protectedNetworks) { - if ((mNetConfigs[p] != null) && (mProtectedNetworks.contains(p) == false)) { + if (mLegacyTypeTracker.isTypeSupported(p) && !mProtectedNetworks.contains(p)) { mProtectedNetworks.add(p); } else { if (DBG) loge("Ignoring protectedNetwork " + p); } } - mWolSupportedInterfaces = new ArraySet( - mContext.getResources().getStringArray( - com.android.internal.R.array.config_wakeonlan_supported_interfaces)); - mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); mPermissionMonitor = new PermissionMonitor(mContext, mNetd); @@ -1257,10 +1300,10 @@ public class ConnectivityService extends IConnectivityManager.Stub mQosCallbackTracker = new QosCallbackTracker(mHandler, mNetworkRequestCounter); final int dailyLimit = Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.NETWORK_SWITCH_NOTIFICATION_DAILY_LIMIT, + ConnectivitySettingsManager.NETWORK_SWITCH_NOTIFICATION_DAILY_LIMIT, LingerMonitor.DEFAULT_NOTIFICATION_DAILY_LIMIT); final long rateLimit = Settings.Global.getLong(mContext.getContentResolver(), - Settings.Global.NETWORK_SWITCH_NOTIFICATION_RATE_LIMIT_MILLIS, + ConnectivitySettingsManager.NETWORK_SWITCH_NOTIFICATION_RATE_LIMIT_MILLIS, LingerMonitor.DEFAULT_NOTIFICATION_RATE_LIMIT_MILLIS); mLingerMonitor = new LingerMonitor(mContext, mNotifier, dailyLimit, rateLimit); @@ -1271,20 +1314,31 @@ public class ConnectivityService extends IConnectivityManager.Stub mDnsManager = new DnsManager(mContext, mDnsResolver); registerPrivateDnsSettingsCallbacks(); + // This NAI is a sentinel used to offer no service to apps that are on a multi-layer + // request that doesn't allow fallback to the default network. It should never be visible + // to apps. As such, it's not in the list of NAIs and doesn't need many of the normal + // arguments like the handler or the DnsResolver. + // TODO : remove this ; it is probably better handled with a sentinel request. mNoServiceNetwork = new NetworkAgentInfo(null, new Network(NO_SERVICE_NET_ID), new NetworkInfo(TYPE_NONE, 0, "", ""), - new LinkProperties(), new NetworkCapabilities(), 0, mContext, - null, new NetworkAgentConfig(), this, null, - null, 0, INVALID_UID, mQosCallbackTracker, mDeps); + new LinkProperties(), new NetworkCapabilities(), + new NetworkScore.Builder().setLegacyInt(0).build(), mContext, null, + new NetworkAgentConfig(), this, null, null, 0, INVALID_UID, mQosCallbackTracker, + mDeps); } private static NetworkCapabilities createDefaultNetworkCapabilitiesForUid(int uid) { + return createDefaultNetworkCapabilitiesForUidRange(new UidRange(uid, uid)); + } + + private static NetworkCapabilities createDefaultNetworkCapabilitiesForUidRange( + @NonNull final UidRange uids) { final NetworkCapabilities netCap = new NetworkCapabilities(); netCap.addCapability(NET_CAPABILITY_INTERNET); netCap.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED); netCap.removeCapability(NET_CAPABILITY_NOT_VPN); - netCap.setSingleUid(uid); + netCap.setUids(UidRange.toIntRanges(Collections.singleton(uids))); return netCap; } @@ -1367,10 +1421,10 @@ public class ConnectivityService extends IConnectivityManager.Stub } private void handleConfigureAlwaysOnNetworks() { - handleAlwaysOnNetworkRequest( - mDefaultMobileDataRequest, Settings.Global.MOBILE_DATA_ALWAYS_ON, true); - handleAlwaysOnNetworkRequest(mDefaultWifiRequest, Settings.Global.WIFI_ALWAYS_REQUESTED, - false); + handleAlwaysOnNetworkRequest(mDefaultMobileDataRequest, + ConnectivitySettingsManager.MOBILE_DATA_ALWAYS_ON, true /* defaultValue */); + handleAlwaysOnNetworkRequest(mDefaultWifiRequest, + ConnectivitySettingsManager.WIFI_ALWAYS_REQUESTED, false /* defaultValue */); handleAlwaysOnNetworkRequest(mDefaultVehicleRequest, com.android.internal.R.bool.config_vehicleInternalNetworkAlwaysRequested); } @@ -1383,12 +1437,12 @@ public class ConnectivityService extends IConnectivityManager.Stub // Watch for whether or not to keep mobile data always on. mSettingsObserver.observe( - Settings.Global.getUriFor(Settings.Global.MOBILE_DATA_ALWAYS_ON), + Settings.Global.getUriFor(ConnectivitySettingsManager.MOBILE_DATA_ALWAYS_ON), EVENT_CONFIGURE_ALWAYS_ON_NETWORKS); // Watch for whether or not to keep wifi always on. mSettingsObserver.observe( - Settings.Global.getUriFor(Settings.Global.WIFI_ALWAYS_REQUESTED), + Settings.Global.getUriFor(ConnectivitySettingsManager.WIFI_ALWAYS_REQUESTED), EVENT_CONFIGURE_ALWAYS_ON_NETWORKS); } @@ -1720,12 +1774,13 @@ public class ConnectivityService extends IConnectivityManager.Stub nai.network, createWithLocationInfoSanitizedIfNecessaryWhenParceled( nc, false /* includeLocationSensitiveInfo */, - mDeps.getCallingUid(), callingPackageName, callingAttributionTag)); + getCallingPid(), mDeps.getCallingUid(), callingPackageName, + callingAttributionTag)); } } // No need to check mLockdownEnabled. If it's true, getVpnUnderlyingNetworks returns null. - final Network[] networks = getVpnUnderlyingNetworks(Binder.getCallingUid()); + final Network[] networks = getVpnUnderlyingNetworks(mDeps.getCallingUid()); if (null != networks) { for (final Network network : networks) { final NetworkCapabilities nc = getNetworkCapabilitiesInternal(network); @@ -1735,7 +1790,7 @@ public class ConnectivityService extends IConnectivityManager.Stub createWithLocationInfoSanitizedIfNecessaryWhenParceled( nc, false /* includeLocationSensitiveInfo */, - mDeps.getCallingUid(), callingPackageName, + getCallingPid(), mDeps.getCallingUid(), callingPackageName, callingAttributionTag)); } } @@ -1818,7 +1873,7 @@ public class ConnectivityService extends IConnectivityManager.Stub return createWithLocationInfoSanitizedIfNecessaryWhenParceled( getNetworkCapabilitiesInternal(network), false /* includeLocationSensitiveInfo */, - mDeps.getCallingUid(), callingPackageName, callingAttributionTag); + getCallingPid(), mDeps.getCallingUid(), callingPackageName, callingAttributionTag); } @VisibleForTesting @@ -1837,40 +1892,137 @@ public class ConnectivityService extends IConnectivityManager.Stub return newNc; } - private boolean hasLocationPermission(int callerUid, @NonNull String callerPkgName, - @Nullable String callingAttributionTag) { - final long token = Binder.clearCallingIdentity(); - try { - return mLocationPermissionChecker.checkLocationPermission( - callerPkgName, callingAttributionTag, callerUid, null /* message */); - } finally { - Binder.restoreCallingIdentity(token); + /** + * Wrapper used to cache the permission check results performed for the corresponding + * app. This avoid performing multiple permission checks for different fields in + * NetworkCapabilities. + * Note: This wrapper does not support any sort of invalidation and thus must not be + * persistent or long-lived. It may only be used for the time necessary to + * compute the redactions required by one particular NetworkCallback or + * synchronous call. + */ + private class RedactionPermissionChecker { + private final int mCallingPid; + private final int mCallingUid; + @NonNull private final String mCallingPackageName; + @Nullable private final String mCallingAttributionTag; + + private Boolean mHasLocationPermission = null; + private Boolean mHasLocalMacAddressPermission = null; + private Boolean mHasSettingsPermission = null; + + RedactionPermissionChecker(int callingPid, int callingUid, + @NonNull String callingPackageName, @Nullable String callingAttributionTag) { + mCallingPid = callingPid; + mCallingUid = callingUid; + mCallingPackageName = callingPackageName; + mCallingAttributionTag = callingAttributionTag; + } + + private boolean hasLocationPermissionInternal() { + final long token = Binder.clearCallingIdentity(); + try { + return mLocationPermissionChecker.checkLocationPermission( + mCallingPackageName, mCallingAttributionTag, mCallingUid, + null /* message */); + } finally { + Binder.restoreCallingIdentity(token); + } + } + + /** + * Returns whether the app holds location permission or not (might return cached result + * if the permission was already checked before). + */ + public boolean hasLocationPermission() { + if (mHasLocationPermission == null) { + // If there is no cached result, perform the check now. + mHasLocationPermission = hasLocationPermissionInternal(); + } + return mHasLocationPermission; + } + + /** + * Returns whether the app holds local mac address permission or not (might return cached + * result if the permission was already checked before). + */ + public boolean hasLocalMacAddressPermission() { + if (mHasLocalMacAddressPermission == null) { + // If there is no cached result, perform the check now. + mHasLocalMacAddressPermission = + checkLocalMacAddressPermission(mCallingPid, mCallingUid); + } + return mHasLocalMacAddressPermission; + } + + /** + * Returns whether the app holds settings permission or not (might return cached + * result if the permission was already checked before). + */ + public boolean hasSettingsPermission() { + if (mHasSettingsPermission == null) { + // If there is no cached result, perform the check now. + mHasSettingsPermission = checkSettingsPermission(mCallingPid, mCallingUid); + } + return mHasSettingsPermission; + } + } + + private static boolean shouldRedact(@NetworkCapabilities.RedactionType long redactions, + @NetworkCapabilities.NetCapability long redaction) { + return (redactions & redaction) != 0; + } + + /** + * Use the provided |applicableRedactions| to check the receiving app's + * permissions and clear/set the corresponding bit in the returned bitmask. The bitmask + * returned will be used to ensure the necessary redactions are performed by NetworkCapabilities + * before being sent to the corresponding app. + */ + private @NetworkCapabilities.RedactionType long retrieveRequiredRedactions( + @NetworkCapabilities.RedactionType long applicableRedactions, + @NonNull RedactionPermissionChecker redactionPermissionChecker, + boolean includeLocationSensitiveInfo) { + long redactions = applicableRedactions; + if (shouldRedact(redactions, REDACT_FOR_ACCESS_FINE_LOCATION)) { + if (includeLocationSensitiveInfo + && redactionPermissionChecker.hasLocationPermission()) { + redactions &= ~REDACT_FOR_ACCESS_FINE_LOCATION; + } + } + if (shouldRedact(redactions, REDACT_FOR_LOCAL_MAC_ADDRESS)) { + if (redactionPermissionChecker.hasLocalMacAddressPermission()) { + redactions &= ~REDACT_FOR_LOCAL_MAC_ADDRESS; + } } + if (shouldRedact(redactions, REDACT_FOR_NETWORK_SETTINGS)) { + if (redactionPermissionChecker.hasSettingsPermission()) { + redactions &= ~REDACT_FOR_NETWORK_SETTINGS; + } + } + return redactions; } @VisibleForTesting @Nullable NetworkCapabilities createWithLocationInfoSanitizedIfNecessaryWhenParceled( @Nullable NetworkCapabilities nc, boolean includeLocationSensitiveInfo, - int callerUid, @NonNull String callerPkgName, @Nullable String callingAttributionTag) { + int callingPid, int callingUid, @NonNull String callingPkgName, + @Nullable String callingAttributionTag) { if (nc == null) { return null; } - Boolean hasLocationPermission = null; - final NetworkCapabilities newNc; // Avoid doing location permission check if the transport info has no location sensitive // data. - if (includeLocationSensitiveInfo - && nc.getTransportInfo() != null - && nc.getTransportInfo().hasLocationSensitiveFields()) { - hasLocationPermission = - hasLocationPermission(callerUid, callerPkgName, callingAttributionTag); - newNc = new NetworkCapabilities(nc, hasLocationPermission); - } else { - newNc = new NetworkCapabilities(nc, false /* parcelLocationSensitiveFields */); - } + final RedactionPermissionChecker redactionPermissionChecker = + new RedactionPermissionChecker(callingPid, callingUid, callingPkgName, + callingAttributionTag); + final long redactions = retrieveRequiredRedactions( + nc.getApplicableRedactions(), redactionPermissionChecker, + includeLocationSensitiveInfo); + final NetworkCapabilities newNc = new NetworkCapabilities(nc, redactions); // Reset owner uid if not destined for the owner app. - if (callerUid != nc.getOwnerUid()) { + if (callingUid != nc.getOwnerUid()) { newNc.setOwnerUid(INVALID_UID); return newNc; } @@ -1879,23 +2031,17 @@ public class ConnectivityService extends IConnectivityManager.Stub // Owner UIDs already checked above. No need to re-check. return newNc; } - // If the caller does not want location sensitive data & target SDK >= S, then mask info. - // Else include the owner UID iff the caller has location permission to provide backwards + // If the calling does not want location sensitive data & target SDK >= S, then mask info. + // Else include the owner UID iff the calling has location permission to provide backwards // compatibility for older apps. if (!includeLocationSensitiveInfo && isTargetSdkAtleast( - Build.VERSION_CODES.S, callerUid, callerPkgName)) { + Build.VERSION_CODES.S, callingUid, callingPkgName)) { newNc.setOwnerUid(INVALID_UID); return newNc; } - - if (hasLocationPermission == null) { - // Location permission not checked yet, check now for masking owner UID. - hasLocationPermission = - hasLocationPermission(callerUid, callerPkgName, callingAttributionTag); - } // Reset owner uid if the app has no location permission. - if (!hasLocationPermission) { + if (!redactionPermissionChecker.hasLocationPermission()) { newNc.setOwnerUid(INVALID_UID); } return newNc; @@ -1942,6 +2088,18 @@ public class ConnectivityService extends IConnectivityManager.Stub } } + @Override + public @RestrictBackgroundStatus int getRestrictBackgroundStatusByCaller() { + enforceAccessPermission(); + final int callerUid = Binder.getCallingUid(); + final long token = Binder.clearCallingIdentity(); + try { + return mPolicyManager.getRestrictBackgroundStatus(callerUid); + } finally { + Binder.restoreCallingIdentity(token); + } + } + // TODO: Consider delete this function or turn it into a no-op method. @Override public NetworkState[] getAllNetworkState() { @@ -2177,53 +2335,17 @@ public class ConnectivityService extends IConnectivityManager.Stub } } - private final INetworkPolicyListener mPolicyListener = new NetworkPolicyManager.Listener() { + private final NetworkPolicyCallback mPolicyCallback = new NetworkPolicyCallback() { @Override - public void onUidRulesChanged(int uid, int uidRules) { - mHandler.sendMessage(mHandler.obtainMessage(EVENT_UID_RULES_CHANGED, uid, uidRules)); - } - @Override - public void onRestrictBackgroundChanged(boolean restrictBackground) { - // caller is NPMS, since we only register with them - if (LOGD_BLOCKED_NETWORKINFO) { - log("onRestrictBackgroundChanged(restrictBackground=" + restrictBackground + ")"); - } - mHandler.sendMessage(mHandler.obtainMessage( - EVENT_DATA_SAVER_CHANGED, restrictBackground ? 1 : 0, 0)); + public void onUidBlockedReasonChanged(int uid, int blockedReasons) { + mHandler.sendMessage(mHandler.obtainMessage(EVENT_UID_BLOCKED_REASON_CHANGED, + uid, blockedReasons)); } }; - void handleUidRulesChanged(int uid, int newRules) { - // skip update when we've already applied rules - final int oldRules = mUidRules.get(uid, RULE_NONE); - if (oldRules == newRules) return; - - maybeNotifyNetworkBlockedForNewUidRules(uid, newRules); - - if (newRules == RULE_NONE) { - mUidRules.delete(uid); - } else { - mUidRules.put(uid, newRules); - } - } - - void handleRestrictBackgroundChanged(boolean restrictBackground) { - if (mRestrictBackground == restrictBackground) return; - - final List<UidRange> blockedRanges = mVpnBlockedUidRanges; - for (final NetworkAgentInfo nai : mNetworkAgentInfos) { - final boolean curMetered = nai.networkCapabilities.isMetered(); - maybeNotifyNetworkBlocked(nai, curMetered, curMetered, mRestrictBackground, - restrictBackground, blockedRanges, blockedRanges); - } - - mRestrictBackground = restrictBackground; - } - - private boolean isUidBlockedByRules(int uid, int uidRules, boolean isNetworkMetered, - boolean isBackgroundRestricted) { - return mPolicyManager.checkUidNetworkingBlocked(uid, uidRules, isNetworkMetered, - isBackgroundRestricted); + void handleUidBlockedReasonChanged(int uid, int blockedReasons) { + maybeNotifyNetworkBlockedForNewState(uid, blockedReasons); + mUidBlockedReasons.put(uid, blockedReasons); } private boolean checkAnyPermissionOf(String... permissions) { @@ -2410,6 +2532,11 @@ public class ConnectivityService extends IConnectivityManager.Stub mContext.enforceCallingOrSelfPermission(KeepaliveTracker.PERMISSION, "ConnectivityService"); } + private boolean checkLocalMacAddressPermission(int pid, int uid) { + return PERMISSION_GRANTED == mContext.checkPermission( + Manifest.permission.LOCAL_MAC_ADDRESS, pid, uid); + } + private void sendConnectedBroadcast(NetworkInfo info) { sendGeneralBroadcast(info, CONNECTIVITY_ACTION); } @@ -2594,13 +2721,6 @@ public class ConnectivityService extends IConnectivityManager.Stub } catch (RemoteException | ServiceSpecificException e) { loge("Can't set TCP buffer sizes:" + e); } - - final Integer rwndValue = Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.TCP_DEFAULT_INIT_RWND, - mSystemProperties.getInt("net.tcp.default_init_rwnd", 0)); - if (rwndValue != 0) { - mSystemProperties.setTcpInitRwnd(rwndValue); - } } @Override @@ -2617,9 +2737,8 @@ public class ConnectivityService extends IConnectivityManager.Stub // if the system property isn't set, use the value for the apn type int ret = RESTORE_DEFAULT_NETWORK_DELAY; - if ((networkType <= ConnectivityManager.MAX_NETWORK_TYPE) && - (mNetConfigs[networkType] != null)) { - ret = mNetConfigs[networkType].restoreTime; + if (mLegacyTypeTracker.isTypeSupported(networkType)) { + ret = mLegacyTypeTracker.getRestoreTimerForType(networkType); } return ret; } @@ -2705,19 +2824,16 @@ public class ConnectivityService extends IConnectivityManager.Stub pw.decreaseIndent(); pw.println(); - pw.print("Restrict background: "); - pw.println(mRestrictBackground); - pw.println(); - pw.println("Status for known UIDs:"); pw.increaseIndent(); - final int size = mUidRules.size(); + final int size = mUidBlockedReasons.size(); for (int i = 0; i < size; i++) { // Don't crash if the array is modified while dumping in bugreports. try { - final int uid = mUidRules.keyAt(i); - final int uidRules = mUidRules.get(uid, RULE_NONE); - pw.println("UID=" + uid + " rules=" + uidRulesToString(uidRules)); + final int uid = mUidBlockedReasons.keyAt(i); + final int blockedReasons = mUidBlockedReasons.valueAt(i); + pw.println("UID=" + uid + " blockedReasons=" + + blockedReasonsToString(blockedReasons)); } catch (ArrayIndexOutOfBoundsException e) { pw.println(" ArrayIndexOutOfBoundsException"); } catch (ConcurrentModificationException e) { @@ -2852,7 +2968,7 @@ public class ConnectivityService extends IConnectivityManager.Stub if (0 == defaultRequest.mRequests.size()) { pw.println("none, this should never occur."); } else { - pw.println(defaultRequest.mRequests.get(0).networkCapabilities.getUids()); + pw.println(defaultRequest.mRequests.get(0).networkCapabilities.getUidRanges()); } pw.decreaseIndent(); pw.decreaseIndent(); @@ -2947,12 +3063,15 @@ public class ConnectivityService extends IConnectivityManager.Stub break; } case NetworkAgent.EVENT_NETWORK_SCORE_CHANGED: { - updateNetworkScore(nai, msg.arg1); + updateNetworkScore(nai, (NetworkScore) arg.second); break; } case NetworkAgent.EVENT_SET_EXPLICITLY_SELECTED: { if (nai.everConnected) { loge("ERROR: cannot call explicitlySelected on already-connected network"); + // Note that if the NAI had been connected, this would affect the + // score, and therefore would require re-mixing the score and performing + // a rematch. } nai.networkAgentConfig.explicitlySelected = toBool(msg.arg1); nai.networkAgentConfig.acceptUnvalidated = toBool(msg.arg1) && toBool(msg.arg2); @@ -3058,7 +3177,8 @@ public class ConnectivityService extends IConnectivityManager.Stub nai.lastCaptivePortalDetected = visible; nai.everCaptivePortalDetected |= visible; if (nai.lastCaptivePortalDetected && - Settings.Global.CAPTIVE_PORTAL_MODE_AVOID == getCaptivePortalMode()) { + ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE_AVOID + == getCaptivePortalMode()) { if (DBG) log("Avoiding captive portal network: " + nai.toShortString()); nai.onPreventAutomaticReconnect(); teardownUnneededNetwork(nai); @@ -3169,8 +3289,8 @@ public class ConnectivityService extends IConnectivityManager.Stub private int getCaptivePortalMode() { return Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.CAPTIVE_PORTAL_MODE, - Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT); + ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE, + ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE_PROMPT); } private boolean maybeHandleNetworkAgentInfoMessage(Message msg) { @@ -3638,7 +3758,7 @@ public class ConnectivityService extends IConnectivityManager.Stub log("Replacing " + existingRequest.mRequests.get(0) + " with " + nri.mRequests.get(0) + " because their intents matched."); } - handleReleaseNetworkRequest(existingRequest.mRequests.get(0), getCallingUid(), + handleReleaseNetworkRequest(existingRequest.mRequests.get(0), mDeps.getCallingUid(), /* callOnUnavailable */ false); } handleRegisterNetworkRequest(nri); @@ -3654,6 +3774,7 @@ public class ConnectivityService extends IConnectivityManager.Stub mNetworkRequestInfoLogs.log("REGISTER " + nri); for (final NetworkRequest req : nri.mRequests) { mNetworkRequests.put(req, nri); + // TODO: Consider update signal strength for other types. if (req.isListen()) { for (final NetworkAgentInfo network : mNetworkAgentInfos) { if (req.networkCapabilities.hasSignalStrength() @@ -3746,18 +3867,19 @@ public class ConnectivityService extends IConnectivityManager.Stub // listen requests won't keep up a network satisfying it. If this is not a multilayer // request, return immediately. For multilayer requests, check to see if any of the // multilayer requests may have a potential satisfier. - if (!nri.isMultilayerRequest() && nri.mRequests.get(0).isListen()) { + if (!nri.isMultilayerRequest() && (nri.mRequests.get(0).isListen() + || nri.mRequests.get(0).isListenForBest())) { return false; } for (final NetworkRequest req : nri.mRequests) { // This multilayer listen request is satisfied therefore no further requests need to be // evaluated deeming this network not a potential satisfier. - if (req.isListen() && nri.getActiveRequest() == req) { + if ((req.isListen() || req.isListenForBest()) && nri.getActiveRequest() == req) { return false; } // As non-multilayer listen requests have already returned, the below would only happen // for a multilayer request therefore continue to the next request if available. - if (req.isListen()) { + if (req.isListen() || req.isListenForBest()) { continue; } // If this Network is already the highest scoring Network for a request, or if @@ -3797,8 +3919,7 @@ public class ConnectivityService extends IConnectivityManager.Stub ? mNetworkRequests.get(request) : getNriForAppRequest(request); if (nri != null) { - if (Process.SYSTEM_UID != callingUid && Process.NETWORK_STACK_UID != callingUid - && nri.mUid != callingUid) { + if (Process.SYSTEM_UID != callingUid && nri.mUid != callingUid) { log(String.format("UID %d attempted to %s for unowned request %s", callingUid, requestedOperation, nri)); return null; @@ -4035,6 +4156,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // network, we should respect the user's option and don't need to popup the // PARTIAL_CONNECTIVITY notification to user again. nai.networkAgentConfig.acceptPartialConnectivity = accept; + nai.updateScoreForNetworkAgentConfigUpdate(); rematchAllNetworksAndRequests(); sendUpdatedScoreToFactories(nai); } @@ -4297,7 +4419,7 @@ public class ConnectivityService extends IConnectivityManager.Stub Intent intent = new Intent(action); if (type != NotificationType.PRIVATE_DNS_BROKEN) { - intent.setData(Uri.fromParts("netId", Integer.toString(nai.network.getNetId()), null)); + intent.putExtra(ConnectivityManager.EXTRA_NETWORK, nai.network); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // Some OEMs have their own Settings package. Thus, need to get the current using // Settings package name instead of just use default name "com.android.settings". @@ -4393,7 +4515,13 @@ public class ConnectivityService extends IConnectivityManager.Stub final NetworkPolicyManager netPolicyManager = mContext.getSystemService(NetworkPolicyManager.class); - final int networkPreference = netPolicyManager.getMultipathPreference(network); + final long token = Binder.clearCallingIdentity(); + final int networkPreference; + try { + networkPreference = netPolicyManager.getMultipathPreference(network); + } finally { + Binder.restoreCallingIdentity(token); + } if (networkPreference != 0) { return networkPreference; } @@ -4512,22 +4640,24 @@ public class ConnectivityService extends IConnectivityManager.Stub handlePrivateDnsValidationUpdate( (PrivateDnsValidationUpdate) msg.obj); break; - case EVENT_UID_RULES_CHANGED: - handleUidRulesChanged(msg.arg1, msg.arg2); - break; - case EVENT_DATA_SAVER_CHANGED: - handleRestrictBackgroundChanged(toBool(msg.arg1)); + case EVENT_UID_BLOCKED_REASON_CHANGED: + handleUidBlockedReasonChanged(msg.arg1, msg.arg2); break; case EVENT_SET_REQUIRE_VPN_FOR_UIDS: handleSetRequireVpnForUids(toBool(msg.arg1), (UidRange[]) msg.obj); break; case EVENT_SET_OEM_NETWORK_PREFERENCE: { - final Pair<OemNetworkPreferences, IOnSetOemNetworkPreferenceListener> arg = - (Pair<OemNetworkPreferences, - IOnSetOemNetworkPreferenceListener>) msg.obj; + final Pair<OemNetworkPreferences, IOnCompleteListener> arg = + (Pair<OemNetworkPreferences, IOnCompleteListener>) msg.obj; handleSetOemNetworkPreference(arg.first, arg.second); break; } + case EVENT_SET_PROFILE_NETWORK_PREFERENCE: { + final Pair<ProfileNetworkPreferences.Preference, IOnCompleteListener> arg = + (Pair<ProfileNetworkPreferences.Preference, IOnCompleteListener>) + msg.obj; + handleSetProfileNetworkPreference(arg.first, arg.second); + } case EVENT_REPORT_NETWORK_ACTIVITY: mNetworkActivityTracker.handleReportNetworkActivity(); break; @@ -4601,7 +4731,9 @@ public class ConnectivityService extends IConnectivityManager.Stub } mWakelockLogs.log("ACQUIRE for " + forWhom); Message msg = mHandler.obtainMessage(EVENT_EXPIRE_NET_TRANSITION_WAKELOCK); - mHandler.sendMessageDelayed(msg, mNetTransitionWakeLockTimeout); + final int lockTimeout = mResources.get().getInteger( + com.android.connectivity.resources.R.integer.config_networkTransitionTimeout); + mHandler.sendMessageDelayed(msg, lockTimeout); } // Called when we gain a new default network to release the network transition wakelock in a @@ -4824,6 +4956,10 @@ public class ConnectivityService extends IConnectivityManager.Stub Log.wtf(TAG, s); } + private static void logwtf(String s, Throwable t) { + Log.wtf(TAG, s, t); + } + private static void loge(String s) { Log.e(TAG, s); } @@ -4978,8 +5114,8 @@ public class ConnectivityService extends IConnectivityManager.Stub for (final NetworkAgentInfo nai : mNetworkAgentInfos) { final boolean curMetered = nai.networkCapabilities.isMetered(); - maybeNotifyNetworkBlocked(nai, curMetered, curMetered, mRestrictBackground, - mRestrictBackground, mVpnBlockedUidRanges, newVpnBlockedUidRanges); + maybeNotifyNetworkBlocked(nai, curMetered, curMetered, + mVpnBlockedUidRanges, newVpnBlockedUidRanges); } mVpnBlockedUidRanges = newVpnBlockedUidRanges; @@ -5096,6 +5232,9 @@ public class ConnectivityService extends IConnectivityManager.Stub private void onUserRemoved(UserHandle user) { mPermissionMonitor.onUserRemoved(user); + // If there was a network preference for this user, remove it. + handleSetProfileNetworkPreference(new ProfileNetworkPreferences.Preference(user, null), + null /* listener */); if (mOemNetworkPreferences.getNetworkPreferences().size() > 0) { handleSetOemNetworkPreference(mOemNetworkPreferences, null); } @@ -5254,9 +5393,8 @@ public class ConnectivityService extends IConnectivityManager.Stub private Set<UidRange> getUids() { // networkCapabilities.getUids() returns a defensive copy. // multilayer requests will all have the same uids so return the first one. - final Set<UidRange> uids = null == mRequests.get(0).networkCapabilities.getUids() - ? new ArraySet<>() : mRequests.get(0).networkCapabilities.getUids(); - return uids; + final Set<UidRange> uids = mRequests.get(0).networkCapabilities.getUidRanges(); + return (null == uids) ? new ArraySet<>() : uids; } NetworkRequestInfo(@NonNull final NetworkRequest r, @Nullable final PendingIntent pi, @@ -5539,8 +5677,10 @@ public class ConnectivityService extends IConnectivityManager.Stub // request if the app changes network state. http://b/29964605 enforceMeteredApnPolicy(networkCapabilities); break; - case TRACK_BEST: - throw new UnsupportedOperationException("Not implemented yet"); + case LISTEN_FOR_BEST: + enforceAccessPermission(); + networkCapabilities = new NetworkCapabilities(networkCapabilities); + break; default: throw new IllegalArgumentException("Unsupported request type " + reqType); } @@ -5548,11 +5688,17 @@ public class ConnectivityService extends IConnectivityManager.Stub ensureSufficientPermissionsForRequest(networkCapabilities, Binder.getCallingPid(), callingUid, callingPackageName); - // Set the UID range for this request to the single UID of the requester, or to an empty - // set of UIDs if the caller has the appropriate permission and UIDs have not been set. + // Enforce FOREGROUND if the caller does not have permission to use background network. + if (reqType == LISTEN_FOR_BEST) { + restrictBackgroundRequestForCaller(networkCapabilities); + } + + // Set the UID range for this request to the single UID of the requester, unless the + // requester has the permission to specify other UIDs. // This will overwrite any allowed UIDs in the requested capabilities. Though there // are no visible methods to set the UIDs, an app could use reflection to try and get // networks for other apps so it's essential that the UIDs are overwritten. + // Also set the requester UID and package name in the request. restrictRequestUidsForCallerAndSetRequestorInfo(networkCapabilities, callingUid, callingPackageName); @@ -5701,14 +5847,14 @@ public class ConnectivityService extends IConnectivityManager.Stub private void releasePendingNetworkRequestWithDelay(PendingIntent operation) { mHandler.sendMessageDelayed( mHandler.obtainMessage(EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT, - getCallingUid(), 0, operation), mReleasePendingIntentDelayMs); + mDeps.getCallingUid(), 0, operation), mReleasePendingIntentDelayMs); } @Override public void releasePendingNetworkRequest(PendingIntent operation) { Objects.requireNonNull(operation, "PendingIntent cannot be null."); mHandler.sendMessage(mHandler.obtainMessage(EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT, - getCallingUid(), 0, operation)); + mDeps.getCallingUid(), 0, operation)); } // In order to implement the compatibility measure for pre-M apps that call @@ -5805,7 +5951,7 @@ public class ConnectivityService extends IConnectivityManager.Stub public void releaseNetworkRequest(NetworkRequest networkRequest) { ensureNetworkRequestHasType(networkRequest); mHandler.sendMessage(mHandler.obtainMessage( - EVENT_RELEASE_NETWORK_REQUEST, getCallingUid(), 0, networkRequest)); + EVENT_RELEASE_NETWORK_REQUEST, mDeps.getCallingUid(), 0, networkRequest)); } private void handleRegisterNetworkProvider(NetworkProviderInfo npi) { @@ -5886,10 +6032,16 @@ public class ConnectivityService extends IConnectivityManager.Stub @GuardedBy("mBlockedAppUids") private final HashSet<Integer> mBlockedAppUids = new HashSet<>(); - // Current OEM network preferences. + // Current OEM network preferences. This object must only be written to on the handler thread. + // Since it is immutable and always non-null, other threads may read it if they only care + // about seeing a consistent object but not that it is current. @NonNull private OemNetworkPreferences mOemNetworkPreferences = new OemNetworkPreferences.Builder().build(); + // Current per-profile network preferences. This object follows the same threading rules as + // the OEM network preferences above. + @NonNull + private ProfileNetworkPreferences mProfileNetworkPreferences = new ProfileNetworkPreferences(); // The always-on request for an Internet-capable network that apps without a specific default // fall back to. @@ -6048,7 +6200,7 @@ public class ConnectivityService extends IConnectivityManager.Stub for (final NetworkRequestInfo nri : mDefaultNetworkRequests) { // Currently, all network requests will have the same uids therefore checking the first // one is sufficient. If/when uids are tracked at the nri level, this can change. - final Set<UidRange> uids = nri.mRequests.get(0).networkCapabilities.getUids(); + final Set<UidRange> uids = nri.mRequests.get(0).networkCapabilities.getUidRanges(); if (null == uids) { continue; } @@ -6079,20 +6231,6 @@ public class ConnectivityService extends IConnectivityManager.Stub return nai == getDefaultNetwork(); } - // TODO : remove this method. It's a stopgap measure to help sheperding a number of dependent - // changes that would conflict throughout the automerger graph. Having this method temporarily - // helps with the process of going through with all these dependent changes across the entire - // tree. - /** - * Register a new agent. {@see #registerNetworkAgent} below. - */ - public Network registerNetworkAgent(INetworkAgent na, NetworkInfo networkInfo, - LinkProperties linkProperties, NetworkCapabilities networkCapabilities, - int currentScore, NetworkAgentConfig networkAgentConfig) { - return registerNetworkAgent(na, networkInfo, linkProperties, networkCapabilities, - currentScore, networkAgentConfig, NetworkProvider.ID_NONE); - } - /** * Register a new agent with ConnectivityService to handle a network. * @@ -6103,7 +6241,7 @@ public class ConnectivityService extends IConnectivityManager.Stub * later : see {@link #updateLinkProperties}. * @param networkCapabilities the initial capabilites of this network. They can be updated * later : see {@link #updateCapabilities}. - * @param currentScore the initial score of the network. See + * @param initialScore the initial score of the network. See * {@link NetworkAgentInfo#getCurrentScore}. * @param networkAgentConfig metadata about the network. This is never updated. * @param providerId the ID of the provider owning this NetworkAgent. @@ -6111,10 +6249,12 @@ public class ConnectivityService extends IConnectivityManager.Stub */ public Network registerNetworkAgent(INetworkAgent na, NetworkInfo networkInfo, LinkProperties linkProperties, NetworkCapabilities networkCapabilities, - int currentScore, NetworkAgentConfig networkAgentConfig, int providerId) { + @NonNull NetworkScore initialScore, NetworkAgentConfig networkAgentConfig, + int providerId) { Objects.requireNonNull(networkInfo, "networkInfo must not be null"); Objects.requireNonNull(linkProperties, "linkProperties must not be null"); Objects.requireNonNull(networkCapabilities, "networkCapabilities must not be null"); + Objects.requireNonNull(initialScore, "initialScore must not be null"); Objects.requireNonNull(networkAgentConfig, "networkAgentConfig must not be null"); if (networkCapabilities.hasTransport(TRANSPORT_TEST)) { enforceAnyPermissionOf(Manifest.permission.MANAGE_TEST_NETWORKS); @@ -6126,7 +6266,7 @@ public class ConnectivityService extends IConnectivityManager.Stub final long token = Binder.clearCallingIdentity(); try { return registerNetworkAgentInternal(na, networkInfo, linkProperties, - networkCapabilities, currentScore, networkAgentConfig, providerId, uid); + networkCapabilities, initialScore, networkAgentConfig, providerId, uid); } finally { Binder.restoreCallingIdentity(token); } @@ -6134,7 +6274,8 @@ public class ConnectivityService extends IConnectivityManager.Stub private Network registerNetworkAgentInternal(INetworkAgent na, NetworkInfo networkInfo, LinkProperties linkProperties, NetworkCapabilities networkCapabilities, - int currentScore, NetworkAgentConfig networkAgentConfig, int providerId, int uid) { + NetworkScore currentScore, NetworkAgentConfig networkAgentConfig, int providerId, + int uid) { if (networkCapabilities.hasTransport(TRANSPORT_TEST)) { // 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 @@ -6500,7 +6641,7 @@ public class ConnectivityService extends IConnectivityManager.Stub return; } - final Set<UidRange> ranges = nai.networkCapabilities.getUids(); + final Set<UidRange> ranges = nai.networkCapabilities.getUidRanges(); final int vpnAppUid = nai.networkCapabilities.getOwnerUid(); // TODO: this create a window of opportunity for apps to receive traffic between the time // when the old rules are removed and the time when new rules are added. To fix this, @@ -6515,6 +6656,11 @@ public class ConnectivityService extends IConnectivityManager.Stub } private void updateWakeOnLan(@NonNull LinkProperties lp) { + if (mWolSupportedInterfaces == null) { + mWolSupportedInterfaces = new ArraySet<>(mResources.get().getStringArray( + com.android.connectivity.resources.R.array + .config_wakeonlan_supported_interfaces)); + } lp.setWakeOnLanSupported(mWolSupportedInterfaces.contains(lp.getInterfaceName())); } @@ -6751,8 +6897,8 @@ public class ConnectivityService extends IConnectivityManager.Stub final boolean meteredChanged = oldMetered != newMetered; if (meteredChanged) { - maybeNotifyNetworkBlocked(nai, oldMetered, newMetered, mRestrictBackground, - mRestrictBackground, mVpnBlockedUidRanges, mVpnBlockedUidRanges); + maybeNotifyNetworkBlocked(nai, oldMetered, newMetered, + mVpnBlockedUidRanges, mVpnBlockedUidRanges); } final boolean roamingChanged = prevNc.hasCapability(NET_CAPABILITY_NOT_ROAMING) @@ -6860,8 +7006,8 @@ public class ConnectivityService extends IConnectivityManager.Stub private void updateUids(NetworkAgentInfo nai, NetworkCapabilities prevNc, NetworkCapabilities newNc) { - Set<UidRange> prevRanges = null == prevNc ? null : prevNc.getUids(); - Set<UidRange> newRanges = null == newNc ? null : newNc.getUids(); + Set<UidRange> prevRanges = null == prevNc ? null : prevNc.getUidRanges(); + Set<UidRange> newRanges = null == newNc ? null : newNc.getUidRanges(); if (null == prevRanges) prevRanges = new ArraySet<>(); if (null == newRanges) newRanges = new ArraySet<>(); final Set<UidRange> prevRangesCopy = new ArraySet<>(prevRanges); @@ -7097,7 +7243,7 @@ public class ConnectivityService extends IConnectivityManager.Stub putParcelable( bundle, createWithLocationInfoSanitizedIfNecessaryWhenParceled( - nc, includeLocationSensitiveInfo, nri.mUid, + nc, includeLocationSensitiveInfo, nri.mPid, nri.mUid, nrForCallback.getRequestorPackageName(), nri.mCallingAttributionTag)); putParcelable(bundle, linkPropertiesRestrictedForCallerPermissions( @@ -7118,7 +7264,7 @@ public class ConnectivityService extends IConnectivityManager.Stub putParcelable( bundle, createWithLocationInfoSanitizedIfNecessaryWhenParceled( - netCap, includeLocationSensitiveInfo, nri.mUid, + netCap, includeLocationSensitiveInfo, nri.mPid, nri.mUid, nrForCallback.getRequestorPackageName(), nri.mCallingAttributionTag)); break; @@ -7853,7 +7999,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } } - private void updateNetworkScore(@NonNull final NetworkAgentInfo nai, final int score) { + private void updateNetworkScore(@NonNull final NetworkAgentInfo nai, final NetworkScore score) { if (VDBG || DDBG) log("updateNetworkScore for " + nai.toShortString() + " to " + score); nai.setScore(score); rematchAllNetworksAndRequests(); @@ -7875,8 +8021,8 @@ public class ConnectivityService extends IConnectivityManager.Stub final boolean metered = nai.networkCapabilities.isMetered(); boolean blocked; blocked = isUidBlockedByVpn(nri.mUid, mVpnBlockedUidRanges); - blocked |= isUidBlockedByRules(nri.mUid, mUidRules.get(nri.mUid), - metered, mRestrictBackground); + blocked |= NetworkPolicyManager.isUidBlocked( + mUidBlockedReasons.get(nri.mUid, BLOCKED_REASON_NONE), metered); callCallbackForRequest(nri, nai, ConnectivityManager.CALLBACK_AVAILABLE, blocked ? 1 : 0); } @@ -7894,16 +8040,14 @@ public class ConnectivityService extends IConnectivityManager.Stub * * @param nai The target NetworkAgentInfo. * @param oldMetered True if the previous network capabilities is metered. - * @param newRestrictBackground True if data saver is enabled. */ private void maybeNotifyNetworkBlocked(NetworkAgentInfo nai, boolean oldMetered, - boolean newMetered, boolean oldRestrictBackground, boolean newRestrictBackground, - List<UidRange> oldBlockedUidRanges, List<UidRange> newBlockedUidRanges) { + boolean newMetered, List<UidRange> oldBlockedUidRanges, + List<UidRange> newBlockedUidRanges) { for (int i = 0; i < nai.numNetworkRequests(); i++) { NetworkRequest nr = nai.requestAt(i); NetworkRequestInfo nri = mNetworkRequests.get(nr); - final int uidRules = mUidRules.get(nri.mUid); final boolean oldBlocked, newBlocked, oldVpnBlocked, newVpnBlocked; oldVpnBlocked = isUidBlockedByVpn(nri.mUid, oldBlockedUidRanges); @@ -7911,10 +8055,11 @@ public class ConnectivityService extends IConnectivityManager.Stub ? isUidBlockedByVpn(nri.mUid, newBlockedUidRanges) : oldVpnBlocked; - oldBlocked = oldVpnBlocked || isUidBlockedByRules(nri.mUid, uidRules, oldMetered, - oldRestrictBackground); - newBlocked = newVpnBlocked || isUidBlockedByRules(nri.mUid, uidRules, newMetered, - newRestrictBackground); + final int blockedReasons = mUidBlockedReasons.get(nri.mUid, BLOCKED_REASON_NONE); + oldBlocked = oldVpnBlocked || NetworkPolicyManager.isUidBlocked( + blockedReasons, oldMetered); + newBlocked = newVpnBlocked || NetworkPolicyManager.isUidBlocked( + blockedReasons, newMetered); if (oldBlocked != newBlocked) { callCallbackForRequest(nri, nai, ConnectivityManager.CALLBACK_BLK_CHANGED, @@ -7924,19 +8069,20 @@ public class ConnectivityService extends IConnectivityManager.Stub } /** - * Notify apps with a given UID of the new blocked state according to new uid rules. + * Notify apps with a given UID of the new blocked state according to new uid state. * @param uid The uid for which the rules changed. - * @param newRules The new rules to apply. + * @param blockedReasons The reasons for why an uid is blocked. */ - private void maybeNotifyNetworkBlockedForNewUidRules(int uid, int newRules) { + private void maybeNotifyNetworkBlockedForNewState(int uid, int blockedReasons) { for (final NetworkAgentInfo nai : mNetworkAgentInfos) { final boolean metered = nai.networkCapabilities.isMetered(); final boolean vpnBlocked = isUidBlockedByVpn(uid, mVpnBlockedUidRanges); final boolean oldBlocked, newBlocked; - oldBlocked = vpnBlocked || isUidBlockedByRules( - uid, mUidRules.get(uid), metered, mRestrictBackground); - newBlocked = vpnBlocked || isUidBlockedByRules( - uid, newRules, metered, mRestrictBackground); + + oldBlocked = vpnBlocked || NetworkPolicyManager.isUidBlocked( + mUidBlockedReasons.get(uid, BLOCKED_REASON_NONE), metered); + newBlocked = vpnBlocked || NetworkPolicyManager.isUidBlocked( + blockedReasons, metered); if (oldBlocked == newBlocked) { continue; } @@ -8076,15 +8222,15 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public String getCaptivePortalServerUrl() { enforceNetworkStackOrSettingsPermission(); - String settingUrl = mContext.getResources().getString( - R.string.config_networkCaptivePortalServerUrl); + String settingUrl = mResources.get().getString( + com.android.connectivity.resources.R.string.config_networkCaptivePortalServerUrl); if (!TextUtils.isEmpty(settingUrl)) { return settingUrl; } settingUrl = Settings.Global.getString(mContext.getContentResolver(), - Settings.Global.CAPTIVE_PORTAL_HTTP_URL); + ConnectivitySettingsManager.CAPTIVE_PORTAL_HTTP_URL); if (!TextUtils.isEmpty(settingUrl)) { return settingUrl; } @@ -8166,11 +8312,11 @@ public class ConnectivityService extends IConnectivityManager.Stub // restore private DNS settings to default mode (opportunistic) if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_PRIVATE_DNS)) { Settings.Global.putString(mContext.getContentResolver(), - Settings.Global.PRIVATE_DNS_MODE, PRIVATE_DNS_MODE_OPPORTUNISTIC); + ConnectivitySettingsManager.PRIVATE_DNS_MODE, PRIVATE_DNS_MODE_OPPORTUNISTIC); } Settings.Global.putString(mContext.getContentResolver(), - Settings.Global.NETWORK_AVOID_BAD_WIFI, null); + ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI, null); } @Override @@ -8283,7 +8429,7 @@ public class ConnectivityService extends IConnectivityManager.Stub final NetworkAgentInfo vpn = getVpnForUid(uid); if (vpn == null || getVpnType(vpn) != VpnManager.TYPE_VPN_SERVICE - || vpn.networkCapabilities.getOwnerUid() != Binder.getCallingUid()) { + || vpn.networkCapabilities.getOwnerUid() != mDeps.getCallingUid()) { return INVALID_UID; } @@ -8875,13 +9021,13 @@ public class ConnectivityService extends IConnectivityManager.Stub private int transportTypeToLegacyType(int type) { switch (type) { case NetworkCapabilities.TRANSPORT_CELLULAR: - return ConnectivityManager.TYPE_MOBILE; + return TYPE_MOBILE; case NetworkCapabilities.TRANSPORT_WIFI: - return ConnectivityManager.TYPE_WIFI; + return TYPE_WIFI; case NetworkCapabilities.TRANSPORT_BLUETOOTH: - return ConnectivityManager.TYPE_BLUETOOTH; + return TYPE_BLUETOOTH; case NetworkCapabilities.TRANSPORT_ETHERNET: - return ConnectivityManager.TYPE_ETHERNET; + return TYPE_ETHERNET; default: loge("Unexpected transport in transportTypeToLegacyType: " + type); } @@ -8922,13 +9068,13 @@ public class ConnectivityService extends IConnectivityManager.Stub if (networkAgent.networkCapabilities.hasTransport( NetworkCapabilities.TRANSPORT_CELLULAR)) { timeout = Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.DATA_ACTIVITY_TIMEOUT_MOBILE, + ConnectivitySettingsManager.DATA_ACTIVITY_TIMEOUT_MOBILE, 10); type = NetworkCapabilities.TRANSPORT_CELLULAR; } else if (networkAgent.networkCapabilities.hasTransport( NetworkCapabilities.TRANSPORT_WIFI)) { timeout = Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.DATA_ACTIVITY_TIMEOUT_WIFI, + ConnectivitySettingsManager.DATA_ACTIVITY_TIMEOUT_WIFI, 15); type = NetworkCapabilities.TRANSPORT_WIFI; } else { @@ -9096,6 +9242,143 @@ public class ConnectivityService extends IConnectivityManager.Stub mQosCallbackTracker.unregisterCallback(callback); } + // Network preference per-profile and OEM network preferences can't be set at the same + // time, because it is unclear what should happen if both preferences are active for + // one given UID. To make it possible, the stack would have to clarify what would happen + // in case both are active at the same time. The implementation may have to be adjusted + // to implement the resulting rules. For example, a priority could be defined between them, + // where the OEM preference would be considered less or more important than the enterprise + // preference ; this would entail implementing the priorities somehow, e.g. by doing + // UID arithmetic with UID ranges or passing a priority to netd so that the routing rules + // are set at the right level. Other solutions are possible, e.g. merging of the + // preferences for the relevant UIDs. + private static void throwConcurrentPreferenceException() { + throw new IllegalStateException("Can't set NetworkPreferenceForUser and " + + "set OemNetworkPreference at the same time"); + } + + /** + * Request that a user profile is put by default on a network matching a given preference. + * + * See the documentation for the individual preferences for a description of the supported + * behaviors. + * + * @param profile the profile concerned. + * @param preference the preference for this profile, as one of the PROFILE_NETWORK_PREFERENCE_* + * constants. + * @param listener an optional listener to listen for completion of the operation. + */ + @Override + public void setProfileNetworkPreference(@NonNull final UserHandle profile, + @ConnectivityManager.ProfileNetworkPreference final int preference, + @Nullable final IOnCompleteListener listener) { + Objects.requireNonNull(profile); + PermissionUtils.enforceNetworkStackPermission(mContext); + if (DBG) { + log("setProfileNetworkPreference " + profile + " to " + preference); + } + if (profile.getIdentifier() < 0) { + throw new IllegalArgumentException("Must explicitly specify a user handle (" + + "UserHandle.CURRENT not supported)"); + } + final UserManager um; + try { + um = mContext.createContextAsUser(profile, 0 /* flags */) + .getSystemService(UserManager.class); + } catch (IllegalStateException e) { + throw new IllegalArgumentException("Profile does not exist"); + } + if (!um.isManagedProfile()) { + throw new IllegalArgumentException("Profile must be a managed profile"); + } + // Strictly speaking, mOemNetworkPreferences should only be touched on the + // handler thread. However it is an immutable object, so reading the reference is + // safe - it's just possible the value is slightly outdated. For the final check, + // see #handleSetProfileNetworkPreference. But if this can be caught here it is a + // lot easier to understand, so opportunistically check it. + if (!mOemNetworkPreferences.isEmpty()) { + throwConcurrentPreferenceException(); + } + final NetworkCapabilities nc; + switch (preference) { + case ConnectivityManager.PROFILE_NETWORK_PREFERENCE_DEFAULT: + nc = null; + break; + case ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE: + final UidRange uids = UidRange.createForUser(profile); + nc = createDefaultNetworkCapabilitiesForUidRange(uids); + nc.addCapability(NET_CAPABILITY_ENTERPRISE); + nc.removeCapability(NET_CAPABILITY_NOT_RESTRICTED); + break; + default: + throw new IllegalArgumentException( + "Invalid preference in setProfileNetworkPreference"); + } + mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_PROFILE_NETWORK_PREFERENCE, + new Pair<>(new ProfileNetworkPreferences.Preference(profile, nc), listener))); + } + + private void validateNetworkCapabilitiesOfProfileNetworkPreference( + @Nullable final NetworkCapabilities nc) { + if (null == nc) return; // Null caps are always allowed. It means to remove the setting. + ensureRequestableCapabilities(nc); + } + + private ArraySet<NetworkRequestInfo> createNrisFromProfileNetworkPreferences( + @NonNull final ProfileNetworkPreferences prefs) { + final ArraySet<NetworkRequestInfo> result = new ArraySet<>(); + for (final ProfileNetworkPreferences.Preference pref : prefs.preferences) { + // The NRI for a user should be comprised of two layers: + // - The request for the capabilities + // - The request for the default network, for fallback. Create an image of it to + // have the correct UIDs in it (also a request can only be part of one NRI, because + // of lookups in 1:1 associations like mNetworkRequests). + // Note that denying a fallback can be implemented simply by not adding the second + // request. + final ArrayList<NetworkRequest> nrs = new ArrayList<>(); + nrs.add(createNetworkRequest(NetworkRequest.Type.REQUEST, pref.capabilities)); + nrs.add(createDefaultRequest()); + setNetworkRequestUids(nrs, UidRange.fromIntRanges(pref.capabilities.getUids())); + final NetworkRequestInfo nri = new NetworkRequestInfo(nrs); + result.add(nri); + } + return result; + } + + private void handleSetProfileNetworkPreference( + @NonNull final ProfileNetworkPreferences.Preference preference, + @Nullable final IOnCompleteListener listener) { + // setProfileNetworkPreference and setOemNetworkPreference are mutually exclusive, in + // particular because it's not clear what preference should win in case both apply + // to the same app. + // The binder call has already checked this, but as mOemNetworkPreferences is only + // touched on the handler thread, it's theoretically not impossible that it has changed + // since. + if (!mOemNetworkPreferences.isEmpty()) { + // This may happen on a device with an OEM preference set when a user is removed. + // In this case, it's safe to ignore. In particular this happens in the tests. + loge("handleSetProfileNetworkPreference, but OEM network preferences not empty"); + return; + } + + validateNetworkCapabilitiesOfProfileNetworkPreference(preference.capabilities); + + mProfileNetworkPreferences = mProfileNetworkPreferences.plus(preference); + final ArraySet<NetworkRequestInfo> nris = + createNrisFromProfileNetworkPreferences(mProfileNetworkPreferences); + replaceDefaultNetworkRequestsForPreference(nris); + // Finally, rematch. + rematchAllNetworksAndRequests(); + + if (null != listener) { + try { + listener.onComplete(); + } catch (RemoteException e) { + loge("Listener for setProfileNetworkPreference has died"); + } + } + } + private void enforceAutomotiveDevice() { final boolean isAutomotiveDevice = mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE); @@ -9114,17 +9397,26 @@ public class ConnectivityService extends IConnectivityManager.Stub * Calling this will overwrite the existing preference. * * @param preference {@link OemNetworkPreferences} The application network preference to be set. - * @param listener {@link ConnectivityManager.OnSetOemNetworkPreferenceListener} Listener used + * @param listener {@link ConnectivityManager.OnCompleteListener} Listener used * to communicate completion of setOemNetworkPreference(); */ @Override public void setOemNetworkPreference( @NonNull final OemNetworkPreferences preference, - @Nullable final IOnSetOemNetworkPreferenceListener listener) { + @Nullable final IOnCompleteListener listener) { enforceAutomotiveDevice(); enforceOemNetworkPreferencesPermission(); + if (!mProfileNetworkPreferences.isEmpty()) { + // Strictly speaking, mProfileNetworkPreferences should only be touched on the + // handler thread. However it is an immutable object, so reading the reference is + // safe - it's just possible the value is slightly outdated. For the final check, + // see #handleSetOemPreference. But if this can be caught here it is a + // lot easier to understand, so opportunistically check it. + throwConcurrentPreferenceException(); + } + Objects.requireNonNull(preference, "OemNetworkPreferences must be non-null"); validateOemNetworkPreferences(preference); mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_OEM_NETWORK_PREFERENCE, @@ -9143,11 +9435,22 @@ public class ConnectivityService extends IConnectivityManager.Stub private void handleSetOemNetworkPreference( @NonNull final OemNetworkPreferences preference, - @Nullable final IOnSetOemNetworkPreferenceListener listener) { + @Nullable final IOnCompleteListener listener) { Objects.requireNonNull(preference, "OemNetworkPreferences must be non-null"); if (DBG) { log("set OEM network preferences :" + preference.toString()); } + // setProfileNetworkPreference and setOemNetworkPreference are mutually exclusive, in + // particular because it's not clear what preference should win in case both apply + // to the same app. + // The binder call has already checked this, but as mOemNetworkPreferences is only + // touched on the handler thread, it's theoretically not impossible that it has changed + // since. + if (!mProfileNetworkPreferences.isEmpty()) { + logwtf("handleSetOemPreference, but per-profile network preferences not empty"); + return; + } + final ArraySet<NetworkRequestInfo> nris = new OemNetworkRequestFactory().createNrisFromOemNetworkPreferences(preference); replaceDefaultNetworkRequestsForPreference(nris); @@ -9251,9 +9554,8 @@ public class ConnectivityService extends IConnectivityManager.Stub private static void setNetworkRequestUids(@NonNull final List<NetworkRequest> requests, @NonNull final Set<UidRange> uids) { - final Set<UidRange> ranges = new ArraySet<>(uids); for (final NetworkRequest req : requests) { - req.networkCapabilities.setUids(ranges); + req.networkCapabilities.setUids(UidRange.toIntRanges(uids)); } } diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java index 10d6570929ed..3ea0ce173745 100644 --- a/services/core/java/com/android/server/NetworkManagementService.java +++ b/services/core/java/com/android/server/NetworkManagementService.java @@ -643,7 +643,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub { String route, String gateway, String ifName) throws RemoteException { final RouteInfo processRoute = new RouteInfo(new IpPrefix(route), ("".equals(gateway)) ? null : InetAddresses.parseNumericAddress(gateway), - ifName); + ifName, RouteInfo.RTN_UNICAST); mDaemonHandler.post(() -> notifyRouteChange(updated, processRoute)); } diff --git a/services/core/java/com/android/server/PersistentDataBlockService.java b/services/core/java/com/android/server/PersistentDataBlockService.java index 00d8b0f1bed4..351e616b433b 100644 --- a/services/core/java/com/android/server/PersistentDataBlockService.java +++ b/services/core/java/com/android/server/PersistentDataBlockService.java @@ -23,6 +23,7 @@ import android.app.ActivityManager; import android.content.Context; import android.content.pm.PackageManager; import android.os.Binder; +import android.os.FileUtils; import android.os.IBinder; import android.os.RemoteException; import android.os.SystemProperties; @@ -103,6 +104,9 @@ import java.util.concurrent.TimeUnit; public class PersistentDataBlockService extends SystemService { private static final String TAG = PersistentDataBlockService.class.getSimpleName(); + private static final String GSI_SANDBOX = "/data/gsi_persistent_data"; + private static final String GSI_RUNNING_PROP = "ro.gsid.image_running"; + private static final String PERSISTENT_DATA_BLOCK_PROP = "ro.frp.pst"; private static final int HEADER_SIZE = 8; // Magic number to mark block device as adhering to the format consumed by this service @@ -127,12 +131,13 @@ public class PersistentDataBlockService extends SystemService { private static final String FLASH_LOCK_UNLOCKED = "0"; private final Context mContext; - private final String mDataBlockFile; + private final boolean mIsRunningDSU; private final Object mLock = new Object(); private final CountDownLatch mInitDoneSignal = new CountDownLatch(1); private int mAllowedUid = -1; private long mBlockDeviceSize; + private String mDataBlockFile; @GuardedBy("mLock") private boolean mIsWritable = true; @@ -141,6 +146,7 @@ public class PersistentDataBlockService extends SystemService { super(context); mContext = context; mDataBlockFile = SystemProperties.get(PERSISTENT_DATA_BLOCK_PROP); + mIsRunningDSU = SystemProperties.getBoolean(GSI_RUNNING_PROP, false); mBlockDeviceSize = -1; // Load lazily } @@ -284,14 +290,28 @@ public class PersistentDataBlockService extends SystemService { return true; } + private FileOutputStream getBlockOutputStream() throws IOException { + if (!mIsRunningDSU) { + return new FileOutputStream(new File(mDataBlockFile)); + } else { + File sandbox = new File(GSI_SANDBOX); + File realpdb = new File(SystemProperties.get(PERSISTENT_DATA_BLOCK_PROP)); + if (!sandbox.exists()) { + FileUtils.copy(realpdb, sandbox); + mDataBlockFile = GSI_SANDBOX; + } + Slog.i(TAG, "PersistentDataBlock copy-on-write"); + return new FileOutputStream(sandbox); + } + } + private boolean computeAndWriteDigestLocked() { byte[] digest = computeDigestLocked(null); if (digest != null) { DataOutputStream outputStream; try { - outputStream = new DataOutputStream( - new FileOutputStream(new File(mDataBlockFile))); - } catch (FileNotFoundException e) { + outputStream = new DataOutputStream(getBlockOutputStream()); + } catch (IOException e) { Slog.e(TAG, "partition not available?", e); return false; } @@ -356,8 +376,8 @@ public class PersistentDataBlockService extends SystemService { private void formatPartitionLocked(boolean setOemUnlockEnabled) { DataOutputStream outputStream; try { - outputStream = new DataOutputStream(new FileOutputStream(new File(mDataBlockFile))); - } catch (FileNotFoundException e) { + outputStream = new DataOutputStream(getBlockOutputStream()); + } catch (IOException e) { Slog.e(TAG, "partition not available?", e); return; } @@ -382,8 +402,8 @@ public class PersistentDataBlockService extends SystemService { private void doSetOemUnlockEnabledLocked(boolean enabled) { FileOutputStream outputStream; try { - outputStream = new FileOutputStream(new File(mDataBlockFile)); - } catch (FileNotFoundException e) { + outputStream = getBlockOutputStream(); + } catch (IOException e) { Slog.e(TAG, "partition not available", e); return; } @@ -459,8 +479,8 @@ public class PersistentDataBlockService extends SystemService { DataOutputStream outputStream; try { - outputStream = new DataOutputStream(new FileOutputStream(new File(mDataBlockFile))); - } catch (FileNotFoundException e) { + outputStream = new DataOutputStream(getBlockOutputStream()); + } catch (IOException e) { Slog.e(TAG, "partition not available?", e); return -1; } @@ -545,6 +565,17 @@ public class PersistentDataBlockService extends SystemService { public void wipe() { enforceOemUnlockWritePermission(); + if (mIsRunningDSU) { + File sandbox = new File(GSI_SANDBOX); + if (sandbox.exists()) { + if (sandbox.delete()) { + mDataBlockFile = SystemProperties.get(PERSISTENT_DATA_BLOCK_PROP); + } else { + Slog.e(TAG, "Failed to wipe sandbox persistent data block"); + } + } + return; + } synchronized (mLock) { int ret = nativeWipe(mDataBlockFile); @@ -704,8 +735,8 @@ public class PersistentDataBlockService extends SystemService { private void writeDataBuffer(long offset, ByteBuffer dataBuffer) { FileOutputStream outputStream; try { - outputStream = new FileOutputStream(new File(mDataBlockFile)); - } catch (FileNotFoundException e) { + outputStream = getBlockOutputStream(); + } catch (IOException e) { Slog.e(TAG, "partition not available", e); return; } diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java index dce919db1b07..78ffcbdaff4d 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -60,6 +60,7 @@ import android.telephony.CellSignalStrengthNr; import android.telephony.CellSignalStrengthTdscdma; import android.telephony.CellSignalStrengthWcdma; import android.telephony.DisconnectCause; +import android.telephony.LinkCapacityEstimate; import android.telephony.LocationAccessPolicy; import android.telephony.PhoneCapability; import android.telephony.PhoneStateListener; @@ -318,7 +319,10 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { private int[] mDataEnabledReason; - private Map<Integer, Long> mAllowedNetworkTypesList; + private int[] mAllowedNetworkTypeReason; + private long[] mAllowedNetworkTypeValue; + + private List<List<LinkCapacityEstimate>> mLinkCapacityEstimateLists; /** * Per-phone map of precise data connection state. The key of the map is the pair of transport @@ -350,6 +354,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { TelephonyCallback.EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED); REQUIRE_PRECISE_PHONE_STATE_PERMISSION.add( TelephonyCallback.EVENT_DATA_ENABLED_CHANGED); + REQUIRE_PRECISE_PHONE_STATE_PERMISSION.add( + TelephonyCallback.EVENT_LINK_CAPACITY_ESTIMATE_CHANGED); } private boolean isLocationPermissionRequired(Set<Integer> events) { @@ -383,7 +389,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { private boolean isPrivilegedPhoneStatePermissionRequired(Set<Integer> events) { return events.contains(TelephonyCallback.EVENT_SRVCC_STATE_CHANGED) || events.contains(TelephonyCallback.EVENT_VOICE_ACTIVATION_STATE_CHANGED) - || events.contains(TelephonyCallback.EVENT_RADIO_POWER_STATE_CHANGED); + || events.contains(TelephonyCallback.EVENT_RADIO_POWER_STATE_CHANGED) + || events.contains(TelephonyCallback.EVENT_ALLOWED_NETWORK_TYPE_LIST_CHANGED); } private static final int MSG_USER_SWITCHED = 1; @@ -527,6 +534,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mTelephonyDisplayInfos = copyOf(mTelephonyDisplayInfos, mNumPhones); mIsDataEnabled= copyOf(mIsDataEnabled, mNumPhones); mDataEnabledReason = copyOf(mDataEnabledReason, mNumPhones); + mAllowedNetworkTypeReason = copyOf(mAllowedNetworkTypeReason, mNumPhones); + mAllowedNetworkTypeValue = copyOf(mAllowedNetworkTypeValue, mNumPhones); // ds -> ss switch. if (mNumPhones < oldNumPhones) { @@ -535,6 +544,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { cutListToSize(mPreciseDataConnectionStates, mNumPhones); cutListToSize(mBarringInfo, mNumPhones); cutListToSize(mPhysicalChannelConfigs, mNumPhones); + cutListToSize(mLinkCapacityEstimateLists, mNumPhones); return; } @@ -571,6 +581,9 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mPhysicalChannelConfigs.add(i, new PhysicalChannelConfig.Builder().build()); mIsDataEnabled[i] = false; mDataEnabledReason[i] = TelephonyManager.DATA_ENABLED_REASON_USER; + mAllowedNetworkTypeReason[i] = -1; + mAllowedNetworkTypeValue[i] = -1; + mLinkCapacityEstimateLists.add(i, new ArrayList<>()); } } @@ -630,9 +643,12 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mBarringInfo = new ArrayList<>(); mTelephonyDisplayInfos = new TelephonyDisplayInfo[numPhones]; mPhysicalChannelConfigs = new ArrayList<>(); + mAllowedNetworkTypeReason = new int[numPhones]; + mAllowedNetworkTypeValue = new long[numPhones]; mIsDataEnabled = new boolean[numPhones]; mDataEnabledReason = new int[numPhones]; - mAllowedNetworkTypesList = new HashMap<>(); + mLinkCapacityEstimateLists = new ArrayList<>(); + for (int i = 0; i < numPhones; i++) { mCallState[i] = TelephonyManager.CALL_STATE_IDLE; mDataActivity[i] = TelephonyManager.DATA_ACTIVITY_NONE; @@ -665,6 +681,9 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mPhysicalChannelConfigs.add(i, new PhysicalChannelConfig.Builder().build()); mIsDataEnabled[i] = false; mDataEnabledReason[i] = TelephonyManager.DATA_ENABLED_REASON_USER; + mAllowedNetworkTypeReason[i] = -1; + mAllowedNetworkTypeValue[i] = -1; + mLinkCapacityEstimateLists.add(i, new ArrayList<>()); } mAppOps = mContext.getSystemService(AppOpsManager.class); @@ -1166,9 +1185,12 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } } if (events.contains( - TelephonyCallback.EVENT_ALLOWED_NETWORK_TYPE_LIST_CHANGED)) { + TelephonyCallback.EVENT_LINK_CAPACITY_ESTIMATE_CHANGED)) { try { - r.callback.onAllowedNetworkTypesChanged(mAllowedNetworkTypesList); + if (mLinkCapacityEstimateLists.get(phoneId) != null) { + r.callback.onLinkCapacityEstimateChanged(mLinkCapacityEstimateLists + .get(phoneId)); + } } catch (RemoteException ex) { remove(r.binder); } @@ -2423,18 +2445,19 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { * * @param phoneId the phone id. * @param subId the subId. - * @param allowedNetworkTypesList Map associating all allowed network type reasons with reason's - * allowed network type values. + * @param reason the allowed network type reason. + * @param allowedNetworkType the allowed network type value. */ - public void notifyAllowedNetworkTypesChanged(int phoneId, int subId, - Map allowedNetworkTypesList) { + public void notifyAllowedNetworkTypesChanged(int phoneId, int subId, int reason, + long allowedNetworkType) { if (!checkNotifyPermission("notifyAllowedNetworkTypesChanged()")) { return; } synchronized (mRecords) { if (validatePhoneId(phoneId)) { - mAllowedNetworkTypesList = allowedNetworkTypesList; + mAllowedNetworkTypeReason[phoneId] = reason; + mAllowedNetworkTypeValue[phoneId] = allowedNetworkType; for (Record r : mRecords) { if (r.matchTelephonyCallbackEvent( @@ -2442,10 +2465,48 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { && idMatch(r.subId, subId, phoneId)) { try { if (VDBG) { - log("notifyAllowedNetworkTypesChanged: AllowedNetworkTypesList= " - + mAllowedNetworkTypesList.toString()); + log("notifyAllowedNetworkTypesChanged: reason= " + reason + + ", allowed network type:" + + TelephonyManager.convertNetworkTypeBitmaskToString( + allowedNetworkType)); } - r.callback.onAllowedNetworkTypesChanged(mAllowedNetworkTypesList); + r.callback.onAllowedNetworkTypesChanged(reason, allowedNetworkType); + } catch (RemoteException ex) { + mRemoveList.add(r.binder); + } + } + } + } + handleRemoveListLocked(); + } + } + + /** + * Notify that the link capacity estimate has changed. + * @param phoneId the phone id. + * @param subId the subscription id. + * @param linkCapacityEstimateList a list of {@link LinkCapacityEstimate} + */ + public void notifyLinkCapacityEstimateChanged(int phoneId, int subId, + List<LinkCapacityEstimate> linkCapacityEstimateList) { + if (!checkNotifyPermission("notifyLinkCapacityEstimateChanged()")) { + return; + } + + if (VDBG) { + log("notifyLinkCapacityEstimateChanged: linkCapacityEstimateList =" + + linkCapacityEstimateList); + } + + synchronized (mRecords) { + if (validatePhoneId(phoneId)) { + mLinkCapacityEstimateLists.set(phoneId, linkCapacityEstimateList); + for (Record r : mRecords) { + if (r.matchTelephonyCallbackEvent( + TelephonyCallback.EVENT_LINK_CAPACITY_ESTIMATE_CHANGED) + && idMatch(r.subId, subId, phoneId)) { + try { + r.callback.onLinkCapacityEstimateChanged(linkCapacityEstimateList); } catch (RemoteException ex) { mRemoveList.add(r.binder); } @@ -2500,6 +2561,9 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { pw.println("mTelephonyDisplayInfo=" + mTelephonyDisplayInfos[i]); pw.println("mIsDataEnabled=" + mIsDataEnabled); pw.println("mDataEnabledReason=" + mDataEnabledReason); + pw.println("mAllowedNetworkTypeReason=" + mAllowedNetworkTypeReason[i]); + pw.println("mAllowedNetworkTypeValue=" + mAllowedNetworkTypeValue[i]); + pw.println("mLinkCapacityEstimateList=" + mLinkCapacityEstimateLists.get(i)); pw.decreaseIndent(); } pw.println("mCarrierNetworkChangeState=" + mCarrierNetworkChangeState); @@ -2764,6 +2828,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { LocationAccessPolicy.LocationPermissionQuery.Builder locationQueryBuilder = new LocationAccessPolicy.LocationPermissionQuery.Builder() .setCallingPackage(callingPackage) + .setCallingFeatureId(callingFeatureId) .setMethod(message + " events: " + events) .setCallingPid(Binder.getCallingPid()) .setCallingUid(Binder.getCallingUid()); @@ -2913,6 +2978,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { LocationAccessPolicy.LocationPermissionQuery query = new LocationAccessPolicy.LocationPermissionQuery.Builder() .setCallingPackage(r.callingPackage) + .setCallingFeatureId(r.callingFeatureId) .setCallingPid(r.callerPid) .setCallingUid(r.callerUid) .setMethod("TelephonyRegistry push") @@ -2936,6 +3002,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { LocationAccessPolicy.LocationPermissionQuery query = new LocationAccessPolicy.LocationPermissionQuery.Builder() .setCallingPackage(r.callingPackage) + .setCallingFeatureId(r.callingFeatureId) .setCallingPid(r.callerPid) .setCallingUid(r.callerUid) .setMethod("TelephonyRegistry push") diff --git a/services/core/java/com/android/server/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java index 1ef93f4da255..6c18cdea51fa 100644 --- a/services/core/java/com/android/server/VcnManagementService.java +++ b/services/core/java/com/android/server/VcnManagementService.java @@ -64,7 +64,7 @@ import android.util.Slog; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting.Visibility; -import com.android.internal.util.LocationPermissionChecker; +import com.android.net.module.util.LocationPermissionChecker; import com.android.server.vcn.TelephonySubscriptionTracker; import com.android.server.vcn.Vcn; import com.android.server.vcn.VcnContext; diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java index a8478476b7e6..a37115d1f5c7 100644 --- a/services/core/java/com/android/server/Watchdog.java +++ b/services/core/java/com/android/server/Watchdog.java @@ -75,7 +75,8 @@ public class Watchdog extends Thread { // can trigger the watchdog. // Note 2: The debug value is already below the wait time in ZygoteConnection. Wrapped // applications may not work with a debug build. CTS will fail. - private static final long DEFAULT_TIMEOUT = DB ? 10 * 1000 : 60 * 1000; + private static final long DEFAULT_TIMEOUT = + (DB ? 10 * 1000 : 60 * 1000) * Build.HW_TIMEOUT_MULTIPLIER; private static final long CHECK_INTERVAL = DEFAULT_TIMEOUT / 2; // These are temporally ordered: larger values as lateness increases diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index dd0e1f6458f9..ca4b9c38b593 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -140,14 +140,14 @@ public final class ActiveServices { private static final int DEBUG_FGS_ENFORCE_TYPE = 1; // How long we wait for a service to finish executing. - static final int SERVICE_TIMEOUT = 20*1000; + static final int SERVICE_TIMEOUT = 20 * 1000 * Build.HW_TIMEOUT_MULTIPLIER; // How long we wait for a service to finish executing. static final int SERVICE_BACKGROUND_TIMEOUT = SERVICE_TIMEOUT * 10; // How long the startForegroundService() grace period is to get around to // calling startForeground() before we ANR + stop it. - static final int SERVICE_START_FOREGROUND_TIMEOUT = 10*1000; + static final int SERVICE_START_FOREGROUND_TIMEOUT = 10 * 1000 * Build.HW_TIMEOUT_MULTIPLIER; final ActivityManagerService mAm; diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index bd08b628483e..cc5a25a57e38 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -478,7 +478,7 @@ public class ActivityManagerService extends IActivityManager.Stub // How long we wait for a launched process to attach to the activity manager // before we decide it's never going to come up for real. - static final int PROC_START_TIMEOUT = 10*1000; + static final int PROC_START_TIMEOUT = 10 * 1000 * Build.HW_TIMEOUT_MULTIPLIER; // How long we wait to kill an application zygote, after the last process using // it has gone away. static final int KILL_APP_ZYGOTE_DELAY_MS = 5 * 1000; @@ -490,8 +490,8 @@ public class ActivityManagerService extends IActivityManager.Stub static final int PROC_START_TIMEOUT_WITH_WRAPPER = 1200*1000; // How long we allow a receiver to run before giving up on it. - static final int BROADCAST_FG_TIMEOUT = 10*1000; - static final int BROADCAST_BG_TIMEOUT = 60*1000; + static final int BROADCAST_FG_TIMEOUT = 10 * 1000 * Build.HW_TIMEOUT_MULTIPLIER; + static final int BROADCAST_BG_TIMEOUT = 60 * 1000 * Build.HW_TIMEOUT_MULTIPLIER; public static final int MY_PID = myPid(); @@ -573,7 +573,8 @@ public class ActivityManagerService extends IActivityManager.Stub private static final int MAX_BUGREPORT_TITLE_SIZE = 50; private static final int MAX_BUGREPORT_DESCRIPTION_SIZE = 150; - private static final int NATIVE_DUMP_TIMEOUT_MS = 2000; // 2 seconds; + private static final int NATIVE_DUMP_TIMEOUT_MS = + 2000 * Build.HW_TIMEOUT_MULTIPLIER; // 2 seconds; private static final int JAVA_DUMP_MINIMUM_SIZE = 100; // 100 bytes. OomAdjuster mOomAdjuster; diff --git a/services/core/java/com/android/server/am/BroadcastConstants.java b/services/core/java/com/android/server/am/BroadcastConstants.java index be17b1bc600c..54b3e648c9bc 100644 --- a/services/core/java/com/android/server/am/BroadcastConstants.java +++ b/services/core/java/com/android/server/am/BroadcastConstants.java @@ -18,6 +18,7 @@ package com.android.server.am; import android.content.ContentResolver; import android.database.ContentObserver; +import android.os.Build; import android.os.Handler; import android.provider.Settings; import android.util.KeyValueListParser; @@ -42,12 +43,13 @@ public class BroadcastConstants { "bcast_allow_bg_activity_start_timeout"; // All time intervals are in milliseconds - private static final long DEFAULT_TIMEOUT = 10_000; - private static final long DEFAULT_SLOW_TIME = 5_000; - private static final long DEFAULT_DEFERRAL = 5_000; + private static final long DEFAULT_TIMEOUT = 10_000 * Build.HW_TIMEOUT_MULTIPLIER; + private static final long DEFAULT_SLOW_TIME = 5_000 * Build.HW_TIMEOUT_MULTIPLIER; + private static final long DEFAULT_DEFERRAL = 5_000 * Build.HW_TIMEOUT_MULTIPLIER; private static final float DEFAULT_DEFERRAL_DECAY_FACTOR = 0.75f; private static final long DEFAULT_DEFERRAL_FLOOR = 0; - private static final long DEFAULT_ALLOW_BG_ACTIVITY_START_TIMEOUT = 10_000; + private static final long DEFAULT_ALLOW_BG_ACTIVITY_START_TIMEOUT = + 10_000 * Build.HW_TIMEOUT_MULTIPLIER; // All time constants are in milliseconds diff --git a/services/core/java/com/android/server/am/OWNERS b/services/core/java/com/android/server/am/OWNERS index 1c38c86d08c8..90d940939be8 100644 --- a/services/core/java/com/android/server/am/OWNERS +++ b/services/core/java/com/android/server/am/OWNERS @@ -30,6 +30,10 @@ per-file BatteryExternalStats* = file:/BATTERY_STATS_OWNERS michaelwr@google.com narayan@google.com +# Voice Interaction +per-file *Assist* = file:/core/java/android/service/voice/OWNERS +per-file *Voice* = file:/core/java/android/service/voice/OWNERS + per-file SettingsToPropertiesMapper.java = omakoto@google.com, svetoslavganov@google.com, yamasani@google.com per-file CarUserSwitchingDialog.java = keunyoung@google.com, felipeal@google.com, gurunagarajan@google.com diff --git a/services/core/java/com/android/server/apphibernation/AppHibernationService.java b/services/core/java/com/android/server/apphibernation/AppHibernationService.java index 968cf5f1df91..b3373d0bb536 100644 --- a/services/core/java/com/android/server/apphibernation/AppHibernationService.java +++ b/services/core/java/com/android/server/apphibernation/AppHibernationService.java @@ -173,7 +173,9 @@ public final class AppHibernationService extends SystemService { if (!checkHibernationEnabled("isHibernatingForUser")) { return false; } - + getContext().enforceCallingOrSelfPermission( + android.Manifest.permission.MANAGE_APP_HIBERNATION, + "Caller does not have MANAGE_APP_HIBERNATION permission."); userId = handleIncomingUser(userId, "isHibernating"); if (!mUserManager.isUserUnlockingOrUnlocked(userId)) { Slog.e(TAG, "Attempt to get hibernation state of stopped or nonexistent user " @@ -202,6 +204,9 @@ public final class AppHibernationService extends SystemService { if (!checkHibernationEnabled("isHibernatingGlobally")) { return false; } + getContext().enforceCallingOrSelfPermission( + android.Manifest.permission.MANAGE_APP_HIBERNATION, + "Caller does not have MANAGE_APP_HIBERNATION permission."); synchronized (mLock) { GlobalLevelState state = mGlobalHibernationStates.get(packageName); if (state == null) { @@ -223,6 +228,9 @@ public final class AppHibernationService extends SystemService { if (!checkHibernationEnabled("setHibernatingForUser")) { return; } + getContext().enforceCallingOrSelfPermission( + android.Manifest.permission.MANAGE_APP_HIBERNATION, + "Caller does not have MANAGE_APP_HIBERNATION permission."); userId = handleIncomingUser(userId, "setHibernating"); if (!mUserManager.isUserUnlockingOrUnlocked(userId)) { Slog.w(TAG, "Attempt to set hibernation state for a stopped or nonexistent user " @@ -263,6 +271,9 @@ public final class AppHibernationService extends SystemService { if (!checkHibernationEnabled("setHibernatingGlobally")) { return; } + getContext().enforceCallingOrSelfPermission( + android.Manifest.permission.MANAGE_APP_HIBERNATION, + "Caller does not have MANAGE_APP_HIBERNATION permission."); synchronized (mLock) { GlobalLevelState state = mGlobalHibernationStates.get(packageName); if (state == null) { @@ -282,6 +293,35 @@ public final class AppHibernationService extends SystemService { } /** + * Get the hibernating packages for the given user. This is equivalent to the list of + * packages for the user that return true for {@link #isHibernatingForUser}. + */ + @NonNull List<String> getHibernatingPackagesForUser(int userId) { + ArrayList<String> hibernatingPackages = new ArrayList<>(); + if (!checkHibernationEnabled("getHibernatingPackagesForUser")) { + return hibernatingPackages; + } + getContext().enforceCallingOrSelfPermission( + android.Manifest.permission.MANAGE_APP_HIBERNATION, + "Caller does not have MANAGE_APP_HIBERNATION permission."); + userId = handleIncomingUser(userId, "getHibernatingPackagesForUser"); + if (!mUserManager.isUserUnlockingOrUnlocked(userId)) { + Slog.w(TAG, "Attempt to get hibernating packages for a stopped or nonexistent user " + + userId); + return hibernatingPackages; + } + synchronized (mLock) { + Map<String, UserLevelState> userStates = mUserStates.get(userId); + for (UserLevelState state : userStates.values()) { + if (state.hibernated) { + hibernatingPackages.add(state.packageName); + } + } + return hibernatingPackages; + } + } + + /** * Put an app into hibernation for a given user, allowing user-level optimizations to occur. * * @param pkgState package hibernation state @@ -608,6 +648,11 @@ public final class AppHibernationService extends SystemService { } @Override + public List<String> getHibernatingPackagesForUser(int userId) { + return mService.getHibernatingPackagesForUser(userId); + } + + @Override public void onShellCommand(@Nullable FileDescriptor in, @Nullable FileDescriptor out, @Nullable FileDescriptor err, @NonNull String[] args, @Nullable ShellCallback callback, @NonNull ResultReceiver resultReceiver) { diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java index ed3a223b5dd7..b355730c6450 100644 --- a/services/core/java/com/android/server/clipboard/ClipboardService.java +++ b/services/core/java/com/android/server/clipboard/ClipboardService.java @@ -65,6 +65,7 @@ import com.android.server.wm.WindowManagerInternal; import java.io.IOException; import java.io.RandomAccessFile; +import java.util.Arrays; import java.util.HashSet; import java.util.List; @@ -80,21 +81,20 @@ class HostClipboardMonitor implements Runnable { private static final String PIPE_NAME = "pipe:clipboard"; private static final String PIPE_DEVICE = "/dev/qemu_pipe"; + private static byte[] createOpenHandshake() { + // String.getBytes doesn't include the null terminator, + // but the QEMU pipe device requires the pipe service name + // to be null-terminated. + + final byte[] bits = Arrays.copyOf(PIPE_NAME.getBytes(), PIPE_NAME.length() + 1); + bits[PIPE_NAME.length()] = 0; + return bits; + } + private void openPipe() { try { - // String.getBytes doesn't include the null terminator, - // but the QEMU pipe device requires the pipe service name - // to be null-terminated. - byte[] b = new byte[PIPE_NAME.length() + 1]; - b[PIPE_NAME.length()] = 0; - System.arraycopy( - PIPE_NAME.getBytes(), - 0, - b, - 0, - PIPE_NAME.length()); mPipe = new RandomAccessFile(PIPE_DEVICE, "rw"); - mPipe.write(b); + mPipe.write(createOpenHandshake()); } catch (IOException e) { try { if (mPipe != null) mPipe.close(); @@ -158,7 +158,7 @@ public class ClipboardService extends SystemService { private static final String TAG = "ClipboardService"; private static final boolean IS_EMULATOR = - SystemProperties.getBoolean("ro.kernel.qemu", false); + SystemProperties.getBoolean("ro.boot.qemu", false); private final ActivityManagerInternal mAmInternal; private final IUriGrantsManager mUgm; diff --git a/services/core/java/com/android/server/connectivity/ConnectivityConstants.java b/services/core/java/com/android/server/connectivity/ConnectivityConstants.java index 0fb6fecd4fe2..325a2cd7bd69 100644 --- a/services/core/java/com/android/server/connectivity/ConnectivityConstants.java +++ b/services/core/java/com/android/server/connectivity/ConnectivityConstants.java @@ -18,18 +18,10 @@ package com.android.server.connectivity; /** * A class encapsulating various constants used by Connectivity. + * TODO : remove this class. * @hide */ public class ConnectivityConstants { - - // Penalty applied to scores of Networks that have not been validated. - public static final int UNVALIDATED_SCORE_PENALTY = 40; - - // Score for explicitly connected network. - // - // This ensures that a) the explicitly selected network is never trumped by anything else, and - // b) the explicitly selected network is never torn down. - public static final int EXPLICITLY_SELECTED_NETWORK_SCORE = 100; // VPNs typically have priority over other networks. Give them a score that will // let them win every single time. public static final int VPN_DEFAULT_SCORE = 101; diff --git a/services/core/java/com/android/server/connectivity/DnsManager.java b/services/core/java/com/android/server/connectivity/DnsManager.java index 4f6b5301e56f..ffeb77d1d109 100644 --- a/services/core/java/com/android/server/connectivity/DnsManager.java +++ b/services/core/java/com/android/server/connectivity/DnsManager.java @@ -16,23 +16,23 @@ package com.android.server.connectivity; -import static android.net.ConnectivityManager.PRIVATE_DNS_DEFAULT_MODE_FALLBACK; import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF; import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME; +import static android.net.ConnectivitySettingsManager.DNS_RESOLVER_MAX_SAMPLES; +import static android.net.ConnectivitySettingsManager.DNS_RESOLVER_MIN_SAMPLES; +import static android.net.ConnectivitySettingsManager.DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS; +import static android.net.ConnectivitySettingsManager.DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT; +import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_DEFAULT_MODE; +import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE; +import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_SPECIFIER; import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.VALIDATION_RESULT_FAILURE; import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.VALIDATION_RESULT_SUCCESS; -import static android.provider.Settings.Global.DNS_RESOLVER_MAX_SAMPLES; -import static android.provider.Settings.Global.DNS_RESOLVER_MIN_SAMPLES; -import static android.provider.Settings.Global.DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS; -import static android.provider.Settings.Global.DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT; -import static android.provider.Settings.Global.PRIVATE_DNS_DEFAULT_MODE; -import static android.provider.Settings.Global.PRIVATE_DNS_MODE; -import static android.provider.Settings.Global.PRIVATE_DNS_SPECIFIER; import android.annotation.NonNull; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; +import android.net.ConnectivityManager; import android.net.IDnsResolver; import android.net.InetAddresses; import android.net.LinkProperties; @@ -127,13 +127,17 @@ public class DnsManager { private static final int DNS_RESOLVER_DEFAULT_MIN_SAMPLES = 8; private static final int DNS_RESOLVER_DEFAULT_MAX_SAMPLES = 64; - public static PrivateDnsConfig getPrivateDnsConfig(ContentResolver cr) { - final String mode = getPrivateDnsMode(cr); + /** + * Get PrivateDnsConfig. + */ + public static PrivateDnsConfig getPrivateDnsConfig(Context context) { + final String mode = ConnectivityManager.getPrivateDnsMode(context); final boolean useTls = !TextUtils.isEmpty(mode) && !PRIVATE_DNS_MODE_OFF.equals(mode); if (PRIVATE_DNS_MODE_PROVIDER_HOSTNAME.equals(mode)) { - final String specifier = getStringSetting(cr, PRIVATE_DNS_SPECIFIER); + final String specifier = getStringSetting(context.getContentResolver(), + PRIVATE_DNS_SPECIFIER); return new PrivateDnsConfig(specifier, null); } @@ -268,7 +272,7 @@ public class DnsManager { } public PrivateDnsConfig getPrivateDnsConfig() { - return getPrivateDnsConfig(mContentResolver); + return getPrivateDnsConfig(mContext); } public void removeNetwork(Network network) { @@ -479,13 +483,6 @@ public class DnsManager { return result; } - private static String getPrivateDnsMode(ContentResolver cr) { - String mode = getStringSetting(cr, PRIVATE_DNS_MODE); - if (TextUtils.isEmpty(mode)) mode = getStringSetting(cr, PRIVATE_DNS_DEFAULT_MODE); - if (TextUtils.isEmpty(mode)) mode = PRIVATE_DNS_DEFAULT_MODE_FALLBACK; - return mode; - } - private static String getStringSetting(ContentResolver cr, String which) { return Settings.Global.getString(cr, which); } diff --git a/services/core/java/com/android/server/connectivity/FullScore.java b/services/core/java/com/android/server/connectivity/FullScore.java new file mode 100644 index 000000000000..028cfee36593 --- /dev/null +++ b/services/core/java/com/android/server/connectivity/FullScore.java @@ -0,0 +1,211 @@ +/* + * Copyright (C) 2021 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; + +import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; +import static android.net.NetworkCapabilities.TRANSPORT_VPN; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.net.NetworkAgentConfig; +import android.net.NetworkCapabilities; +import android.net.NetworkScore; + +import com.android.internal.annotations.VisibleForTesting; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.StringJoiner; + +/** + * This class represents how desirable a network is. + * + * FullScore is very similar to NetworkScore, but it contains the bits that are managed + * by ConnectivityService. This provides static guarantee that all users must know whether + * they are handling a score that had the CS-managed bits set. + */ +public class FullScore { + // This will be removed soon. Do *NOT* depend on it for any new code that is not part of + // a migration. + private final int mLegacyInt; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = {"POLICY_"}, value = { + POLICY_IS_VALIDATED, + POLICY_IS_VPN, + POLICY_EVER_USER_SELECTED, + POLICY_ACCEPT_UNVALIDATED + }) + public @interface Policy { + } + + // Agent-managed policies are in NetworkScore. They start from 1. + // CS-managed policies, counting from 63 downward + // This network is validated. CS-managed because the source of truth is in NetworkCapabilities. + /** @hide */ + public static final int POLICY_IS_VALIDATED = 63; + + // This is a VPN and behaves as one for scoring purposes. + /** @hide */ + public static final int POLICY_IS_VPN = 62; + + // This network has been selected by the user manually from settings or a 3rd party app + // at least once. {@see NetworkAgentConfig#explicitlySelected}. + /** @hide */ + public static final int POLICY_EVER_USER_SELECTED = 61; + + // The user has indicated in UI that this network should be used even if it doesn't + // validate. {@see NetworkAgentConfig#acceptUnvalidated}. + /** @hide */ + public static final int POLICY_ACCEPT_UNVALIDATED = 60; + + // To help iterate when printing + @VisibleForTesting + static final int MIN_CS_MANAGED_POLICY = POLICY_ACCEPT_UNVALIDATED; + @VisibleForTesting + static final int MAX_CS_MANAGED_POLICY = POLICY_IS_VALIDATED; + + @VisibleForTesting + static @NonNull String policyNameOf(final int policy) { + switch (policy) { + case POLICY_IS_VALIDATED: return "IS_VALIDATED"; + case POLICY_IS_VPN: return "IS_VPN"; + case POLICY_EVER_USER_SELECTED: return "EVER_USER_SELECTED"; + case POLICY_ACCEPT_UNVALIDATED: return "ACCEPT_UNVALIDATED"; + } + throw new IllegalArgumentException("Unknown policy : " + policy); + } + + // Bitmask of all the policies applied to this score. + private final long mPolicies; + + FullScore(final int legacyInt, final long policies) { + mLegacyInt = legacyInt; + mPolicies = policies; + } + + /** + * Given a score supplied by the NetworkAgent and CS-managed objects, produce a full score. + * + * @param score the score supplied by the agent + * @param caps the NetworkCapabilities of the network + * @param config the NetworkAgentConfig of the network + * @return an FullScore that is appropriate to use for ranking. + */ + public static FullScore fromNetworkScore(@NonNull final NetworkScore score, + @NonNull final NetworkCapabilities caps, @NonNull final NetworkAgentConfig config) { + return withPolicies(score.getLegacyInt(), caps.hasCapability(NET_CAPABILITY_VALIDATED), + caps.hasTransport(TRANSPORT_VPN), + config.explicitlySelected, + config.acceptUnvalidated); + } + + /** + * Return a new score given updated caps and config. + * + * @param caps the NetworkCapabilities of the network + * @param config the NetworkAgentConfig of the network + * @return a score with the policies from the arguments reset + */ + public FullScore mixInScore(@NonNull final NetworkCapabilities caps, + @NonNull final NetworkAgentConfig config) { + return withPolicies(mLegacyInt, caps.hasCapability(NET_CAPABILITY_VALIDATED), + caps.hasTransport(TRANSPORT_VPN), + config.explicitlySelected, + config.acceptUnvalidated); + } + + private static FullScore withPolicies(@NonNull final int legacyInt, + final boolean isValidated, + final boolean isVpn, + final boolean everUserSelected, + final boolean acceptUnvalidated) { + return new FullScore(legacyInt, + (isValidated ? 1L << POLICY_IS_VALIDATED : 0) + | (isVpn ? 1L << POLICY_IS_VPN : 0) + | (everUserSelected ? 1L << POLICY_EVER_USER_SELECTED : 0) + | (acceptUnvalidated ? 1L << POLICY_ACCEPT_UNVALIDATED : 0)); + } + + /** + * For backward compatibility, get the legacy int. + * This will be removed before S is published. + */ + public int getLegacyInt() { + return getLegacyInt(false /* pretendValidated */); + } + + public int getLegacyIntAsValidated() { + return getLegacyInt(true /* pretendValidated */); + } + + // TODO : remove these two constants + // Penalty applied to scores of Networks that have not been validated. + private static final int UNVALIDATED_SCORE_PENALTY = 40; + + // Score for a network that can be used unvalidated + private static final int ACCEPT_UNVALIDATED_NETWORK_SCORE = 100; + + private int getLegacyInt(boolean pretendValidated) { + // If the user has chosen this network at least once, give it the maximum score when + // checking to pretend it's validated, or if it doesn't need to validate because the + // user said to use it even if it doesn't validate. + // This ensures that networks that have been selected in UI are not torn down before the + // user gets a chance to prefer it when a higher-scoring network (e.g., Ethernet) is + // available. + if (hasPolicy(POLICY_EVER_USER_SELECTED) + && (hasPolicy(POLICY_ACCEPT_UNVALIDATED) || pretendValidated)) { + return ACCEPT_UNVALIDATED_NETWORK_SCORE; + } + + int score = mLegacyInt; + // Except for VPNs, networks are subject to a penalty for not being validated. + // Apply the penalty unless the network is a VPN, or it's validated or pretending to be. + if (!hasPolicy(POLICY_IS_VALIDATED) && !pretendValidated && !hasPolicy(POLICY_IS_VPN)) { + score -= UNVALIDATED_SCORE_PENALTY; + } + if (score < 0) score = 0; + return score; + } + + /** + * @return whether this score has a particular policy. + */ + @VisibleForTesting + public boolean hasPolicy(final int policy) { + return 0 != (mPolicies & (1L << policy)); + } + + // Example output : + // Score(50 ; Policies : EVER_USER_SELECTED&IS_VALIDATED) + @Override + public String toString() { + final StringJoiner sj = new StringJoiner( + "&", // delimiter + "Score(" + mLegacyInt + " ; Policies : ", // prefix + ")"); // suffix + for (int i = NetworkScore.MIN_AGENT_MANAGED_POLICY; + i <= NetworkScore.MAX_AGENT_MANAGED_POLICY; ++i) { + if (hasPolicy(i)) sj.add(policyNameOf(i)); + } + for (int i = MIN_CS_MANAGED_POLICY; i <= MAX_CS_MANAGED_POLICY; ++i) { + if (hasPolicy(i)) sj.add(policyNameOf(i)); + } + return sj.toString(); + } +} diff --git a/services/core/java/com/android/server/connectivity/MockableSystemProperties.java b/services/core/java/com/android/server/connectivity/MockableSystemProperties.java index ef767341d609..a25b89ac039a 100644 --- a/services/core/java/com/android/server/connectivity/MockableSystemProperties.java +++ b/services/core/java/com/android/server/connectivity/MockableSystemProperties.java @@ -17,7 +17,6 @@ package com.android.server.connectivity; import android.os.SystemProperties; -import android.sysprop.NetworkProperties; public class MockableSystemProperties { @@ -32,10 +31,4 @@ public class MockableSystemProperties { public boolean getBoolean(String key, boolean def) { return SystemProperties.getBoolean(key, def); } - /** - * Set net.tcp_def_init_rwnd to the tcp initial receive window size. - */ - public void setTcpInitRwnd(int value) { - NetworkProperties.tcp_init_rwnd(value); - } } diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java index 803cc9d31c35..103ab957f312 100644 --- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java +++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java @@ -25,6 +25,8 @@ import android.content.Context; import android.net.CaptivePortalData; import android.net.IDnsResolver; import android.net.INetd; +import android.net.INetworkAgent; +import android.net.INetworkAgentRegistry; import android.net.INetworkMonitor; import android.net.LinkProperties; import android.net.NattKeepalivePacketData; @@ -35,6 +37,7 @@ import android.net.NetworkCapabilities; import android.net.NetworkInfo; import android.net.NetworkMonitorManager; import android.net.NetworkRequest; +import android.net.NetworkScore; import android.net.NetworkStateSnapshot; import android.net.QosCallbackException; import android.net.QosFilter; @@ -50,8 +53,6 @@ import android.util.Log; import android.util.Pair; import android.util.SparseArray; -import com.android.connectivity.aidl.INetworkAgent; -import com.android.connectivity.aidl.INetworkAgentRegistry; import com.android.internal.util.WakeupMessage; import com.android.server.ConnectivityService; @@ -302,8 +303,9 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { // validated). private boolean mInactive; - // This represents the quality of the network with no clear scale. - private int mScore; + // This represents the quality of the network. As opposed to NetworkScore, FullScore includes + // the ConnectivityService-managed bits. + private FullScore mScore; // The list of NetworkRequests being satisfied by this Network. private final SparseArray<NetworkRequest> mNetworkRequests = new SparseArray<>(); @@ -338,7 +340,8 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { private final QosCallbackTracker mQosCallbackTracker; public NetworkAgentInfo(INetworkAgent na, Network net, NetworkInfo info, - @NonNull LinkProperties lp, @NonNull NetworkCapabilities nc, int score, Context context, + @NonNull LinkProperties lp, @NonNull NetworkCapabilities nc, + @NonNull NetworkScore score, Context context, Handler handler, NetworkAgentConfig config, ConnectivityService connService, INetd netd, IDnsResolver dnsResolver, int factorySerialNumber, int creatorUid, QosCallbackTracker qosCallbackTracker, ConnectivityService.Dependencies deps) { @@ -354,12 +357,12 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { networkInfo = info; linkProperties = lp; networkCapabilities = nc; - mScore = score; + networkAgentConfig = config; + setScore(score); // uses members networkCapabilities and networkAgentConfig clatd = new Nat464Xlat(this, netd, dnsResolver, deps); mConnService = connService; mContext = context; mHandler = handler; - networkAgentConfig = config; this.factorySerialNumber = factorySerialNumber; this.creatorUid = creatorUid; mQosCallbackTracker = qosCallbackTracker; @@ -603,9 +606,9 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { } @Override - public void sendScore(int score) { - mHandler.obtainMessage(NetworkAgent.EVENT_NETWORK_SCORE_CHANGED, score, 0, - new Pair<>(NetworkAgentInfo.this, null)).sendToTarget(); + public void sendScore(@NonNull final NetworkScore score) { + mHandler.obtainMessage(NetworkAgent.EVENT_NETWORK_SCORE_CHANGED, + new Pair<>(NetworkAgentInfo.this, score)).sendToTarget(); } @Override @@ -665,6 +668,7 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { @NonNull final NetworkCapabilities nc) { final NetworkCapabilities oldNc = networkCapabilities; networkCapabilities = nc; + mScore = mScore.mixInScore(networkCapabilities, networkAgentConfig); final NetworkMonitorManager nm = mNetworkMonitor; if (nm != null) { nm.notifyNetworkCapabilitiesChanged(nc); @@ -717,6 +721,7 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { break; case LISTEN: + case LISTEN_FOR_BEST: case TRACK_DEFAULT: case TRACK_SYSTEM_DEFAULT: break; @@ -841,30 +846,6 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { return isVPN(); } - private int getCurrentScore(boolean pretendValidated) { - // TODO: We may want to refactor this into a NetworkScore class that takes a base score from - // the NetworkAgent and signals from the NetworkAgent and uses those signals to modify the - // score. The NetworkScore class would provide a nice place to centralize score constants - // so they are not scattered about the transports. - - // If this network is explicitly selected and the user has decided to use it even if it's - // unvalidated, give it the maximum score. Also give it the maximum score if it's explicitly - // selected and we're trying to see what its score could be. This ensures that we don't tear - // down an explicitly selected network before the user gets a chance to prefer it when - // a higher-scoring network (e.g., Ethernet) is available. - if (networkAgentConfig.explicitlySelected - && (networkAgentConfig.acceptUnvalidated || pretendValidated)) { - return ConnectivityConstants.EXPLICITLY_SELECTED_NETWORK_SCORE; - } - - int score = mScore; - if (!lastValidated && !pretendValidated && !ignoreWifiUnvalidationPenalty() && !isVPN()) { - score -= ConnectivityConstants.UNVALIDATED_SCORE_PENALTY; - } - if (score < 0) score = 0; - return score; - } - // Return true on devices configured to ignore score penalty for wifi networks // that become unvalidated (b/31075769). private boolean ignoreWifiUnvalidationPenalty() { @@ -877,17 +858,29 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { // Get the current score for this Network. This may be modified from what the // NetworkAgent sent, as it has modifiers applied to it. public int getCurrentScore() { - return getCurrentScore(false); + return mScore.getLegacyInt(); } // Get the current score for this Network as if it was validated. This may be modified from // what the NetworkAgent sent, as it has modifiers applied to it. public int getCurrentScoreAsValidated() { - return getCurrentScore(true); + return mScore.getLegacyIntAsValidated(); } - public void setScore(final int score) { - mScore = score; + /** + * Mix-in the ConnectivityService-managed bits in the score. + */ + public void setScore(final NetworkScore score) { + mScore = FullScore.fromNetworkScore(score, networkCapabilities, networkAgentConfig); + } + + /** + * Update the ConnectivityService-managed bits in the score. + * + * Call this after updating the network agent config. + */ + public void updateScoreForNetworkAgentConfigUpdate() { + mScore = mScore.mixInScore(networkCapabilities, networkAgentConfig); } /** diff --git a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java index 508739f2e1e0..0c0d45995a2b 100644 --- a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java +++ b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java @@ -28,6 +28,8 @@ import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.content.res.Resources; +import android.graphics.drawable.Icon; +import android.net.ConnectivityResources; import android.net.NetworkSpecifier; import android.net.TelephonyNetworkSpecifier; import android.net.wifi.WifiInfo; @@ -40,7 +42,7 @@ import android.util.SparseArray; import android.util.SparseIntArray; import android.widget.Toast; -import com.android.internal.R; +import com.android.connectivity.resources.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; @@ -82,6 +84,7 @@ public class NetworkNotificationManager { // The context is for the current user (system server) private final Context mContext; + private final Resources mResources; private final TelephonyManager mTelephonyManager; // The notification manager is created from a context for User.ALL, so notifications // will be sent to all users. @@ -96,6 +99,7 @@ public class NetworkNotificationManager { (NotificationManager) c.createContextAsUser(UserHandle.ALL, 0 /* flags */) .getSystemService(Context.NOTIFICATION_SERVICE); mNotificationTypeMap = new SparseIntArray(); + mResources = new ConnectivityResources(mContext).get(); } @VisibleForTesting @@ -113,20 +117,19 @@ public class NetworkNotificationManager { return -1; } - private static String getTransportName(final int transportType) { - Resources r = Resources.getSystem(); - String[] networkTypes = r.getStringArray(R.array.network_switch_type_name); + private String getTransportName(final int transportType) { + String[] networkTypes = mResources.getStringArray(R.array.network_switch_type_name); try { return networkTypes[transportType]; } catch (IndexOutOfBoundsException e) { - return r.getString(R.string.network_switch_type_name_unknown); + return mResources.getString(R.string.network_switch_type_name_unknown); } } private static int getIcon(int transportType) { return (transportType == TRANSPORT_WIFI) - ? R.drawable.stat_notify_wifi_in_range : // TODO: Distinguish ! from ?. - R.drawable.stat_notify_rssi_in_range; + ? R.drawable.stat_notify_wifi_in_range // TODO: Distinguish ! from ?. + : R.drawable.stat_notify_rssi_in_range; } /** @@ -156,7 +159,7 @@ public class NetworkNotificationManager { final String tag = tagFor(id); final int eventId = notifyType.eventId; final int transportType; - final String name; + final CharSequence name; if (nai != null) { transportType = approximateTransportType(nai); final String extraInfo = nai.networkInfo.getExtraInfo(); @@ -194,10 +197,10 @@ public class NetworkNotificationManager { tag, nameOf(eventId), getTransportName(transportType), name, highPriority)); } - Resources r = mContext.getResources(); + final Resources r = mResources; final CharSequence title; final CharSequence details; - int icon = getIcon(transportType); + Icon icon = Icon.createWithResource(r, getIcon(transportType)); if (notifyType == NotificationType.NO_INTERNET && transportType == TRANSPORT_WIFI) { title = r.getString(R.string.wifi_no_internet, name); details = r.getString(R.string.wifi_no_internet_detailed); @@ -272,8 +275,7 @@ public class NetworkNotificationManager { .setSmallIcon(icon) .setAutoCancel(true) .setTicker(title) - .setColor(mContext.getColor( - com.android.internal.R.color.system_notification_accent_color)) + .setColor(mContext.getColor(android.R.color.system_notification_accent_color)) .setContentTitle(title) .setContentIntent(intent) .setLocalOnly(true) @@ -353,7 +355,7 @@ public class NetworkNotificationManager { public void showToast(NetworkAgentInfo fromNai, NetworkAgentInfo toNai) { String fromTransport = getTransportName(approximateTransportType(fromNai)); String toTransport = getTransportName(approximateTransportType(toNai)); - String text = mContext.getResources().getString( + String text = mResources.getString( R.string.network_switch_metered_toast, fromTransport, toTransport); Toast.makeText(mContext, text, Toast.LENGTH_LONG).show(); } diff --git a/services/core/java/com/android/server/connectivity/ProfileNetworkPreferences.java b/services/core/java/com/android/server/connectivity/ProfileNetworkPreferences.java new file mode 100644 index 000000000000..dd2815d9e2e3 --- /dev/null +++ b/services/core/java/com/android/server/connectivity/ProfileNetworkPreferences.java @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2021 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; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.net.NetworkCapabilities; +import android.os.UserHandle; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * A data class containing all the per-profile network preferences. + * + * A given profile can only have one preference. + */ +public class ProfileNetworkPreferences { + /** + * A single preference, as it applies to a given user profile. + */ + public static class Preference { + @NonNull public final UserHandle user; + // Capabilities are only null when sending an object to remove the setting for a user + @Nullable public final NetworkCapabilities capabilities; + + public Preference(@NonNull final UserHandle user, + @Nullable final NetworkCapabilities capabilities) { + this.user = user; + this.capabilities = null == capabilities ? null : new NetworkCapabilities(capabilities); + } + + /** toString */ + public String toString() { + return "[ProfileNetworkPreference user=" + user + " caps=" + capabilities + "]"; + } + } + + @NonNull public final List<Preference> preferences; + + public ProfileNetworkPreferences() { + preferences = Collections.EMPTY_LIST; + } + + private ProfileNetworkPreferences(@NonNull final List<Preference> list) { + preferences = Collections.unmodifiableList(list); + } + + /** + * Returns a new object consisting of this object plus the passed preference. + * + * If a preference already exists for the same user, it will be replaced by the passed + * preference. Passing a Preference object containing a null capabilities object is equivalent + * to (and indeed, implemented as) removing the preference for this user. + */ + public ProfileNetworkPreferences plus(@NonNull final Preference pref) { + final ArrayList<Preference> newPrefs = new ArrayList<>(); + for (final Preference existingPref : preferences) { + if (!existingPref.user.equals(pref.user)) { + newPrefs.add(existingPref); + } + } + if (null != pref.capabilities) { + newPrefs.add(pref); + } + return new ProfileNetworkPreferences(newPrefs); + } + + public boolean isEmpty() { + return preferences.isEmpty(); + } +} diff --git a/services/core/java/com/android/server/connectivity/ProxyTracker.java b/services/core/java/com/android/server/connectivity/ProxyTracker.java index 8b9c83678777..f572b46a9b58 100644 --- a/services/core/java/com/android/server/connectivity/ProxyTracker.java +++ b/services/core/java/com/android/server/connectivity/ProxyTracker.java @@ -16,10 +16,10 @@ package com.android.server.connectivity; -import static android.provider.Settings.Global.GLOBAL_HTTP_PROXY_EXCLUSION_LIST; -import static android.provider.Settings.Global.GLOBAL_HTTP_PROXY_HOST; -import static android.provider.Settings.Global.GLOBAL_HTTP_PROXY_PAC; -import static android.provider.Settings.Global.GLOBAL_HTTP_PROXY_PORT; +import static android.net.ConnectivitySettingsManager.GLOBAL_HTTP_PROXY_EXCLUSION_LIST; +import static android.net.ConnectivitySettingsManager.GLOBAL_HTTP_PROXY_HOST; +import static android.net.ConnectivitySettingsManager.GLOBAL_HTTP_PROXY_PAC; +import static android.net.ConnectivitySettingsManager.GLOBAL_HTTP_PROXY_PORT; import static android.provider.Settings.Global.HTTP_PROXY; import android.annotation.NonNull; @@ -34,7 +34,6 @@ import android.net.ProxyInfo; import android.net.Uri; import android.os.Binder; import android.os.Handler; -import android.os.HandlerExecutor; import android.os.UserHandle; import android.provider.Settings; import android.text.TextUtils; @@ -105,7 +104,7 @@ public class ProxyTracker { PacProxyInstalledListener listener = new PacProxyInstalledListener(pacChangedEvent); mPacProxyManager.addPacProxyInstalledListener( - new HandlerExecutor(mConnectivityServiceHandler), listener); + mConnectivityServiceHandler::post, listener); } // Convert empty ProxyInfo's to null as null-checks are used to determine if proxies are present diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java index 124c3741ad57..30e0c7e9b9aa 100644 --- a/services/core/java/com/android/server/connectivity/Vpn.java +++ b/services/core/java/com/android/server/connectivity/Vpn.java @@ -19,6 +19,7 @@ package com.android.server.connectivity; import static android.Manifest.permission.BIND_VPN_SERVICE; import static android.net.ConnectivityManager.NETID_UNSET; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED; +import static android.os.UserHandle.PER_USER_RANGE; import static android.net.RouteInfo.RTN_THROW; import static android.net.RouteInfo.RTN_UNREACHABLE; import static android.net.VpnManager.NOTIFICATION_CHANNEL_VPN; @@ -68,8 +69,8 @@ import android.net.NetworkInfo; import android.net.NetworkInfo.DetailedState; import android.net.NetworkProvider; import android.net.NetworkRequest; +import android.net.NetworkScore; import android.net.RouteInfo; -import android.net.UidRange; import android.net.UidRangeParcel; import android.net.UnderlyingNetworkInfo; import android.net.VpnManager; @@ -1174,11 +1175,13 @@ public class Vpn { if (!allowIPv4) { lp.addRoute(new RouteInfo(new IpPrefix( - NetworkStackConstants.IPV4_ADDR_ANY, 0), RTN_UNREACHABLE)); + NetworkStackConstants.IPV4_ADDR_ANY, 0), null /*gateway*/, + null /*iface*/, RTN_UNREACHABLE)); } if (!allowIPv6) { lp.addRoute(new RouteInfo(new IpPrefix( - NetworkStackConstants.IPV6_ADDR_ANY, 0), RTN_UNREACHABLE)); + NetworkStackConstants.IPV6_ADDR_ANY, 0), null /*gateway*/, + null /*iface*/, RTN_UNREACHABLE)); } // Concatenate search domains into a string. @@ -1239,7 +1242,7 @@ public class Vpn { mLegacyState = LegacyVpnInfo.STATE_CONNECTING; updateState(DetailedState.CONNECTING, "agentConnect"); - NetworkAgentConfig networkAgentConfig = new NetworkAgentConfig(); + NetworkAgentConfig networkAgentConfig = new NetworkAgentConfig.Builder().build(); networkAgentConfig.allowBypass = mConfig.allowBypass && !mLockdown; mNetworkCapabilities.setOwnerUid(mOwnerUID); @@ -1258,9 +1261,11 @@ public class Vpn { } mNetworkAgent = new NetworkAgent(mContext, mLooper, NETWORKTYPE /* logtag */, - mNetworkCapabilities, lp, VPN_DEFAULT_SCORE, networkAgentConfig, mNetworkProvider) { + mNetworkCapabilities, lp, + new NetworkScore.Builder().setLegacyInt(VPN_DEFAULT_SCORE).build(), + networkAgentConfig, mNetworkProvider) { @Override - public void unwanted() { + public void onNetworkUnwanted() { // We are user controlled, not driven by NetworkRequest. } }; @@ -1346,7 +1351,7 @@ public class Vpn { String oldInterface = mInterface; Connection oldConnection = mConnection; NetworkAgent oldNetworkAgent = mNetworkAgent; - Set<UidRange> oldUsers = mNetworkCapabilities.getUids(); + Set<Range<Integer>> oldUsers = mNetworkCapabilities.getUids(); // Configure the interface. Abort if any of these steps fails. ParcelFileDescriptor tun = ParcelFileDescriptor.adoptFd(jniCreate(config.mtu)); @@ -1452,7 +1457,7 @@ public class Vpn { } /** - * Creates a {@link Set} of non-intersecting {@link UidRange} objects including all UIDs + * Creates a {@link Set} of non-intersecting {@code Range<Integer>} objects including all UIDs * associated with one user, and any restricted profiles attached to that user. * * <p>If one of {@param allowedApplications} or {@param disallowedApplications} is provided, @@ -1465,10 +1470,10 @@ public class Vpn { * @param disallowedApplications (optional) List of applications to deny. */ @VisibleForTesting - Set<UidRange> createUserAndRestrictedProfilesRanges(@UserIdInt int userId, + Set<Range<Integer>> createUserAndRestrictedProfilesRanges(@UserIdInt int userId, @Nullable List<String> allowedApplications, @Nullable List<String> disallowedApplications) { - final Set<UidRange> ranges = new ArraySet<>(); + final Set<Range<Integer>> ranges = new ArraySet<>(); // Assign the top-level user to the set of ranges addUserToRanges(ranges, userId, allowedApplications, disallowedApplications); @@ -1492,20 +1497,20 @@ public class Vpn { } /** - * Updates a {@link Set} of non-intersecting {@link UidRange} objects to include all UIDs + * Updates a {@link Set} of non-intersecting {@code Range<Integer>} objects to include all UIDs * associated with one user. * * <p>If one of {@param allowedApplications} or {@param disallowedApplications} is provided, * the UID ranges will match the app allowlist or denylist specified there. Otherwise, all UIDs * in the user will be included. * - * @param ranges {@link Set} of {@link UidRange}s to which to add. + * @param ranges {@link Set} of {@code Range<Integer>}s to which to add. * @param userId The userId to add to {@param ranges}. * @param allowedApplications (optional) allowlist of applications to include. * @param disallowedApplications (optional) denylist of applications to exclude. */ @VisibleForTesting - void addUserToRanges(@NonNull Set<UidRange> ranges, @UserIdInt int userId, + void addUserToRanges(@NonNull Set<Range<Integer>> ranges, @UserIdInt int userId, @Nullable List<String> allowedApplications, @Nullable List<String> disallowedApplications) { if (allowedApplications != null) { @@ -1515,40 +1520,41 @@ public class Vpn { if (start == -1) { start = uid; } else if (uid != stop + 1) { - ranges.add(new UidRange(start, stop)); + ranges.add(new Range<Integer>(start, stop)); start = uid; } stop = uid; } - if (start != -1) ranges.add(new UidRange(start, stop)); + if (start != -1) ranges.add(new Range<Integer>(start, stop)); } else if (disallowedApplications != null) { // Add all ranges for user skipping UIDs for disallowedApplications. - final UidRange userRange = UidRange.createForUser(UserHandle.of(userId)); - int start = userRange.start; + final Range<Integer> userRange = createUidRangeForUser(userId); + int start = userRange.getLower(); for (int uid : getAppsUids(disallowedApplications, userId)) { if (uid == start) { start++; } else { - ranges.add(new UidRange(start, uid - 1)); + ranges.add(new Range<Integer>(start, uid - 1)); start = uid + 1; } } - if (start <= userRange.stop) ranges.add(new UidRange(start, userRange.stop)); + if (start <= userRange.getUpper()) { + ranges.add(new Range<Integer>(start, userRange.getUpper())); + } } else { // Add all UIDs for the user. - ranges.add(UidRange.createForUser(UserHandle.of(userId))); + ranges.add(createUidRangeForUser(userId)); } } // Returns the subset of the full list of active UID ranges the VPN applies to (mVpnUsers) that // apply to userId. - private static List<UidRange> uidRangesForUser(int userId, Set<UidRange> existingRanges) { - // UidRange#createForUser returns the entire range of UIDs available to a macro-user. - // This is something like 0-99999 ; {@see UserHandle#PER_USER_RANGE} - final UidRange userRange = UidRange.createForUser(UserHandle.of(userId)); - final List<UidRange> ranges = new ArrayList<>(); - for (UidRange range : existingRanges) { - if (userRange.containsRange(range)) { + private static List<Range<Integer>> uidRangesForUser(int userId, + Set<Range<Integer>> existingRanges) { + final Range<Integer> userRange = createUidRangeForUser(userId); + final List<Range<Integer>> ranges = new ArrayList<>(); + for (Range<Integer> range : existingRanges) { + if (userRange.contains(range)) { ranges.add(range); } } @@ -1565,7 +1571,7 @@ public class Vpn { UserInfo user = mUserManager.getUserInfo(userId); if (user.isRestricted() && user.restrictedProfileParentId == mUserId) { synchronized(Vpn.this) { - final Set<UidRange> existingRanges = mNetworkCapabilities.getUids(); + final Set<Range<Integer>> existingRanges = mNetworkCapabilities.getUids(); if (existingRanges != null) { try { addUserToRanges(existingRanges, userId, mConfig.allowedApplications, @@ -1593,10 +1599,10 @@ public class Vpn { UserInfo user = mUserManager.getUserInfo(userId); if (user.isRestricted() && user.restrictedProfileParentId == mUserId) { synchronized(Vpn.this) { - final Set<UidRange> existingRanges = mNetworkCapabilities.getUids(); + final Set<Range<Integer>> existingRanges = mNetworkCapabilities.getUids(); if (existingRanges != null) { try { - final List<UidRange> removedRanges = + final List<Range<Integer>> removedRanges = uidRangesForUser(userId, existingRanges); existingRanges.removeAll(removedRanges); mNetworkCapabilities.setUids(existingRanges); @@ -1657,7 +1663,7 @@ public class Vpn { final Set<UidRangeParcel> rangesToRemove = new ArraySet<>(mBlockedUidsAsToldToConnectivity); final Set<UidRangeParcel> rangesToAdd; if (enforce) { - final Set<UidRange> restrictedProfilesRanges = + final Set<Range<Integer>> restrictedProfilesRanges = createUserAndRestrictedProfilesRanges(mUserId, /* allowedApplications */ null, /* disallowedApplications */ exemptedPackages); @@ -1666,11 +1672,12 @@ public class Vpn { // The UID range of the first user (0-99999) would block the IPSec traffic, which comes // directly from the kernel and is marked as uid=0. So we adjust the range to allow // it through (b/69873852). - for (UidRange range : restrictedProfilesRanges) { - if (range.start == 0 && range.stop != 0) { - rangesThatShouldBeBlocked.add(new UidRangeParcel(1, range.stop)); - } else if (range.start != 0) { - rangesThatShouldBeBlocked.add(new UidRangeParcel(range.start, range.stop)); + for (Range<Integer> range : restrictedProfilesRanges) { + if (range.getLower() == 0 && range.getUpper() != 0) { + rangesThatShouldBeBlocked.add(new UidRangeParcel(1, range.getUpper())); + } else if (range.getLower() != 0) { + rangesThatShouldBeBlocked.add( + new UidRangeParcel(range.getLower(), range.getUpper())); } } @@ -1692,12 +1699,12 @@ public class Vpn { } /** - * Tell ConnectivityService to add or remove a list of {@link UidRange}s to the list of UIDs - * that are only allowed to make connections through sockets that have had {@code protect()} - * called on them. + * Tell ConnectivityService to add or remove a list of {@link UidRangeParcel}s to the list of + * UIDs that are only allowed to make connections through sockets that have had + * {@code protect()} called on them. * * @param enforce {@code true} to add to the denylist, {@code false} to remove. - * @param ranges {@link Collection} of {@link UidRange}s to add (if {@param enforce} is + * @param ranges {@link Collection} of {@link UidRangeParcel}s to add (if {@param enforce} is * {@code true}) or to remove. * @return {@code true} if all of the UIDs were added/removed. {@code false} otherwise, * including added ranges that already existed or removed ones that didn't. @@ -2696,7 +2703,8 @@ public class Vpn { mConfig.routes.clear(); for (final RouteInfo route : oldRoutes) { - mConfig.routes.add(new RouteInfo(route.getDestination(), RTN_UNREACHABLE)); + mConfig.routes.add(new RouteInfo(route.getDestination(), null /*gateway*/, + null /*iface*/, RTN_UNREACHABLE)); } if (mNetworkAgent != null) { mNetworkAgent.sendLinkProperties(makeLinkProperties()); @@ -3035,10 +3043,12 @@ public class Vpn { // Add a throw route for the VPN server endpoint, if one was specified. if (endpointAddress instanceof Inet4Address) { mConfig.routes.add(new RouteInfo( - new IpPrefix(endpointAddress, 32), RTN_THROW)); + new IpPrefix(endpointAddress, 32), null /*gateway*/, + null /*iface*/, RTN_THROW)); } else if (endpointAddress instanceof Inet6Address) { mConfig.routes.add(new RouteInfo( - new IpPrefix(endpointAddress, 128), RTN_THROW)); + new IpPrefix(endpointAddress, 128), null /*gateway*/, + null /*iface*/, RTN_THROW)); } else { Log.e(TAG, "Unknown IP address family for VPN endpoint: " + endpointAddress); @@ -3338,4 +3348,12 @@ public class Vpn { firstChildSessionCallback); } } + + /** + * Returns the entire range of UIDs available to a macro-user. This is something like 0-99999. + */ + @VisibleForTesting + static Range<Integer> createUidRangeForUser(int userId) { + return new Range<Integer>(userId * PER_USER_RANGE, (userId + 1) * PER_USER_RANGE - 1); + } } diff --git a/services/core/java/com/android/server/connectivity/VpnIkev2Utils.java b/services/core/java/com/android/server/connectivity/VpnIkev2Utils.java index fa03e59f2f2e..47eb3eb70434 100644 --- a/services/core/java/com/android/server/connectivity/VpnIkev2Utils.java +++ b/services/core/java/com/android/server/connectivity/VpnIkev2Utils.java @@ -405,7 +405,8 @@ public class VpnIkev2Utils { for (final IkeTrafficSelector selector : trafficSelectors) { for (final IpPrefix prefix : new IpRange(selector.startingAddress, selector.endingAddress).asIpPrefixes()) { - routes.add(new RouteInfo(prefix, null)); + routes.add(new RouteInfo(prefix, null /*gateway*/, null /*iface*/, + RouteInfo.RTN_UNICAST)); } } diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java index 294d7e257b6e..0215188bc1a4 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsService.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java @@ -92,7 +92,6 @@ import android.provider.Settings.SettingNotFoundException; import android.security.AndroidKeyStoreMaintenance; import android.security.Authorization; import android.security.KeyStore; -import android.security.keystore.AndroidKeyStoreProvider; import android.security.keystore.KeyProperties; import android.security.keystore.KeyProtection; import android.security.keystore.UserNotAuthenticatedException; @@ -157,7 +156,6 @@ import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import java.util.Objects; -import java.util.Optional; import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -264,13 +262,7 @@ public class LockSettingsService extends ILockSettings.Stub { @Override public void onStart() { - Optional<Boolean> keystore2_enabled = - android.sysprop.Keystore2Properties.keystore2_enabled(); - if (keystore2_enabled.isPresent() && keystore2_enabled.get()) { - android.security.keystore2.AndroidKeyStoreProvider.install(); - } else { - AndroidKeyStoreProvider.install(); - } + android.security.keystore2.AndroidKeyStoreProvider.install(); mLockSettingsService = new LockSettingsService(getContext()); publishBinderService("lock_settings", mLockSettingsService); } diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index aee0947f39f9..aecac7576bcf 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -56,6 +56,23 @@ import static android.net.NetworkIdentity.OEM_NONE; import static android.net.NetworkPolicy.LIMIT_DISABLED; import static android.net.NetworkPolicy.SNOOZE_NEVER; import static android.net.NetworkPolicy.WARNING_DISABLED; +import static android.net.NetworkPolicyManager.ALLOWED_METERED_REASON_MASK; +import static android.net.NetworkPolicyManager.ALLOWED_METERED_REASON_USER_EXEMPTED; +import static android.net.NetworkPolicyManager.ALLOWED_REASON_FOREGROUND; +import static android.net.NetworkPolicyManager.ALLOWED_REASON_NONE; +import static android.net.NetworkPolicyManager.ALLOWED_REASON_POWER_SAVE_ALLOWLIST; +import static android.net.NetworkPolicyManager.ALLOWED_REASON_POWER_SAVE_EXCEPT_IDLE_ALLOWLIST; +import static android.net.NetworkPolicyManager.ALLOWED_REASON_RESTRICTED_MODE_PERMISSIONS; +import static android.net.NetworkPolicyManager.ALLOWED_REASON_SYSTEM; +import static android.net.NetworkPolicyManager.BLOCKED_METERED_REASON_ADMIN_DISABLED; +import static android.net.NetworkPolicyManager.BLOCKED_METERED_REASON_DATA_SAVER; +import static android.net.NetworkPolicyManager.BLOCKED_METERED_REASON_MASK; +import static android.net.NetworkPolicyManager.BLOCKED_METERED_REASON_USER_RESTRICTED; +import static android.net.NetworkPolicyManager.BLOCKED_REASON_APP_STANDBY; +import static android.net.NetworkPolicyManager.BLOCKED_REASON_BATTERY_SAVER; +import static android.net.NetworkPolicyManager.BLOCKED_REASON_DOZE; +import static android.net.NetworkPolicyManager.BLOCKED_REASON_NONE; +import static android.net.NetworkPolicyManager.BLOCKED_REASON_RESTRICTED_MODE; import static android.net.NetworkPolicyManager.EXTRA_NETWORK_TEMPLATE; import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT; import static android.net.NetworkPolicyManager.MASK_ALL_NETWORKS; @@ -244,6 +261,7 @@ import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.StatLogger; import com.android.internal.util.XmlUtils; import com.android.net.module.util.NetworkIdentityUtils; +import com.android.net.module.util.PermissionUtils; import com.android.server.EventLogTags; import com.android.server.LocalServices; import com.android.server.ServiceThread; @@ -414,6 +432,14 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { private static final int MSG_SET_NETWORK_TEMPLATE_ENABLED = 18; private static final int MSG_SUBSCRIPTION_PLANS_CHANGED = 19; private static final int MSG_STATS_PROVIDER_LIMIT_REACHED = 20; + // TODO: Add similar docs for other messages. + /** + * Message to indicate that reasons for why an uid is blocked changed. + * arg1 = uid + * arg2 = oldBlockedReasons + * obj = newBlockedReasons + */ + private static final int MSG_BLOCKED_REASON_CHANGED = 21; private static final int UID_MSG_STATE_CHANGED = 100; private static final int UID_MSG_GONE = 101; @@ -560,7 +586,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { /** Foreground at UID granularity. */ @GuardedBy("mUidRulesFirstLock") - final SparseArray<UidState> mUidState = new SparseArray<UidState>(); + private final SparseArray<UidState> mUidState = new SparseArray<>(); + + @GuardedBy("mUidRulesFirstLock") + private final SparseArray<UidBlockedState> mUidBlockedState = new SparseArray<>(); /** Map from network ID to last observed meteredness state */ @GuardedBy("mNetworkPoliciesSecondLock") @@ -2879,15 +2908,18 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } @Override - public void registerListener(INetworkPolicyListener listener) { + public void registerListener(@NonNull INetworkPolicyListener listener) { + Objects.requireNonNull(listener); // TODO: Remove CONNECTIVITY_INTERNAL and the *AnyPermissionOf methods above after all apps // have declared OBSERVE_NETWORK_POLICY. enforceAnyPermissionOf(CONNECTIVITY_INTERNAL, OBSERVE_NETWORK_POLICY); mListeners.register(listener); + // TODO: Send callbacks to the newly registered listener } @Override - public void unregisterListener(INetworkPolicyListener listener) { + public void unregisterListener(@NonNull INetworkPolicyListener listener) { + Objects.requireNonNull(listener); // TODO: Remove CONNECTIVITY_INTERNAL and the *AnyPermissionOf methods above after all apps // have declared OBSERVE_NETWORK_POLICY. enforceAnyPermissionOf(CONNECTIVITY_INTERNAL, OBSERVE_NETWORK_POLICY); @@ -3081,8 +3113,16 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { @Override public int getRestrictBackgroundByCaller() { mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG); - final int uid = Binder.getCallingUid(); + return getRestrictBackgroundStatusInternal(Binder.getCallingUid()); + } + @Override + public int getRestrictBackgroundStatus(int uid) { + PermissionUtils.enforceNetworkStackPermission(mContext); + return getRestrictBackgroundStatusInternal(uid); + } + + private int getRestrictBackgroundStatusInternal(int uid) { synchronized (mUidRulesFirstLock) { // Must clear identity because getUidPolicy() is restricted to system. final long token = Binder.clearCallingIdentity(); @@ -3551,6 +3591,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { * Get multipath preference value for the given network. */ public int getMultipathPreference(Network network) { + PermissionUtils.enforceNetworkStackPermission(mContext); final Integer preference = mMultipathPolicyTracker.getMultipathPreference(network); if (preference != null) { return preference; @@ -3923,6 +3964,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { mUidRules.put(uid, newUidRule); mHandler.obtainMessage(MSG_RULES_CHANGED, uid, newUidRule).sendToTarget(); } + updateBlockedReasonsForRestrictedModeUL(uid); }); if (mRestrictedNetworkingMode) { // firewall rules only need to be set when this mode is being enabled. @@ -3943,6 +3985,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { mUidRules.put(uid, newUidRule); mHandler.obtainMessage(MSG_RULES_CHANGED, uid, newUidRule).sendToTarget(); } + updateBlockedReasonsForRestrictedModeUL(uid); // if restricted networking mode is on, and the app has an access exemption, the uid rule // will not change, but the firewall rule will have to be updated. @@ -3954,6 +3997,31 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } + private void updateBlockedReasonsForRestrictedModeUL(int uid) { + UidBlockedState uidBlockedState = mUidBlockedState.get(uid); + if (uidBlockedState == null) { + uidBlockedState = new UidBlockedState(); + mUidBlockedState.put(uid, uidBlockedState); + } + final int oldEffectiveBlockedReasons = uidBlockedState.effectiveBlockedReasons; + if (mRestrictedNetworkingMode) { + uidBlockedState.blockedReasons |= BLOCKED_REASON_RESTRICTED_MODE; + } else { + uidBlockedState.blockedReasons &= ~BLOCKED_REASON_RESTRICTED_MODE; + } + if (hasRestrictedModeAccess(uid)) { + uidBlockedState.allowedReasons |= ALLOWED_REASON_RESTRICTED_MODE_PERMISSIONS; + } else { + uidBlockedState.allowedReasons &= ALLOWED_REASON_RESTRICTED_MODE_PERMISSIONS; + } + uidBlockedState.updateEffectiveBlockedReasons(); + if (oldEffectiveBlockedReasons != uidBlockedState.effectiveBlockedReasons) { + mHandler.obtainMessage(MSG_BLOCKED_REASON_CHANGED, uid, + uidBlockedState.effectiveBlockedReasons, oldEffectiveBlockedReasons) + .sendToTarget(); + } + } + private int getNewRestrictedModeUidRule(int uid, int oldUidRule) { int newRule = oldUidRule; newRule &= ~MASK_RESTRICTED_MODE_NETWORKS; @@ -4074,11 +4142,21 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { boolean isWhitelisted = mPowerSaveTempWhitelistAppIds.get(appId) || mPowerSaveWhitelistAppIds.get(appId); if (!deviceIdleMode) { - isWhitelisted = isWhitelisted || mPowerSaveWhitelistExceptIdleAppIds.get(appId); + isWhitelisted = isWhitelisted || isWhitelistedFromPowerSaveExceptIdleUL(uid); } return isWhitelisted; } + /** + * Returns whether a uid is allowlisted from power saving restrictions, except Device idle + * (eg: Battery Saver and app idle). + */ + @GuardedBy("mUidRulesFirstLock") + private boolean isWhitelistedFromPowerSaveExceptIdleUL(int uid) { + final int appId = UserHandle.getAppId(uid); + return mPowerSaveWhitelistExceptIdleAppIds.get(appId); + } + // NOTE: since both fw_dozable and fw_powersave uses the same map // (mPowerSaveTempWhitelistAppIds) for allowlisting, we can reuse their logic in this method. @GuardedBy("mUidRulesFirstLock") @@ -4523,6 +4601,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { final int oldUidRules = mUidRules.get(uid, RULE_NONE); final boolean isForeground = isUidForegroundOnRestrictBackgroundUL(uid); final boolean isRestrictedByAdmin = isRestrictedByAdminUL(uid); + UidBlockedState uidBlockedState = mUidBlockedState.get(uid); + if (uidBlockedState == null) { + uidBlockedState = new UidBlockedState(); + mUidBlockedState.put(uid, uidBlockedState); + } final boolean isDenied = (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0; final boolean isAllowed = (uidPolicy & POLICY_ALLOW_METERED_BACKGROUND) != 0; @@ -4547,6 +4630,16 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } + int newBlockedReasons = BLOCKED_REASON_NONE; + int newAllowedReasons = ALLOWED_REASON_NONE; + newBlockedReasons |= (isRestrictedByAdmin ? BLOCKED_METERED_REASON_ADMIN_DISABLED : 0); + newBlockedReasons |= (mRestrictBackground ? BLOCKED_METERED_REASON_DATA_SAVER : 0); + newBlockedReasons |= (isDenied ? BLOCKED_METERED_REASON_USER_RESTRICTED : 0); + + newAllowedReasons |= (isSystem(uid) ? ALLOWED_REASON_SYSTEM : 0); + newAllowedReasons |= (isForeground ? ALLOWED_REASON_FOREGROUND : 0); + newAllowedReasons |= (isAllowed ? ALLOWED_METERED_REASON_USER_EXEMPTED : 0); + if (LOGV) { Log.v(TAG, "updateRuleForRestrictBackgroundUL(" + uid + ")" + ": isForeground=" +isForeground @@ -4618,6 +4711,18 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { // Dispatch changed rule to existing listeners. mHandler.obtainMessage(MSG_RULES_CHANGED, uid, newUidRules).sendToTarget(); + + final int oldEffectiveBlockedReasons = uidBlockedState.effectiveBlockedReasons; + uidBlockedState.blockedReasons = (uidBlockedState.blockedReasons + & ~BLOCKED_METERED_REASON_MASK) | newBlockedReasons; + uidBlockedState.allowedReasons = (uidBlockedState.allowedReasons + & ~ALLOWED_METERED_REASON_MASK) | newAllowedReasons; + uidBlockedState.updateEffectiveBlockedReasons(); + if (oldEffectiveBlockedReasons != uidBlockedState.effectiveBlockedReasons) { + mHandler.obtainMessage(MSG_BLOCKED_REASON_CHANGED, uid, + uidBlockedState.effectiveBlockedReasons, oldEffectiveBlockedReasons) + .sendToTarget(); + } } } @@ -4692,6 +4797,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { // Copy existing uid rules and clear ALL_NETWORK rules. int newUidRules = oldUidRules & (~MASK_ALL_NETWORKS); + UidBlockedState uidBlockedState = mUidBlockedState.get(uid); + if (uidBlockedState == null) { + uidBlockedState = new UidBlockedState(); + mUidBlockedState.put(uid, uidBlockedState); + } + // First step: define the new rule based on user restrictions and foreground state. // NOTE: if statements below could be inlined, but it's easier to understand the logic @@ -4704,6 +4815,20 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { newUidRules |= isWhitelisted ? RULE_ALLOW_ALL : RULE_REJECT_ALL; } + int newBlockedReasons = BLOCKED_REASON_NONE; + int newAllowedReasons = ALLOWED_REASON_NONE; + newBlockedReasons |= (mRestrictPower ? BLOCKED_REASON_BATTERY_SAVER : 0); + newBlockedReasons |= (mDeviceIdleMode ? BLOCKED_REASON_DOZE : 0); + newBlockedReasons |= (isUidIdle ? BLOCKED_REASON_APP_STANDBY : 0); + newBlockedReasons |= (uidBlockedState.blockedReasons & BLOCKED_REASON_RESTRICTED_MODE); + + newAllowedReasons |= (isSystem(uid) ? ALLOWED_REASON_SYSTEM : 0); + newAllowedReasons |= (isForeground ? ALLOWED_REASON_FOREGROUND : 0); + newAllowedReasons |= (isWhitelistedFromPowerSaveUL(uid, true) + ? ALLOWED_REASON_POWER_SAVE_ALLOWLIST : 0); + newAllowedReasons |= (isWhitelistedFromPowerSaveExceptIdleUL(uid) + ? ALLOWED_REASON_POWER_SAVE_EXCEPT_IDLE_ALLOWLIST : 0); + if (LOGV) { Log.v(TAG, "updateRulesForPowerRestrictionsUL(" + uid + ")" + ", isIdle: " + isUidIdle @@ -4735,6 +4860,18 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { mHandler.obtainMessage(MSG_RULES_CHANGED, uid, newUidRules).sendToTarget(); } + final int oldEffectiveBlockedReasons = uidBlockedState.effectiveBlockedReasons; + uidBlockedState.blockedReasons = (uidBlockedState.blockedReasons + & BLOCKED_METERED_REASON_MASK) | newBlockedReasons; + uidBlockedState.allowedReasons = (uidBlockedState.allowedReasons + & ALLOWED_METERED_REASON_MASK) | newAllowedReasons; + uidBlockedState.updateEffectiveBlockedReasons(); + if (oldEffectiveBlockedReasons != uidBlockedState.effectiveBlockedReasons) { + mHandler.obtainMessage(MSG_BLOCKED_REASON_CHANGED, uid, + uidBlockedState.effectiveBlockedReasons, oldEffectiveBlockedReasons) + .sendToTarget(); + } + return newUidRules; } @@ -4764,61 +4901,57 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } private void dispatchUidRulesChanged(INetworkPolicyListener listener, int uid, int uidRules) { - if (listener != null) { - try { - listener.onUidRulesChanged(uid, uidRules); - } catch (RemoteException ignored) { - } + try { + listener.onUidRulesChanged(uid, uidRules); + } catch (RemoteException ignored) { } } private void dispatchMeteredIfacesChanged(INetworkPolicyListener listener, String[] meteredIfaces) { - if (listener != null) { - try { - listener.onMeteredIfacesChanged(meteredIfaces); - } catch (RemoteException ignored) { - } + try { + listener.onMeteredIfacesChanged(meteredIfaces); + } catch (RemoteException ignored) { } } private void dispatchRestrictBackgroundChanged(INetworkPolicyListener listener, boolean restrictBackground) { - if (listener != null) { - try { - listener.onRestrictBackgroundChanged(restrictBackground); - } catch (RemoteException ignored) { - } + try { + listener.onRestrictBackgroundChanged(restrictBackground); + } catch (RemoteException ignored) { } } private void dispatchUidPoliciesChanged(INetworkPolicyListener listener, int uid, int uidPolicies) { - if (listener != null) { - try { - listener.onUidPoliciesChanged(uid, uidPolicies); - } catch (RemoteException ignored) { - } + try { + listener.onUidPoliciesChanged(uid, uidPolicies); + } catch (RemoteException ignored) { } } private void dispatchSubscriptionOverride(INetworkPolicyListener listener, int subId, int overrideMask, int overrideValue, int[] networkTypes) { - if (listener != null) { - try { - listener.onSubscriptionOverride(subId, overrideMask, overrideValue, networkTypes); - } catch (RemoteException ignored) { - } + try { + listener.onSubscriptionOverride(subId, overrideMask, overrideValue, networkTypes); + } catch (RemoteException ignored) { } } private void dispatchSubscriptionPlansChanged(INetworkPolicyListener listener, int subId, SubscriptionPlan[] plans) { - if (listener != null) { - try { - listener.onSubscriptionPlansChanged(subId, plans); - } catch (RemoteException ignored) { - } + try { + listener.onSubscriptionPlansChanged(subId, plans); + } catch (RemoteException ignored) { + } + } + + private void dispatchBlockedReasonChanged(INetworkPolicyListener listener, int uid, + int oldBlockedReasons, int newBlockedReasons) { + try { + listener.onBlockedReasonChanged(uid, oldBlockedReasons, newBlockedReasons); + } catch (RemoteException ignored) { } } @@ -4975,6 +5108,19 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { mListeners.finishBroadcast(); return true; } + case MSG_BLOCKED_REASON_CHANGED: { + final int uid = msg.arg1; + final int newBlockedReasons = msg.arg2; + final int oldBlockedReasons = (int) msg.obj; + final int length = mListeners.beginBroadcast(); + for (int i = 0; i < length; i++) { + final INetworkPolicyListener listener = mListeners.getBroadcastItem(i); + dispatchBlockedReasonChanged(listener, uid, + oldBlockedReasons, newBlockedReasons); + } + mListeners.finishBroadcast(); + return true; + } default: { return false; } @@ -5706,6 +5852,51 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { return (bundle != null) ? bundle.getBoolean(key, defaultValue) : defaultValue; } + private class UidBlockedState { + public int blockedReasons; + public int allowedReasons; + public int effectiveBlockedReasons; + + UidBlockedState() { + blockedReasons = BLOCKED_REASON_NONE; + allowedReasons = ALLOWED_REASON_NONE; + effectiveBlockedReasons = BLOCKED_REASON_NONE; + } + + void updateEffectiveBlockedReasons() { + effectiveBlockedReasons = blockedReasons; + // If the uid is not subject to any blocked reasons, then return early + if (blockedReasons == BLOCKED_REASON_NONE) { + return; + } + if ((allowedReasons & ALLOWED_REASON_SYSTEM) != 0) { + effectiveBlockedReasons = BLOCKED_REASON_NONE; + } + if ((allowedReasons & ALLOWED_REASON_FOREGROUND) != 0) { + effectiveBlockedReasons &= ~BLOCKED_REASON_BATTERY_SAVER; + effectiveBlockedReasons &= ~BLOCKED_REASON_DOZE; + effectiveBlockedReasons &= ~BLOCKED_REASON_APP_STANDBY; + effectiveBlockedReasons &= ~BLOCKED_METERED_REASON_DATA_SAVER; + effectiveBlockedReasons &= ~BLOCKED_METERED_REASON_USER_RESTRICTED; + } + if ((allowedReasons & ALLOWED_REASON_POWER_SAVE_ALLOWLIST) != 0) { + effectiveBlockedReasons &= ~BLOCKED_REASON_BATTERY_SAVER; + effectiveBlockedReasons &= ~BLOCKED_REASON_DOZE; + effectiveBlockedReasons &= ~BLOCKED_REASON_APP_STANDBY; + } + if ((allowedReasons & ALLOWED_REASON_POWER_SAVE_EXCEPT_IDLE_ALLOWLIST) != 0) { + effectiveBlockedReasons &= ~BLOCKED_REASON_BATTERY_SAVER; + effectiveBlockedReasons &= ~BLOCKED_REASON_APP_STANDBY; + } + if ((allowedReasons & ALLOWED_REASON_RESTRICTED_MODE_PERMISSIONS) != 0) { + effectiveBlockedReasons &= ~BLOCKED_REASON_RESTRICTED_MODE; + } + if ((allowedReasons & ALLOWED_METERED_REASON_USER_EXEMPTED) != 0) { + effectiveBlockedReasons &= ~BLOCKED_METERED_REASON_DATA_SAVER; + } + } + } + private class NotificationId { private final String mTag; private final int mId; diff --git a/services/core/java/com/android/server/os/NativeTombstoneManager.java b/services/core/java/com/android/server/os/NativeTombstoneManager.java index 9c4c5101cb6c..cc6a8243799d 100644 --- a/services/core/java/com/android/server/os/NativeTombstoneManager.java +++ b/services/core/java/com/android/server/os/NativeTombstoneManager.java @@ -411,8 +411,13 @@ public final class NativeTombstoneManager { processName = stream.readString(Tombstone.PROCESS_NAME); break; - case (int) Tombstone.CAUSE: - long token = stream.start(Tombstone.CAUSE); + case (int) Tombstone.CAUSES: + if (!crashReason.equals("")) { + // Causes appear in decreasing order of likelihood. For now we only + // want the most likely crash reason here, so ignore all others. + break; + } + long token = stream.start(Tombstone.CAUSES); cause: while (stream.nextField() != ProtoInputStream.NO_MORE_FIELDS) { switch (stream.getFieldNumber()) { diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java index b39a6b4f4658..5d8b75d2af4e 100644 --- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java +++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java @@ -52,6 +52,7 @@ import android.os.PowerManager; import android.os.SystemClock; import android.os.SystemProperties; import android.os.UserHandle; +import android.os.Trace; import android.os.WorkSource; import android.os.storage.StorageManager; import android.util.Log; @@ -62,6 +63,8 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.util.IndentingPrintWriter; import com.android.server.pm.Installer.InstallerException; import com.android.server.pm.dex.ArtManagerService; +import com.android.server.pm.dex.ArtStatsLogUtils; +import com.android.server.pm.dex.ArtStatsLogUtils.ArtStatsLogger; import com.android.server.pm.dex.DexManager; import com.android.server.pm.dex.DexoptOptions; import com.android.server.pm.dex.DexoptUtils; @@ -99,6 +102,8 @@ public class PackageDexOptimizer { private final PowerManager.WakeLock mDexoptWakeLock; private volatile boolean mSystemReady; + private final ArtStatsLogger mArtStatsLogger = new ArtStatsLogger(); + PackageDexOptimizer(Installer installer, Object installLock, Context context, String wakeLockTag) { this.mInstaller = installer; @@ -252,6 +257,28 @@ public class PackageDexOptimizer { profileUpdated, classLoaderContexts[i], dexoptFlags, sharedGid, packageStats, options.isDowngrade(), profileName, dexMetadataPath, options.getCompilationReason()); + + // Only report metrics for base apk for now. + // TODO: add ISA and APK type to metrics. + if (pkg.getBaseCodePath().equals(path)) { + Trace.traceBegin(Trace.TRACE_TAG_PACKAGE_MANAGER, "dex2oat-metrics"); + try { + long sessionId = Math.randomLongInternal(); + ArtStatsLogUtils.writeStatsLog( + mArtStatsLogger, + sessionId, + path, + compilerFilter, + sharedGid, + packageStats.getCompileTime(path), + dexMetadataPath, + options.getCompilationReason(), + newResult); + } finally { + Trace.traceEnd(Trace.TRACE_TAG_PACKAGE_MANAGER); + } + } + // The end result is: // - FAILED if any path failed, // - PERFORMED if at least one path needed compilation, diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java index 06b54b5c21fc..4038bf290161 100644 --- a/services/core/java/com/android/server/pm/StagingManager.java +++ b/services/core/java/com/android/server/pm/StagingManager.java @@ -203,7 +203,7 @@ public class StagingManager { newSigningDetails = ApkSignatureVerifier.verify(apexPath, minSignatureScheme); } catch (PackageParserException e) { throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED, - "Failed to parse APEX package " + apexPath, e); + "Failed to parse APEX package " + apexPath + " : " + e, e); } // Get signing details of the existing package @@ -221,7 +221,8 @@ public class StagingManager { existingApexPkg.applicationInfo.sourceDir, SignatureSchemeVersion.JAR); } catch (PackageParserException e) { throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED, - "Failed to parse APEX package " + existingApexPkg.applicationInfo.sourceDir, e); + "Failed to parse APEX package " + existingApexPkg.applicationInfo.sourceDir + + " : " + e, e); } // Verify signing details for upgrade @@ -283,7 +284,7 @@ public class StagingManager { } } catch (PackageParserException e) { throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED, - "Failed to parse APEX package " + apexInfo.modulePath, e); + "Failed to parse APEX package " + apexInfo.modulePath + " : " + e, e); } final PackageInfo activePackage = mApexManager.getPackageInfo(packageInfo.packageName, ApexManager.MATCH_ACTIVE_PACKAGE); diff --git a/services/core/java/com/android/server/pm/dex/ArtStatsLogUtils.java b/services/core/java/com/android/server/pm/dex/ArtStatsLogUtils.java new file mode 100644 index 000000000000..c8dc1b1ff562 --- /dev/null +++ b/services/core/java/com/android/server/pm/dex/ArtStatsLogUtils.java @@ -0,0 +1,226 @@ +/* + * Copyright (C) 2021 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.pm.dex; + +import static com.android.internal.art.ArtStatsLog.ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INSTALL_BULK_DOWNGRADED; +import static com.android.internal.art.ArtStatsLog.ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INSTALL_BULK_SECONDARY; +import static com.android.internal.art.ArtStatsLog.ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INSTALL_BULK_SECONDARY_DOWNGRADED; +import static com.android.internal.art.ArtStatsLog.ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_FAKE_RUN_FROM_APK_FALLBACK; +import static com.android.internal.art.ArtStatsLog.ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_FAKE_RUN_FROM_VDEX_FALLBACK; + +import android.util.jar.StrictJarFile; +import android.util.Slog; + +import com.android.internal.art.ArtStatsLog; +import com.android.server.pm.PackageManagerService; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.zip.ZipEntry; + +/** Utils class to report ART metrics to statsd. */ +public class ArtStatsLogUtils { + private static final String TAG = ArtStatsLogUtils.class.getSimpleName(); + private static final String PROFILE_DEX_METADATA = "primary.prof"; + private static final String VDEX_DEX_METADATA = "primary.vdex"; + + + private static final int ART_COMPILATION_REASON_INSTALL_BULK_SECONDARY = + ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INSTALL_BULK_SECONDARY; + private static final int ART_COMPILATION_REASON_INSTALL_BULK_DOWNGRADED = + ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INSTALL_BULK_DOWNGRADED; + private static final int ART_COMPILATION_REASON_INSTALL_BULK_SECONDARY_DOWNGRADED = + ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INSTALL_BULK_SECONDARY_DOWNGRADED; + + private static final int ART_COMPILATION_FILTER_FAKE_RUN_FROM_APK_FALLBACK = + ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_FAKE_RUN_FROM_APK_FALLBACK; + private static final int ART_COMPILATION_FILTER_FAKE_RUN_FROM_VDEX_FALLBACK = + ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_FAKE_RUN_FROM_VDEX_FALLBACK; + + private static final Map<Integer, Integer> COMPILATION_REASON_MAP = new HashMap(); + + static { + COMPILATION_REASON_MAP.put(PackageManagerService.REASON_UNKNOWN, ArtStatsLog. + ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_UNKNOWN); + COMPILATION_REASON_MAP.put(PackageManagerService.REASON_FIRST_BOOT, ArtStatsLog. + ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_FIRST_BOOT); + COMPILATION_REASON_MAP.put(PackageManagerService.REASON_BOOT_AFTER_OTA, ArtStatsLog. + ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_BOOT); + COMPILATION_REASON_MAP.put(PackageManagerService.REASON_POST_BOOT, ArtStatsLog. + ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_POST_BOOT); + COMPILATION_REASON_MAP.put(PackageManagerService.REASON_INSTALL, ArtStatsLog. + ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INSTALL); + COMPILATION_REASON_MAP.put(PackageManagerService.REASON_INSTALL_FAST, ArtStatsLog. + ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INSTALL_FAST); + COMPILATION_REASON_MAP.put(PackageManagerService.REASON_INSTALL_BULK, ArtStatsLog. + ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INSTALL_BULK); + COMPILATION_REASON_MAP.put(PackageManagerService.REASON_INSTALL_BULK_SECONDARY, + ART_COMPILATION_REASON_INSTALL_BULK_SECONDARY); + COMPILATION_REASON_MAP.put(PackageManagerService.REASON_INSTALL_BULK_DOWNGRADED, + ART_COMPILATION_REASON_INSTALL_BULK_DOWNGRADED); + COMPILATION_REASON_MAP.put(PackageManagerService.REASON_INSTALL_BULK_SECONDARY_DOWNGRADED, + ART_COMPILATION_REASON_INSTALL_BULK_SECONDARY_DOWNGRADED); + COMPILATION_REASON_MAP.put(PackageManagerService.REASON_BACKGROUND_DEXOPT, ArtStatsLog. + ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_BG_DEXOPT); + COMPILATION_REASON_MAP.put(PackageManagerService.REASON_AB_OTA, ArtStatsLog. + ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_AB_OTA); + COMPILATION_REASON_MAP.put(PackageManagerService.REASON_INACTIVE_PACKAGE_DOWNGRADE, + ArtStatsLog. + ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INACTIVE); + COMPILATION_REASON_MAP.put(PackageManagerService.REASON_SHARED, + ArtStatsLog.ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_SHARED); + } + + private static final Map<String, Integer> COMPILE_FILTER_MAP = new HashMap(); + + static { + COMPILE_FILTER_MAP.put("error", ArtStatsLog. + ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_ERROR); + COMPILE_FILTER_MAP.put("unknown", ArtStatsLog. + ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_UNKNOWN); + COMPILE_FILTER_MAP.put("assume-verified", ArtStatsLog. + ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_ASSUMED_VERIFIED); + COMPILE_FILTER_MAP.put("extract", ArtStatsLog. + ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_EXTRACT); + COMPILE_FILTER_MAP.put("verify", ArtStatsLog. + ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_VERIFY); + COMPILE_FILTER_MAP.put("quicken", ArtStatsLog. + ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_QUICKEN); + COMPILE_FILTER_MAP.put("space-profile", ArtStatsLog. + ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_SPACE_PROFILE); + COMPILE_FILTER_MAP.put("space", ArtStatsLog. + ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_SPACE); + COMPILE_FILTER_MAP.put("speed-profile", ArtStatsLog. + ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_SPEED_PROFILE); + COMPILE_FILTER_MAP.put("speed", ArtStatsLog. + ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_SPEED); + COMPILE_FILTER_MAP.put("everything-profile", ArtStatsLog. + ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_EVERYTHING_PROFILE); + COMPILE_FILTER_MAP.put("everything", ArtStatsLog. + ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_EVERYTHING); + COMPILE_FILTER_MAP.put("run-from-apk", ArtStatsLog. + ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_FAKE_RUN_FROM_APK); + COMPILE_FILTER_MAP.put("run-from-apk-fallback", + ART_COMPILATION_FILTER_FAKE_RUN_FROM_APK_FALLBACK); + COMPILE_FILTER_MAP.put("run-from-vdex-fallback", + ART_COMPILATION_FILTER_FAKE_RUN_FROM_VDEX_FALLBACK); + } + + public static void writeStatsLog( + ArtStatsLogger logger, + long sessionId, + String path, + String compilerFilter, + int uid, + long compileTime, + String dexMetadataPath, + int compilationReason, + int result) { + int dexMetadataType = getDexMetadataType(dexMetadataPath); + logger.write( + sessionId, + uid, + compilationReason, + compilerFilter, + ArtStatsLog.ART_DATUM_REPORTED__KIND__ART_DATUM_DEX2OAT_RESULT_CODE, + result, + dexMetadataType); + logger.write( + sessionId, + uid, + compilationReason, + compilerFilter, + ArtStatsLog.ART_DATUM_REPORTED__KIND__ART_DATUM_DEX2OAT_TOTAL_TIME, + compileTime, + dexMetadataType); + } + + private static int getDexMetadataType(String dexMetadataPath) { + if (dexMetadataPath == null) { + return ArtStatsLog.ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_NONE; + } + StrictJarFile jarFile = null; + try { + jarFile = new StrictJarFile(dexMetadataPath, + /*verify=*/ false, + /*signatureSchemeRollbackProtectionsEnforced=*/false); + boolean hasProfile = findFileName(jarFile, PROFILE_DEX_METADATA); + boolean hasVdex = findFileName(jarFile, VDEX_DEX_METADATA); + if (hasProfile && hasVdex) { + return ArtStatsLog. + ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_PROFILE_AND_VDEX; + } else if (hasProfile) { + return ArtStatsLog. + ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_PROFILE; + } else if (hasVdex) { + return ArtStatsLog. + ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_VDEX; + } else { + return ArtStatsLog. + ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_UNKNOWN; + } + } catch (IOException ignore) { + Slog.e(TAG, "Error when parsing dex metadata " + dexMetadataPath); + return ArtStatsLog.ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_ERROR; + } finally { + try { + if (jarFile != null) { + jarFile.close(); + } + } catch (IOException ignore) { + } + } + } + + private static boolean findFileName(StrictJarFile jarFile, String filename) throws IOException { + Iterator<ZipEntry> it = jarFile.iterator(); + while (it.hasNext()) { + ZipEntry entry = it.next(); + if (entry.getName().equals(filename)) { + return true; + } + } + return false; + } + + public static class ArtStatsLogger { + public void write( + long sessionId, + int uid, + int compilationReason, + String compilerFilter, + int kind, + long value, + int dexMetadataType) { + ArtStatsLog.write( + ArtStatsLog.ART_DATUM_REPORTED, + sessionId, + uid, + COMPILE_FILTER_MAP.getOrDefault(compilerFilter, ArtStatsLog. + ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_UNKNOWN), + COMPILATION_REASON_MAP.getOrDefault(compilationReason, ArtStatsLog. + ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_UNKNOWN), + /*timestamp_millis=*/ 0L, + ArtStatsLog.ART_DATUM_REPORTED__THREAD_TYPE__ART_THREAD_MAIN, + kind, + value, + dexMetadataType); + } + } +} diff --git a/services/core/java/com/android/server/pm/dex/DexManager.java b/services/core/java/com/android/server/pm/dex/DexManager.java index 349561d3f1d1..37f317557aeb 100644 --- a/services/core/java/com/android/server/pm/dex/DexManager.java +++ b/services/core/java/com/android/server/pm/dex/DexManager.java @@ -986,7 +986,7 @@ public class DexManager { * Fetches the battery manager object and caches it if it hasn't been fetched already. */ private BatteryManager getBatteryManager() { - if (mBatteryManager == null) { + if (mBatteryManager == null && mContext != null) { mBatteryManager = mContext.getSystemService(BatteryManager.class); } @@ -1008,10 +1008,6 @@ public class DexManager { && mPowerManager.getCurrentThermalStatus() >= PowerManager.THERMAL_STATUS_SEVERE); - if (DEBUG) { - Log.d(TAG, "Battery, thermal, or memory are critical: " + isBtmCritical); - } - return isBtmCritical; } diff --git a/services/core/java/com/android/server/policy/LegacyGlobalActions.java b/services/core/java/com/android/server/policy/LegacyGlobalActions.java index 9c3a39440054..5b48abb3e1f2 100644 --- a/services/core/java/com/android/server/policy/LegacyGlobalActions.java +++ b/services/core/java/com/android/server/policy/LegacyGlobalActions.java @@ -24,11 +24,11 @@ import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; +import android.content.pm.PackageManager; import android.content.pm.UserInfo; import android.database.ContentObserver; import android.graphics.drawable.Drawable; import android.media.AudioManager; -import android.net.ConnectivityManager; import android.os.Build; import android.os.Handler; import android.os.Message; @@ -113,7 +113,7 @@ class LegacyGlobalActions implements DialogInterface.OnDismissListener, DialogIn private boolean mDeviceProvisioned = false; private ToggleAction.State mAirplaneState = ToggleAction.State.Off; private boolean mIsWaitingForEcmExit = false; - private boolean mHasTelephony; + private final boolean mHasTelephony; private boolean mHasVibrator; private final boolean mShowSilentToggle; private final EmergencyAffordanceManager mEmergencyAffordanceManager; @@ -137,9 +137,8 @@ class LegacyGlobalActions implements DialogInterface.OnDismissListener, DialogIn filter.addAction(TelephonyManager.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED); context.registerReceiver(mBroadcastReceiver, filter); - ConnectivityManager cm = (ConnectivityManager) - context.getSystemService(Context.CONNECTIVITY_SERVICE); - mHasTelephony = cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE); + mHasTelephony = + context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY); // get notified of phone state changes TelephonyManager telephonyManager = diff --git a/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java b/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java index fd2d8e1b834b..beebb3145018 100644 --- a/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java +++ b/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java @@ -16,6 +16,8 @@ package com.android.server.recoverysystem; +import static android.os.UserHandle.USER_SYSTEM; + import android.annotation.IntDef; import android.content.Context; import android.content.IntentSender; @@ -33,12 +35,14 @@ import android.os.RemoteException; import android.os.ResultReceiver; import android.os.ShellCallback; import android.os.SystemProperties; +import android.provider.DeviceConfig; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Slog; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.util.FrameworkStatsLog; import com.android.internal.widget.LockSettingsInternal; import com.android.internal.widget.RebootEscrowListener; import com.android.server.LocalServices; @@ -52,6 +56,8 @@ import java.io.FileDescriptor; import java.io.FileWriter; import java.io.IOException; import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; /** * The recovery system service is responsible for coordinating recovery related @@ -127,10 +133,28 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo /** * The action to perform upon resume on reboot clear request for a given client. */ - @IntDef({ROR_NOT_REQUESTED, + @IntDef({ ROR_NOT_REQUESTED, ROR_REQUESTED_NEED_CLEAR, ROR_REQUESTED_SKIP_CLEAR}) - private @interface ResumeOnRebootActionsOnClear{} + private @interface ResumeOnRebootActionsOnClear {} + + /** + * The error code for reboots initiated by resume on reboot clients. + */ + private static final int REBOOT_ERROR_NONE = 0; + private static final int REBOOT_ERROR_UNKNOWN = 1; + private static final int REBOOT_ERROR_INVALID_PACKAGE_NAME = 2; + private static final int REBOOT_ERROR_LSKF_NOT_CAPTURED = 3; + private static final int REBOOT_ERROR_SLOT_MISMATCH = 4; + private static final int REBOOT_ERROR_ARM_REBOOT_ESCROW_FAILURE = 5; + + @IntDef({ REBOOT_ERROR_NONE, + REBOOT_ERROR_UNKNOWN, + REBOOT_ERROR_INVALID_PACKAGE_NAME, + REBOOT_ERROR_LSKF_NOT_CAPTURED, + REBOOT_ERROR_SLOT_MISMATCH, + REBOOT_ERROR_ARM_REBOOT_ESCROW_FAILURE}) + private @interface ResumeOnRebootRebootErrorCode {} static class Injector { protected final Context mContext; @@ -202,6 +226,35 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo public void threadSleep(long millis) throws InterruptedException { Thread.sleep(millis); } + + public int getUidFromPackageName(String packageName) { + try { + return mContext.getPackageManager().getPackageUidAsUser(packageName, USER_SYSTEM); + } catch (PackageManager.NameNotFoundException e) { + Slog.w(TAG, "Failed to find uid for " + packageName); + } + return -1; + } + + public void reportRebootEscrowPreparationMetrics(int uid, + @ResumeOnRebootActionsOnRequest int requestResult, int requestedClientCount) { + FrameworkStatsLog.write(FrameworkStatsLog.REBOOT_ESCROW_PREPARATION_REPORTED, uid, + requestResult, requestedClientCount); + } + + public void reportRebootEscrowLskfCapturedMetrics(int uid, int requestedClientCount, + int requestedToLskfCapturedDurationInSeconds) { + FrameworkStatsLog.write(FrameworkStatsLog.REBOOT_ESCROW_LSKF_CAPTURE_REPORTED, uid, + requestedClientCount, requestedToLskfCapturedDurationInSeconds); + } + + public void reportRebootEscrowRebootMetrics(int errorCode, int uid, + int preparedClientCount, int requestCount, boolean slotSwitch, boolean serverBased, + int lskfCapturedToRebootDurationInSeconds, int lskfCapturedCounts) { + FrameworkStatsLog.write(FrameworkStatsLog.REBOOT_ESCROW_REBOOT_REPORTED, errorCode, + uid, preparedClientCount, requestCount, slotSwitch, serverBased, + lskfCapturedToRebootDurationInSeconds, lskfCapturedCounts); + } } /** @@ -367,6 +420,16 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo } } + private void reportMetricsOnRequestLskf(String packageName, int requestResult) { + int uid = mInjector.getUidFromPackageName(packageName); + int pendingRequestCount; + synchronized (this) { + pendingRequestCount = mCallerPendingRequest.size(); + } + + mInjector.reportRebootEscrowPreparationMetrics(uid, requestResult, pendingRequestCount); + } + @Override // Binder call public boolean requestLskf(String packageName, IntentSender intentSender) { enforcePermissionForResumeOnReboot(); @@ -378,6 +441,8 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo @ResumeOnRebootActionsOnRequest int action = updateRoRPreparationStateOnNewRequest( packageName, intentSender); + reportMetricsOnRequestLskf(packageName, action); + switch (action) { case ROR_SKIP_PREPARATION_AND_NOTIFY: // We consider the preparation done if someone else has prepared. @@ -420,12 +485,26 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo return needPreparation ? ROR_NEED_PREPARATION : ROR_SKIP_PREPARATION_NOT_NOTIFY; } + private void reportMetricsOnPreparedForReboot() { + List<String> preparedClients; + synchronized (this) { + preparedClients = new ArrayList<>(mCallerPreparedForReboot); + } + + for (String packageName : preparedClients) { + int uid = mInjector.getUidFromPackageName(packageName); + mInjector.reportRebootEscrowLskfCapturedMetrics(uid, preparedClients.size(), + -1 /* duration */); + } + } + @Override public void onPreparedForReboot(boolean ready) { if (!ready) { return; } updateRoRPreparationStateOnPreparedForReboot(); + reportMetricsOnPreparedForReboot(); } private synchronized void updateRoRPreparationStateOnPreparedForReboot() { @@ -548,22 +627,49 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo return true; } - private boolean rebootWithLskfImpl(String packageName, String reason, boolean slotSwitch) { + private @ResumeOnRebootRebootErrorCode int armRebootEscrow(String packageName, + boolean slotSwitch) { if (packageName == null) { Slog.w(TAG, "Missing packageName when rebooting with lskf."); - return false; + return REBOOT_ERROR_INVALID_PACKAGE_NAME; } if (!isLskfCaptured(packageName)) { - return false; + return REBOOT_ERROR_LSKF_NOT_CAPTURED; } if (!verifySlotForNextBoot(slotSwitch)) { - return false; + return REBOOT_ERROR_SLOT_MISMATCH; } - // TODO(xunchang) write the vbmeta digest along with the escrowKey before reboot. if (!mInjector.getLockSettingsService().armRebootEscrow()) { Slog.w(TAG, "Failure to escrow key for reboot"); + return REBOOT_ERROR_ARM_REBOOT_ESCROW_FAILURE; + } + + return REBOOT_ERROR_NONE; + } + + private void reportMetricsOnRebootWithLskf(String packageName, boolean slotSwitch, + @ResumeOnRebootRebootErrorCode int errorCode) { + int uid = mInjector.getUidFromPackageName(packageName); + boolean serverBased = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_OTA, + "server_based_ror_enabled", false); + int preparedClientCount; + synchronized (this) { + preparedClientCount = mCallerPreparedForReboot.size(); + } + + // TODO(b/179105110) report the true value of duration and counts + mInjector.reportRebootEscrowRebootMetrics(errorCode, uid, preparedClientCount, + 1 /* request count */, slotSwitch, serverBased, + -1 /* duration */, 1 /* lskf capture count */); + } + + private boolean rebootWithLskfImpl(String packageName, String reason, boolean slotSwitch) { + @ResumeOnRebootRebootErrorCode int errorCode = armRebootEscrow(packageName, slotSwitch); + reportMetricsOnRebootWithLskf(packageName, slotSwitch, errorCode); + + if (errorCode != REBOOT_ERROR_NONE) { return false; } diff --git a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java index 69a153f79a1b..9589505ef251 100644 --- a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java +++ b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java @@ -42,7 +42,6 @@ import android.net.LinkAddress; import android.net.LinkProperties; import android.net.Network; import android.net.NetworkAgent; -import android.net.NetworkAgent.ValidationStatus; import android.net.NetworkAgentConfig; import android.net.NetworkCapabilities; import android.net.RouteInfo; @@ -1442,17 +1441,16 @@ public class VcnGatewayConnection extends StateMachine { caps, lp, Vcn.getNetworkScore(), - new NetworkAgentConfig(), + new NetworkAgentConfig.Builder().build(), mVcnContext.getVcnNetworkProvider()) { @Override - public void unwanted() { + public void onNetworkUnwanted() { Slog.d(TAG, "NetworkAgent was unwanted"); teardownAsynchronously(); } @Override - public void onValidationStatus( - @ValidationStatus int status, @Nullable Uri redirectUri) { + public void onValidationStatus(int status, @Nullable Uri redirectUri) { if (status == NetworkAgent.VALIDATION_STATUS_VALID) { clearFailedAttemptCounterAndSafeModeAlarm(); } @@ -1798,8 +1796,10 @@ public class VcnGatewayConnection extends StateMachine { lp.addDnsServer(addr); } - lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null)); - lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null)); + lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null /*gateway*/, + null /*iface*/, RouteInfo.RTN_UNICAST)); + lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null /*gateway*/, + null /*iface*/, RouteInfo.RTN_UNICAST)); lp.setMtu(gatewayConnectionConfig.getMaxMtu()); diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java index 7e6b7cd05762..e060171bde47 100644 --- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java @@ -110,6 +110,7 @@ import android.content.pm.UserInfo; import android.content.res.Configuration; import android.graphics.Rect; import android.os.Binder; +import android.os.Build; import android.os.Bundle; import android.os.Debug; import android.os.Handler; @@ -165,13 +166,13 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { static final String TAG_TASKS = TAG + POSTFIX_TASKS; /** How long we wait until giving up on the last activity telling us it is idle. */ - private static final int IDLE_TIMEOUT = 10 * 1000; + private static final int IDLE_TIMEOUT = 10 * 1000 * Build.HW_TIMEOUT_MULTIPLIER; /** How long we can hold the sleep wake lock before giving up. */ - private static final int SLEEP_TIMEOUT = 5 * 1000; + private static final int SLEEP_TIMEOUT = 5 * 1000 * Build.HW_TIMEOUT_MULTIPLIER; // How long we can hold the launch wake lock before giving up. - private static final int LAUNCH_TIMEOUT = 10 * 1000; + private static final int LAUNCH_TIMEOUT = 10 * 1000 * Build.HW_TIMEOUT_MULTIPLIER; /** How long we wait until giving up on the activity telling us it released the top state. */ private static final int TOP_RESUMED_STATE_LOSS_TIMEOUT = 500; diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index 816a6a065e69..f55a983a8b0d 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -312,9 +312,10 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION; // How long we wait until we timeout on key dispatching. - public static final int KEY_DISPATCHING_TIMEOUT_MS = 5 * 1000; + public static final int KEY_DISPATCHING_TIMEOUT_MS = 5 * 1000 * Build.HW_TIMEOUT_MULTIPLIER; // How long we wait until we timeout on key dispatching during instrumentation. - static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT_MS = 60 * 1000; + static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT_MS = + 60 * 1000 * Build.HW_TIMEOUT_MULTIPLIER; // How long we permit background activity starts after an activity in the process // started or finished. static final long ACTIVITY_BG_START_GRACE_PERIOD_MS = 10 * 1000; diff --git a/services/core/jni/com_android_server_SystemServer.cpp b/services/core/jni/com_android_server_SystemServer.cpp index 729fa71af169..d18043f6b3e9 100644 --- a/services/core/jni/com_android_server_SystemServer.cpp +++ b/services/core/jni/com_android_server_SystemServer.cpp @@ -100,16 +100,9 @@ static void android_server_SystemServer_initZygoteChildHeapProfiling(JNIEnv* /* } static void android_server_SystemServer_fdtrackAbort(JNIEnv*, jobject) { - raise(BIONIC_SIGNAL_FDTRACK); - - // Wait for a bit to allow fdtrack to dump backtraces to logcat. - std::this_thread::sleep_for(5s); - - // Abort on a different thread to avoid ART dumping runtime stacks. - std::thread([]() { - LOG_ALWAYS_FATAL("b/140703823: aborting due to fd leak: check logs for fd " - "backtraces"); - }).join(); + sigval val; + val.sival_int = 1; + sigqueue(getpid(), BIONIC_SIGNAL_FDTRACK, val); } static jlong android_server_SystemServer_startIncrementalService(JNIEnv* env, jclass klass, diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 6badafa34dfd..736a6f68725e 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -15621,10 +15621,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { Objects.requireNonNull(who, "ComponentName is null"); enforceDeviceOwner(who); - String currentMode = mInjector.settingsGlobalGetString(PRIVATE_DNS_MODE); - if (currentMode == null) { - currentMode = ConnectivityManager.PRIVATE_DNS_DEFAULT_MODE_FALLBACK; - } + final String currentMode = ConnectivityManager.getPrivateDnsMode(mContext); switch (currentMode) { case ConnectivityManager.PRIVATE_DNS_MODE_OFF: return PRIVATE_DNS_MODE_OFF; diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 7bde760191b5..46ec65d7567c 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -332,8 +332,6 @@ public final class SystemServer { private static final String UNCRYPT_PACKAGE_FILE = "/cache/recovery/uncrypt_file"; private static final String BLOCK_MAP_FILE = "/cache/recovery/block.map"; - private static final String GSI_RUNNING_PROP = "ro.gsid.image_running"; - // maximum number of binder threads used for system_server // will be higher than the system default private static final int sMaxBinderThreads = 31; @@ -1127,7 +1125,7 @@ public final class SystemServer { false); boolean enableLeftyService = SystemProperties.getBoolean("config.enable_lefty", false); - boolean isEmulator = SystemProperties.get("ro.kernel.qemu").equals("1"); + boolean isEmulator = SystemProperties.get("ro.boot.qemu").equals("1"); boolean isWatch = context.getPackageManager().hasSystemFeature( PackageManager.FEATURE_WATCH); @@ -1443,8 +1441,7 @@ public final class SystemServer { t.traceEnd(); final boolean hasPdb = !SystemProperties.get(PERSISTENT_DATA_BLOCK_PROP).equals(""); - final boolean hasGsi = SystemProperties.getInt(GSI_RUNNING_PROP, 0) > 0; - if (hasPdb && !hasGsi) { + if (hasPdb) { t.traceBegin("StartPersistentDataBlock"); mSystemServiceManager.startService(PersistentDataBlockService.class); t.traceEnd(); diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java b/services/tests/mockingservicestests/src/com/android/server/pm/dex/DexManagerTests.java index ee0a16a70265..2e0cadf264cf 100644 --- a/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java +++ b/services/tests/mockingservicestests/src/com/android/server/pm/dex/DexManagerTests.java @@ -11,7 +11,7 @@ * 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 + * limitations under the License. */ package com.android.server.pm.dex; @@ -28,28 +28,34 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.res.Resources; +import android.os.BatteryManager; import android.os.Build; +import android.os.PowerManager; import android.os.UserHandle; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; +import com.android.dx.mockito.inline.extended.ExtendedMockito; +import com.android.dx.mockito.inline.extended.StaticMockitoSession; import com.android.server.pm.Installer; +import com.android.server.pm.PackageManagerService; import dalvik.system.DelegateLastClassLoader; import dalvik.system.PathClassLoader; import dalvik.system.VMRuntime; +import org.junit.After; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; import org.mockito.quality.Strictness; import java.io.File; @@ -69,9 +75,15 @@ public class DexManagerTests { DelegateLastClassLoader.class.getName(); private static final String UNSUPPORTED_CLASS_LOADER_NAME = "unsupported.class_loader"; - @Rule public MockitoRule mockito = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS); + private static final int TEST_BATTERY_LEVEL_CRITICAL = 10; + private static final int TEST_BATTERY_LEVEL_DEFAULT = 80; + + public StaticMockitoSession mMockitoSession; @Mock Installer mInstaller; @Mock IPackageManager mPM; + @Mock BatteryManager mMockBatteryManager; + @Mock PowerManager mMockPowerManager; + private final Object mInstallLock = new Object(); private DexManager mDexManager; @@ -117,7 +129,37 @@ public class DexManagerTests { mSystemServerJarUpdatedContext = new TestData("android", isa, mUser0, DELEGATE_LAST_CLASS_LOADER_NAME); - mDexManager = new DexManager(/*Context*/ null, mPM, /*PackageDexOptimizer*/ null, + // Initialize Static Mocking + + mMockitoSession = ExtendedMockito.mockitoSession() + .initMocks(this) + .strictness(Strictness.LENIENT) + .startMocking(); + + // Mock.... + + mMockBatteryManager = ExtendedMockito.mock(BatteryManager.class); + mMockPowerManager = ExtendedMockito.mock(PowerManager.class); + + setDefaultMockValues(); + + Resources mockResources = ExtendedMockito.mock(Resources.class); + ExtendedMockito.when(mockResources + .getInteger(com.android.internal.R.integer.config_criticalBatteryWarningLevel)) + .thenReturn(15); + + Context mockContext = ExtendedMockito.mock(Context.class); + ExtendedMockito.doReturn(mockResources) + .when(mockContext) + .getResources(); + ExtendedMockito.doReturn(mMockBatteryManager) + .when(mockContext) + .getSystemService(BatteryManager.class); + ExtendedMockito.doReturn(mMockPowerManager) + .when(mockContext) + .getSystemService(PowerManager.class); + + mDexManager = new DexManager(mockContext, mPM, /*PackageDexOptimizer*/ null, mInstaller, mInstallLock); // Foo and Bar are available to user0. @@ -128,6 +170,25 @@ public class DexManagerTests { mDexManager.load(existingPackages); } + @After + public void teardown() throws Exception { + mMockitoSession.finishMocking(); + } + + private void setDefaultMockValues() { + ExtendedMockito.doReturn(BatteryManager.BATTERY_STATUS_DISCHARGING) + .when(mMockBatteryManager) + .getIntProperty(BatteryManager.BATTERY_PROPERTY_STATUS); + + ExtendedMockito.doReturn(TEST_BATTERY_LEVEL_DEFAULT) + .when(mMockBatteryManager) + .getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY); + + ExtendedMockito.doReturn(PowerManager.THERMAL_STATUS_NONE) + .when(mMockPowerManager) + .getCurrentThermalStatus(); + } + @Test public void testNotifyPrimaryUse() { // The main dex file and splits are re-loaded by the app. @@ -633,6 +694,114 @@ public class DexManagerTests { assertNoDclInfo(mSystemServerJarInvalid); } + @Test + public void testInstallScenarioToReasonDefault() { + assertEquals( + PackageManagerService.REASON_INSTALL, + mDexManager.getCompilationReasonForInstallScenario( + PackageManager.INSTALL_SCENARIO_DEFAULT)); + + assertEquals( + PackageManagerService.REASON_INSTALL_FAST, + mDexManager.getCompilationReasonForInstallScenario( + PackageManager.INSTALL_SCENARIO_FAST)); + + assertEquals( + PackageManagerService.REASON_INSTALL_BULK, + mDexManager.getCompilationReasonForInstallScenario( + PackageManager.INSTALL_SCENARIO_BULK)); + + assertEquals( + PackageManagerService.REASON_INSTALL_BULK_SECONDARY, + mDexManager.getCompilationReasonForInstallScenario( + PackageManager.INSTALL_SCENARIO_BULK_SECONDARY)); + } + + @Test + public void testInstallScenarioToReasonThermal() { + ExtendedMockito.doReturn(PowerManager.THERMAL_STATUS_SEVERE) + .when(mMockPowerManager) + .getCurrentThermalStatus(); + + assertEquals( + PackageManagerService.REASON_INSTALL, + mDexManager.getCompilationReasonForInstallScenario( + PackageManager.INSTALL_SCENARIO_DEFAULT)); + + assertEquals( + PackageManagerService.REASON_INSTALL_FAST, + mDexManager.getCompilationReasonForInstallScenario( + PackageManager.INSTALL_SCENARIO_FAST)); + + assertEquals( + PackageManagerService.REASON_INSTALL_BULK_DOWNGRADED, + mDexManager.getCompilationReasonForInstallScenario( + PackageManager.INSTALL_SCENARIO_BULK)); + + assertEquals( + PackageManagerService.REASON_INSTALL_BULK_SECONDARY_DOWNGRADED, + mDexManager.getCompilationReasonForInstallScenario( + PackageManager.INSTALL_SCENARIO_BULK_SECONDARY)); + } + + @Test + public void testInstallScenarioToReasonBatteryDischarging() { + ExtendedMockito.doReturn(TEST_BATTERY_LEVEL_CRITICAL) + .when(mMockBatteryManager) + .getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY); + + assertEquals( + PackageManagerService.REASON_INSTALL, + mDexManager.getCompilationReasonForInstallScenario( + PackageManager.INSTALL_SCENARIO_DEFAULT)); + + assertEquals( + PackageManagerService.REASON_INSTALL_FAST, + mDexManager.getCompilationReasonForInstallScenario( + PackageManager.INSTALL_SCENARIO_FAST)); + + assertEquals( + PackageManagerService.REASON_INSTALL_BULK_DOWNGRADED, + mDexManager.getCompilationReasonForInstallScenario( + PackageManager.INSTALL_SCENARIO_BULK)); + + assertEquals( + PackageManagerService.REASON_INSTALL_BULK_SECONDARY_DOWNGRADED, + mDexManager.getCompilationReasonForInstallScenario( + PackageManager.INSTALL_SCENARIO_BULK_SECONDARY)); + } + + @Test + public void testInstallScenarioToReasonBatteryCharging() { + ExtendedMockito.doReturn(TEST_BATTERY_LEVEL_CRITICAL) + .when(mMockBatteryManager) + .getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY); + + ExtendedMockito.doReturn(BatteryManager.BATTERY_STATUS_CHARGING) + .when(mMockBatteryManager) + .getIntProperty(BatteryManager.BATTERY_PROPERTY_STATUS); + + assertEquals( + PackageManagerService.REASON_INSTALL, + mDexManager.getCompilationReasonForInstallScenario( + PackageManager.INSTALL_SCENARIO_DEFAULT)); + + assertEquals( + PackageManagerService.REASON_INSTALL_FAST, + mDexManager.getCompilationReasonForInstallScenario( + PackageManager.INSTALL_SCENARIO_FAST)); + + assertEquals( + PackageManagerService.REASON_INSTALL_BULK, + mDexManager.getCompilationReasonForInstallScenario( + PackageManager.INSTALL_SCENARIO_BULK)); + + assertEquals( + PackageManagerService.REASON_INSTALL_BULK_SECONDARY, + mDexManager.getCompilationReasonForInstallScenario( + PackageManager.INSTALL_SCENARIO_BULK_SECONDARY)); + } + private void assertSecondaryUse(TestData testData, PackageUseInfo pui, List<String> secondaries, boolean isUsedByOtherApps, int ownerUserId, String[] expectedContexts) { diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/dex/OWNERS b/services/tests/mockingservicestests/src/com/android/server/pm/dex/OWNERS new file mode 100644 index 000000000000..5492dc8e37a3 --- /dev/null +++ b/services/tests/mockingservicestests/src/com/android/server/pm/dex/OWNERS @@ -0,0 +1 @@ +include platform/art:/OWNERS
\ No newline at end of file diff --git a/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest/OWNERS b/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest/OWNERS new file mode 100644 index 000000000000..e95633abe79a --- /dev/null +++ b/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest/OWNERS @@ -0,0 +1 @@ +include /core/java/android/app/admin/OWNERS diff --git a/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest2/OWNERS b/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest2/OWNERS new file mode 100644 index 000000000000..e95633abe79a --- /dev/null +++ b/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest2/OWNERS @@ -0,0 +1 @@ +include /core/java/android/app/admin/OWNERS diff --git a/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest3/OWNERS b/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest3/OWNERS new file mode 100644 index 000000000000..e95633abe79a --- /dev/null +++ b/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest3/OWNERS @@ -0,0 +1 @@ +include /core/java/android/app/admin/OWNERS diff --git a/services/tests/servicestests/assets/OwnersTest/OWNERS b/services/tests/servicestests/assets/OwnersTest/OWNERS new file mode 100644 index 000000000000..e95633abe79a --- /dev/null +++ b/services/tests/servicestests/assets/OwnersTest/OWNERS @@ -0,0 +1 @@ +include /core/java/android/app/admin/OWNERS diff --git a/services/tests/servicestests/assets/PolicyVersionUpgraderTest/OWNERS b/services/tests/servicestests/assets/PolicyVersionUpgraderTest/OWNERS new file mode 100644 index 000000000000..e95633abe79a --- /dev/null +++ b/services/tests/servicestests/assets/PolicyVersionUpgraderTest/OWNERS @@ -0,0 +1 @@ +include /core/java/android/app/admin/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java b/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java index 1c9683803857..1b8ab2175458 100644 --- a/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java @@ -18,6 +18,7 @@ package com.android.server.apphibernation; import static android.content.pm.PackageManager.MATCH_ANY_USER; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.mockito.AdditionalAnswers.returnsArgAt; import static org.mockito.ArgumentMatchers.any; @@ -67,6 +68,7 @@ public final class AppHibernationServiceTest { private static final String PACKAGE_SCHEME = "package"; private static final String PACKAGE_NAME_1 = "package1"; private static final String PACKAGE_NAME_2 = "package2"; + private static final String PACKAGE_NAME_3 = "package3"; private static final int USER_ID_1 = 1; private static final int USER_ID_2 = 2; @@ -107,6 +109,8 @@ public final class AppHibernationServiceTest { List<PackageInfo> packages = new ArrayList<>(); packages.add(makePackageInfo(PACKAGE_NAME_1)); + packages.add(makePackageInfo(PACKAGE_NAME_2)); + packages.add(makePackageInfo(PACKAGE_NAME_3)); doReturn(new ParceledListSlice<>(packages)).when(mIPackageManager).getInstalledPackages( intThat(arg -> (arg & MATCH_ANY_USER) != 0), anyInt()); mAppHibernationService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED); @@ -179,6 +183,26 @@ public final class AppHibernationServiceTest { assertTrue(mAppHibernationService.isHibernatingGlobally(PACKAGE_NAME_1)); } + @Test + public void testGetHibernatingPackagesForUser_returnsCorrectPackages() throws RemoteException { + // GIVEN an unlocked user with all packages installed + UserInfo userInfo = + addUser(USER_ID_2, new String[]{PACKAGE_NAME_1, PACKAGE_NAME_2, PACKAGE_NAME_3}); + mAppHibernationService.onUserUnlocking(new SystemService.TargetUser(userInfo)); + doReturn(true).when(mUserManager).isUserUnlockingOrUnlocked(USER_ID_2); + + // WHEN packages are hibernated for the user + mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_1, USER_ID_2, true); + mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_2, USER_ID_2, true); + + // THEN the hibernating packages returned matches + List<String> hibernatingPackages = + mAppHibernationService.getHibernatingPackagesForUser(USER_ID_2); + assertEquals(2, hibernatingPackages.size()); + assertTrue(hibernatingPackages.contains(PACKAGE_NAME_1)); + assertTrue(hibernatingPackages.contains(PACKAGE_NAME_2)); + } + /** * Add a mock user with one package. */ diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java index a38745f2a66e..d9af51f819c3 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java @@ -42,7 +42,6 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.os.FileUtils; -import android.security.keystore.AndroidKeyStoreSecretKey; import android.security.keystore.KeyGenParameterSpec; import android.security.keystore.KeyProperties; import android.security.keystore.recovery.KeyChainSnapshot; @@ -109,7 +108,7 @@ public class KeySyncTaskTest { private RecoverySnapshotStorage mRecoverySnapshotStorage; private RecoverableKeyStoreDb mRecoverableKeyStoreDb; private File mDatabaseFile; - private AndroidKeyStoreSecretKey mWrappingKey; + private SecretKey mWrappingKey; private PlatformEncryptionKey mEncryptKey; private KeySyncTask mKeySyncTask; @@ -848,7 +847,7 @@ public class KeySyncTaskTest { return keyGenerator.generateKey(); } - private AndroidKeyStoreSecretKey generateAndroidKeyStoreKey() throws Exception { + private SecretKey generateAndroidKeyStoreKey() throws Exception { KeyGenerator keyGenerator = KeyGenerator.getInstance( KEY_ALGORITHM, ANDROID_KEY_STORE_PROVIDER); @@ -857,7 +856,7 @@ public class KeySyncTaskTest { .setBlockModes(KeyProperties.BLOCK_MODE_GCM) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) .build()); - return (AndroidKeyStoreSecretKey) keyGenerator.generateKey(); + return keyGenerator.generateKey(); } private static byte[] utf8Bytes(String s) { diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyGeneratorTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyGeneratorTest.java index c295177814b0..64130266b2c4 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyGeneratorTest.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyGeneratorTest.java @@ -23,7 +23,6 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import android.content.Context; -import android.security.keystore.AndroidKeyStoreSecretKey; import android.security.keystore.KeyGenParameterSpec; import android.security.keystore.KeyProperties; @@ -45,6 +44,7 @@ import java.util.Random; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; +import javax.crypto.SecretKey; import javax.crypto.spec.GCMParameterSpec; @SmallTest @@ -77,7 +77,7 @@ public class RecoverableKeyGeneratorTest { mDatabaseFile = context.getDatabasePath(DATABASE_FILE_NAME); mRecoverableKeyStoreDb = RecoverableKeyStoreDb.newInstance(context); - AndroidKeyStoreSecretKey platformKey = generatePlatformKey(); + SecretKey platformKey = generatePlatformKey(); mPlatformKey = new PlatformEncryptionKey(TEST_GENERATION_ID, platformKey); mDecryptKey = new PlatformDecryptionKey(TEST_GENERATION_ID, platformKey); mRecoverableKeyGenerator = RecoverableKeyGenerator.newInstance(mRecoverableKeyStoreDb); @@ -168,7 +168,7 @@ public class RecoverableKeyGeneratorTest { assertArrayEquals(rawMaterial, unwrappedMaterial); } - private AndroidKeyStoreSecretKey generatePlatformKey() throws Exception { + private SecretKey generatePlatformKey() throws Exception { KeyGenerator keyGenerator = KeyGenerator.getInstance( KEY_ALGORITHM, ANDROID_KEY_STORE_PROVIDER); @@ -177,7 +177,7 @@ public class RecoverableKeyGeneratorTest { .setBlockModes(KeyProperties.BLOCK_MODE_GCM) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) .build()); - return (AndroidKeyStoreSecretKey) keyGenerator.generateKey(); + return keyGenerator.generateKey(); } private static byte[] randomBytes(int n) { diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java index ac7447006444..f4e74bab2bd4 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java @@ -45,7 +45,6 @@ import android.content.Intent; import android.os.Binder; import android.os.ServiceSpecificException; import android.os.UserHandle; -import android.security.keystore.AndroidKeyStoreSecretKey; import android.security.keystore.KeyGenParameterSpec; import android.security.keystore.KeyProperties; import android.security.keystore.recovery.KeyChainProtectionParams; @@ -1311,7 +1310,7 @@ public class RecoverableKeyStoreManagerTest { mRecoverableKeyStoreDb.setShouldCreateSnapshot(userId, uid, false); } - private AndroidKeyStoreSecretKey generateAndroidKeyStoreKey() throws Exception { + private SecretKey generateAndroidKeyStoreKey() throws Exception { KeyGenerator keyGenerator = KeyGenerator.getInstance( KEY_ALGORITHM, ANDROID_KEY_STORE_PROVIDER); @@ -1320,6 +1319,6 @@ public class RecoverableKeyStoreManagerTest { .setBlockModes(KeyProperties.BLOCK_MODE_GCM) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) .build()); - return (AndroidKeyStoreSecretKey) keyGenerator.generateKey(); + return keyGenerator.generateKey(); } } diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/WrappedKeyTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/WrappedKeyTest.java index 9813ab74721e..60052f7114b3 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/WrappedKeyTest.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/WrappedKeyTest.java @@ -21,7 +21,6 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import android.security.keystore.AndroidKeyStoreSecretKey; import android.security.keystore.KeyGenParameterSpec; import android.security.keystore.KeyProperties; import android.util.Pair; @@ -117,7 +116,7 @@ public class WrappedKeyTest { @Test public void decryptWrappedKeys_decryptsWrappedKeys_nullMetadata() throws Exception { String alias = "karlin"; - AndroidKeyStoreSecretKey platformKey = generateAndroidKeyStoreKey(); + SecretKey platformKey = generateAndroidKeyStoreKey(); SecretKey appKey = generateKey(); WrappedKey wrappedKey = WrappedKey.fromSecretKey( new PlatformEncryptionKey(GENERATION_ID, platformKey), appKey, NULL_METADATA); @@ -136,7 +135,7 @@ public class WrappedKeyTest { @Test public void decryptWrappedKeys_decryptsWrappedKeys_nonNullMetadata() throws Exception { String alias = "karlin"; - AndroidKeyStoreSecretKey platformKey = generateAndroidKeyStoreKey(); + SecretKey platformKey = generateAndroidKeyStoreKey(); SecretKey appKey = generateKey(); WrappedKey wrappedKey = WrappedKey.fromSecretKey( new PlatformEncryptionKey(GENERATION_ID, platformKey), appKey, NON_NULL_METADATA); @@ -155,7 +154,7 @@ public class WrappedKeyTest { @Test public void decryptWrappedKeys_doesNotDieIfSomeKeysAreUnwrappable() throws Exception { String alias = "karlin"; - AndroidKeyStoreSecretKey platformKey = generateAndroidKeyStoreKey(); + SecretKey platformKey = generateAndroidKeyStoreKey(); SecretKey appKey = generateKey(); WrappedKey wrappedKey = WrappedKey.fromSecretKey( new PlatformEncryptionKey(GENERATION_ID, platformKey), appKey, NULL_METADATA); @@ -171,7 +170,7 @@ public class WrappedKeyTest { @Test public void decryptWrappedKeys_throwsIfPlatformKeyGenerationIdDoesNotMatch() throws Exception { - AndroidKeyStoreSecretKey platformKey = generateAndroidKeyStoreKey(); + SecretKey platformKey = generateAndroidKeyStoreKey(); WrappedKey wrappedKey = WrappedKey.fromSecretKey( new PlatformEncryptionKey(GENERATION_ID, platformKey), generateKey(), /*metadata=*/ null); @@ -197,7 +196,7 @@ public class WrappedKeyTest { return keyGenerator.generateKey(); } - private AndroidKeyStoreSecretKey generateAndroidKeyStoreKey() throws Exception { + private SecretKey generateAndroidKeyStoreKey() throws Exception { KeyGenerator keyGenerator = KeyGenerator.getInstance( KEY_ALGORITHM, ANDROID_KEY_STORE_PROVIDER); @@ -207,6 +206,6 @@ public class WrappedKeyTest { .setBlockModes(KeyProperties.BLOCK_MODE_GCM) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) .build()); - return (AndroidKeyStoreSecretKey) keyGenerator.generateKey(); + return keyGenerator.generateKey(); } } diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/ArtStatsLogUtilsTest.java b/services/tests/servicestests/src/com/android/server/pm/dex/ArtStatsLogUtilsTest.java new file mode 100644 index 000000000000..13d75a77507f --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/pm/dex/ArtStatsLogUtilsTest.java @@ -0,0 +1,292 @@ +/* + * Copyright (C) 2021 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.pm.dex; + +import static org.mockito.Mockito.inOrder; + +import com.android.internal.art.ArtStatsLog; +import com.android.server.pm.dex.ArtStatsLogUtils.ArtStatsLogger; + +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.Mock; +import org.mockito.InOrder; +import org.mockito.MockitoAnnotations; + +import java.io.IOException; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +/** + * Unit tests for {@link com.android.server.pm.dex.ArtStatsLogUtils}. + * + * Run with "atest ArtStatsLogUtilsTest". + */ +@RunWith(JUnit4.class) +public final class ArtStatsLogUtilsTest { + private static final String TAG = ArtStatsLogUtilsTest.class.getSimpleName(); + private static final String COMPILER_FILTER = "space-profile"; + private static final String PROFILE_DEX_METADATA = "primary.prof"; + private static final String VDEX_DEX_METADATA = "primary.vdex"; + private static final byte[] DEX_CONTENT = "dexData".getBytes(); + private static final int COMPILATION_REASON = 1; + private static final int RESULT_CODE = 222; + private static final int UID = 111; + private static final long COMPILE_TIME = 333L; + private static final long SESSION_ID = 444L; + + @Mock + ArtStatsLogger mockLogger; + + private static Path TEST_DIR; + private static Path DEX; + private static Path NON_DEX; + + @BeforeClass + public static void setUpAll() throws IOException { + TEST_DIR = Files.createTempDirectory(null); + DEX = Files.createFile(TEST_DIR.resolve("classes.dex")); + NON_DEX = Files.createFile(TEST_DIR.resolve("test.dex")); + Files.write(DEX, DEX_CONTENT); + Files.write(NON_DEX, "empty".getBytes()); + } + + @AfterClass + public static void tearnDownAll() { + deleteSliently(DEX); + deleteSliently(NON_DEX); + deleteSliently(TEST_DIR); + } + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + } + + @Test + public void testProfileAndVdexDexMetadata() throws IOException { + // Setup + Path dexMetadataPath = null; + Path apk = null; + try { + dexMetadataPath = createDexMetadata(PROFILE_DEX_METADATA, VDEX_DEX_METADATA); + apk = zipFiles(".apk", DEX, NON_DEX, dexMetadataPath); + + // Act + ArtStatsLogUtils.writeStatsLog( + mockLogger, + SESSION_ID, + apk.toString(), + COMPILER_FILTER, + UID, + COMPILE_TIME, + dexMetadataPath.toString(), + COMPILATION_REASON, + RESULT_CODE); + + // Assert + verifyWrites(ArtStatsLog. + ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_PROFILE_AND_VDEX); + } finally { + deleteSliently(dexMetadataPath); + deleteSliently(apk); + } + } + + @Test + public void testProfileOnlyDexMetadata() throws IOException { + // Setup + Path dexMetadataPath = null; + Path apk = null; + try { + dexMetadataPath = createDexMetadata(PROFILE_DEX_METADATA); + apk = zipFiles(".apk", DEX, NON_DEX, dexMetadataPath); + + // Act + ArtStatsLogUtils.writeStatsLog( + mockLogger, + SESSION_ID, + apk.toString(), + COMPILER_FILTER, + UID, + COMPILE_TIME, + dexMetadataPath.toString(), + COMPILATION_REASON, + RESULT_CODE); + + // Assert + verifyWrites(ArtStatsLog. + ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_PROFILE); + } finally { + deleteSliently(dexMetadataPath); + deleteSliently(apk); + } + } + + @Test + public void testVdexOnlyDexMetadata() throws IOException { + // Setup + Path dexMetadataPath = null; + Path apk = null; + try { + dexMetadataPath = createDexMetadata(VDEX_DEX_METADATA); + apk = zipFiles(".apk", DEX, NON_DEX, dexMetadataPath); + + // Act + ArtStatsLogUtils.writeStatsLog( + mockLogger, + SESSION_ID, + apk.toString(), + COMPILER_FILTER, + UID, + COMPILE_TIME, + dexMetadataPath.toString(), + COMPILATION_REASON, + RESULT_CODE); + + // Assert + verifyWrites(ArtStatsLog. + ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_VDEX); + } finally { + deleteSliently(dexMetadataPath); + deleteSliently(apk); + } + } + + @Test + public void testNoneDexMetadata() throws IOException { + // Setup + Path apk = null; + try { + apk = zipFiles(".apk", DEX, NON_DEX); + + // Act + ArtStatsLogUtils.writeStatsLog( + mockLogger, + SESSION_ID, + apk.toString(), + COMPILER_FILTER, + UID, + COMPILE_TIME, + /*dexMetadataPath=*/ null, + COMPILATION_REASON, + RESULT_CODE); + + // Assert + verifyWrites(ArtStatsLog. + ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_NONE); + } finally { + deleteSliently(apk); + } + } + + @Test + public void testUnKnownDexMetadata() throws IOException { + // Setup + Path dexMetadataPath = null; + Path apk = null; + try { + dexMetadataPath = createDexMetadata("unknown"); + apk = zipFiles(".apk", DEX, NON_DEX, dexMetadataPath); + + // Act + ArtStatsLogUtils.writeStatsLog( + mockLogger, + SESSION_ID, + apk.toString(), + COMPILER_FILTER, + UID, + COMPILE_TIME, + dexMetadataPath.toString(), + COMPILATION_REASON, + RESULT_CODE); + + // Assert + verifyWrites(ArtStatsLog. + ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_UNKNOWN); + } finally { + deleteSliently(dexMetadataPath); + deleteSliently(apk); + } + } + + private void verifyWrites(int dexMetadataType) { + InOrder inorder = inOrder(mockLogger); + inorder.verify(mockLogger).write( + SESSION_ID, UID, + COMPILATION_REASON, + COMPILER_FILTER, + ArtStatsLog.ART_DATUM_REPORTED__KIND__ART_DATUM_DEX2OAT_RESULT_CODE, + RESULT_CODE, + dexMetadataType); + inorder.verify(mockLogger).write( + SESSION_ID, + UID, + COMPILATION_REASON, + COMPILER_FILTER, + ArtStatsLog.ART_DATUM_REPORTED__KIND__ART_DATUM_DEX2OAT_TOTAL_TIME, + COMPILE_TIME, + dexMetadataType); + } + + private Path zipFiles(String suffix, Path... files) throws IOException { + Path zipFile = Files.createTempFile(null, suffix); + try (final OutputStream os = Files.newOutputStream(zipFile)) { + try (final ZipOutputStream zos = new ZipOutputStream(os)) { + for (Path file : files) { + ZipEntry zipEntry = new ZipEntry(file.getFileName().toString()); + zos.putNextEntry(zipEntry); + zos.write(Files.readAllBytes(file)); + zos.closeEntry(); + } + } + } + return zipFile; + } + + private Path createDexMetadata(String... entryNames) throws IOException { + Path zipFile = Files.createTempFile(null, ".dm"); + try (final OutputStream os = Files.newOutputStream(zipFile)) { + try (final ZipOutputStream zos = new ZipOutputStream(os)) { + for (String entryName : entryNames) { + ZipEntry zipEntry = new ZipEntry(entryName); + zos.putNextEntry(zipEntry); + zos.write(entryName.getBytes()); + zos.closeEntry(); + } + } + } + return zipFile; + } + + private static void deleteSliently(Path file) { + if (file != null) { + try { + Files.deleteIfExists(file); + } catch (IOException e) { + // ignore + } + } + } +} diff --git a/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTest.java b/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTest.java index 9b8a2a82c6df..324e5929f77f 100644 --- a/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTest.java @@ -18,6 +18,7 @@ package com.android.server.recoverysystem; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; +import static org.mockito.AdditionalMatchers.not; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; @@ -70,6 +71,7 @@ public class RecoverySystemServiceTest { private FileWriter mUncryptUpdateFileWriter; private LockSettingsInternal mLockSettingsInternal; private IBootControl mIBootControl; + private RecoverySystemServiceTestable.IMetricsReporter mMetricsReporter; private static final String FAKE_OTA_PACKAGE_NAME = "fake.ota.package"; private static final String FAKE_OTHER_PACKAGE_NAME = "fake.other.package"; @@ -94,9 +96,11 @@ public class RecoverySystemServiceTest { when(mIBootControl.getCurrentSlot()).thenReturn(0); when(mIBootControl.getActiveBootSlot()).thenReturn(1); + mMetricsReporter = mock(RecoverySystemServiceTestable.IMetricsReporter.class); + mRecoverySystemService = new RecoverySystemServiceTestable(mContext, mSystemProperties, powerManager, mUncryptUpdateFileWriter, mUncryptSocket, mLockSettingsInternal, - mIBootControl); + mIBootControl, mMetricsReporter); } @Test @@ -227,12 +231,24 @@ public class RecoverySystemServiceTest { } @Test + public void requestLskf_reportMetrics() throws Exception { + IntentSender intentSender = mock(IntentSender.class); + assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, intentSender), + is(true)); + verify(mMetricsReporter).reportRebootEscrowPreparationMetrics( + eq(1000), eq(0) /* need preparation */, eq(1) /* client count */); + } + + + @Test public void requestLskf_success() throws Exception { IntentSender intentSender = mock(IntentSender.class); assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, intentSender), is(true)); mRecoverySystemService.onPreparedForReboot(true); verify(intentSender).sendIntent(any(), anyInt(), any(), any(), any()); + verify(mMetricsReporter).reportRebootEscrowLskfCapturedMetrics( + eq(1000), eq(1) /* client count */, anyInt() /* duration */); } @Test @@ -255,6 +271,8 @@ public class RecoverySystemServiceTest { assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, intentSender), is(true)); verify(intentSender, never()).sendIntent(any(), anyInt(), any(), any(), any()); + verify(mMetricsReporter, never()).reportRebootEscrowLskfCapturedMetrics( + anyInt(), anyInt(), anyInt()); } @Test @@ -337,6 +355,9 @@ public class RecoverySystemServiceTest { assertThat(mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, "ab-update", true), is(true)); verify(mIPowerManager).reboot(anyBoolean(), eq("ab-update"), anyBoolean()); + verify(mMetricsReporter).reportRebootEscrowRebootMetrics(eq(0), eq(1000), + eq(1) /* client count */, eq(1) /* request count */, eq(true) /* slot switch */, + anyBoolean(), anyInt(), eq(1) /* lskf capture count */); } @@ -373,6 +394,20 @@ public class RecoverySystemServiceTest { verify(mIPowerManager).reboot(anyBoolean(), eq("ab-update"), anyBoolean()); } + @Test + public void rebootWithLskf_multiClient_success_reportMetrics() throws Exception { + assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, null), is(true)); + assertThat(mRecoverySystemService.requestLskf(FAKE_OTHER_PACKAGE_NAME, null), is(true)); + mRecoverySystemService.onPreparedForReboot(true); + + // Client B's clear won't affect client A's preparation. + assertThat(mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, "ab-update", true), + is(true)); + verify(mIPowerManager).reboot(anyBoolean(), eq("ab-update"), anyBoolean()); + verify(mMetricsReporter).reportRebootEscrowRebootMetrics(eq(0), eq(1000), + eq(2) /* client count */, eq(1) /* request count */, eq(true) /* slot switch */, + anyBoolean(), anyInt(), eq(1) /* lskf capture count */); + } @Test public void rebootWithLskf_multiClient_ClientBSuccess() throws Exception { @@ -384,12 +419,18 @@ public class RecoverySystemServiceTest { assertThat(mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, null, true), is(false)); verifyNoMoreInteractions(mIPowerManager); + verify(mMetricsReporter).reportRebootEscrowRebootMetrics(not(eq(0)), eq(1000), + eq(1) /* client count */, eq(1) /* request count */, eq(true) /* slot switch */, + anyBoolean(), anyInt(), eq(1) /* lskf capture count */); assertThat(mRecoverySystemService.requestLskf(FAKE_OTHER_PACKAGE_NAME, null), is(true)); assertThat( mRecoverySystemService.rebootWithLskf(FAKE_OTHER_PACKAGE_NAME, "ab-update", true), is(true)); verify(mIPowerManager).reboot(anyBoolean(), eq("ab-update"), anyBoolean()); + verify(mMetricsReporter).reportRebootEscrowRebootMetrics(eq(0), eq(2000), + eq(1) /* client count */, eq(1) /* request count */, eq(true) /* slot switch */, + anyBoolean(), anyInt(), eq(1) /* lskf capture count */); } @Test diff --git a/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTestable.java b/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTestable.java index 0727e5adb9ca..a894178fca06 100644 --- a/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTestable.java +++ b/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTestable.java @@ -32,11 +32,12 @@ public class RecoverySystemServiceTestable extends RecoverySystemService { private final UncryptSocket mUncryptSocket; private final LockSettingsInternal mLockSettingsInternal; private final IBootControl mIBootControl; + private final IMetricsReporter mIMetricsReporter; MockInjector(Context context, FakeSystemProperties systemProperties, PowerManager powerManager, FileWriter uncryptPackageFileWriter, UncryptSocket uncryptSocket, LockSettingsInternal lockSettingsInternal, - IBootControl bootControl) { + IBootControl bootControl, IMetricsReporter metricsReporter) { super(context); mSystemProperties = systemProperties; mPowerManager = powerManager; @@ -44,6 +45,7 @@ public class RecoverySystemServiceTestable extends RecoverySystemService { mUncryptSocket = uncryptSocket; mLockSettingsInternal = lockSettingsInternal; mIBootControl = bootControl; + mIMetricsReporter = metricsReporter; } @Override @@ -94,14 +96,45 @@ public class RecoverySystemServiceTestable extends RecoverySystemService { public IBootControl getBootControl() { return mIBootControl; } + @Override + public int getUidFromPackageName(String packageName) { + if ("fake.ota.package".equals(packageName)) { + return 1000; + } + if ("fake.other.package".equals(packageName)) { + return 2000; + } + return 3000; + } + + @Override + public void reportRebootEscrowPreparationMetrics(int uid, int requestResult, + int requestedClientCount) { + mIMetricsReporter.reportRebootEscrowPreparationMetrics(uid, requestResult, + requestedClientCount); + } + + public void reportRebootEscrowLskfCapturedMetrics(int uid, int requestedClientCount, + int requestedToLskfCapturedDurationInSeconds) { + mIMetricsReporter.reportRebootEscrowLskfCapturedMetrics(uid, requestedClientCount, + requestedToLskfCapturedDurationInSeconds); + } + + public void reportRebootEscrowRebootMetrics(int errorCode, int uid, int preparedClientCount, + int requestCount, boolean slotSwitch, boolean serverBased, + int lskfCapturedToRebootDurationInSeconds, int lskfCapturedCounts) { + mIMetricsReporter.reportRebootEscrowRebootMetrics(errorCode, uid, preparedClientCount, + requestCount, slotSwitch, serverBased, lskfCapturedToRebootDurationInSeconds, + lskfCapturedCounts); + } } RecoverySystemServiceTestable(Context context, FakeSystemProperties systemProperties, PowerManager powerManager, FileWriter uncryptPackageFileWriter, UncryptSocket uncryptSocket, LockSettingsInternal lockSettingsInternal, - IBootControl bootControl) { + IBootControl bootControl, IMetricsReporter metricsReporter) { super(new MockInjector(context, systemProperties, powerManager, uncryptPackageFileWriter, - uncryptSocket, lockSettingsInternal, bootControl)); + uncryptSocket, lockSettingsInternal, bootControl, metricsReporter)); } public static class FakeSystemProperties { @@ -131,4 +164,17 @@ public class RecoverySystemServiceTestable extends RecoverySystemService { return mCtlStart; } } + + public interface IMetricsReporter { + void reportRebootEscrowPreparationMetrics(int uid, int requestResult, + int requestedClientCount); + + void reportRebootEscrowLskfCapturedMetrics(int uid, int requestedClientCount, + int requestedToLskfCapturedDurationInSeconds); + + void reportRebootEscrowRebootMetrics(int errorCode, int uid, int preparedClientCount, + int requestCount, boolean slotSwitch, boolean serverBased, + int lskfCapturedToRebootDurationInSeconds, int lskfCapturedCounts); + } + } diff --git a/services/usb/java/com/android/server/usb/UsbPortManager.java b/services/usb/java/com/android/server/usb/UsbPortManager.java index ec7d4bd0d8c0..647a2a2ec53d 100644 --- a/services/usb/java/com/android/server/usb/UsbPortManager.java +++ b/services/usb/java/com/android/server/usb/UsbPortManager.java @@ -60,9 +60,9 @@ import android.os.Parcelable; import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; +import android.service.ServiceProtoEnums; import android.service.usb.UsbPortInfoProto; import android.service.usb.UsbPortManagerProto; -import android.service.usb.UsbServiceProto; import android.util.ArrayMap; import android.util.Log; import android.util.Slog; @@ -992,15 +992,15 @@ public class UsbPortManager { private static int convertContaminantDetectionStatusToProto(int contaminantDetectionStatus) { switch (contaminantDetectionStatus) { case UsbPortStatus.CONTAMINANT_DETECTION_NOT_SUPPORTED: - return UsbServiceProto.CONTAMINANT_STATUS_NOT_SUPPORTED; + return ServiceProtoEnums.CONTAMINANT_STATUS_NOT_SUPPORTED; case UsbPortStatus.CONTAMINANT_DETECTION_DISABLED: - return UsbServiceProto.CONTAMINANT_STATUS_DISABLED; + return ServiceProtoEnums.CONTAMINANT_STATUS_DISABLED; case UsbPortStatus.CONTAMINANT_DETECTION_NOT_DETECTED: - return UsbServiceProto.CONTAMINANT_STATUS_NOT_DETECTED; + return ServiceProtoEnums.CONTAMINANT_STATUS_NOT_DETECTED; case UsbPortStatus.CONTAMINANT_DETECTION_DETECTED: - return UsbServiceProto.CONTAMINANT_STATUS_DETECTED; + return ServiceProtoEnums.CONTAMINANT_STATUS_DETECTED; default: - return UsbServiceProto.CONTAMINANT_STATUS_UNKNOWN; + return ServiceProtoEnums.CONTAMINANT_STATUS_UNKNOWN; } } diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index dc05488618cf..464d37510034 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -2898,6 +2898,18 @@ public class CarrierConfigManager { public static final String KEY_RTT_SUPPORTED_FOR_VT_BOOL = "rtt_supported_for_vt_bool"; /** + * Indicates if the carrier supports upgrading a call that was previously an RTT call to VT. + */ + public static final String KEY_VT_UPGRADE_SUPPORTED_FOR_DOWNGRADED_RTT_CALL_BOOL = + "vt_upgrade_supported_for_downgraded_rtt_call"; + + /** + * Indicates if the carrier supports upgrading a call that was previously a VT call to RTT. + */ + public static final String KEY_RTT_UPGRADE_SUPPORTED_FOR_DOWNGRADED_VT_CALL_BOOL = + "rtt_upgrade_supported_for_downgraded_vt_call"; + + /** * Indicates if the carrier supports upgrading a voice call to an RTT call during the call. */ public static final String KEY_RTT_UPGRADE_SUPPORTED_BOOL = "rtt_upgrade_supported_bool"; @@ -4256,6 +4268,14 @@ public class CarrierConfigManager { public static final String KEY_STORE_SIM_PIN_FOR_UNATTENDED_REBOOT_BOOL = "store_sim_pin_for_unattended_reboot_bool"; + /** + * Determine whether "Enable 2G" toggle can be shown. + * + * Used to trade privacy/security against potentially reduced carrier coverage for some + * carriers. + */ + public static final String KEY_HIDE_ENABLE_2G = "hide_enable_2g_bool"; + /** The default value for every variable. */ private final static PersistableBundle sDefaults; @@ -4618,6 +4638,8 @@ public class CarrierConfigManager { sDefaults.putBoolean(KEY_TTY_SUPPORTED_BOOL, true); sDefaults.putBoolean(KEY_HIDE_TTY_HCO_VCO_WITH_RTT_BOOL, false); sDefaults.putBoolean(KEY_RTT_SUPPORTED_WHILE_ROAMING_BOOL, false); + sDefaults.putBoolean(KEY_RTT_UPGRADE_SUPPORTED_FOR_DOWNGRADED_VT_CALL_BOOL, true); + sDefaults.putBoolean(KEY_VT_UPGRADE_SUPPORTED_FOR_DOWNGRADED_RTT_CALL_BOOL, true); sDefaults.putBoolean(KEY_DISABLE_CHARGE_INDICATION_BOOL, false); sDefaults.putBoolean(KEY_SUPPORT_NO_REPLY_TIMER_FOR_CFNRY_BOOL, true); sDefaults.putStringArray(KEY_FEATURE_ACCESS_CODES_STRING_ARRAY, null); @@ -4811,6 +4833,7 @@ public class CarrierConfigManager { sDefaults.putStringArray(KEY_ALLOWED_INITIAL_ATTACH_APN_TYPES_STRING_ARRAY, new String[]{"ia", "default", "ims", "mms", "dun", "emergency"}); sDefaults.putBoolean(KEY_STORE_SIM_PIN_FOR_UNATTENDED_REBOOT_BOOL, true); + sDefaults.putBoolean(KEY_HIDE_ENABLE_2G, false); } /** diff --git a/telephony/java/android/telephony/DataSpecificRegistrationInfo.java b/telephony/java/android/telephony/DataSpecificRegistrationInfo.java index 597fe8f85cfa..957f683292f7 100644 --- a/telephony/java/android/telephony/DataSpecificRegistrationInfo.java +++ b/telephony/java/android/telephony/DataSpecificRegistrationInfo.java @@ -68,22 +68,22 @@ public final class DataSpecificRegistrationInfo implements Parcelable { public final boolean isEnDcAvailable; /** - * Provides network support info for LTE VoPS and LTE Emergency bearer support + * Provides network support info for VoPS and Emergency bearer support */ @Nullable - private final LteVopsSupportInfo mLteVopsSupportInfo; + private final VopsSupportInfo mVopsSupportInfo; /** * @hide */ DataSpecificRegistrationInfo( int maxDataCalls, boolean isDcNrRestricted, boolean isNrAvailable, - boolean isEnDcAvailable, @Nullable LteVopsSupportInfo lteVops) { + boolean isEnDcAvailable, @Nullable VopsSupportInfo vops) { this.maxDataCalls = maxDataCalls; this.isDcNrRestricted = isDcNrRestricted; this.isNrAvailable = isNrAvailable; this.isEnDcAvailable = isEnDcAvailable; - this.mLteVopsSupportInfo = lteVops; + this.mVopsSupportInfo = vops; } /** @@ -97,7 +97,7 @@ public final class DataSpecificRegistrationInfo implements Parcelable { isDcNrRestricted = dsri.isDcNrRestricted; isNrAvailable = dsri.isNrAvailable; isEnDcAvailable = dsri.isEnDcAvailable; - mLteVopsSupportInfo = dsri.mLteVopsSupportInfo; + mVopsSupportInfo = dsri.mVopsSupportInfo; } private DataSpecificRegistrationInfo(/* @NonNull */ Parcel source) { @@ -105,7 +105,7 @@ public final class DataSpecificRegistrationInfo implements Parcelable { isDcNrRestricted = source.readBoolean(); isNrAvailable = source.readBoolean(); isEnDcAvailable = source.readBoolean(); - mLteVopsSupportInfo = LteVopsSupportInfo.CREATOR.createFromParcel(source); + mVopsSupportInfo = source.readParcelable(VopsSupportInfo.class.getClassLoader()); } @Override @@ -114,7 +114,7 @@ public final class DataSpecificRegistrationInfo implements Parcelable { dest.writeBoolean(isDcNrRestricted); dest.writeBoolean(isNrAvailable); dest.writeBoolean(isEnDcAvailable); - mLteVopsSupportInfo.writeToParcel(dest, flags); + dest.writeParcelable(mVopsSupportInfo, flags); } @Override @@ -131,15 +131,15 @@ public final class DataSpecificRegistrationInfo implements Parcelable { .append(" isDcNrRestricted = " + isDcNrRestricted) .append(" isNrAvailable = " + isNrAvailable) .append(" isEnDcAvailable = " + isEnDcAvailable) - .append(" " + mLteVopsSupportInfo) + .append(" " + mVopsSupportInfo) .append(" }") .toString(); } @Override public int hashCode() { - return Objects.hash(maxDataCalls, isDcNrRestricted, isNrAvailable, isEnDcAvailable, - mLteVopsSupportInfo); + return Objects.hash(maxDataCalls, isDcNrRestricted, isNrAvailable, + isEnDcAvailable, mVopsSupportInfo); } @Override @@ -153,7 +153,7 @@ public final class DataSpecificRegistrationInfo implements Parcelable { && this.isDcNrRestricted == other.isDcNrRestricted && this.isNrAvailable == other.isNrAvailable && this.isEnDcAvailable == other.isEnDcAvailable - && Objects.equals(mLteVopsSupportInfo, other.mLteVopsSupportInfo); + && Objects.equals(mVopsSupportInfo, other.mVopsSupportInfo); } public static final @NonNull Parcelable.Creator<DataSpecificRegistrationInfo> CREATOR = @@ -171,10 +171,26 @@ public final class DataSpecificRegistrationInfo implements Parcelable { /** * @return The LTE VOPS (Voice over Packet Switched) support information + * + * @deprecated use {@link #getVopsSupportInfo()} */ + @Deprecated @NonNull public LteVopsSupportInfo getLteVopsSupportInfo() { - return mLteVopsSupportInfo; + return mVopsSupportInfo instanceof LteVopsSupportInfo + ? (LteVopsSupportInfo) mVopsSupportInfo + : new LteVopsSupportInfo(LteVopsSupportInfo.LTE_STATUS_NOT_AVAILABLE, + LteVopsSupportInfo.LTE_STATUS_NOT_AVAILABLE); } + /** + * @return The VOPS (Voice over Packet Switched) support information. + * + * The instance of {@link LTEVopsSupportInfo}, or {@link NrVopsSupportInfo}, + * null if there is there is no VOPS support information available. + */ + @Nullable + public VopsSupportInfo getVopsSupportInfo() { + return mVopsSupportInfo; + } } diff --git a/telephony/java/android/telephony/LinkCapacityEstimate.aidl b/telephony/java/android/telephony/LinkCapacityEstimate.aidl new file mode 100644 index 000000000000..286f33fc9810 --- /dev/null +++ b/telephony/java/android/telephony/LinkCapacityEstimate.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony; + +parcelable LinkCapacityEstimate;
\ No newline at end of file diff --git a/telephony/java/android/telephony/LinkCapacityEstimate.java b/telephony/java/android/telephony/LinkCapacityEstimate.java new file mode 100644 index 000000000000..deeb80961c3c --- /dev/null +++ b/telephony/java/android/telephony/LinkCapacityEstimate.java @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.Objects; + +/** + * Link Capacity Estimate from the modem + * @hide + */ +@SystemApi +public final class LinkCapacityEstimate implements Parcelable { + /** A value indicates that the capacity estimate is not available */ + public static final int INVALID = -1; + + /** + * LCE for the primary network + */ + public static final int LCE_TYPE_PRIMARY = 0; + + /** + * LCE for the secondary network + */ + public static final int LCE_TYPE_SECONDARY = 1; + + /** + * Combined LCE for primary network and secondary network reported by the legacy modem + */ + public static final int LCE_TYPE_COMBINED = 2; + + /** @hide */ + @IntDef(prefix = { "LCE_TYPE_" }, value = { + LCE_TYPE_PRIMARY, + LCE_TYPE_SECONDARY, + LCE_TYPE_COMBINED, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface LceType {} + + private final @LceType int mType; + + /** Downlink capacity estimate in kbps */ + private final int mDownlinkCapacityKbps; + + /** Uplink capacity estimate in kbps */ + private final int mUplinkCapacityKbps; + + /** + * Constructor for link capacity estimate + */ + public LinkCapacityEstimate(@LceType int type, + int downlinkCapacityKbps, int uplinkCapacityKbps) { + mDownlinkCapacityKbps = downlinkCapacityKbps; + mUplinkCapacityKbps = uplinkCapacityKbps; + mType = type; + } + + /** + * @hide + */ + public LinkCapacityEstimate(Parcel in) { + mDownlinkCapacityKbps = in.readInt(); + mUplinkCapacityKbps = in.readInt(); + mType = in.readInt(); + } + + /** + * Retrieves the type of LCE + * @return The type of link capacity estimate + */ + public @LceType int getType() { + return mType; + } + + /** + * Retrieves the downlink bandwidth in Kbps. + * This will be {@link #INVALID} if the network is not connected + * @return The estimated first hop downstream (network to device) bandwidth. + */ + public int getDownlinkCapacityKbps() { + return mDownlinkCapacityKbps; + } + + /** + * Retrieves the uplink bandwidth in Kbps. + * This will be {@link #INVALID} if the network is not connected + * + * @return The estimated first hop upstream (device to network) bandwidth. + */ + public int getUplinkCapacityKbps() { + return mUplinkCapacityKbps; + } + + @Override + public String toString() { + return new StringBuilder() + .append("{mType=") + .append(mType) + .append(", mDownlinkCapacityKbps=") + .append(mDownlinkCapacityKbps) + .append(", mUplinkCapacityKbps=") + .append(mUplinkCapacityKbps) + .append("}") + .toString(); + } + + /** + * {@link Parcelable#describeContents} + */ + public int describeContents() { + return 0; + } + + /** + * {@link Parcelable#writeToParcel} + * @hide + */ + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeInt(mDownlinkCapacityKbps); + dest.writeInt(mUplinkCapacityKbps); + dest.writeInt(mType); + } + + @Override + public boolean equals(@Nullable Object o) { + if (o == null || !(o instanceof LinkCapacityEstimate) || hashCode() != o.hashCode()) { + return false; + } + + if (this == o) { + return true; + } + + LinkCapacityEstimate that = (LinkCapacityEstimate) o; + return mDownlinkCapacityKbps == that.mDownlinkCapacityKbps + && mUplinkCapacityKbps == that.mUplinkCapacityKbps + && mType == that.mType; + } + + @Override + public int hashCode() { + return Objects.hash(mDownlinkCapacityKbps, mUplinkCapacityKbps, mType); + } + + public static final + @android.annotation.NonNull Parcelable.Creator<LinkCapacityEstimate> CREATOR = + new Parcelable.Creator() { + public LinkCapacityEstimate createFromParcel(Parcel in) { + return new LinkCapacityEstimate(in); + } + + public LinkCapacityEstimate[] newArray(int size) { + return new LinkCapacityEstimate[size]; + } + }; +} diff --git a/telephony/java/android/telephony/LteVopsSupportInfo.java b/telephony/java/android/telephony/LteVopsSupportInfo.java index 83e41bf3df3b..87761e21350b 100644 --- a/telephony/java/android/telephony/LteVopsSupportInfo.java +++ b/telephony/java/android/telephony/LteVopsSupportInfo.java @@ -21,7 +21,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.os.Parcel; -import android.os.Parcelable; +import android.telephony.AccessNetworkConstants.AccessNetworkType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -32,7 +32,7 @@ import java.util.Objects; * @hide */ @SystemApi -public final class LteVopsSupportInfo implements Parcelable { +public final class LteVopsSupportInfo extends VopsSupportInfo { /**@hide*/ @Retention(RetentionPolicy.SOURCE) @@ -42,7 +42,10 @@ public final class LteVopsSupportInfo implements Parcelable { public @interface LteVopsStatus {} /** * Indicates information not available from modem. + * + * @deprecated as no instance will be created in this case */ + @Deprecated public static final int LTE_STATUS_NOT_AVAILABLE = 1; /** @@ -82,13 +85,38 @@ public final class LteVopsSupportInfo implements Parcelable { return mEmcBearerSupport; } + /** + * Returns whether VoPS is supported by the network + */ + @Override + public boolean isVopsSupported() { + return mVopsSupport == LTE_STATUS_SUPPORTED; + } + + /** + * Returns whether emergency service is supported by the network + */ + @Override + public boolean isEmergencyServiceSupported() { + return mEmcBearerSupport == LTE_STATUS_SUPPORTED; + } + + /** + * Returns whether emergency service fallback is supported by the network + */ + @Override + public boolean isEmergencyServiceFallbackSupported() { + return false; + } + @Override public int describeContents() { return 0; } @Override - public void writeToParcel(Parcel out, int flags) { + public void writeToParcel(@NonNull Parcel out, int flags) { + super.writeToParcel(out, flags, AccessNetworkType.EUTRAN); out.writeInt(mVopsSupport); out.writeInt(mEmcBearerSupport); } @@ -124,6 +152,8 @@ public final class LteVopsSupportInfo implements Parcelable { new Creator<LteVopsSupportInfo>() { @Override public LteVopsSupportInfo createFromParcel(Parcel in) { + // Skip the type info. + in.readInt(); return new LteVopsSupportInfo(in); } @@ -133,6 +163,11 @@ public final class LteVopsSupportInfo implements Parcelable { } }; + /** @hide */ + protected static LteVopsSupportInfo createFromParcelBody(Parcel in) { + return new LteVopsSupportInfo(in); + } + private LteVopsSupportInfo(Parcel in) { mVopsSupport = in.readInt(); mEmcBearerSupport = in.readInt(); diff --git a/telephony/java/android/telephony/NetworkRegistrationInfo.java b/telephony/java/android/telephony/NetworkRegistrationInfo.java index a78f81331c8c..5fb60d7599ea 100644 --- a/telephony/java/android/telephony/NetworkRegistrationInfo.java +++ b/telephony/java/android/telephony/NetworkRegistrationInfo.java @@ -293,11 +293,12 @@ public final class NetworkRegistrationInfo implements Parcelable { @Nullable CellIdentity cellIdentity, @Nullable String rplmn, int maxDataCalls, boolean isDcNrRestricted, boolean isNrAvailable, boolean isEndcAvailable, - LteVopsSupportInfo lteVopsSupportInfo) { + @Nullable VopsSupportInfo vopsSupportInfo) { this(domain, transportType, registrationState, accessNetworkTechnology, rejectCause, emergencyOnly, availableServices, cellIdentity, rplmn); mDataSpecificInfo = new DataSpecificRegistrationInfo( - maxDataCalls, isDcNrRestricted, isNrAvailable, isEndcAvailable, lteVopsSupportInfo); + maxDataCalls, isDcNrRestricted, isNrAvailable, + isEndcAvailable, vopsSupportInfo); updateNrState(); } diff --git a/telephony/java/android/telephony/NrVopsSupportInfo.aidl b/telephony/java/android/telephony/NrVopsSupportInfo.aidl new file mode 100644 index 000000000000..460a58971837 --- /dev/null +++ b/telephony/java/android/telephony/NrVopsSupportInfo.aidl @@ -0,0 +1,19 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony; + +parcelable NrVopsSupportInfo; diff --git a/telephony/java/android/telephony/NrVopsSupportInfo.java b/telephony/java/android/telephony/NrVopsSupportInfo.java new file mode 100644 index 000000000000..155ee384b5b0 --- /dev/null +++ b/telephony/java/android/telephony/NrVopsSupportInfo.java @@ -0,0 +1,260 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.os.Parcel; +import android.telephony.AccessNetworkConstants.AccessNetworkType; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.Objects; + +/** + * Class stores information related to NR network VoPS support + * @hide + */ +@SystemApi +public final class NrVopsSupportInfo extends VopsSupportInfo { + + /** + * Indicates network does not support vops + */ + public static final int NR_STATUS_VOPS_NOT_SUPPORTED = 0; + + /** + * Indicates network supports vops over 3gpp access. + */ + public static final int NR_STATUS_VOPS_3GPP_SUPPORTED = 1; + + /** + * Indicates network supports vops over non 3gpp access + */ + public static final int NR_STATUS_VOPS_NON_3GPP_SUPPORTED = 2; + + /**@hide*/ + @Retention(RetentionPolicy.SOURCE) + @IntDef( + prefix = {"NR_STATUS_VOPS_"}, + value = { + NR_STATUS_VOPS_NOT_SUPPORTED, + NR_STATUS_VOPS_3GPP_SUPPORTED, + NR_STATUS_VOPS_NON_3GPP_SUPPORTED + }) + public @interface NrVopsStatus {} + + /** + * Indicates network does not support emergency service + */ + public static final int NR_STATUS_EMC_NOT_SUPPORTED = 0; + + /** + * Indicates network supports emergency service in NR connected to 5GCN only + */ + public static final int NR_STATUS_EMC_5GCN_ONLY = 1; + + /** + * Indicates network supports emergency service in E-UTRA connected to 5GCN only + */ + public static final int NR_STATUS_EMC_EUTRA_5GCN_ONLY = 2; + + /** + * Indicates network supports emergency service in NR connected to 5GCN and + * E-UTRA connected to 5GCN + */ + public static final int NR_STATUS_EMC_NR_EUTRA_5GCN = 3; + + /**@hide*/ + @Retention(RetentionPolicy.SOURCE) + @IntDef( + prefix = {"NR_STATUS_EMC_"}, + value = { + NR_STATUS_EMC_NOT_SUPPORTED, + NR_STATUS_EMC_5GCN_ONLY, + NR_STATUS_EMC_EUTRA_5GCN_ONLY, + NR_STATUS_EMC_NR_EUTRA_5GCN + }) + public @interface NrEmcStatus {} + + /** + * Indicates network does not support emergency service + */ + public static final int NR_STATUS_EMF_NOT_SUPPORTED = 0; + + /** + * Indicates network supports emergency service fallback in NR connected to 5GCN only + */ + public static final int NR_STATUS_EMF_5GCN_ONLY = 1; + + /** + * Indicates network supports emergency service fallback in E-UTRA connected to 5GCN only + */ + public static final int NR_STATUS_EMF_EUTRA_5GCN_ONLY = 2; + + /** + * Indicates network supports emergency service fallback in NR connected to 5GCN + * and E-UTRA connected to 5GCN + */ + public static final int NR_STATUS_EMF_NR_EUTRA_5GCN = 3; + + /**@hide*/ + @Retention(RetentionPolicy.SOURCE) + @IntDef( + prefix = {"NR_STATUS_EMF_"}, + value = { + NR_STATUS_EMF_NOT_SUPPORTED, + NR_STATUS_EMF_5GCN_ONLY, + NR_STATUS_EMF_EUTRA_5GCN_ONLY, + NR_STATUS_EMF_NR_EUTRA_5GCN + }) + public @interface NrEmfStatus {} + + @NrVopsStatus + private final int mVopsSupport; + @NrEmcStatus + private final int mEmcSupport; + @NrEmfStatus + private final int mEmfSupport; + + public NrVopsSupportInfo(@NrVopsStatus int vops, @NrEmcStatus int emc, @NrEmcStatus int emf) { + mVopsSupport = vops; + mEmcSupport = emc; + mEmfSupport = emf; + } + + /** + * Provides the NR VoPS support capability as described in: + * 3GPP 24.501 EPS network feature support -> IMS VoPS + */ + public @NrVopsStatus int getVopsSupport() { + return mVopsSupport; + } + + /** + * Provides the NR Emergency bearer support capability as described in: + * 3GPP 24.501 EPS network feature support -> EMC, and + * 38.331 SIB1 : ims-EmergencySupport + */ + public @NrEmcStatus int getEmcSupport() { + return mEmcSupport; + } + + /** + * Provides the NR emergency service fallback support capability as + * described in 3GPP 24.501 EPS network feature support -> EMF + */ + public @NrEmfStatus int getEmfSupport() { + return mEmfSupport; + } + + /** + * Returns whether VoPS is supported by the network + */ + @Override + public boolean isVopsSupported() { + return mVopsSupport != NR_STATUS_VOPS_NOT_SUPPORTED; + } + + /** + * Returns whether emergency service is supported by the network + */ + @Override + public boolean isEmergencyServiceSupported() { + return mEmcSupport != NR_STATUS_EMC_NOT_SUPPORTED; + } + + /** + * Returns whether emergency service fallback is supported by the network + */ + public boolean isEmergencyServiceFallbackSupported() { + return mEmfSupport != NR_STATUS_EMF_NOT_SUPPORTED; + } + + /** + * Implement the Parcelable interface + */ + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel out, int flags) { + super.writeToParcel(out, flags, AccessNetworkType.NGRAN); + out.writeInt(mVopsSupport); + out.writeInt(mEmcSupport); + out.writeInt(mEmfSupport); + } + + @Override + public boolean equals(@Nullable Object o) { + if (o == null || !(o instanceof NrVopsSupportInfo)) { + return false; + } + if (this == o) return true; + NrVopsSupportInfo other = (NrVopsSupportInfo) o; + return mVopsSupport == other.mVopsSupport + && mEmcSupport == other.mEmcSupport + && mEmfSupport == other.mEmfSupport; + } + + @Override + public int hashCode() { + return Objects.hash(mVopsSupport, mEmcSupport, mEmfSupport); + } + + /** + * @return string representation. + */ + @NonNull + @Override + public String toString() { + return ("NrVopsSupportInfo : " + + " mVopsSupport = " + mVopsSupport + + " mEmcSupport = " + mEmcSupport + + " mEmfSupport = " + mEmfSupport); + } + + public static final @android.annotation.NonNull Creator<NrVopsSupportInfo> CREATOR = + new Creator<NrVopsSupportInfo>() { + @Override + public NrVopsSupportInfo createFromParcel(Parcel in) { + // Skip the type info. + in.readInt(); + return new NrVopsSupportInfo(in); + } + + @Override + public NrVopsSupportInfo[] newArray(int size) { + return new NrVopsSupportInfo[size]; + } + }; + + /** @hide */ + protected static NrVopsSupportInfo createFromParcelBody(Parcel in) { + return new NrVopsSupportInfo(in); + } + + private NrVopsSupportInfo(Parcel in) { + mVopsSupport = in.readInt(); + mEmcSupport = in.readInt(); + mEmfSupport = in.readInt(); + } +} diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java index b958bff6d00b..ce5a8ccf0fd0 100644 --- a/telephony/java/android/telephony/SmsManager.java +++ b/telephony/java/android/telephony/SmsManager.java @@ -2127,7 +2127,7 @@ public final class SmsManager { ret = iccISms.getSmsCapacityOnIccForSubscriber(getSubscriptionId()); } } catch (RemoteException ex) { - throw new RuntimeException(ex); + Log.e(TAG, "getSmsCapacityOnIcc() RemoteException", ex); } return ret; } diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 364c9be9614a..846d9a7f259f 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -129,6 +129,8 @@ import java.util.Objects; import java.util.UUID; import java.util.concurrent.Executor; import java.util.function.Consumer; +import java.util.stream.Collectors; +import java.util.stream.IntStream; /** * Provides access to information about the telephony services on @@ -3116,6 +3118,10 @@ public class TelephonyManager { return NETWORK_TYPE_BITMASK_LTE_CA; case NETWORK_TYPE_NR: return NETWORK_TYPE_BITMASK_NR; + case NETWORK_TYPE_IWLAN: + return NETWORK_TYPE_BITMASK_IWLAN; + case NETWORK_TYPE_IDEN: + return (1 << (NETWORK_TYPE_IDEN - 1)); default: return NETWORK_TYPE_BITMASK_UNKNOWN; } @@ -8224,7 +8230,8 @@ public class TelephonyManager { @IntDef({ ALLOWED_NETWORK_TYPES_REASON_USER, ALLOWED_NETWORK_TYPES_REASON_POWER, - ALLOWED_NETWORK_TYPES_REASON_CARRIER + ALLOWED_NETWORK_TYPES_REASON_CARRIER, + ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G }) @Retention(RetentionPolicy.SOURCE) public @interface AllowedNetworkTypesReason { @@ -8261,21 +8268,36 @@ public class TelephonyManager { public static final int ALLOWED_NETWORK_TYPES_REASON_CARRIER = 2; /** - * Set the allowed network types of the device and - * provide the reason triggering the allowed network change. + * To indicate allowed network type change is requested by the user via the 2G toggle. + * + * @hide + */ + @SystemApi + public static final int ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G = 3; + + /** + * Set the allowed network types of the device and provide the reason triggering the allowed + * network change. * This can be called for following reasons * <ol> * <li>Allowed network types control by USER {@link #ALLOWED_NETWORK_TYPES_REASON_USER} * <li>Allowed network types control by power manager * {@link #ALLOWED_NETWORK_TYPES_REASON_POWER} * <li>Allowed network types control by carrier {@link #ALLOWED_NETWORK_TYPES_REASON_CARRIER} + * <li>Allowed network types control by the user-controlled "Allow 2G" toggle + * {@link #ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G} * </ol> * This API will result in allowing an intersection of allowed network types for all reasons, * including the configuration done through other reasons. + * + * The functionality of this API with the parameter + * {@link #ALLOWED_NETWORK_TYPES_REASON_CARRIER} is the same as the API + * {@link TelephonyManager#setAllowedNetworkTypes}. Use this API instead of + * {@link TelephonyManager#setAllowedNetworkTypes}. * <p> * If {@link android.telephony.TelephonyManager#isRadioInterfaceCapabilitySupported} * ({@link TelephonyManager#CAPABILITY_ALLOWED_NETWORK_TYPES_USED}) returns true, then - * setAllowedNetworkTypesBitmap is used on the radio interface. Otherwise, + * setAllowedNetworkTypesBitmap is used on the radio interface. Otherwise, * setPreferredNetworkTypesBitmap is used instead. * * @param reason the reason the allowed network type change is taking place @@ -8315,21 +8337,17 @@ public class TelephonyManager { * {@link #getAllowedNetworkTypesForReason} returns allowed network type for a * specific reason. * - * <p>Requires Permission: - * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE READ_PRIVILEGED_PHONE_STATE} - * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}). - * * @param reason the reason the allowed network type change is taking place * @return the allowed network type bitmask * @throws IllegalStateException if the Telephony process is not currently available. * @throws IllegalArgumentException if invalid AllowedNetworkTypesReason is passed. * @hide */ - @SystemApi @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @RequiresFeature( enforcement = "android.telephony.TelephonyManager#isRadioInterfaceCapabilitySupported", value = TelephonyManager.CAPABILITY_ALLOWED_NETWORK_TYPES_USED) + @SystemApi public @NetworkTypeBitMask long getAllowedNetworkTypesForReason( @AllowedNetworkTypesReason int reason) { if (!isValidAllowedNetworkTypesReason(reason)) { @@ -8358,6 +8376,7 @@ public class TelephonyManager { case TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER: case TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_POWER: case TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_CARRIER: + case TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G: return true; } return false; @@ -8373,6 +8392,25 @@ public class TelephonyManager { } /** + * Returns a string representation of the allowed network types{@link NetworkTypeBitMask}. + * + * @param networkTypeBitmask The bitmask of allowed network types. + * @return the name of the allowed network types + * @hide + */ + public static String convertNetworkTypeBitmaskToString( + @NetworkTypeBitMask long networkTypeBitmask) { + String networkTypeName = IntStream.rangeClosed(NETWORK_TYPE_GPRS, NETWORK_TYPE_NR) + .filter(x -> { + return (networkTypeBitmask & getBitMaskForNetworkType(x)) + == getBitMaskForNetworkType(x); + }) + .mapToObj(x -> getNetworkTypeName(x)) + .collect(Collectors.joining("|")); + return TextUtils.isEmpty(networkTypeName) ? "UNKNOWN" : networkTypeName; + } + + /** * Set the preferred network type to global mode which includes LTE, CDMA, EvDo and GSM/WCDMA. * * <p>Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}). @@ -12079,6 +12117,7 @@ public class TelephonyManager { NETWORK_TYPE_BITMASK_LTE, NETWORK_TYPE_BITMASK_LTE_CA, NETWORK_TYPE_BITMASK_NR, + NETWORK_TYPE_BITMASK_IWLAN }) public @interface NetworkTypeBitMask {} @@ -13981,33 +14020,6 @@ public class TelephonyManager { } /** - * Get carrier bandwidth. In case of Dual connected network this will report - * bandwidth per primary and secondary network. - * @return CarrierBandwidth with bandwidth of both primary and secondary carrier. - * @throws IllegalStateException if the Telephony process is not currently available. - * @hide - */ - @SystemApi - @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) - @NonNull - public CarrierBandwidth getCarrierBandwidth() { - try { - ITelephony service = getITelephony(); - if (service != null) { - return service.getCarrierBandwidth(getSubId()); - } else { - throw new IllegalStateException("telephony service is null."); - } - } catch (RemoteException ex) { - Log.e(TAG, "getCarrierBandwidth RemoteException", ex); - ex.rethrowFromSystemServer(); - } - - //Should not reach. Adding return statement to make compiler happy - return null; - } - - /** * Called when userActivity is signalled in the power manager. * This should only be called from system Uid. * @hide @@ -14601,6 +14613,11 @@ public class TelephonyManager { */ public void registerTelephonyCallback(@NonNull @CallbackExecutor Executor executor, @NonNull TelephonyCallback callback) { + + if (mContext == null) { + throw new IllegalStateException("telephony service is null."); + } + if (executor == null || callback == null) { throw new IllegalArgumentException("TelephonyCallback and executor must be non-null"); } @@ -14927,7 +14944,9 @@ public class TelephonyManager { public static final int PREPARE_UNATTENDED_REBOOT_PIN_REQUIRED = 1; /** - * The unattended reboot was not prepared due to generic error. + * The unattended reboot was not prepared due to a non-recoverable error. After this error, + * the client that manages the unattended reboot should not try to invoke the API again + * until the next power cycle. * @hide */ @SystemApi diff --git a/telephony/java/android/telephony/VopsSupportInfo.aidl b/telephony/java/android/telephony/VopsSupportInfo.aidl new file mode 100644 index 000000000000..31c608fe9546 --- /dev/null +++ b/telephony/java/android/telephony/VopsSupportInfo.aidl @@ -0,0 +1,19 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony; + +parcelable VopsSupportInfo; diff --git a/telephony/java/android/telephony/VopsSupportInfo.java b/telephony/java/android/telephony/VopsSupportInfo.java new file mode 100644 index 000000000000..f89bfa9b60b4 --- /dev/null +++ b/telephony/java/android/telephony/VopsSupportInfo.java @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony; + +import android.annotation.NonNull; +import android.annotation.SuppressLint; +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; +import android.telephony.AccessNetworkConstants.AccessNetworkType; + +/** + * Abstract base class for the information related to network VoPS support. + * This is the base class for XxVopsSupportInfo which represent VoPS support + * information for specific network access techonology. + * @hide + */ +@SuppressLint("ParcelNotFinal") +@SystemApi +public abstract class VopsSupportInfo implements Parcelable { + + /** + * @hide + */ + public VopsSupportInfo() {} + + /** + * Returns whether VoPS is supported by the network + */ + public abstract boolean isVopsSupported(); + + /** + * Returns whether emergency service is supported by the network + */ + public abstract boolean isEmergencyServiceSupported(); + + /** + * Returns whether emergency service fallback is supported by the network + */ + public abstract boolean isEmergencyServiceFallbackSupported(); + + /** + * Implement the Parcelable interface + */ + @Override + public int describeContents() { + return 0; + } + + /** Implement the Parcelable interface */ + @Override + public abstract void writeToParcel(@NonNull Parcel dest, int flags); + + /** + * Used by child classes for parceling. + * + * @hide + */ + protected void writeToParcel(@NonNull Parcel dest, int flags, int type) { + dest.writeInt(type); + } + + /** Implement the Parcelable interface */ + public static final @android.annotation.NonNull Creator<VopsSupportInfo> CREATOR = + new Creator<VopsSupportInfo>() { + @Override + public VopsSupportInfo createFromParcel(Parcel in) { + int type = in.readInt(); + switch (type) { + case AccessNetworkType.EUTRAN: + return LteVopsSupportInfo.createFromParcelBody(in); + case AccessNetworkType.NGRAN: + return NrVopsSupportInfo.createFromParcelBody(in); + default: throw new RuntimeException("Bad VopsSupportInfo Parcel"); + } + } + + @Override + public VopsSupportInfo[] newArray(int size) { + return new VopsSupportInfo[size]; + } + }; + + @Override + public abstract int hashCode(); + + @Override + public abstract boolean equals(Object o); +} diff --git a/telephony/java/android/telephony/data/SliceInfo.java b/telephony/java/android/telephony/data/SliceInfo.java index 51857a7b4908..609d1112d5b4 100644 --- a/telephony/java/android/telephony/data/SliceInfo.java +++ b/telephony/java/android/telephony/data/SliceInfo.java @@ -29,7 +29,12 @@ import java.lang.annotation.RetentionPolicy; import java.util.Objects; /** - * Represents a S-NSSAI as defined in 3GPP TS 24.501. + * Represents a S-NSSAI as defined in 3GPP TS 24.501, which represents a network slice. + * + * There are 2 main fields that define a slice, SliceServiceType and SliceDifferentiator. + * SliceServiceType defines the type of service provided by the slice, and SliceDifferentiator is + * used to differentiate between multiple slices of the same type. If the devices is not on HPLMN, + * the mappedHplmn versions of these 2 fields indicate the corresponding values in HPLMN. * * @hide */ diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index f74484bd4fd8..45702c311ff3 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -31,7 +31,6 @@ import android.service.carrier.CarrierIdentifier; import android.telecom.PhoneAccount; import android.telecom.PhoneAccountHandle; import android.telephony.CallForwardingInfo; -import android.telephony.CarrierBandwidth; import android.telephony.CarrierRestrictionRules; import android.telephony.CellIdentity; import android.telephony.CellInfo; @@ -54,6 +53,7 @@ import android.telephony.TelephonyHistogram; import android.telephony.VisualVoicemailSmsFilterSettings; import android.telephony.emergency.EmergencyNumber; import android.telephony.ims.RcsClientConfiguration; +import android.telephony.ims.RcsContactUceCapability; import android.telephony.ims.aidl.IImsCapabilityCallback; import android.telephony.ims.aidl.IImsConfig; import android.telephony.ims.aidl.IImsConfigCallback; @@ -2219,12 +2219,6 @@ interface ITelephony { boolean isNrDualConnectivityEnabled(int subId); /** - * Get carrier bandwidth per primary and secondary carrier - * @return CarrierBandwidth with bandwidth of both primary and secondary carrier. - */ - CarrierBandwidth getCarrierBandwidth(int subId); - - /** * Checks whether the device supports the given capability on the radio interface. * * @param capability the name of the capability @@ -2357,6 +2351,41 @@ interface ITelephony { void setDeviceUceEnabled(boolean isEnabled); /** + * Add feature tags to the IMS registration being tracked by UCE and potentially + * generate a new PUBLISH to the network. + * Note: This is designed for a SHELL command only. + */ + RcsContactUceCapability addUceRegistrationOverrideShell(int subId, in List<String> featureTags); + + /** + * Remove feature tags from the IMS registration being tracked by UCE and potentially + * generate a new PUBLISH to the network. + * Note: This is designed for a SHELL command only. + */ + RcsContactUceCapability removeUceRegistrationOverrideShell(int subId, + in List<String> featureTags); + + /** + * Clear overridden feature tags in the IMS registration being tracked by UCE and potentially + * generate a new PUBLISH to the network. + * Note: This is designed for a SHELL command only. + */ + RcsContactUceCapability clearUceRegistrationOverrideShell(int subId); + + /** + * Get the latest RcsContactUceCapability structure that is used in SIP PUBLISH procedures. + * Note: This is designed for a SHELL command only. + */ + RcsContactUceCapability getLatestRcsContactUceCapabilityShell(int subId); + + /** + * Returns the last PIDF XML sent to the network during the last PUBLISH or "none" if the + * device does not have an active PUBLISH. + * Note: This is designed for a SHELL command only. + */ + String getLastUcePidfXmlShell(int subId); + + /** * Set a SignalStrengthUpdateRequest to receive notification when Signal Strength breach the * specified thresholds. */ diff --git a/tests/net/Android.bp b/tests/net/Android.bp index 7f0318a135dc..e1a424f214a5 100644 --- a/tests/net/Android.bp +++ b/tests/net/Android.bp @@ -79,6 +79,7 @@ android_test { "android.test.runner", "android.test.base", "android.test.mock", + "ServiceConnectivityResources", ], jni_libs: [ "libservice-connectivity", diff --git a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java index 0dfec7592274..d40b88ca599f 100644 --- a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java +++ b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java @@ -35,6 +35,9 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE; import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY; import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P; +import static android.net.NetworkCapabilities.REDACT_FOR_ACCESS_FINE_LOCATION; +import static android.net.NetworkCapabilities.REDACT_FOR_LOCAL_MAC_ADDRESS; +import static android.net.NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS; import static android.net.NetworkCapabilities.RESTRICTED_CAPABILITIES; import static android.net.NetworkCapabilities.SIGNAL_STRENGTH_UNSPECIFIED; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; @@ -51,7 +54,6 @@ import static com.android.testutils.MiscAsserts.assertEmpty; import static com.android.testutils.MiscAsserts.assertThrows; import static com.android.testutils.ParcelUtils.assertParcelSane; import static com.android.testutils.ParcelUtils.assertParcelingIsLossless; -import static com.android.testutils.ParcelUtils.parcelingRoundTrip; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; @@ -62,13 +64,13 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.junit.Assume.assumeTrue; -import android.net.wifi.WifiInfo; import android.net.wifi.aware.DiscoverySession; import android.net.wifi.aware.PeerHandle; import android.net.wifi.aware.WifiAwareNetworkSpecifier; import android.os.Build; import android.test.suitebuilder.annotation.SmallTest; import android.util.ArraySet; +import android.util.Range; import androidx.test.runner.AndroidJUnit4; @@ -240,72 +242,93 @@ public class NetworkCapabilitiesTest { @Test public void testSetUids() { final NetworkCapabilities netCap = new NetworkCapabilities(); - final Set<UidRange> uids = new ArraySet<>(); - uids.add(new UidRange(50, 100)); - uids.add(new UidRange(3000, 4000)); - netCap.setUids(uids); - assertTrue(netCap.appliesToUid(50)); - assertTrue(netCap.appliesToUid(80)); - assertTrue(netCap.appliesToUid(100)); + // Null uids match all UIDs + netCap.setUids(null); + assertTrue(netCap.appliesToUid(10)); + assertTrue(netCap.appliesToUid(200)); assertTrue(netCap.appliesToUid(3000)); - assertTrue(netCap.appliesToUid(3001)); - assertFalse(netCap.appliesToUid(10)); - assertFalse(netCap.appliesToUid(25)); - assertFalse(netCap.appliesToUid(49)); - assertFalse(netCap.appliesToUid(101)); - assertFalse(netCap.appliesToUid(2000)); - assertFalse(netCap.appliesToUid(100000)); - + assertTrue(netCap.appliesToUid(10010)); assertTrue(netCap.appliesToUidRange(new UidRange(50, 100))); assertTrue(netCap.appliesToUidRange(new UidRange(70, 72))); assertTrue(netCap.appliesToUidRange(new UidRange(3500, 3912))); - assertFalse(netCap.appliesToUidRange(new UidRange(1, 100))); - assertFalse(netCap.appliesToUidRange(new UidRange(49, 100))); - assertFalse(netCap.appliesToUidRange(new UidRange(1, 10))); - assertFalse(netCap.appliesToUidRange(new UidRange(60, 101))); - assertFalse(netCap.appliesToUidRange(new UidRange(60, 3400))); - - NetworkCapabilities netCap2 = new NetworkCapabilities(); - // A new netcap object has null UIDs, so anything will satisfy it. - assertTrue(netCap2.satisfiedByUids(netCap)); - // Still not equal though. - assertFalse(netCap2.equalsUids(netCap)); - netCap2.setUids(uids); - assertTrue(netCap2.satisfiedByUids(netCap)); - assertTrue(netCap.equalsUids(netCap2)); - assertTrue(netCap2.equalsUids(netCap)); - - uids.add(new UidRange(600, 700)); - netCap2.setUids(uids); - assertFalse(netCap2.satisfiedByUids(netCap)); - assertFalse(netCap.appliesToUid(650)); - assertTrue(netCap2.appliesToUid(650)); - netCap.combineCapabilities(netCap2); - assertTrue(netCap2.satisfiedByUids(netCap)); - assertTrue(netCap.appliesToUid(650)); - assertFalse(netCap.appliesToUid(500)); - - assertTrue(new NetworkCapabilities().satisfiedByUids(netCap)); - netCap.combineCapabilities(new NetworkCapabilities()); - assertTrue(netCap.appliesToUid(500)); assertTrue(netCap.appliesToUidRange(new UidRange(1, 100000))); - assertFalse(netCap2.appliesToUid(500)); - assertFalse(netCap2.appliesToUidRange(new UidRange(1, 100000))); - assertTrue(new NetworkCapabilities().satisfiedByUids(netCap)); + + if (isAtLeastS()) { + final Set<Range<Integer>> uids = new ArraySet<>(); + uids.add(uidRange(50, 100)); + uids.add(uidRange(3000, 4000)); + netCap.setUids(uids); + assertTrue(netCap.appliesToUid(50)); + assertTrue(netCap.appliesToUid(80)); + assertTrue(netCap.appliesToUid(100)); + assertTrue(netCap.appliesToUid(3000)); + assertTrue(netCap.appliesToUid(3001)); + assertFalse(netCap.appliesToUid(10)); + assertFalse(netCap.appliesToUid(25)); + assertFalse(netCap.appliesToUid(49)); + assertFalse(netCap.appliesToUid(101)); + assertFalse(netCap.appliesToUid(2000)); + assertFalse(netCap.appliesToUid(100000)); + + assertTrue(netCap.appliesToUidRange(new UidRange(50, 100))); + assertTrue(netCap.appliesToUidRange(new UidRange(70, 72))); + assertTrue(netCap.appliesToUidRange(new UidRange(3500, 3912))); + assertFalse(netCap.appliesToUidRange(new UidRange(1, 100))); + assertFalse(netCap.appliesToUidRange(new UidRange(49, 100))); + assertFalse(netCap.appliesToUidRange(new UidRange(1, 10))); + assertFalse(netCap.appliesToUidRange(new UidRange(60, 101))); + assertFalse(netCap.appliesToUidRange(new UidRange(60, 3400))); + + NetworkCapabilities netCap2 = new NetworkCapabilities(); + // A new netcap object has null UIDs, so anything will satisfy it. + assertTrue(netCap2.satisfiedByUids(netCap)); + // Still not equal though. + assertFalse(netCap2.equalsUids(netCap)); + netCap2.setUids(uids); + assertTrue(netCap2.satisfiedByUids(netCap)); + assertTrue(netCap.equalsUids(netCap2)); + assertTrue(netCap2.equalsUids(netCap)); + + uids.add(uidRange(600, 700)); + netCap2.setUids(uids); + assertFalse(netCap2.satisfiedByUids(netCap)); + assertFalse(netCap.appliesToUid(650)); + assertTrue(netCap2.appliesToUid(650)); + netCap.combineCapabilities(netCap2); + assertTrue(netCap2.satisfiedByUids(netCap)); + assertTrue(netCap.appliesToUid(650)); + assertFalse(netCap.appliesToUid(500)); + + assertTrue(new NetworkCapabilities().satisfiedByUids(netCap)); + netCap.combineCapabilities(new NetworkCapabilities()); + assertTrue(netCap.appliesToUid(500)); + assertTrue(netCap.appliesToUidRange(new UidRange(1, 100000))); + assertFalse(netCap2.appliesToUid(500)); + assertFalse(netCap2.appliesToUidRange(new UidRange(1, 100000))); + assertTrue(new NetworkCapabilities().satisfiedByUids(netCap)); + + // Null uids satisfies everything. + netCap.setUids(null); + assertTrue(netCap2.satisfiedByUids(netCap)); + assertTrue(netCap.satisfiedByUids(netCap2)); + netCap2.setUids(null); + assertTrue(netCap2.satisfiedByUids(netCap)); + assertTrue(netCap.satisfiedByUids(netCap2)); + } } @Test public void testParcelNetworkCapabilities() { - final Set<UidRange> uids = new ArraySet<>(); - uids.add(new UidRange(50, 100)); - uids.add(new UidRange(3000, 4000)); + final Set<Range<Integer>> uids = new ArraySet<>(); + uids.add(uidRange(50, 100)); + uids.add(uidRange(3000, 4000)); final NetworkCapabilities netCap = new NetworkCapabilities() .addCapability(NET_CAPABILITY_INTERNET) - .setUids(uids) .addCapability(NET_CAPABILITY_EIMS) .addCapability(NET_CAPABILITY_NOT_METERED); if (isAtLeastS()) { netCap.setSubIds(Set.of(TEST_SUBID1, TEST_SUBID2)); + netCap.setUids(uids); } else if (isAtLeastR()) { netCap.setOwnerUid(123); netCap.setAdministratorUids(new int[] {5, 11}); @@ -330,63 +353,53 @@ public class NetworkCapabilitiesTest { testParcelSane(netCap); } - private NetworkCapabilities createNetworkCapabilitiesWithWifiInfo() { - // uses a real WifiInfo to test parceling of sensitive data. - final WifiInfo wifiInfo = new WifiInfo.Builder() - .setSsid("sssid1234".getBytes()) - .setBssid("00:11:22:33:44:55") - .build(); + private void testParcelSane(NetworkCapabilities cap) { + if (isAtLeastS()) { + assertParcelSane(cap, 17); + } else if (isAtLeastR()) { + assertParcelSane(cap, 15); + } else { + assertParcelSane(cap, 11); + } + } + + private static NetworkCapabilities createNetworkCapabilitiesWithTransportInfo() { return new NetworkCapabilities() .addCapability(NET_CAPABILITY_INTERNET) .addCapability(NET_CAPABILITY_EIMS) .addCapability(NET_CAPABILITY_NOT_METERED) .setSSID(TEST_SSID) - .setTransportInfo(wifiInfo) + .setTransportInfo(new TestTransportInfo()) .setRequestorPackageName("com.android.test") .setRequestorUid(9304); } @Test - public void testParcelNetworkCapabilitiesWithLocationSensitiveFields() { + public void testNetworkCapabilitiesCopyWithNoRedactions() { assumeTrue(isAtLeastS()); - final NetworkCapabilities netCap = createNetworkCapabilitiesWithWifiInfo(); - final NetworkCapabilities netCapWithLocationSensitiveFields = - new NetworkCapabilities(netCap, true); - - assertParcelingIsLossless(netCapWithLocationSensitiveFields); - testParcelSane(netCapWithLocationSensitiveFields); - - assertEquals(netCapWithLocationSensitiveFields, - parcelingRoundTrip(netCapWithLocationSensitiveFields)); + final NetworkCapabilities netCap = createNetworkCapabilitiesWithTransportInfo(); + final NetworkCapabilities netCapWithNoRedactions = + new NetworkCapabilities(netCap, NetworkCapabilities.REDACT_NONE); + TestTransportInfo testTransportInfo = + (TestTransportInfo) netCapWithNoRedactions.getTransportInfo(); + assertFalse(testTransportInfo.locationRedacted); + assertFalse(testTransportInfo.localMacAddressRedacted); + assertFalse(testTransportInfo.settingsRedacted); } @Test - public void testParcelNetworkCapabilitiesWithoutLocationSensitiveFields() { + public void testNetworkCapabilitiesCopyWithoutLocationSensitiveFields() { assumeTrue(isAtLeastS()); - final NetworkCapabilities netCap = createNetworkCapabilitiesWithWifiInfo(); - final NetworkCapabilities netCapWithoutLocationSensitiveFields = - new NetworkCapabilities(netCap, false); - - final NetworkCapabilities sanitizedNetCap = - new NetworkCapabilities(netCapWithoutLocationSensitiveFields); - final WifiInfo sanitizedWifiInfo = new WifiInfo.Builder() - .setSsid(new byte[0]) - .setBssid(WifiInfo.DEFAULT_MAC_ADDRESS) - .build(); - sanitizedNetCap.setTransportInfo(sanitizedWifiInfo); - assertEquals(sanitizedNetCap, parcelingRoundTrip(netCapWithoutLocationSensitiveFields)); - } - - private void testParcelSane(NetworkCapabilities cap) { - if (isAtLeastS()) { - assertParcelSane(cap, 17); - } else if (isAtLeastR()) { - assertParcelSane(cap, 15); - } else { - assertParcelSane(cap, 11); - } + final NetworkCapabilities netCap = createNetworkCapabilitiesWithTransportInfo(); + final NetworkCapabilities netCapWithNoRedactions = + new NetworkCapabilities(netCap, REDACT_FOR_ACCESS_FINE_LOCATION); + TestTransportInfo testTransportInfo = + (TestTransportInfo) netCapWithNoRedactions.getTransportInfo(); + assertTrue(testTransportInfo.locationRedacted); + assertFalse(testTransportInfo.localMacAddressRedacted); + assertFalse(testTransportInfo.settingsRedacted); } @Test @@ -540,12 +553,16 @@ public class NetworkCapabilitiesTest { assertFalse(nc1.satisfiedByNetworkCapabilities(nc2)); } - private ArraySet<UidRange> uidRange(int from, int to) { - final ArraySet<UidRange> range = new ArraySet<>(1); - range.add(new UidRange(from, to)); + private ArraySet<Range<Integer>> uidRanges(int from, int to) { + final ArraySet<Range<Integer>> range = new ArraySet<>(1); + range.add(uidRange(from, to)); return range; } + private Range<Integer> uidRange(int from, int to) { + return new Range<Integer>(from, to); + } + @Test @IgnoreUpTo(Build.VERSION_CODES.Q) public void testSetAdministratorUids() { NetworkCapabilities nc = @@ -601,23 +618,23 @@ public class NetworkCapabilitiesTest { } catch (IllegalStateException expected) {} nc1.setSSID(TEST_SSID); - nc1.setUids(uidRange(10, 13)); - assertNotEquals(nc1, nc2); - nc2.combineCapabilities(nc1); // Everything + 10~13 is still everything. - assertNotEquals(nc1, nc2); - nc1.combineCapabilities(nc2); // 10~13 + everything is everything. - assertEquals(nc1, nc2); - nc1.setUids(uidRange(10, 13)); - nc2.setUids(uidRange(20, 23)); - assertNotEquals(nc1, nc2); - nc1.combineCapabilities(nc2); - assertTrue(nc1.appliesToUid(12)); - assertFalse(nc2.appliesToUid(12)); - assertTrue(nc1.appliesToUid(22)); - assertTrue(nc2.appliesToUid(22)); - - // Verify the subscription id list can be combined only when they are equal. if (isAtLeastS()) { + nc1.setUids(uidRanges(10, 13)); + assertNotEquals(nc1, nc2); + nc2.combineCapabilities(nc1); // Everything + 10~13 is still everything. + assertNotEquals(nc1, nc2); + nc1.combineCapabilities(nc2); // 10~13 + everything is everything. + assertEquals(nc1, nc2); + nc1.setUids(uidRanges(10, 13)); + nc2.setUids(uidRanges(20, 23)); + assertNotEquals(nc1, nc2); + nc1.combineCapabilities(nc2); + assertTrue(nc1.appliesToUid(12)); + assertFalse(nc2.appliesToUid(12)); + assertTrue(nc1.appliesToUid(22)); + assertTrue(nc2.appliesToUid(22)); + + // Verify the subscription id list can be combined only when they are equal. nc1.setSubIds(Set.of(TEST_SUBID1, TEST_SUBID2)); nc2.setSubIds(Set.of(TEST_SUBID2)); assertThrows(IllegalStateException.class, () -> nc2.combineCapabilities(nc1)); @@ -773,8 +790,11 @@ public class NetworkCapabilitiesTest { if (isAtLeastR()) { assertTrue(DIFFERENT_TEST_SSID.equals(nc2.getSsid())); } - - nc1.setUids(uidRange(10, 13)); + if (isAtLeastS()) { + nc1.setUids(uidRanges(10, 13)); + } else { + nc1.setUids(null); + } nc2.set(nc1); // Overwrites, as opposed to combineCapabilities assertEquals(nc1, nc2); @@ -1033,18 +1053,42 @@ public class NetworkCapabilitiesTest { } catch (IllegalArgumentException e) { } } - private class TestTransportInfo implements TransportInfo { + /** + * Test TransportInfo to verify redaction mechanism. + */ + private static class TestTransportInfo implements TransportInfo { + public final boolean locationRedacted; + public final boolean localMacAddressRedacted; + public final boolean settingsRedacted; + TestTransportInfo() { + locationRedacted = false; + localMacAddressRedacted = false; + settingsRedacted = false; + } + + TestTransportInfo(boolean locationRedacted, + boolean localMacAddressRedacted, + boolean settingsRedacted) { + this.locationRedacted = locationRedacted; + this.localMacAddressRedacted = + localMacAddressRedacted; + this.settingsRedacted = settingsRedacted; } @Override - public TransportInfo makeCopy(boolean parcelLocationSensitiveFields) { - return this; + public TransportInfo makeCopy(@NetworkCapabilities.RedactionType long redactions) { + return new TestTransportInfo( + (redactions & NetworkCapabilities.REDACT_FOR_ACCESS_FINE_LOCATION) != 0, + (redactions & REDACT_FOR_LOCAL_MAC_ADDRESS) != 0, + (redactions & REDACT_FOR_NETWORK_SETTINGS) != 0 + ); } @Override - public boolean hasLocationSensitiveFields() { - return false; + public @NetworkCapabilities.RedactionType long getApplicableRedactions() { + return REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_LOCAL_MAC_ADDRESS + | REDACT_FOR_NETWORK_SETTINGS; } } @@ -1055,7 +1099,7 @@ public class NetworkCapabilitiesTest { final int requestUid = 10100; final int[] administratorUids = {ownerUid, 10001}; final TelephonyNetworkSpecifier specifier = new TelephonyNetworkSpecifier(1); - final TestTransportInfo transportInfo = new TestTransportInfo(); + final TransportInfo transportInfo = new TransportInfo() {}; final String ssid = "TEST_SSID"; final String packageName = "com.google.test.networkcapabilities"; final NetworkCapabilities nc = new NetworkCapabilities.Builder() diff --git a/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt b/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt index 2a2dc5628ecd..db49e0b0047e 100644 --- a/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt +++ b/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt @@ -44,12 +44,10 @@ import android.util.Log import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.platform.app.InstrumentationRegistry import com.android.server.ConnectivityService -import com.android.server.LocalServices import com.android.server.NetworkAgentWrapper import com.android.server.TestNetIdManager import com.android.server.connectivity.MockableSystemProperties import com.android.server.connectivity.ProxyTracker -import com.android.server.net.NetworkPolicyManagerInternal import com.android.testutils.TestableNetworkCallback import org.junit.After import org.junit.Before @@ -162,10 +160,6 @@ class ConnectivityServiceIntegrationTest { networkStackClient.init() networkStackClient.start() - LocalServices.removeServiceForTest(NetworkPolicyManagerInternal::class.java) - LocalServices.addService(NetworkPolicyManagerInternal::class.java, - mock(NetworkPolicyManagerInternal::class.java)) - service = TestConnectivityService(makeDependencies()) cm = ConnectivityManager(context, service) context.addMockSystemService(Context.CONNECTIVITY_SERVICE, cm) diff --git a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java index 01d8186c7d1b..e2d43cbb8efd 100644 --- a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java +++ b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java @@ -44,11 +44,11 @@ import android.net.NetworkProvider; import android.net.NetworkSpecifier; import android.net.QosFilter; import android.net.SocketKeepalive; -import android.net.UidRange; import android.os.ConditionVariable; import android.os.HandlerThread; import android.os.Message; import android.util.Log; +import android.util.Range; import com.android.net.module.util.ArrayTrackRecord; import com.android.server.connectivity.ConnectivityConstants; @@ -222,7 +222,7 @@ public class NetworkAgentWrapper implements TestableNetworkCallback.HasNetwork { mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); } - public void setUids(Set<UidRange> uids) { + public void setUids(Set<Range<Integer>> uids) { mNetworkCapabilities.setUids(uids); mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); } diff --git a/tests/net/java/android/net/VpnTransportInfoTest.java b/tests/net/java/android/net/VpnTransportInfoTest.java index d04c87b29c25..b7a42ec29356 100644 --- a/tests/net/java/android/net/VpnTransportInfoTest.java +++ b/tests/net/java/android/net/VpnTransportInfoTest.java @@ -42,7 +42,13 @@ public class VpnTransportInfoTest { VpnTransportInfo v1 = new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM); VpnTransportInfo v2 = new VpnTransportInfo(VpnManager.TYPE_VPN_SERVICE); VpnTransportInfo v3 = new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM); + VpnTransportInfo v4 = new VpnTransportInfo(VpnManager.TYPE_VPN_LEGACY); + VpnTransportInfo v5 = new VpnTransportInfo(VpnManager.TYPE_VPN_OEM); + assertNotEquals(v1, v2); + assertNotEquals(v3, v4); + assertNotEquals(v4, v5); + assertEquals(v1, v3); assertEquals(v1.hashCode(), v3.hashCode()); } diff --git a/tests/net/java/android/net/util/KeepaliveUtilsTest.kt b/tests/net/java/android/net/util/KeepaliveUtilsTest.kt index 8ea226db938e..b62bdbcfb5eb 100644 --- a/tests/net/java/android/net/util/KeepaliveUtilsTest.kt +++ b/tests/net/java/android/net/util/KeepaliveUtilsTest.kt @@ -18,6 +18,7 @@ package android.net.util import android.content.Context import android.content.res.Resources +import android.net.ConnectivityResources import android.net.NetworkCapabilities import android.net.NetworkCapabilities.MAX_TRANSPORT import android.net.NetworkCapabilities.TRANSPORT_CELLULAR @@ -26,13 +27,15 @@ import android.net.NetworkCapabilities.TRANSPORT_VPN import android.net.NetworkCapabilities.TRANSPORT_WIFI import androidx.test.filters.SmallTest import com.android.internal.R +import org.junit.After import org.junit.Assert.assertArrayEquals import org.junit.Assert.assertEquals import org.junit.Assert.fail import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import org.mockito.ArgumentMatchers +import org.mockito.ArgumentMatchers.eq +import org.mockito.Mockito.any import org.mockito.Mockito.doReturn import org.mockito.Mockito.mock @@ -47,21 +50,33 @@ import org.mockito.Mockito.mock class KeepaliveUtilsTest { // Prepare mocked context with given resource strings. - private fun getMockedContextWithStringArrayRes(id: Int, res: Array<out String?>?): Context { + private fun getMockedContextWithStringArrayRes( + id: Int, + name: String, + res: Array<out String?>? + ): Context { val mockRes = mock(Resources::class.java) - doReturn(res).`when`(mockRes).getStringArray(ArgumentMatchers.eq(id)) + doReturn(res).`when`(mockRes).getStringArray(eq(id)) + doReturn(id).`when`(mockRes).getIdentifier(eq(name), any(), any()) return mock(Context::class.java).apply { doReturn(mockRes).`when`(this).getResources() + ConnectivityResources.setResourcesContextForTest(this) } } + @After + fun tearDown() { + ConnectivityResources.setResourcesContextForTest(null) + } + @Test fun testGetSupportedKeepalives() { fun assertRunWithException(res: Array<out String?>?) { try { val mockContext = getMockedContextWithStringArrayRes( - R.array.config_networkSupportedKeepaliveCount, res) + R.array.config_networkSupportedKeepaliveCount, + "config_networkSupportedKeepaliveCount", res) KeepaliveUtils.getSupportedKeepalives(mockContext) fail("Expected KeepaliveDeviceConfigurationException") } catch (expected: KeepaliveUtils.KeepaliveDeviceConfigurationException) { @@ -89,7 +104,8 @@ class KeepaliveUtilsTest { val expectedValidRes = intArrayOf(3, 0, 0, 0, 4, 0, 0, 0) val mockContext = getMockedContextWithStringArrayRes( - R.array.config_networkSupportedKeepaliveCount, validRes) + R.array.config_networkSupportedKeepaliveCount, + "config_networkSupportedKeepaliveCount", validRes) val actual = KeepaliveUtils.getSupportedKeepalives(mockContext) assertArrayEquals(expectedValidRes, actual) } diff --git a/tests/net/java/android/net/util/MultinetworkPolicyTrackerTest.kt b/tests/net/java/android/net/util/MultinetworkPolicyTrackerTest.kt index c1315f64c56b..25aa6266577e 100644 --- a/tests/net/java/android/net/util/MultinetworkPolicyTrackerTest.kt +++ b/tests/net/java/android/net/util/MultinetworkPolicyTrackerTest.kt @@ -21,18 +21,20 @@ import android.content.res.Resources import android.net.ConnectivityManager.MULTIPATH_PREFERENCE_HANDOVER import android.net.ConnectivityManager.MULTIPATH_PREFERENCE_PERFORMANCE import android.net.ConnectivityManager.MULTIPATH_PREFERENCE_RELIABILITY +import android.net.ConnectivityResources +import android.net.ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI +import android.net.ConnectivitySettingsManager.NETWORK_METERED_MULTIPATH_PREFERENCE import android.net.util.MultinetworkPolicyTracker.ActiveDataSubscriptionIdListener import android.provider.Settings -import android.provider.Settings.Global.NETWORK_AVOID_BAD_WIFI -import android.provider.Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE import android.telephony.SubscriptionInfo import android.telephony.SubscriptionManager import android.telephony.TelephonyManager import android.test.mock.MockContentResolver import androidx.test.filters.SmallTest import androidx.test.runner.AndroidJUnit4 -import com.android.internal.R +import com.android.connectivity.resources.R import com.android.internal.util.test.FakeSettingsProvider +import org.junit.After import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue @@ -41,6 +43,7 @@ import org.junit.runner.RunWith import org.mockito.ArgumentCaptor import org.mockito.ArgumentMatchers.anyInt import org.mockito.ArgumentMatchers.argThat +import org.mockito.ArgumentMatchers.eq import org.mockito.Mockito.any import org.mockito.Mockito.doReturn import org.mockito.Mockito.mock @@ -57,6 +60,8 @@ import org.mockito.Mockito.verify @SmallTest class MultinetworkPolicyTrackerTest { private val resources = mock(Resources::class.java).also { + doReturn(R.integer.config_networkAvoidBadWifi).`when`(it).getIdentifier( + eq("config_networkAvoidBadWifi"), eq("integer"), any()) doReturn(0).`when`(it).getInteger(R.integer.config_networkAvoidBadWifi) } private val telephonyManager = mock(TelephonyManager::class.java) @@ -75,6 +80,7 @@ class MultinetworkPolicyTrackerTest { doReturn(resources).`when`(it).resources doReturn(it).`when`(it).createConfigurationContext(any()) Settings.Global.putString(resolver, NETWORK_AVOID_BAD_WIFI, "1") + ConnectivityResources.setResourcesContextForTest(it) } private val tracker = MultinetworkPolicyTracker(context, null /* handler */) @@ -85,6 +91,11 @@ class MultinetworkPolicyTrackerTest { assertEquals(preference, tracker.meteredMultipathPreference) } + @After + fun tearDown() { + ConnectivityResources.setResourcesContextForTest(null) + } + @Test fun testUpdateMeteredMultipathPreference() { assertMultipathPreference(MULTIPATH_PREFERENCE_HANDOVER) diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 2c8c8a6409ea..cc1bee5a5104 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -23,6 +23,8 @@ import static android.content.Intent.ACTION_USER_ADDED; import static android.content.Intent.ACTION_USER_REMOVED; import static android.content.Intent.ACTION_USER_UNLOCKED; import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED; +import static android.content.pm.PackageManager.FEATURE_WIFI; +import static android.content.pm.PackageManager.FEATURE_WIFI_DIRECT; import static android.content.pm.PackageManager.GET_PERMISSIONS; import static android.content.pm.PackageManager.MATCH_ANY_USER; import static android.content.pm.PackageManager.PERMISSION_DENIED; @@ -35,11 +37,14 @@ import static android.net.ConnectivityManager.NETID_UNSET; import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF; import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC; import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME; +import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_DEFAULT; +import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE; import static android.net.ConnectivityManager.TYPE_ETHERNET; import static android.net.ConnectivityManager.TYPE_MOBILE; import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA; import static android.net.ConnectivityManager.TYPE_MOBILE_MMS; import static android.net.ConnectivityManager.TYPE_MOBILE_SUPL; +import static android.net.ConnectivityManager.TYPE_PROXY; import static android.net.ConnectivityManager.TYPE_VPN; import static android.net.ConnectivityManager.TYPE_WIFI; import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_DNS; @@ -77,15 +82,19 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED; import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P; import static android.net.NetworkCapabilities.NET_CAPABILITY_XCAP; +import static android.net.NetworkCapabilities.REDACT_FOR_ACCESS_FINE_LOCATION; +import static android.net.NetworkCapabilities.REDACT_FOR_LOCAL_MAC_ADDRESS; +import static android.net.NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS; +import static android.net.NetworkCapabilities.REDACT_NONE; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET; import static android.net.NetworkCapabilities.TRANSPORT_VPN; import static android.net.NetworkCapabilities.TRANSPORT_WIFI; import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE; -import static android.net.NetworkPolicyManager.RULE_ALLOW_METERED; -import static android.net.NetworkPolicyManager.RULE_NONE; -import static android.net.NetworkPolicyManager.RULE_REJECT_ALL; -import static android.net.NetworkPolicyManager.RULE_REJECT_METERED; +import static android.net.NetworkPolicyManager.BLOCKED_METERED_REASON_DATA_SAVER; +import static android.net.NetworkPolicyManager.BLOCKED_METERED_REASON_USER_RESTRICTED; +import static android.net.NetworkPolicyManager.BLOCKED_REASON_BATTERY_SAVER; +import static android.net.NetworkPolicyManager.BLOCKED_REASON_NONE; import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID; import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK; import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY; @@ -174,6 +183,8 @@ import android.net.ConnectivityManager.NetworkCallback; import android.net.ConnectivityManager.PacketKeepalive; import android.net.ConnectivityManager.PacketKeepaliveCallback; import android.net.ConnectivityManager.TooManyRequestsException; +import android.net.ConnectivityResources; +import android.net.ConnectivitySettingsManager; import android.net.ConnectivityThread; import android.net.DataStallReportParcelable; import android.net.EthernetManager; @@ -182,8 +193,7 @@ import android.net.IDnsResolver; import android.net.INetd; import android.net.INetworkMonitor; import android.net.INetworkMonitorCallbacks; -import android.net.INetworkPolicyListener; -import android.net.IOnSetOemNetworkPreferenceListener; +import android.net.IOnCompleteListener; import android.net.IQosCallback; import android.net.InetAddresses; import android.net.InterfaceConfigurationParcel; @@ -201,7 +211,9 @@ import android.net.NetworkFactory; import android.net.NetworkInfo; import android.net.NetworkInfo.DetailedState; import android.net.NetworkPolicyManager; +import android.net.NetworkPolicyManager.NetworkPolicyCallback; import android.net.NetworkRequest; +import android.net.NetworkScore; import android.net.NetworkSpecifier; import android.net.NetworkStack; import android.net.NetworkStackClient; @@ -229,7 +241,6 @@ import android.net.resolv.aidl.PrivateDnsValidationEventParcel; import android.net.shared.NetworkMonitorUtils; import android.net.shared.PrivateDnsConfig; import android.net.util.MultinetworkPolicyTracker; -import android.net.wifi.WifiInfo; import android.os.BadParcelableException; import android.os.Binder; import android.os.Build; @@ -260,12 +271,14 @@ import android.text.TextUtils; import android.util.ArraySet; import android.util.Log; import android.util.Pair; +import android.util.Range; import android.util.SparseArray; import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; +import com.android.connectivity.resources.R; import com.android.internal.net.VpnConfig; import com.android.internal.net.VpnProfile; import com.android.internal.util.ArrayUtils; @@ -284,7 +297,6 @@ import com.android.server.connectivity.QosCallbackTracker; import com.android.server.connectivity.Vpn; import com.android.server.connectivity.VpnProfileStore; import com.android.server.net.NetworkPinner; -import com.android.server.net.NetworkPolicyManagerInternal; import com.android.testutils.ExceptionUtils; import com.android.testutils.HandlerUtils; import com.android.testutils.RecorderCallback.CallbackEntry; @@ -376,6 +388,11 @@ public class ConnectivityServiceTest { // Set a non-zero value to verify the flow to set tcp init rwnd value. private static final int TEST_TCP_INIT_RWND = 60; + // Used for testing the per-work-profile default network. + private static final int TEST_APP_ID = 103; + private static final int TEST_WORK_PROFILE_USER_ID = 2; + private static final int TEST_WORK_PROFILE_APP_UID = + UserHandle.getUid(TEST_WORK_PROFILE_USER_ID, TEST_APP_ID); private static final String CLAT_PREFIX = "v4-"; private static final String MOBILE_IFNAME = "test_rmnet_data0"; private static final String WIFI_IFNAME = "test_wlan0"; @@ -410,7 +427,7 @@ public class ConnectivityServiceTest { private TestNetworkAgentWrapper mEthernetNetworkAgent; private MockVpn mMockVpn; private Context mContext; - private INetworkPolicyListener mPolicyListener; + private NetworkPolicyCallback mPolicyCallback; private WrappedMultinetworkPolicyTracker mPolicyTracker; private HandlerThread mAlarmManagerThread; private TestNetIdManager mNetIdManager; @@ -419,10 +436,10 @@ public class ConnectivityServiceTest { private VpnManagerService mVpnManagerService; private TestNetworkCallback mDefaultNetworkCallback; private TestNetworkCallback mSystemDefaultNetworkCallback; + private TestNetworkCallback mProfileDefaultNetworkCallback; // State variables required to emulate NetworkPolicyManagerService behaviour. - private int mUidRules = RULE_NONE; - private boolean mRestrictBackground = false; + private int mBlockedReasons = BLOCKED_REASON_NONE; @Mock DeviceIdleInternal mDeviceIdleInternal; @Mock INetworkManagementService mNetworkManagementService; @@ -444,6 +461,7 @@ public class ConnectivityServiceTest { @Mock NetworkPolicyManager mNetworkPolicyManager; @Mock VpnProfileStore mVpnProfileStore; @Mock SystemConfigManager mSystemConfigManager; + @Mock Resources mResources; private ArgumentCaptor<ResolverParamsParcel> mResolverParamsParcelCaptor = ArgumentCaptor.forClass(ResolverParamsParcel.class); @@ -471,7 +489,7 @@ public class ConnectivityServiceTest { private class MockContext extends BroadcastInterceptingContext { private final MockContentResolver mContentResolver; - @Spy private Resources mResources; + @Spy private Resources mInternalResources; private final LinkedBlockingQueue<Intent> mStartedActivities = new LinkedBlockingQueue<>(); // Map of permission name -> PermissionManager.Permission_{GRANTED|DENIED} constant @@ -480,21 +498,15 @@ public class ConnectivityServiceTest { MockContext(Context base, ContentProvider settingsProvider) { super(base); - mResources = spy(base.getResources()); - when(mResources.getStringArray(com.android.internal.R.array.networkAttributes)). - thenReturn(new String[] { + mInternalResources = spy(base.getResources()); + when(mInternalResources.getStringArray(com.android.internal.R.array.networkAttributes)) + .thenReturn(new String[] { "wifi,1,1,1,-1,true", "mobile,0,0,0,-1,true", "mobile_mms,2,0,2,60000,true", "mobile_supl,3,0,2,60000,true", }); - when(mResources.getStringArray( - com.android.internal.R.array.config_wakeonlan_supported_interfaces)) - .thenReturn(new String[]{ - WIFI_WOL_IFNAME, - }); - mContentResolver = new MockContentResolver(); mContentResolver.addProvider(Settings.AUTHORITY, settingsProvider); } @@ -545,13 +557,26 @@ public class ConnectivityServiceTest { return super.getSystemService(name); } + final HashMap<UserHandle, UserManager> mUserManagers = new HashMap<>(); @Override public Context createContextAsUser(UserHandle user, int flags) { final Context asUser = mock(Context.class, AdditionalAnswers.delegatesTo(this)); doReturn(user).when(asUser).getUser(); + doAnswer((inv) -> { + final UserManager um = mUserManagers.computeIfAbsent(user, + u -> mock(UserManager.class, AdditionalAnswers.delegatesTo(mUserManager))); + return um; + }).when(asUser).getSystemService(Context.USER_SERVICE); return asUser; } + public void setWorkProfile(@NonNull final UserHandle userHandle, boolean value) { + // This relies on all contexts for a given user returning the same UM mock + final UserManager umMock = createContextAsUser(userHandle, 0 /* flags */) + .getSystemService(UserManager.class); + doReturn(value).when(umMock).isManagedProfile(); + } + @Override public ContentResolver getContentResolver() { return mContentResolver; @@ -559,7 +584,7 @@ public class ConnectivityServiceTest { @Override public Resources getResources() { - return mResources; + return mInternalResources; } @Override @@ -1082,6 +1107,10 @@ public class ConnectivityServiceTest { public void triggerUnfulfillable(NetworkRequest r) { super.releaseRequestAsUnfulfillableByAnyFactory(r); } + + public void assertNoRequestChanged() { + assertNull(mRequestHistory.poll(0, r -> true)); + } } private Set<UidRange> uidRangesForUids(int... uids) { @@ -1133,7 +1162,7 @@ public class ConnectivityServiceTest { } public void setUids(Set<UidRange> uids) { - mNetworkCapabilities.setUids(uids); + mNetworkCapabilities.setUids(UidRange.toIntRanges(uids)); if (mAgentRegistered) { mMockNetworkAgent.setNetworkCapabilities(mNetworkCapabilities, true); } @@ -1349,28 +1378,13 @@ public class ConnectivityServiceTest { } private void mockUidNetworkingBlocked() { - doAnswer(i -> mContext.getSystemService(NetworkPolicyManager.class) - .checkUidNetworkingBlocked(i.getArgument(0) /* uid */, mUidRules, - i.getArgument(1) /* metered */, mRestrictBackground) + doAnswer(i -> NetworkPolicyManager.isUidBlocked(mBlockedReasons, i.getArgument(1)) ).when(mNetworkPolicyManager).isUidNetworkingBlocked(anyInt(), anyBoolean()); - - doAnswer(inv -> mContext.getSystemService(NetworkPolicyManager.class) - .checkUidNetworkingBlocked(inv.getArgument(0) /* uid */, - inv.getArgument(1) /* uidRules */, - inv.getArgument(2) /* isNetworkMetered */, - inv.getArgument(3) /* isBackgroundRestricted */) - ).when(mNetworkPolicyManager).checkUidNetworkingBlocked( - anyInt(), anyInt(), anyBoolean(), anyBoolean()); } - private void setUidRulesChanged(int uidRules) throws RemoteException { - mUidRules = uidRules; - mPolicyListener.onUidRulesChanged(Process.myUid(), mUidRules); - } - - private void setRestrictBackgroundChanged(boolean restrictBackground) throws RemoteException { - mRestrictBackground = restrictBackground; - mPolicyListener.onRestrictBackgroundChanged(mRestrictBackground); + private void setBlockedReasonChanged(int blockedReasons) { + mBlockedReasons = blockedReasons; + mPolicyCallback.onUidBlockedReasonChanged(Process.myUid(), blockedReasons); } private Nat464Xlat getNat464Xlat(NetworkAgentWrapper mna) { @@ -1407,18 +1421,39 @@ public class ConnectivityServiceTest { fail("ConditionVariable was blocked for more than " + TIMEOUT_MS + "ms"); } - private void registerNetworkCallbackAsUid(NetworkRequest request, NetworkCallback callback, - int uid) { + private <T> T doAsUid(final int uid, @NonNull final Supplier<T> what) { when(mDeps.getCallingUid()).thenReturn(uid); try { - mCm.registerNetworkCallback(request, callback); - waitForIdle(); + return what.get(); } finally { returnRealCallingUid(); } } + private void doAsUid(final int uid, @NonNull final Runnable what) { + doAsUid(uid, () -> { + what.run(); return Void.TYPE; + }); + } + + private void registerNetworkCallbackAsUid(NetworkRequest request, NetworkCallback callback, + int uid) { + doAsUid(uid, () -> { + mCm.registerNetworkCallback(request, callback); + }); + } + + private void registerDefaultNetworkCallbackAsUid(@NonNull final NetworkCallback callback, + final int uid) { + doAsUid(uid, () -> { + mCm.registerDefaultNetworkCallback(callback); + waitForIdle(); + }); + } + private static final int PRIMARY_USER = 0; + private static final UidRange PRIMARY_UIDRANGE = + UidRange.createForUser(UserHandle.of(PRIMARY_USER)); private static final int APP1_UID = UserHandle.getUid(PRIMARY_USER, 10100); private static final int APP2_UID = UserHandle.getUid(PRIMARY_USER, 10101); private static final int VPN_UID = UserHandle.getUid(PRIMARY_USER, 10043); @@ -1464,14 +1499,14 @@ public class ConnectivityServiceTest { Looper.prepare(); } mockDefaultPackages(); + mockHasSystemFeature(FEATURE_WIFI, true); + mockHasSystemFeature(FEATURE_WIFI_DIRECT, true); + doReturn(true).when(mTelephonyManager).isDataCapable(); FakeSettingsProvider.clearSettingsProvider(); mServiceContext = new MockContext(InstrumentationRegistry.getContext(), new FakeSettingsProvider()); mServiceContext.setUseRegisteredHandlers(true); - LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class); - LocalServices.addService( - NetworkPolicyManagerInternal.class, mock(NetworkPolicyManagerInternal.class)); mAlarmManagerThread = new HandlerThread("TestAlarmManager"); mAlarmManagerThread.start(); @@ -1490,10 +1525,11 @@ public class ConnectivityServiceTest { mService.mNascentDelayMs = TEST_NASCENT_DELAY_MS; verify(mDeps).makeMultinetworkPolicyTracker(any(), any(), any()); - final ArgumentCaptor<INetworkPolicyListener> policyListenerCaptor = - ArgumentCaptor.forClass(INetworkPolicyListener.class); - verify(mNetworkPolicyManager).registerListener(policyListenerCaptor.capture()); - mPolicyListener = policyListenerCaptor.getValue(); + final ArgumentCaptor<NetworkPolicyCallback> policyCallbackCaptor = + ArgumentCaptor.forClass(NetworkPolicyCallback.class); + verify(mNetworkPolicyManager).registerNetworkPolicyCallback(any(), + policyCallbackCaptor.capture()); + mPolicyCallback = policyCallbackCaptor.getValue(); // Create local CM before sending system ready so that we can answer // getSystemService() correctly. @@ -1506,7 +1542,7 @@ public class ConnectivityServiceTest { mQosCallbackTracker = mock(QosCallbackTracker.class); // Ensure that the default setting for Captive Portals is used for most tests - setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT); + setCaptivePortalMode(ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE_PROMPT); setAlwaysOnNetworks(false); setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com"); } @@ -1516,10 +1552,7 @@ public class ConnectivityServiceTest { } private ConnectivityService.Dependencies makeDependencies() { - doReturn(TEST_TCP_INIT_RWND).when(mSystemProperties) - .getInt("net.tcp.default_init_rwnd", 0); doReturn(false).when(mSystemProperties).getBoolean("ro.radio.noril", false); - doNothing().when(mSystemProperties).setTcpInitRwnd(anyInt()); final ConnectivityService.Dependencies deps = mock(ConnectivityService.Dependencies.class); doReturn(mCsHandlerThread).when(deps).makeHandlerThread(); doReturn(mNetIdManager).when(deps).makeNetIdManager(); @@ -1534,6 +1567,33 @@ public class ConnectivityServiceTest { }).when(deps).makeMultinetworkPolicyTracker(any(), any(), any()); doReturn(true).when(deps).getCellular464XlatEnabled(); + doReturn(60000).when(mResources).getInteger( + com.android.connectivity.resources.R.integer.config_networkTransitionTimeout); + doReturn("").when(mResources).getString( + com.android.connectivity.resources.R.string.config_networkCaptivePortalServerUrl); + doReturn(new String[]{ WIFI_WOL_IFNAME }).when(mResources).getStringArray( + com.android.connectivity.resources.R.array.config_wakeonlan_supported_interfaces); + doReturn(new String[] { "0,1", "1,3" }).when(mResources).getStringArray( + com.android.connectivity.resources.R.array.config_networkSupportedKeepaliveCount); + doReturn(com.android.connectivity.resources.R.array.config_networkSupportedKeepaliveCount) + .when(mResources).getIdentifier(eq("config_networkSupportedKeepaliveCount"), + eq("array"), any()); + doReturn(com.android.connectivity.resources.R.array.network_switch_type_name) + .when(mResources).getIdentifier(eq("network_switch_type_name"), + eq("array"), any()); + + // We don't test the actual notification value strings, so just return an empty array. + // It doesn't matter what the values are as long as it's not null. + doReturn(new String[0]).when(mResources).getStringArray(R.array.network_switch_type_name); + + final ConnectivityResources connRes = mock(ConnectivityResources.class); + doReturn(mResources).when(connRes).get(); + doReturn(connRes).when(deps).getResources(any()); + + final Context mockResContext = mock(Context.class); + doReturn(mResources).when(mockResContext).getResources(); + ConnectivityResources.setResourcesContextForTest(mockResContext); + return deps; } @@ -1566,6 +1626,7 @@ public class ConnectivityServiceTest { @After public void tearDown() throws Exception { unregisterDefaultNetworkCallbacks(); + maybeTearDownEnterpriseNetwork(); setAlwaysOnNetworks(false); if (mCellNetworkAgent != null) { mCellNetworkAgent.disconnect(); @@ -1588,6 +1649,7 @@ public class ConnectivityServiceTest { waitForIdle(); FakeSettingsProvider.clearSettingsProvider(); + ConnectivityResources.setResourcesContextForTest(null); mCsHandlerThread.quitSafely(); mAlarmManagerThread.quitSafely(); @@ -1776,7 +1838,8 @@ public class ConnectivityServiceTest { assertTrue(mCm.isNetworkSupported(TYPE_WIFI)); assertTrue(mCm.isNetworkSupported(TYPE_MOBILE)); assertTrue(mCm.isNetworkSupported(TYPE_MOBILE_MMS)); - assertFalse(mCm.isNetworkSupported(TYPE_MOBILE_FOTA)); + assertTrue(mCm.isNetworkSupported(TYPE_MOBILE_FOTA)); + assertFalse(mCm.isNetworkSupported(TYPE_PROXY)); // Check that TYPE_ETHERNET is supported. Unlike the asserts above, which only validate our // mocks, this assert exercises the ConnectivityService code path that ensures that @@ -3349,7 +3412,7 @@ public class ConnectivityServiceTest { .addCapability(NET_CAPABILITY_VALIDATED).build(); mCm.registerNetworkCallback(validatedRequest, validatedCallback); - setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_AVOID); + setCaptivePortalMode(ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE_AVOID); // Bring up a network with a captive portal. // Expect it to fail to connect and not result in any callbacks. mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); @@ -3999,20 +4062,21 @@ public class ConnectivityServiceTest { private void setCaptivePortalMode(int mode) { ContentResolver cr = mServiceContext.getContentResolver(); - Settings.Global.putInt(cr, Settings.Global.CAPTIVE_PORTAL_MODE, mode); + Settings.Global.putInt(cr, ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE, mode); } private void setAlwaysOnNetworks(boolean enable) { ContentResolver cr = mServiceContext.getContentResolver(); - Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, enable ? 1 : 0); + Settings.Global.putInt(cr, ConnectivitySettingsManager.MOBILE_DATA_ALWAYS_ON, + enable ? 1 : 0); mService.updateAlwaysOnNetworks(); waitForIdle(); } private void setPrivateDnsSettings(String mode, String specifier) { final ContentResolver cr = mServiceContext.getContentResolver(); - Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_MODE, mode); - Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_SPECIFIER, specifier); + Settings.Global.putString(cr, ConnectivitySettingsManager.PRIVATE_DNS_MODE, mode); + Settings.Global.putString(cr, ConnectivitySettingsManager.PRIVATE_DNS_SPECIFIER, specifier); mService.updatePrivateDnsSettings(); waitForIdle(); } @@ -4250,7 +4314,7 @@ public class ConnectivityServiceTest { @Test public void testAvoidBadWifiSetting() throws Exception { final ContentResolver cr = mServiceContext.getContentResolver(); - final String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI; + final String settingName = ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI; mPolicyTracker.mConfigRestrictsAvoidBadWifi = false; String[] values = new String[] {null, "0", "1"}; @@ -4284,6 +4348,7 @@ public class ConnectivityServiceTest { assertTrue(mPolicyTracker.shouldNotifyWifiUnvalidated()); } + @Ignore("Refactoring in progress b/178071397") @Test public void testAvoidBadWifi() throws Exception { final ContentResolver cr = mServiceContext.getContentResolver(); @@ -4307,7 +4372,7 @@ public class ConnectivityServiceTest { TestNetworkCallback validatedWifiCallback = new TestNetworkCallback(); mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback); - Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 0); + Settings.Global.putInt(cr, ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI, 0); mPolicyTracker.reevaluate(); // Bring up validated cell. @@ -4375,7 +4440,7 @@ public class ConnectivityServiceTest { validatedWifiCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); // Simulate the user selecting "switch" and checking the don't ask again checkbox. - Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1); + Settings.Global.putInt(cr, ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI, 1); mPolicyTracker.reevaluate(); // We now switch to cell. @@ -4388,11 +4453,11 @@ public class ConnectivityServiceTest { // Simulate the user turning the cellular fallback setting off and then on. // We switch to wifi and then to cell. - Settings.Global.putString(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, null); + Settings.Global.putString(cr, ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI, null); mPolicyTracker.reevaluate(); defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); assertEquals(mCm.getActiveNetwork(), wifiNetwork); - Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1); + Settings.Global.putInt(cr, ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI, 1); mPolicyTracker.reevaluate(); defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); assertEquals(mCm.getActiveNetwork(), cellNetwork); @@ -4411,7 +4476,7 @@ public class ConnectivityServiceTest { @Test public void testMeteredMultipathPreferenceSetting() throws Exception { final ContentResolver cr = mServiceContext.getContentResolver(); - final String settingName = Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE; + final String settingName = ConnectivitySettingsManager.NETWORK_METERED_MULTIPATH_PREFERENCE; for (int config : Arrays.asList(0, 3, 2)) { for (String setting: Arrays.asList(null, "0", "2", "1")) { @@ -6887,7 +6952,7 @@ public class ConnectivityServiceTest { final int uid = Process.myUid(); NetworkCapabilities nc = mCm.getNetworkCapabilities(mMockVpn.getNetwork()); assertNotNull("nc=" + nc, nc.getUids()); - assertEquals(nc.getUids(), uidRangesForUids(uid)); + assertEquals(nc.getUids(), UidRange.toIntRanges(uidRangesForUids(uid))); assertVpnTransportInfo(nc, VpnManager.TYPE_VPN_SERVICE); // Set an underlying network and expect to see the VPN transports change. @@ -6912,10 +6977,13 @@ public class ConnectivityServiceTest { // Expect that the VPN UID ranges contain both |uid| and the UID range for the newly-added // restricted user. + final UidRange rRange = UidRange.createForUser(UserHandle.of(RESTRICTED_USER)); + final Range<Integer> restrictUidRange = new Range<Integer>(rRange.start, rRange.stop); + final Range<Integer> singleUidRange = new Range<Integer>(uid, uid); callback.expectCapabilitiesThat(mMockVpn, (caps) -> caps.getUids().size() == 2 - && caps.getUids().contains(new UidRange(uid, uid)) - && caps.getUids().contains(createUidRange(RESTRICTED_USER)) + && caps.getUids().contains(singleUidRange) + && caps.getUids().contains(restrictUidRange) && caps.hasTransport(TRANSPORT_VPN) && caps.hasTransport(TRANSPORT_WIFI)); @@ -6924,8 +6992,8 @@ public class ConnectivityServiceTest { callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); callback.expectCapabilitiesThat(mMockVpn, (caps) -> caps.getUids().size() == 2 - && caps.getUids().contains(new UidRange(uid, uid)) - && caps.getUids().contains(createUidRange(RESTRICTED_USER)) + && caps.getUids().contains(singleUidRange) + && caps.getUids().contains(restrictUidRange) && caps.hasTransport(TRANSPORT_VPN) && !caps.hasTransport(TRANSPORT_WIFI)); @@ -6939,7 +7007,7 @@ public class ConnectivityServiceTest { // change made just before that (i.e., loss of TRANSPORT_WIFI) is preserved. callback.expectCapabilitiesThat(mMockVpn, (caps) -> caps.getUids().size() == 1 - && caps.getUids().contains(new UidRange(uid, uid)) + && caps.getUids().contains(singleUidRange) && caps.hasTransport(TRANSPORT_VPN) && !caps.hasTransport(TRANSPORT_WIFI)); } @@ -7206,7 +7274,7 @@ public class ConnectivityServiceTest { assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); assertExtraInfoFromCmPresent(mCellNetworkAgent); - setUidRulesChanged(RULE_REJECT_ALL); + setBlockedReasonChanged(BLOCKED_REASON_BATTERY_SAVER); cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent); assertNull(mCm.getActiveNetwork()); assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED); @@ -7214,17 +7282,17 @@ public class ConnectivityServiceTest { assertExtraInfoFromCmBlocked(mCellNetworkAgent); // ConnectivityService should cache it not to invoke the callback again. - setUidRulesChanged(RULE_REJECT_METERED); + setBlockedReasonChanged(BLOCKED_METERED_REASON_USER_RESTRICTED); cellNetworkCallback.assertNoCallback(); - setUidRulesChanged(RULE_NONE); + setBlockedReasonChanged(BLOCKED_REASON_NONE); cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent); assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); assertExtraInfoFromCmPresent(mCellNetworkAgent); - setUidRulesChanged(RULE_REJECT_METERED); + setBlockedReasonChanged(BLOCKED_METERED_REASON_DATA_SAVER); cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent); assertNull(mCm.getActiveNetwork()); assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED); @@ -7249,33 +7317,33 @@ public class ConnectivityServiceTest { assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED); assertExtraInfoFromCmBlocked(mCellNetworkAgent); - setUidRulesChanged(RULE_ALLOW_METERED); + setBlockedReasonChanged(BLOCKED_REASON_NONE); cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent); assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); assertExtraInfoFromCmPresent(mCellNetworkAgent); - setUidRulesChanged(RULE_NONE); + setBlockedReasonChanged(BLOCKED_REASON_NONE); cellNetworkCallback.assertNoCallback(); // Restrict background data. Networking is not blocked because the network is unmetered. - setRestrictBackgroundChanged(true); + setBlockedReasonChanged(BLOCKED_METERED_REASON_DATA_SAVER); cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent); assertNull(mCm.getActiveNetwork()); assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED); assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED); assertExtraInfoFromCmBlocked(mCellNetworkAgent); - setRestrictBackgroundChanged(true); + setBlockedReasonChanged(BLOCKED_METERED_REASON_DATA_SAVER); cellNetworkCallback.assertNoCallback(); - setUidRulesChanged(RULE_ALLOW_METERED); + setBlockedReasonChanged(BLOCKED_REASON_NONE); cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent); assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); assertExtraInfoFromCmPresent(mCellNetworkAgent); - setRestrictBackgroundChanged(false); + setBlockedReasonChanged(BLOCKED_REASON_NONE); cellNetworkCallback.assertNoCallback(); assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); @@ -7292,9 +7360,9 @@ public class ConnectivityServiceTest { mockUidNetworkingBlocked(); // No Networkcallbacks invoked before any network is active. - setUidRulesChanged(RULE_REJECT_ALL); - setUidRulesChanged(RULE_NONE); - setUidRulesChanged(RULE_REJECT_METERED); + setBlockedReasonChanged(BLOCKED_REASON_BATTERY_SAVER); + setBlockedReasonChanged(BLOCKED_REASON_NONE); + setBlockedReasonChanged(BLOCKED_METERED_REASON_DATA_SAVER); defaultCallback.assertNoCallback(); mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); @@ -7319,8 +7387,8 @@ public class ConnectivityServiceTest { defaultCallback.expectBlockedStatusCallback(false, mCellNetworkAgent); // Verify there's no Networkcallbacks invoked after data saver on/off. - setRestrictBackgroundChanged(true); - setRestrictBackgroundChanged(false); + setBlockedReasonChanged(BLOCKED_METERED_REASON_DATA_SAVER); + setBlockedReasonChanged(BLOCKED_REASON_NONE); defaultCallback.assertNoCallback(); mCellNetworkAgent.disconnect(); @@ -7597,7 +7665,7 @@ public class ConnectivityServiceTest { assertNotNull(underlying); mMockVpn.setVpnType(VpnManager.TYPE_VPN_LEGACY); // The legacy lockdown VPN only supports userId 0. - final Set<UidRange> ranges = Collections.singleton(createUidRange(PRIMARY_USER)); + final Set<UidRange> ranges = Collections.singleton(PRIMARY_UIDRANGE); mMockVpn.registerAgent(ranges); mMockVpn.setUnderlyingNetworks(new Network[]{underlying}); mMockVpn.connect(true); @@ -7985,7 +8053,6 @@ public class ConnectivityServiceTest { // Switching default network updates TCP buffer sizes. verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES); - verify(mSystemProperties, times(1)).setTcpInitRwnd(eq(TEST_TCP_INIT_RWND)); // Add an IPv4 address. Expect prefix discovery to be stopped. Netd doesn't tell us that // the NAT64 prefix was removed because one was never discovered. cellLp.addLinkAddress(myIpv4); @@ -8471,14 +8538,12 @@ public class ConnectivityServiceTest { mCellNetworkAgent.connect(false); networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES); - verify(mSystemProperties, times(1)).setTcpInitRwnd(eq(TEST_TCP_INIT_RWND)); // Change link Properties should have updated tcp buffer size. LinkProperties lp = new LinkProperties(); lp.setTcpBufferSizes(testTcpBufferSizes); mCellNetworkAgent.sendLinkProperties(lp); networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent); verifyTcpBufferSizeChange(testTcpBufferSizes); - verify(mSystemProperties, times(2)).setTcpInitRwnd(eq(TEST_TCP_INIT_RWND)); // Clean up. mCellNetworkAgent.disconnect(); networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); @@ -8562,7 +8627,7 @@ public class ConnectivityServiceTest { lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null)); lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE)); // The uid range needs to cover the test app so the network is visible to it. - final Set<UidRange> vpnRange = Collections.singleton(createUidRange(PRIMARY_USER)); + final Set<UidRange> vpnRange = Collections.singleton(PRIMARY_UIDRANGE); mMockVpn.establish(lp, VPN_UID, vpnRange); assertVpnUidRangesUpdated(true, vpnRange, VPN_UID); @@ -8590,7 +8655,7 @@ public class ConnectivityServiceTest { lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null)); lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null)); // The uid range needs to cover the test app so the network is visible to it. - final Set<UidRange> vpnRange = Collections.singleton(createUidRange(PRIMARY_USER)); + final Set<UidRange> vpnRange = Collections.singleton(PRIMARY_UIDRANGE); mMockVpn.establish(lp, Process.SYSTEM_UID, vpnRange); assertVpnUidRangesUpdated(true, vpnRange, Process.SYSTEM_UID); @@ -8606,7 +8671,7 @@ public class ConnectivityServiceTest { lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun0")); lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE)); // The uid range needs to cover the test app so the network is visible to it. - final Set<UidRange> vpnRange = Collections.singleton(createUidRange(PRIMARY_USER)); + final Set<UidRange> vpnRange = Collections.singleton(PRIMARY_UIDRANGE); mMockVpn.establish(lp, Process.SYSTEM_UID, vpnRange); assertVpnUidRangesUpdated(true, vpnRange, Process.SYSTEM_UID); @@ -8621,7 +8686,7 @@ public class ConnectivityServiceTest { lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null)); lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null)); // The uid range needs to cover the test app so the network is visible to it. - final Set<UidRange> vpnRange = Collections.singleton(createUidRange(PRIMARY_USER)); + final Set<UidRange> vpnRange = Collections.singleton(PRIMARY_UIDRANGE); mMockVpn.establish(lp, VPN_UID, vpnRange); assertVpnUidRangesUpdated(true, vpnRange, VPN_UID); @@ -8673,7 +8738,7 @@ public class ConnectivityServiceTest { lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE)); lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null)); // The uid range needs to cover the test app so the network is visible to it. - final UidRange vpnRange = createUidRange(PRIMARY_USER); + final UidRange vpnRange = PRIMARY_UIDRANGE; final Set<UidRange> vpnRanges = Collections.singleton(vpnRange); mMockVpn.establish(lp, VPN_UID, vpnRanges); assertVpnUidRangesUpdated(true, vpnRanges, VPN_UID); @@ -8778,29 +8843,34 @@ public class ConnectivityServiceTest { final NetworkCapabilities netCap = new NetworkCapabilities().setOwnerUid(ownerUid); return mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled( - netCap, includeLocationSensitiveInfo, callerUid, + netCap, includeLocationSensitiveInfo, Process.myUid(), callerUid, mContext.getPackageName(), getAttributionTag()) .getOwnerUid(); } - private void verifyWifiInfoCopyNetCapsPermission( + private void verifyTransportInfoCopyNetCapsPermission( int callerUid, boolean includeLocationSensitiveInfo, boolean shouldMakeCopyWithLocationSensitiveFieldsParcelable) { - final WifiInfo wifiInfo = mock(WifiInfo.class); - when(wifiInfo.hasLocationSensitiveFields()).thenReturn(true); - final NetworkCapabilities netCap = new NetworkCapabilities().setTransportInfo(wifiInfo); + final TransportInfo transportInfo = mock(TransportInfo.class); + when(transportInfo.getApplicableRedactions()).thenReturn(REDACT_FOR_ACCESS_FINE_LOCATION); + final NetworkCapabilities netCap = + new NetworkCapabilities().setTransportInfo(transportInfo); mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled( - netCap, includeLocationSensitiveInfo, callerUid, + netCap, includeLocationSensitiveInfo, Process.myPid(), callerUid, mContext.getPackageName(), getAttributionTag()); - verify(wifiInfo).makeCopy(eq(shouldMakeCopyWithLocationSensitiveFieldsParcelable)); + if (shouldMakeCopyWithLocationSensitiveFieldsParcelable) { + verify(transportInfo).makeCopy(REDACT_NONE); + } else { + verify(transportInfo).makeCopy(REDACT_FOR_ACCESS_FINE_LOCATION); + } } - private void verifyOwnerUidAndWifiInfoNetCapsPermission( + private void verifyOwnerUidAndTransportInfoNetCapsPermission( boolean shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag, boolean shouldInclLocationSensitiveOwnerUidWithIncludeFlag, - boolean shouldInclLocationSensitiveWifiInfoWithoutIncludeFlag, - boolean shouldInclLocationSensitiveWifiInfoWithIncludeFlag) { + boolean shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag, + boolean shouldInclLocationSensitiveTransportInfoWithIncludeFlag) { final int myUid = Process.myUid(); final int expectedOwnerUidWithoutIncludeFlag = @@ -8814,13 +8884,13 @@ public class ConnectivityServiceTest { assertEquals(expectedOwnerUidWithIncludeFlag, getOwnerUidNetCapsPermission( myUid, myUid, true /* includeLocationSensitiveInfo */)); - verifyWifiInfoCopyNetCapsPermission(myUid, + verifyTransportInfoCopyNetCapsPermission(myUid, false, /* includeLocationSensitiveInfo */ - shouldInclLocationSensitiveWifiInfoWithoutIncludeFlag); + shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag); - verifyWifiInfoCopyNetCapsPermission(myUid, + verifyTransportInfoCopyNetCapsPermission(myUid, true, /* includeLocationSensitiveInfo */ - shouldInclLocationSensitiveWifiInfoWithIncludeFlag); + shouldInclLocationSensitiveTransportInfoWithIncludeFlag); } @@ -8830,15 +8900,15 @@ public class ConnectivityServiceTest { setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION); - verifyOwnerUidAndWifiInfoNetCapsPermission( + verifyOwnerUidAndTransportInfoNetCapsPermission( // Ensure that we include owner uid even if the request asks to remove it since the // app has necessary permissions and targetSdk < S. true, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */ true, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */ - false, /* shouldInclLocationSensitiveWifiInfoWithoutIncludeFlag */ + false, /* shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag */ // Ensure that we remove location info if the request asks to remove it even if the // app has necessary permissions. - true /* shouldInclLocationSensitiveWifiInfoWithIncludeFlag */ + true /* shouldInclLocationSensitiveTransportInfoWithIncludeFlag */ ); } @@ -8848,15 +8918,15 @@ public class ConnectivityServiceTest { setupLocationPermissions(Build.VERSION_CODES.R, true, AppOpsManager.OPSTR_FINE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION); - verifyOwnerUidAndWifiInfoNetCapsPermission( + verifyOwnerUidAndTransportInfoNetCapsPermission( // Ensure that we include owner uid even if the request asks to remove it since the // app has necessary permissions and targetSdk < S. true, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */ true, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */ - false, /* shouldInclLocationSensitiveWifiInfoWithoutIncludeFlag */ + false, /* shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag */ // Ensure that we remove location info if the request asks to remove it even if the // app has necessary permissions. - true /* shouldInclLocationSensitiveWifiInfoWithIncludeFlag */ + true /* shouldInclLocationSensitiveTransportInfoWithIncludeFlag */ ); } @@ -8867,15 +8937,15 @@ public class ConnectivityServiceTest { setupLocationPermissions(Build.VERSION_CODES.S, true, AppOpsManager.OPSTR_FINE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION); - verifyOwnerUidAndWifiInfoNetCapsPermission( + verifyOwnerUidAndTransportInfoNetCapsPermission( // Ensure that we owner UID if the request asks us to remove it even if the app // has necessary permissions since targetSdk >= S. false, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */ true, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */ - false, /* shouldInclLocationSensitiveWifiInfoWithoutIncludeFlag */ + false, /* shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag */ // Ensure that we remove location info if the request asks to remove it even if the // app has necessary permissions. - true /* shouldInclLocationSensitiveWifiInfoWithIncludeFlag */ + true /* shouldInclLocationSensitiveTransportInfoWithIncludeFlag */ ); } @@ -8885,15 +8955,15 @@ public class ConnectivityServiceTest { setupLocationPermissions(Build.VERSION_CODES.P, true, AppOpsManager.OPSTR_COARSE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION); - verifyOwnerUidAndWifiInfoNetCapsPermission( + verifyOwnerUidAndTransportInfoNetCapsPermission( // Ensure that we owner UID if the request asks us to remove it even if the app // has necessary permissions since targetSdk >= S. true, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */ true, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */ - false, /* shouldInclLocationSensitiveWifiInfoWithoutIncludeFlag */ + false, /* shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag */ // Ensure that we remove location info if the request asks to remove it even if the // app has necessary permissions. - true /* shouldInclLocationSensitiveWifiInfoWithIncludeFlag */ + true /* shouldInclLocationSensitiveTransportInfoWithIncludeFlag */ ); } @@ -8903,11 +8973,11 @@ public class ConnectivityServiceTest { setupLocationPermissions(Build.VERSION_CODES.Q, false, AppOpsManager.OPSTR_FINE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION); - verifyOwnerUidAndWifiInfoNetCapsPermission( + verifyOwnerUidAndTransportInfoNetCapsPermission( false, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */ false, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */ - false, /* shouldInclLocationSensitiveWifiInfoWithoutIncludeFlag */ - false /* shouldInclLocationSensitiveWifiInfoWithIncludeFlag */ + false, /* shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag */ + false /* shouldInclLocationSensitiveTransportInfoWithIncludeFlag */ ); } @@ -8930,11 +9000,11 @@ public class ConnectivityServiceTest { setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_COARSE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION); - verifyOwnerUidAndWifiInfoNetCapsPermission( + verifyOwnerUidAndTransportInfoNetCapsPermission( false, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */ false, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */ - false, /* shouldInclLocationSensitiveWifiInfoWithoutIncludeFlag */ - false /* shouldInclLocationSensitiveWifiInfoWithIncludeFlag */ + false, /* shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag */ + false /* shouldInclLocationSensitiveTransportInfoWithIncludeFlag */ ); } @@ -8944,17 +9014,196 @@ public class ConnectivityServiceTest { // Test that not having fine location permission leads to sanitization. setupLocationPermissions(Build.VERSION_CODES.Q, true, null /* op */, null /* perm */); - verifyOwnerUidAndWifiInfoNetCapsPermission( + verifyOwnerUidAndTransportInfoNetCapsPermission( false, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */ false, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */ - false, /* shouldInclLocationSensitiveWifiInfoWithoutIncludeFlag */ - false /* shouldInclLocationSensitiveWifiInfoWithIncludeFlag */ + false, /* shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag */ + false /* shouldInclLocationSensitiveTransportInfoWithIncludeFlag */ ); } + @Test + public void testCreateForCallerWithLocalMacAddressSanitizedWithLocalMacAddressPermission() + throws Exception { + mServiceContext.setPermission(Manifest.permission.LOCAL_MAC_ADDRESS, PERMISSION_GRANTED); + + final TransportInfo transportInfo = mock(TransportInfo.class); + when(transportInfo.getApplicableRedactions()) + .thenReturn(REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_LOCAL_MAC_ADDRESS); + final NetworkCapabilities netCap = + new NetworkCapabilities().setTransportInfo(transportInfo); + + mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled( + netCap, false /* includeLocationSensitiveInfoInTransportInfo */, + Process.myPid(), Process.myUid(), + mContext.getPackageName(), getAttributionTag()); + // don't redact MAC_ADDRESS fields, only location sensitive fields. + verify(transportInfo).makeCopy(REDACT_FOR_ACCESS_FINE_LOCATION); + } + + @Test + public void testCreateForCallerWithLocalMacAddressSanitizedWithoutLocalMacAddressPermission() + throws Exception { + mServiceContext.setPermission(Manifest.permission.LOCAL_MAC_ADDRESS, PERMISSION_DENIED); + + final TransportInfo transportInfo = mock(TransportInfo.class); + when(transportInfo.getApplicableRedactions()) + .thenReturn(REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_LOCAL_MAC_ADDRESS); + final NetworkCapabilities netCap = + new NetworkCapabilities().setTransportInfo(transportInfo); + + mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled( + netCap, false /* includeLocationSensitiveInfoInTransportInfo */, + Process.myPid(), Process.myUid(), + mContext.getPackageName(), getAttributionTag()); + // redact both MAC_ADDRESS & location sensitive fields. + verify(transportInfo).makeCopy(REDACT_FOR_ACCESS_FINE_LOCATION + | REDACT_FOR_LOCAL_MAC_ADDRESS); + } + + @Test + public void testCreateForCallerWithLocalMacAddressSanitizedWithSettingsPermission() + throws Exception { + mServiceContext.setPermission(Manifest.permission.NETWORK_SETTINGS, PERMISSION_GRANTED); + + final TransportInfo transportInfo = mock(TransportInfo.class); + when(transportInfo.getApplicableRedactions()) + .thenReturn(REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_NETWORK_SETTINGS); + final NetworkCapabilities netCap = + new NetworkCapabilities().setTransportInfo(transportInfo); + + mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled( + netCap, false /* includeLocationSensitiveInfoInTransportInfo */, + Process.myPid(), Process.myUid(), + mContext.getPackageName(), getAttributionTag()); + // don't redact NETWORK_SETTINGS fields, only location sensitive fields. + verify(transportInfo).makeCopy(REDACT_FOR_ACCESS_FINE_LOCATION); + } + + @Test + public void testCreateForCallerWithLocalMacAddressSanitizedWithoutSettingsPermission() + throws Exception { + mServiceContext.setPermission(Manifest.permission.LOCAL_MAC_ADDRESS, PERMISSION_DENIED); + + final TransportInfo transportInfo = mock(TransportInfo.class); + when(transportInfo.getApplicableRedactions()) + .thenReturn(REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_NETWORK_SETTINGS); + final NetworkCapabilities netCap = + new NetworkCapabilities().setTransportInfo(transportInfo); + + mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled( + netCap, false /* includeLocationSensitiveInfoInTransportInfo */, + Process.myPid(), Process.myUid(), + mContext.getPackageName(), getAttributionTag()); + // redact both NETWORK_SETTINGS & location sensitive fields. + verify(transportInfo).makeCopy( + REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_NETWORK_SETTINGS); + } + + /** + * Test TransportInfo to verify redaction mechanism. + */ + private static class TestTransportInfo implements TransportInfo { + public final boolean locationRedacted; + public final boolean localMacAddressRedacted; + public final boolean settingsRedacted; + + TestTransportInfo() { + locationRedacted = false; + localMacAddressRedacted = false; + settingsRedacted = false; + } + + TestTransportInfo(boolean locationRedacted, boolean localMacAddressRedacted, + boolean settingsRedacted) { + this.locationRedacted = locationRedacted; + this.localMacAddressRedacted = + localMacAddressRedacted; + this.settingsRedacted = settingsRedacted; + } + + @Override + public TransportInfo makeCopy(@NetworkCapabilities.RedactionType long redactions) { + return new TestTransportInfo( + (redactions & REDACT_FOR_ACCESS_FINE_LOCATION) != 0, + (redactions & REDACT_FOR_LOCAL_MAC_ADDRESS) != 0, + (redactions & REDACT_FOR_NETWORK_SETTINGS) != 0 + ); + } + + @Override + public @NetworkCapabilities.RedactionType long getApplicableRedactions() { + return REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_LOCAL_MAC_ADDRESS + | REDACT_FOR_NETWORK_SETTINGS; + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof TestTransportInfo)) return false; + TestTransportInfo that = (TestTransportInfo) other; + return that.locationRedacted == this.locationRedacted + && that.localMacAddressRedacted == this.localMacAddressRedacted + && that.settingsRedacted == this.settingsRedacted; + } + + @Override + public int hashCode() { + return Objects.hash(locationRedacted, localMacAddressRedacted, settingsRedacted); + } + } + + private void verifyNetworkCallbackLocationDataInclusionUsingTransportInfoAndOwnerUidInNetCaps( + @NonNull TestNetworkCallback wifiNetworkCallback, int actualOwnerUid, + @NonNull TransportInfo actualTransportInfo, int expectedOwnerUid, + @NonNull TransportInfo expectedTransportInfo) throws Exception { + when(mPackageManager.getTargetSdkVersion(anyString())).thenReturn(Build.VERSION_CODES.S); + final NetworkCapabilities ncTemplate = + new NetworkCapabilities() + .addTransportType(TRANSPORT_WIFI) + .setOwnerUid(actualOwnerUid); + + final NetworkRequest wifiRequest = new NetworkRequest.Builder() + .addTransportType(TRANSPORT_WIFI).build(); + mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback); + + mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, new LinkProperties(), + ncTemplate); + mWiFiNetworkAgent.connect(false); + + wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); + + // Send network capabilities update with TransportInfo to trigger capabilities changed + // callback. + mWiFiNetworkAgent.setNetworkCapabilities( + ncTemplate.setTransportInfo(actualTransportInfo), true); + + wifiNetworkCallback.expectCapabilitiesThat(mWiFiNetworkAgent, + nc -> Objects.equals(expectedOwnerUid, nc.getOwnerUid()) + && Objects.equals(expectedTransportInfo, nc.getTransportInfo())); + + } + + @Test + public void testVerifyLocationDataIsNotIncludedWhenInclFlagNotSet() throws Exception { + final TestNetworkCallback wifiNetworkCallack = new TestNetworkCallback(); + final int ownerUid = Process.myUid(); + final TransportInfo transportInfo = new TestTransportInfo(); + // Even though the test uid holds privileged permissions, mask location fields since + // the callback did not explicitly opt-in to get location data. + final TransportInfo sanitizedTransportInfo = new TestTransportInfo( + true, /* locationRedacted */ + true, /* localMacAddressRedacted */ + true /* settingsRedacted */ + ); + // Should not expect location data since the callback does not set the flag for including + // location data. + verifyNetworkCallbackLocationDataInclusionUsingTransportInfoAndOwnerUidInNetCaps( + wifiNetworkCallack, ownerUid, transportInfo, INVALID_UID, sanitizedTransportInfo); + } + private void setupConnectionOwnerUid(int vpnOwnerUid, @VpnManager.VpnType int vpnType) throws Exception { - final Set<UidRange> vpnRange = Collections.singleton(createUidRange(PRIMARY_USER)); + final Set<UidRange> vpnRange = Collections.singleton(PRIMARY_UIDRANGE); mMockVpn.setVpnType(vpnType); mMockVpn.establish(new LinkProperties(), vpnOwnerUid, vpnRange); assertVpnUidRangesUpdated(true, vpnRange, vpnOwnerUid); @@ -9153,7 +9402,8 @@ public class ConnectivityServiceTest { ConnectivityManager.getNetworkTypeName(TYPE_MOBILE), TelephonyManager.getNetworkTypeName(TelephonyManager.NETWORK_TYPE_LTE)); return new NetworkAgentInfo(null, new Network(NET_ID), info, new LinkProperties(), - nc, 0, mServiceContext, null, new NetworkAgentConfig(), mService, null, null, 0, + nc, new NetworkScore.Builder().setLegacyInt(0).build(), + mServiceContext, null, new NetworkAgentConfig(), mService, null, null, 0, INVALID_UID, mQosCallbackTracker, new ConnectivityService.Dependencies()); } @@ -9513,7 +9763,7 @@ public class ConnectivityServiceTest { lp.setInterfaceName("tun0"); lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null)); lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null)); - final UidRange vpnRange = createUidRange(PRIMARY_USER); + final UidRange vpnRange = PRIMARY_UIDRANGE; Set<UidRange> vpnRanges = Collections.singleton(vpnRange); mMockVpn.establish(lp, VPN_UID, vpnRanges); assertVpnUidRangesUpdated(true, vpnRanges, VPN_UID); @@ -9711,7 +9961,7 @@ public class ConnectivityServiceTest { .thenReturn(hasFeature); } - private UidRange getNriFirstUidRange( + private Range<Integer> getNriFirstUidRange( @NonNull final ConnectivityService.NetworkRequestInfo nri) { return nri.mRequests.get(0).networkCapabilities.getUids().iterator().next(); } @@ -9894,11 +10144,11 @@ public class ConnectivityServiceTest { pref)); // Sort by uid to access nris by index - nris.sort(Comparator.comparingInt(nri -> getNriFirstUidRange(nri).start)); - assertEquals(TEST_PACKAGE_UID, getNriFirstUidRange(nris.get(0)).start); - assertEquals(TEST_PACKAGE_UID, getNriFirstUidRange(nris.get(0)).stop); - assertEquals(testPackageNameUid2, getNriFirstUidRange(nris.get(1)).start); - assertEquals(testPackageNameUid2, getNriFirstUidRange(nris.get(1)).stop); + nris.sort(Comparator.comparingInt(nri -> getNriFirstUidRange(nri).getLower())); + assertEquals(TEST_PACKAGE_UID, (int) getNriFirstUidRange(nris.get(0)).getLower()); + assertEquals(TEST_PACKAGE_UID, (int) getNriFirstUidRange(nris.get(0)).getUpper()); + assertEquals(testPackageNameUid2, (int) getNriFirstUidRange(nris.get(1)).getLower()); + assertEquals(testPackageNameUid2, (int) getNriFirstUidRange(nris.get(1)).getUpper()); } @Test @@ -9928,17 +10178,17 @@ public class ConnectivityServiceTest { // UIDs for all users and all managed packages should be present. // Two users each with two packages. final int expectedUidSize = 2; - final List<UidRange> uids = + final List<Range<Integer>> uids = new ArrayList<>(nris.get(0).mRequests.get(0).networkCapabilities.getUids()); assertEquals(expectedUidSize, uids.size()); // Sort by uid to access nris by index - uids.sort(Comparator.comparingInt(uid -> uid.start)); + uids.sort(Comparator.comparingInt(uid -> uid.getLower())); final int secondUserTestPackageUid = UserHandle.getUid(secondUser, TEST_PACKAGE_UID); - assertEquals(TEST_PACKAGE_UID, uids.get(0).start); - assertEquals(TEST_PACKAGE_UID, uids.get(0).stop); - assertEquals(secondUserTestPackageUid, uids.get(1).start); - assertEquals(secondUserTestPackageUid, uids.get(1).stop); + assertEquals(TEST_PACKAGE_UID, (int) uids.get(0).getLower()); + assertEquals(TEST_PACKAGE_UID, (int) uids.get(0).getUpper()); + assertEquals(secondUserTestPackageUid, (int) uids.get(1).getLower()); + assertEquals(secondUserTestPackageUid, (int) uids.get(1).getUpper()); } @Test @@ -10105,9 +10355,12 @@ public class ConnectivityServiceTest { Manifest.permission.NETWORK_SETTINGS, PERMISSION_GRANTED); mSystemDefaultNetworkCallback = new TestNetworkCallback(); mDefaultNetworkCallback = new TestNetworkCallback(); + mProfileDefaultNetworkCallback = new TestNetworkCallback(); mCm.registerSystemDefaultNetworkCallback(mSystemDefaultNetworkCallback, new Handler(ConnectivityThread.getInstanceLooper())); mCm.registerDefaultNetworkCallback(mDefaultNetworkCallback); + registerDefaultNetworkCallbackAsUid(mProfileDefaultNetworkCallback, + TEST_WORK_PROFILE_APP_UID); mServiceContext.setPermission( Manifest.permission.NETWORK_SETTINGS, PERMISSION_DENIED); } @@ -10119,6 +10372,9 @@ public class ConnectivityServiceTest { if (null != mSystemDefaultNetworkCallback) { mCm.unregisterNetworkCallback(mSystemDefaultNetworkCallback); } + if (null != mProfileDefaultNetworkCallback) { + mCm.unregisterNetworkCallback(mProfileDefaultNetworkCallback); + } } private void setupMultipleDefaultNetworksForOemNetworkPreferenceNotCurrentUidTest( @@ -10174,7 +10430,7 @@ public class ConnectivityServiceTest { oemPrefListener.expectOnComplete(); } - private static class TestOemListenerCallback implements IOnSetOemNetworkPreferenceListener { + private static class TestOemListenerCallback implements IOnCompleteListener { final CompletableFuture<Object> mDone = new CompletableFuture<>(); @Override @@ -11112,11 +11368,494 @@ public class ConnectivityServiceTest { mCm.unregisterNetworkCallback(cellCb); } + // Cannot be part of MockNetworkFactory since it requires method of the test. + private void expectNoRequestChanged(@NonNull MockNetworkFactory factory) { + waitForIdle(); + factory.assertNoRequestChanged(); + } + @Test - public void testRegisterBestMatchingNetworkCallback() throws Exception { - final NetworkRequest request = new NetworkRequest.Builder().build(); - assertThrows(UnsupportedOperationException.class, - () -> mCm.registerBestMatchingNetworkCallback(request, new NetworkCallback(), - mCsHandlerThread.getThreadHandler())); + public void testRegisterBestMatchingNetworkCallback_noIssueToFactory() throws Exception { + // Prepare mock mms factory. + final HandlerThread handlerThread = new HandlerThread("MockCellularFactory"); + handlerThread.start(); + NetworkCapabilities filter = new NetworkCapabilities() + .addTransportType(TRANSPORT_CELLULAR) + .addCapability(NET_CAPABILITY_MMS); + final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(), + mServiceContext, "testFactory", filter, mCsHandlerThread); + testFactory.setScoreFilter(40); + + try { + // Register the factory and expect it will see default request, because all requests + // are sent to all factories. + testFactory.register(); + testFactory.expectRequestAdd(); + testFactory.assertRequestCountEquals(1); + // The factory won't try to start the network since the default request doesn't + // match the filter (no INTERNET capability). + assertFalse(testFactory.getMyStartRequested()); + + // Register callback for listening best matching network. Verify that the request won't + // be sent to factory. + final TestNetworkCallback bestMatchingCb = new TestNetworkCallback(); + mCm.registerBestMatchingNetworkCallback( + new NetworkRequest.Builder().addCapability(NET_CAPABILITY_MMS).build(), + bestMatchingCb, mCsHandlerThread.getThreadHandler()); + bestMatchingCb.assertNoCallback(); + expectNoRequestChanged(testFactory); + testFactory.assertRequestCountEquals(1); + assertFalse(testFactory.getMyStartRequested()); + + // Fire a normal mms request, verify the factory will only see the request. + final TestNetworkCallback mmsNetworkCallback = new TestNetworkCallback(); + final NetworkRequest mmsRequest = new NetworkRequest.Builder() + .addCapability(NET_CAPABILITY_MMS).build(); + mCm.requestNetwork(mmsRequest, mmsNetworkCallback); + testFactory.expectRequestAdd(); + testFactory.assertRequestCountEquals(2); + assertTrue(testFactory.getMyStartRequested()); + + // Unregister best matching callback, verify factory see no change. + mCm.unregisterNetworkCallback(bestMatchingCb); + expectNoRequestChanged(testFactory); + testFactory.assertRequestCountEquals(2); + assertTrue(testFactory.getMyStartRequested()); + } finally { + testFactory.terminate(); + } + } + + @Test + public void testRegisterBestMatchingNetworkCallback_trackBestNetwork() throws Exception { + final TestNetworkCallback bestMatchingCb = new TestNetworkCallback(); + mCm.registerBestMatchingNetworkCallback( + new NetworkRequest.Builder().addCapability(NET_CAPABILITY_TRUSTED).build(), + bestMatchingCb, mCsHandlerThread.getThreadHandler()); + + mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); + mCellNetworkAgent.connect(true); + bestMatchingCb.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); + + mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); + mWiFiNetworkAgent.connect(true); + bestMatchingCb.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); + + // Change something on cellular to trigger capabilities changed, since the callback + // only cares about the best network, verify it received nothing from cellular. + mCellNetworkAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED); + bestMatchingCb.assertNoCallback(); + + // Make cellular the best network again, verify the callback now tracks cellular. + mWiFiNetworkAgent.adjustScore(-50); + bestMatchingCb.expectAvailableCallbacksValidated(mCellNetworkAgent); + + // Make cellular temporary non-trusted, which will not satisfying the request. + // Verify the callback switch from/to the other network accordingly. + mCellNetworkAgent.removeCapability(NET_CAPABILITY_TRUSTED); + bestMatchingCb.expectAvailableCallbacksValidated(mWiFiNetworkAgent); + mCellNetworkAgent.addCapability(NET_CAPABILITY_TRUSTED); + bestMatchingCb.expectAvailableDoubleValidatedCallbacks(mCellNetworkAgent); + + // Verify the callback doesn't care about wifi disconnect. + mWiFiNetworkAgent.disconnect(); + bestMatchingCb.assertNoCallback(); + mCellNetworkAgent.disconnect(); + bestMatchingCb.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); + } + + private UidRangeParcel[] uidRangeFor(final UserHandle handle) { + UidRange range = UidRange.createForUser(handle); + return new UidRangeParcel[] { new UidRangeParcel(range.start, range.stop) }; + } + + private static class TestOnCompleteListener implements Runnable { + final class OnComplete {} + final ArrayTrackRecord<OnComplete>.ReadHead mHistory = + new ArrayTrackRecord<OnComplete>().newReadHead(); + + @Override + public void run() { + mHistory.add(new OnComplete()); + } + + public void expectOnComplete() { + assertNotNull(mHistory.poll(TIMEOUT_MS, it -> true)); + } + } + + private TestNetworkAgentWrapper makeEnterpriseNetworkAgent() throws Exception { + final NetworkCapabilities workNc = new NetworkCapabilities(); + workNc.addCapability(NET_CAPABILITY_ENTERPRISE); + workNc.removeCapability(NET_CAPABILITY_NOT_RESTRICTED); + return new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, new LinkProperties(), workNc); + } + + private TestNetworkCallback mEnterpriseCallback; + private UserHandle setupEnterpriseNetwork() { + final UserHandle userHandle = UserHandle.of(TEST_WORK_PROFILE_USER_ID); + mServiceContext.setWorkProfile(userHandle, true); + + // File a request to avoid the enterprise network being disconnected as soon as the default + // request goes away – it would make impossible to test that networkRemoveUidRanges + // is called, as the network would disconnect first for lack of a request. + mEnterpriseCallback = new TestNetworkCallback(); + final NetworkRequest keepUpRequest = new NetworkRequest.Builder() + .addCapability(NET_CAPABILITY_ENTERPRISE) + .build(); + mCm.requestNetwork(keepUpRequest, mEnterpriseCallback); + return userHandle; + } + + private void maybeTearDownEnterpriseNetwork() { + if (null != mEnterpriseCallback) { + mCm.unregisterNetworkCallback(mEnterpriseCallback); + } + } + + /** + * Make sure per-profile networking preference behaves as expected when the enterprise network + * goes up and down while the preference is active. Make sure they behave as expected whether + * there is a general default network or not. + */ + @Test + public void testPreferenceForUserNetworkUpDown() throws Exception { + final InOrder inOrder = inOrder(mMockNetd); + final UserHandle testHandle = setupEnterpriseNetwork(); + registerDefaultNetworkCallbacks(); + + mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); + mCellNetworkAgent.connect(true); + + mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); + mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); + mProfileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); + inOrder.verify(mMockNetd).networkCreatePhysical(mCellNetworkAgent.getNetwork().netId, + INetd.PERMISSION_NONE); + + final TestOnCompleteListener listener = new TestOnCompleteListener(); + mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE, + r -> r.run(), listener); + listener.expectOnComplete(); + + // Setting a network preference for this user will create a new set of routing rules for + // the UID range that corresponds to this user, so as to define the default network + // for these apps separately. This is true because the multi-layer request relevant to + // this UID range contains a TRACK_DEFAULT, so the range will be moved through UID-specific + // rules to the correct network – in this case the system default network. The case where + // the default network for the profile happens to be the same as the system default + // is not handled specially, the rules are always active as long as a preference is set. + inOrder.verify(mMockNetd).networkAddUidRanges(mCellNetworkAgent.getNetwork().netId, + uidRangeFor(testHandle)); + + // The enterprise network is not ready yet. + assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback, + mProfileDefaultNetworkCallback); + + final TestNetworkAgentWrapper workAgent = makeEnterpriseNetworkAgent(); + workAgent.connect(false); + + mProfileDefaultNetworkCallback.expectAvailableCallbacksUnvalidated(workAgent); + mSystemDefaultNetworkCallback.assertNoCallback(); + mDefaultNetworkCallback.assertNoCallback(); + inOrder.verify(mMockNetd).networkCreatePhysical(workAgent.getNetwork().netId, + INetd.PERMISSION_SYSTEM); + inOrder.verify(mMockNetd).networkAddUidRanges(workAgent.getNetwork().netId, + uidRangeFor(testHandle)); + inOrder.verify(mMockNetd).networkRemoveUidRanges(mCellNetworkAgent.getNetwork().netId, + uidRangeFor(testHandle)); + + // Make sure changes to the work agent send callbacks to the app in the work profile, but + // not to the other apps. + workAgent.setNetworkValid(true /* isStrictMode */); + workAgent.mNetworkMonitor.forceReevaluation(Process.myUid()); + mProfileDefaultNetworkCallback.expectCapabilitiesThat(workAgent, + nc -> nc.hasCapability(NET_CAPABILITY_VALIDATED) + && nc.hasCapability(NET_CAPABILITY_ENTERPRISE)); + assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback); + + workAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED); + mProfileDefaultNetworkCallback.expectCapabilitiesThat(workAgent, nc -> + nc.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)); + assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback); + + // Conversely, change a capability on the system-wide default network and make sure + // that only the apps outside of the work profile receive the callbacks. + mCellNetworkAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED); + mSystemDefaultNetworkCallback.expectCapabilitiesThat(mCellNetworkAgent, nc -> + nc.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)); + mDefaultNetworkCallback.expectCapabilitiesThat(mCellNetworkAgent, nc -> + nc.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)); + mProfileDefaultNetworkCallback.assertNoCallback(); + + // Disconnect and reconnect the system-wide default network and make sure that the + // apps on this network see the appropriate callbacks, and the app on the work profile + // doesn't because it continues to use the enterprise network. + mCellNetworkAgent.disconnect(); + mSystemDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); + mDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); + mProfileDefaultNetworkCallback.assertNoCallback(); + inOrder.verify(mMockNetd).networkDestroy(mCellNetworkAgent.getNetwork().netId); + + mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); + mCellNetworkAgent.connect(true); + mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); + mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); + mProfileDefaultNetworkCallback.assertNoCallback(); + inOrder.verify(mMockNetd).networkCreatePhysical(mCellNetworkAgent.getNetwork().netId, + INetd.PERMISSION_NONE); + + // When the agent disconnects, test that the app on the work profile falls back to the + // default network. + workAgent.disconnect(); + mProfileDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, workAgent); + mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); + assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback); + inOrder.verify(mMockNetd).networkAddUidRanges(mCellNetworkAgent.getNetwork().netId, + uidRangeFor(testHandle)); + inOrder.verify(mMockNetd).networkDestroy(workAgent.getNetwork().netId); + + mCellNetworkAgent.disconnect(); + mSystemDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); + mDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); + mProfileDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); + + // Waiting for the handler to be idle before checking for networkDestroy is necessary + // here because ConnectivityService calls onLost before the network is fully torn down. + waitForIdle(); + inOrder.verify(mMockNetd).networkDestroy(mCellNetworkAgent.getNetwork().netId); + + // If the control comes here, callbacks seem to behave correctly in the presence of + // a default network when the enterprise network goes up and down. Now, make sure they + // also behave correctly in the absence of a system-wide default network. + final TestNetworkAgentWrapper workAgent2 = makeEnterpriseNetworkAgent(); + workAgent2.connect(false); + + mProfileDefaultNetworkCallback.expectAvailableCallbacksUnvalidated(workAgent2); + assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback); + inOrder.verify(mMockNetd).networkCreatePhysical(workAgent2.getNetwork().netId, + INetd.PERMISSION_SYSTEM); + inOrder.verify(mMockNetd).networkAddUidRanges(workAgent2.getNetwork().netId, + uidRangeFor(testHandle)); + + workAgent2.setNetworkValid(true /* isStrictMode */); + workAgent2.mNetworkMonitor.forceReevaluation(Process.myUid()); + mProfileDefaultNetworkCallback.expectCapabilitiesThat(workAgent2, + nc -> nc.hasCapability(NET_CAPABILITY_ENTERPRISE) + && !nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); + assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback); + inOrder.verify(mMockNetd, never()).networkAddUidRanges(anyInt(), any()); + + // When the agent disconnects, test that the app on the work profile falls back to the + // default network. + workAgent2.disconnect(); + mProfileDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, workAgent2); + assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback); + inOrder.verify(mMockNetd).networkDestroy(workAgent2.getNetwork().netId); + + assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback, + mProfileDefaultNetworkCallback); + + // Callbacks will be unregistered by tearDown() + } + + /** + * Test that, in a given networking context, calling setPreferenceForUser to set per-profile + * defaults on then off works as expected. + */ + @Test + public void testSetPreferenceForUserOnOff() throws Exception { + final InOrder inOrder = inOrder(mMockNetd); + final UserHandle testHandle = setupEnterpriseNetwork(); + + // Connect both a regular cell agent and an enterprise network first. + mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); + mCellNetworkAgent.connect(true); + + final TestNetworkAgentWrapper workAgent = makeEnterpriseNetworkAgent(); + workAgent.connect(true); + + final TestOnCompleteListener listener = new TestOnCompleteListener(); + mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE, + r -> r.run(), listener); + listener.expectOnComplete(); + inOrder.verify(mMockNetd).networkCreatePhysical(mCellNetworkAgent.getNetwork().netId, + INetd.PERMISSION_NONE); + inOrder.verify(mMockNetd).networkAddUidRanges(workAgent.getNetwork().netId, + uidRangeFor(testHandle)); + + registerDefaultNetworkCallbacks(); + + mSystemDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); + mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); + mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(workAgent); + + mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_DEFAULT, + r -> r.run(), listener); + listener.expectOnComplete(); + + mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); + assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback); + inOrder.verify(mMockNetd).networkRemoveUidRanges(workAgent.getNetwork().netId, + uidRangeFor(testHandle)); + + workAgent.disconnect(); + mCellNetworkAgent.disconnect(); + + // Callbacks will be unregistered by tearDown() + } + + /** + * Test per-profile default networks for two different profiles concurrently. + */ + @Test + public void testSetPreferenceForTwoProfiles() throws Exception { + final InOrder inOrder = inOrder(mMockNetd); + final UserHandle testHandle2 = setupEnterpriseNetwork(); + final UserHandle testHandle4 = UserHandle.of(TEST_WORK_PROFILE_USER_ID + 2); + mServiceContext.setWorkProfile(testHandle4, true); + registerDefaultNetworkCallbacks(); + + final TestNetworkCallback app4Cb = new TestNetworkCallback(); + final int testWorkProfileAppUid4 = + UserHandle.getUid(testHandle4.getIdentifier(), TEST_APP_ID); + registerDefaultNetworkCallbackAsUid(app4Cb, testWorkProfileAppUid4); + + // Connect both a regular cell agent and an enterprise network first. + mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); + mCellNetworkAgent.connect(true); + + final TestNetworkAgentWrapper workAgent = makeEnterpriseNetworkAgent(); + workAgent.connect(true); + + mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); + mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); + mProfileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); + app4Cb.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); + inOrder.verify(mMockNetd).networkCreatePhysical(mCellNetworkAgent.getNetwork().netId, + INetd.PERMISSION_NONE); + inOrder.verify(mMockNetd).networkCreatePhysical(workAgent.getNetwork().netId, + INetd.PERMISSION_SYSTEM); + + final TestOnCompleteListener listener = new TestOnCompleteListener(); + mCm.setProfileNetworkPreference(testHandle2, PROFILE_NETWORK_PREFERENCE_ENTERPRISE, + r -> r.run(), listener); + listener.expectOnComplete(); + inOrder.verify(mMockNetd).networkAddUidRanges(workAgent.getNetwork().netId, + uidRangeFor(testHandle2)); + + mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(workAgent); + assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback, + app4Cb); + + mCm.setProfileNetworkPreference(testHandle4, PROFILE_NETWORK_PREFERENCE_ENTERPRISE, + r -> r.run(), listener); + listener.expectOnComplete(); + inOrder.verify(mMockNetd).networkAddUidRanges(workAgent.getNetwork().netId, + uidRangeFor(testHandle4)); + + app4Cb.expectAvailableCallbacksValidated(workAgent); + assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback, + mProfileDefaultNetworkCallback); + + mCm.setProfileNetworkPreference(testHandle2, PROFILE_NETWORK_PREFERENCE_DEFAULT, + r -> r.run(), listener); + listener.expectOnComplete(); + inOrder.verify(mMockNetd).networkRemoveUidRanges(workAgent.getNetwork().netId, + uidRangeFor(testHandle2)); + + mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); + assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback, + app4Cb); + + workAgent.disconnect(); + mCellNetworkAgent.disconnect(); + + mCm.unregisterNetworkCallback(app4Cb); + // Other callbacks will be unregistered by tearDown() + } + + @Test + public void testProfilePreferenceRemovedUponUserRemoved() throws Exception { + final InOrder inOrder = inOrder(mMockNetd); + final UserHandle testHandle = setupEnterpriseNetwork(); + + mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); + mCellNetworkAgent.connect(true); + + final TestOnCompleteListener listener = new TestOnCompleteListener(); + mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE, + r -> r.run(), listener); + listener.expectOnComplete(); + inOrder.verify(mMockNetd).networkCreatePhysical(mCellNetworkAgent.getNetwork().netId, + INetd.PERMISSION_NONE); + inOrder.verify(mMockNetd).networkAddUidRanges(mCellNetworkAgent.getNetwork().netId, + uidRangeFor(testHandle)); + + final Intent removedIntent = new Intent(ACTION_USER_REMOVED); + removedIntent.putExtra(Intent.EXTRA_USER, testHandle); + processBroadcast(removedIntent); + + inOrder.verify(mMockNetd).networkRemoveUidRanges(mCellNetworkAgent.getNetwork().netId, + uidRangeFor(testHandle)); + } + + /** + * Make sure that OEM preference and per-profile preference can't be used at the same + * time and throw ISE if tried + */ + @Test + public void testOemPreferenceAndProfilePreferenceExclusive() throws Exception { + final UserHandle testHandle = UserHandle.of(TEST_WORK_PROFILE_USER_ID); + mServiceContext.setWorkProfile(testHandle, true); + final TestOnCompleteListener listener = new TestOnCompleteListener(); + + setupMultipleDefaultNetworksForOemNetworkPreferenceNotCurrentUidTest( + OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY); + assertThrows("Should not be able to set per-profile pref while OEM prefs present", + IllegalStateException.class, () -> + mCm.setProfileNetworkPreference(testHandle, + PROFILE_NETWORK_PREFERENCE_ENTERPRISE, + r -> r.run(), listener)); + + // Empty the OEM prefs + final TestOemListenerCallback oemPrefListener = new TestOemListenerCallback(); + final OemNetworkPreferences emptyOemPref = new OemNetworkPreferences.Builder().build(); + mService.setOemNetworkPreference(emptyOemPref, oemPrefListener); + oemPrefListener.expectOnComplete(); + + mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE, + r -> r.run(), listener); + listener.expectOnComplete(); + assertThrows("Should not be able to set OEM prefs while per-profile pref is on", + IllegalStateException.class , () -> + mService.setOemNetworkPreference(emptyOemPref, oemPrefListener)); + } + + /** + * Make sure wrong preferences for per-profile default networking are rejected. + */ + @Test + public void testProfileNetworkPrefWrongPreference() throws Exception { + final UserHandle testHandle = UserHandle.of(TEST_WORK_PROFILE_USER_ID); + mServiceContext.setWorkProfile(testHandle, true); + assertThrows("Should not be able to set an illegal preference", + IllegalArgumentException.class, + () -> mCm.setProfileNetworkPreference(testHandle, + PROFILE_NETWORK_PREFERENCE_ENTERPRISE + 1, null, null)); + } + + /** + * Make sure requests for per-profile default networking for a non-work profile are + * rejected + */ + @Test + public void testProfileNetworkPrefWrongProfile() throws Exception { + final UserHandle testHandle = UserHandle.of(TEST_WORK_PROFILE_USER_ID); + mServiceContext.setWorkProfile(testHandle, false); + assertThrows("Should not be able to set a user pref for a non-work profile", + IllegalArgumentException.class , () -> + mCm.setProfileNetworkPreference(testHandle, + PROFILE_NETWORK_PREFERENCE_ENTERPRISE, null, null)); } } diff --git a/tests/net/java/com/android/server/LegacyTypeTrackerTest.kt b/tests/net/java/com/android/server/LegacyTypeTrackerTest.kt index a10a3c81bc86..5ec111954fcc 100644 --- a/tests/net/java/com/android/server/LegacyTypeTrackerTest.kt +++ b/tests/net/java/com/android/server/LegacyTypeTrackerTest.kt @@ -21,13 +21,29 @@ package com.android.server +import android.content.Context +import android.content.pm.PackageManager +import android.content.pm.PackageManager.FEATURE_WIFI +import android.content.pm.PackageManager.FEATURE_WIFI_DIRECT import android.net.ConnectivityManager.TYPE_ETHERNET import android.net.ConnectivityManager.TYPE_MOBILE +import android.net.ConnectivityManager.TYPE_MOBILE_CBS +import android.net.ConnectivityManager.TYPE_MOBILE_DUN +import android.net.ConnectivityManager.TYPE_MOBILE_EMERGENCY +import android.net.ConnectivityManager.TYPE_MOBILE_FOTA +import android.net.ConnectivityManager.TYPE_MOBILE_HIPRI +import android.net.ConnectivityManager.TYPE_MOBILE_IA +import android.net.ConnectivityManager.TYPE_MOBILE_IMS +import android.net.ConnectivityManager.TYPE_MOBILE_MMS import android.net.ConnectivityManager.TYPE_MOBILE_SUPL +import android.net.ConnectivityManager.TYPE_VPN import android.net.ConnectivityManager.TYPE_WIFI +import android.net.ConnectivityManager.TYPE_WIFI_P2P import android.net.ConnectivityManager.TYPE_WIMAX +import android.net.EthernetManager import android.net.NetworkInfo.DetailedState.CONNECTED import android.net.NetworkInfo.DetailedState.DISCONNECTED +import android.telephony.TelephonyManager import androidx.test.filters.SmallTest import androidx.test.runner.AndroidJUnit4 import com.android.server.ConnectivityService.LegacyTypeTracker @@ -36,7 +52,6 @@ import org.junit.Assert.assertFalse import org.junit.Assert.assertNull import org.junit.Assert.assertSame import org.junit.Assert.assertTrue -import org.junit.Assert.fail import org.junit.Test import org.junit.runner.RunWith import org.mockito.ArgumentMatchers.any @@ -52,88 +67,130 @@ const val UNSUPPORTED_TYPE = TYPE_WIMAX @RunWith(AndroidJUnit4::class) @SmallTest class LegacyTypeTrackerTest { - private val supportedTypes = arrayOf(TYPE_MOBILE, TYPE_WIFI, TYPE_ETHERNET, TYPE_MOBILE_SUPL) + private val supportedTypes = arrayOf(TYPE_WIFI, TYPE_WIFI_P2P, TYPE_ETHERNET, TYPE_MOBILE, + TYPE_MOBILE_SUPL, TYPE_MOBILE_MMS, TYPE_MOBILE_SUPL, TYPE_MOBILE_DUN, TYPE_MOBILE_HIPRI, + TYPE_MOBILE_FOTA, TYPE_MOBILE_IMS, TYPE_MOBILE_CBS, TYPE_MOBILE_IA, + TYPE_MOBILE_EMERGENCY, TYPE_VPN) private val mMockService = mock(ConnectivityService::class.java).apply { doReturn(false).`when`(this).isDefaultNetwork(any()) } - private val mTracker = LegacyTypeTracker(mMockService).apply { - supportedTypes.forEach { - addSupportedType(it) - } + private val mPm = mock(PackageManager::class.java) + private val mContext = mock(Context::class.java).apply { + doReturn(true).`when`(mPm).hasSystemFeature(FEATURE_WIFI) + doReturn(true).`when`(mPm).hasSystemFeature(FEATURE_WIFI_DIRECT) + doReturn(mPm).`when`(this).packageManager + doReturn(mock(EthernetManager::class.java)).`when`(this).getSystemService( + Context.ETHERNET_SERVICE) + } + private val mTm = mock(TelephonyManager::class.java).apply { + doReturn(true).`when`(this).isDataCapable + } + + private fun makeTracker() = LegacyTypeTracker(mMockService).apply { + loadSupportedTypes(mContext, mTm) } @Test fun testSupportedTypes() { - try { - mTracker.addSupportedType(supportedTypes[0]) - fail("Expected IllegalStateException") - } catch (expected: IllegalStateException) {} + val tracker = makeTracker() supportedTypes.forEach { - assertTrue(mTracker.isTypeSupported(it)) + assertTrue(tracker.isTypeSupported(it)) + } + assertFalse(tracker.isTypeSupported(UNSUPPORTED_TYPE)) + } + + @Test + fun testSupportedTypes_NoEthernet() { + doReturn(null).`when`(mContext).getSystemService(Context.ETHERNET_SERVICE) + assertFalse(makeTracker().isTypeSupported(TYPE_ETHERNET)) + } + + @Test + fun testSupportedTypes_NoTelephony() { + doReturn(false).`when`(mTm).isDataCapable + val tracker = makeTracker() + val nonMobileTypes = arrayOf(TYPE_WIFI, TYPE_WIFI_P2P, TYPE_ETHERNET, TYPE_VPN) + nonMobileTypes.forEach { + assertTrue(tracker.isTypeSupported(it)) + } + supportedTypes.toSet().minus(nonMobileTypes).forEach { + assertFalse(tracker.isTypeSupported(it)) + } + } + + @Test + fun testSupportedTypes_NoWifiDirect() { + doReturn(false).`when`(mPm).hasSystemFeature(FEATURE_WIFI_DIRECT) + val tracker = makeTracker() + assertFalse(tracker.isTypeSupported(TYPE_WIFI_P2P)) + supportedTypes.toSet().minus(TYPE_WIFI_P2P).forEach { + assertTrue(tracker.isTypeSupported(it)) } - assertFalse(mTracker.isTypeSupported(UNSUPPORTED_TYPE)) } @Test fun testSupl() { + val tracker = makeTracker() val mobileNai = mock(NetworkAgentInfo::class.java) - mTracker.add(TYPE_MOBILE, mobileNai) + tracker.add(TYPE_MOBILE, mobileNai) verify(mMockService).sendLegacyNetworkBroadcast(mobileNai, CONNECTED, TYPE_MOBILE) reset(mMockService) - mTracker.add(TYPE_MOBILE_SUPL, mobileNai) + tracker.add(TYPE_MOBILE_SUPL, mobileNai) verify(mMockService).sendLegacyNetworkBroadcast(mobileNai, CONNECTED, TYPE_MOBILE_SUPL) reset(mMockService) - mTracker.remove(TYPE_MOBILE_SUPL, mobileNai, false /* wasDefault */) + tracker.remove(TYPE_MOBILE_SUPL, mobileNai, false /* wasDefault */) verify(mMockService).sendLegacyNetworkBroadcast(mobileNai, DISCONNECTED, TYPE_MOBILE_SUPL) reset(mMockService) - mTracker.add(TYPE_MOBILE_SUPL, mobileNai) + tracker.add(TYPE_MOBILE_SUPL, mobileNai) verify(mMockService).sendLegacyNetworkBroadcast(mobileNai, CONNECTED, TYPE_MOBILE_SUPL) reset(mMockService) - mTracker.remove(mobileNai, false) + tracker.remove(mobileNai, false) verify(mMockService).sendLegacyNetworkBroadcast(mobileNai, DISCONNECTED, TYPE_MOBILE_SUPL) verify(mMockService).sendLegacyNetworkBroadcast(mobileNai, DISCONNECTED, TYPE_MOBILE) } @Test fun testAddNetwork() { + val tracker = makeTracker() val mobileNai = mock(NetworkAgentInfo::class.java) val wifiNai = mock(NetworkAgentInfo::class.java) - mTracker.add(TYPE_MOBILE, mobileNai) - mTracker.add(TYPE_WIFI, wifiNai) - assertSame(mTracker.getNetworkForType(TYPE_MOBILE), mobileNai) - assertSame(mTracker.getNetworkForType(TYPE_WIFI), wifiNai) + tracker.add(TYPE_MOBILE, mobileNai) + tracker.add(TYPE_WIFI, wifiNai) + assertSame(tracker.getNetworkForType(TYPE_MOBILE), mobileNai) + assertSame(tracker.getNetworkForType(TYPE_WIFI), wifiNai) // Make sure adding a second NAI does not change the results. val secondMobileNai = mock(NetworkAgentInfo::class.java) - mTracker.add(TYPE_MOBILE, secondMobileNai) - assertSame(mTracker.getNetworkForType(TYPE_MOBILE), mobileNai) - assertSame(mTracker.getNetworkForType(TYPE_WIFI), wifiNai) + tracker.add(TYPE_MOBILE, secondMobileNai) + assertSame(tracker.getNetworkForType(TYPE_MOBILE), mobileNai) + assertSame(tracker.getNetworkForType(TYPE_WIFI), wifiNai) // Make sure removing a network that wasn't added for this type is a no-op. - mTracker.remove(TYPE_MOBILE, wifiNai, false /* wasDefault */) - assertSame(mTracker.getNetworkForType(TYPE_MOBILE), mobileNai) - assertSame(mTracker.getNetworkForType(TYPE_WIFI), wifiNai) + tracker.remove(TYPE_MOBILE, wifiNai, false /* wasDefault */) + assertSame(tracker.getNetworkForType(TYPE_MOBILE), mobileNai) + assertSame(tracker.getNetworkForType(TYPE_WIFI), wifiNai) // Remove the top network for mobile and make sure the second one becomes the network // of record for this type. - mTracker.remove(TYPE_MOBILE, mobileNai, false /* wasDefault */) - assertSame(mTracker.getNetworkForType(TYPE_MOBILE), secondMobileNai) - assertSame(mTracker.getNetworkForType(TYPE_WIFI), wifiNai) + tracker.remove(TYPE_MOBILE, mobileNai, false /* wasDefault */) + assertSame(tracker.getNetworkForType(TYPE_MOBILE), secondMobileNai) + assertSame(tracker.getNetworkForType(TYPE_WIFI), wifiNai) // Make sure adding a network for an unsupported type does not register it. - mTracker.add(UNSUPPORTED_TYPE, mobileNai) - assertNull(mTracker.getNetworkForType(UNSUPPORTED_TYPE)) + tracker.add(UNSUPPORTED_TYPE, mobileNai) + assertNull(tracker.getNetworkForType(UNSUPPORTED_TYPE)) } @Test fun testBroadcastOnDisconnect() { + val tracker = makeTracker() val mobileNai1 = mock(NetworkAgentInfo::class.java) val mobileNai2 = mock(NetworkAgentInfo::class.java) doReturn(false).`when`(mMockService).isDefaultNetwork(mobileNai1) - mTracker.add(TYPE_MOBILE, mobileNai1) + tracker.add(TYPE_MOBILE, mobileNai1) verify(mMockService).sendLegacyNetworkBroadcast(mobileNai1, CONNECTED, TYPE_MOBILE) reset(mMockService) doReturn(false).`when`(mMockService).isDefaultNetwork(mobileNai2) - mTracker.add(TYPE_MOBILE, mobileNai2) + tracker.add(TYPE_MOBILE, mobileNai2) verify(mMockService, never()).sendLegacyNetworkBroadcast(any(), any(), anyInt()) - mTracker.remove(TYPE_MOBILE, mobileNai1, false /* wasDefault */) + tracker.remove(TYPE_MOBILE, mobileNai1, false /* wasDefault */) verify(mMockService).sendLegacyNetworkBroadcast(mobileNai1, DISCONNECTED, TYPE_MOBILE) verify(mMockService).sendLegacyNetworkBroadcast(mobileNai2, CONNECTED, TYPE_MOBILE) } diff --git a/tests/net/java/com/android/server/connectivity/DnsManagerTest.java b/tests/net/java/com/android/server/connectivity/DnsManagerTest.java index 5760211d9a27..692c50fbef86 100644 --- a/tests/net/java/com/android/server/connectivity/DnsManagerTest.java +++ b/tests/net/java/com/android/server/connectivity/DnsManagerTest.java @@ -18,15 +18,15 @@ package com.android.server.connectivity; import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF; import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME; +import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_DEFAULT_MODE; +import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE; +import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_SPECIFIER; import static android.net.NetworkCapabilities.MAX_TRANSPORT; import static android.net.NetworkCapabilities.MIN_TRANSPORT; import static android.net.NetworkCapabilities.TRANSPORT_VPN; import static android.net.NetworkCapabilities.TRANSPORT_WIFI; import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.VALIDATION_RESULT_FAILURE; import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.VALIDATION_RESULT_SUCCESS; -import static android.provider.Settings.Global.PRIVATE_DNS_DEFAULT_MODE; -import static android.provider.Settings.Global.PRIVATE_DNS_MODE; -import static android.provider.Settings.Global.PRIVATE_DNS_SPECIFIER; import static com.android.testutils.MiscAsserts.assertContainsExactly; import static com.android.testutils.MiscAsserts.assertContainsStringsExactly; @@ -312,14 +312,14 @@ public class DnsManagerTest { @Test public void testOverrideDefaultMode() throws Exception { // Hard-coded default is opportunistic mode. - final PrivateDnsConfig cfgAuto = DnsManager.getPrivateDnsConfig(mContentResolver); + final PrivateDnsConfig cfgAuto = DnsManager.getPrivateDnsConfig(mCtx); assertTrue(cfgAuto.useTls); assertEquals("", cfgAuto.hostname); assertEquals(new InetAddress[0], cfgAuto.ips); // Pretend a gservices push sets the default to "off". Settings.Global.putString(mContentResolver, PRIVATE_DNS_DEFAULT_MODE, "off"); - final PrivateDnsConfig cfgOff = DnsManager.getPrivateDnsConfig(mContentResolver); + final PrivateDnsConfig cfgOff = DnsManager.getPrivateDnsConfig(mCtx); assertFalse(cfgOff.useTls); assertEquals("", cfgOff.hostname); assertEquals(new InetAddress[0], cfgOff.ips); @@ -328,7 +328,7 @@ public class DnsManagerTest { Settings.Global.putString( mContentResolver, PRIVATE_DNS_MODE, PRIVATE_DNS_MODE_PROVIDER_HOSTNAME); Settings.Global.putString(mContentResolver, PRIVATE_DNS_SPECIFIER, "strictmode.com"); - final PrivateDnsConfig cfgStrict = DnsManager.getPrivateDnsConfig(mContentResolver); + final PrivateDnsConfig cfgStrict = DnsManager.getPrivateDnsConfig(mCtx); assertTrue(cfgStrict.useTls); assertEquals("strictmode.com", cfgStrict.hostname); assertEquals(new InetAddress[0], cfgStrict.ips); diff --git a/tests/net/java/com/android/server/connectivity/FullScoreTest.kt b/tests/net/java/com/android/server/connectivity/FullScoreTest.kt new file mode 100644 index 000000000000..eb3b4df1a282 --- /dev/null +++ b/tests/net/java/com/android/server/connectivity/FullScoreTest.kt @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2021 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 + +import android.net.NetworkAgentConfig +import android.net.NetworkCapabilities +import android.text.TextUtils +import android.util.ArraySet +import androidx.test.filters.SmallTest +import androidx.test.runner.AndroidJUnit4 +import com.android.server.connectivity.FullScore.MAX_CS_MANAGED_POLICY +import com.android.server.connectivity.FullScore.POLICY_ACCEPT_UNVALIDATED +import com.android.server.connectivity.FullScore.POLICY_EVER_USER_SELECTED +import com.android.server.connectivity.FullScore.POLICY_IS_VALIDATED +import com.android.server.connectivity.FullScore.POLICY_IS_VPN +import org.junit.Test +import org.junit.runner.RunWith +import kotlin.collections.minOfOrNull +import kotlin.collections.maxOfOrNull +import kotlin.reflect.full.staticProperties +import kotlin.test.assertEquals +import kotlin.test.assertFailsWith +import kotlin.test.assertFalse +import kotlin.test.assertTrue + +@RunWith(AndroidJUnit4::class) +@SmallTest +class FullScoreTest { + // Convenience methods + fun FullScore.withPolicies( + validated: Boolean = false, + vpn: Boolean = false, + onceChosen: Boolean = false, + acceptUnvalidated: Boolean = false + ): FullScore { + val nac = NetworkAgentConfig.Builder().apply { + setUnvalidatedConnectivityAcceptable(acceptUnvalidated) + setExplicitlySelected(onceChosen) + }.build() + val nc = NetworkCapabilities.Builder().apply { + if (vpn) addTransportType(NetworkCapabilities.TRANSPORT_VPN) + if (validated) addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) + }.build() + return mixInScore(nc, nac) + } + + @Test + fun testGetLegacyInt() { + val ns = FullScore(50, 0L /* policy */) + assertEquals(10, ns.legacyInt) // -40 penalty for not being validated + assertEquals(50, ns.legacyIntAsValidated) + + val vpnNs = FullScore(101, 0L /* policy */).withPolicies(vpn = true) + assertEquals(101, vpnNs.legacyInt) // VPNs are not subject to unvalidation penalty + assertEquals(101, vpnNs.legacyIntAsValidated) + assertEquals(101, vpnNs.withPolicies(validated = true).legacyInt) + assertEquals(101, vpnNs.withPolicies(validated = true).legacyIntAsValidated) + + val validatedNs = ns.withPolicies(validated = true) + assertEquals(50, validatedNs.legacyInt) // No penalty, this is validated + assertEquals(50, validatedNs.legacyIntAsValidated) + + val chosenNs = ns.withPolicies(onceChosen = true) + assertEquals(10, chosenNs.legacyInt) + assertEquals(100, chosenNs.legacyIntAsValidated) + assertEquals(10, chosenNs.withPolicies(acceptUnvalidated = true).legacyInt) + assertEquals(50, chosenNs.withPolicies(acceptUnvalidated = true).legacyIntAsValidated) + } + + @Test + fun testToString() { + val string = FullScore(10, 0L /* policy */) + .withPolicies(vpn = true, acceptUnvalidated = true).toString() + assertTrue(string.contains("Score(10"), string) + assertTrue(string.contains("ACCEPT_UNVALIDATED"), string) + assertTrue(string.contains("IS_VPN"), string) + assertFalse(string.contains("IS_VALIDATED"), string) + val foundNames = ArraySet<String>() + getAllPolicies().forEach { + val name = FullScore.policyNameOf(it.get() as Int) + assertFalse(TextUtils.isEmpty(name)) + assertFalse(foundNames.contains(name)) + foundNames.add(name) + } + assertFailsWith<IllegalArgumentException> { + FullScore.policyNameOf(MAX_CS_MANAGED_POLICY + 1) + } + } + + fun getAllPolicies() = Regex("POLICY_.*").let { nameRegex -> + FullScore::class.staticProperties.filter { it.name.matches(nameRegex) } + } + + @Test + fun testHasPolicy() { + val ns = FullScore(50, 0L /* policy */) + assertFalse(ns.hasPolicy(POLICY_IS_VALIDATED)) + assertFalse(ns.hasPolicy(POLICY_IS_VPN)) + assertFalse(ns.hasPolicy(POLICY_EVER_USER_SELECTED)) + assertFalse(ns.hasPolicy(POLICY_ACCEPT_UNVALIDATED)) + assertTrue(ns.withPolicies(validated = true).hasPolicy(POLICY_IS_VALIDATED)) + assertTrue(ns.withPolicies(vpn = true).hasPolicy(POLICY_IS_VPN)) + assertTrue(ns.withPolicies(onceChosen = true).hasPolicy(POLICY_EVER_USER_SELECTED)) + assertTrue(ns.withPolicies(acceptUnvalidated = true).hasPolicy(POLICY_ACCEPT_UNVALIDATED)) + } + + @Test + fun testMinMaxPolicyConstants() { + val policies = getAllPolicies() + + policies.forEach { policy -> + assertTrue(policy.get() as Int >= FullScore.MIN_CS_MANAGED_POLICY) + assertTrue(policy.get() as Int <= FullScore.MAX_CS_MANAGED_POLICY) + } + assertEquals(FullScore.MIN_CS_MANAGED_POLICY, + policies.minOfOrNull { it.get() as Int }) + assertEquals(FullScore.MAX_CS_MANAGED_POLICY, + policies.maxOfOrNull { it.get() as Int }) + } +} diff --git a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java index 1c0ba4f8d8f5..9ab60a41a397 100644 --- a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java +++ b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java @@ -40,6 +40,7 @@ import android.net.NetworkAgentConfig; import android.net.NetworkCapabilities; import android.net.NetworkInfo; import android.net.NetworkProvider; +import android.net.NetworkScore; import android.os.Binder; import android.text.format.DateUtils; @@ -355,8 +356,9 @@ public class LingerMonitorTest { caps.addCapability(0); caps.addTransportType(transport); NetworkAgentInfo nai = new NetworkAgentInfo(null, new Network(netId), info, - new LinkProperties(), caps, 50, mCtx, null, new NetworkAgentConfig() /* config */, - mConnService, mNetd, mDnsResolver, NetworkProvider.ID_NONE, Binder.getCallingUid(), + new LinkProperties(), caps, new NetworkScore.Builder().setLegacyInt(50).build(), + mCtx, null, new NetworkAgentConfig.Builder().build(), mConnService, mNetd, + mDnsResolver, NetworkProvider.ID_NONE, Binder.getCallingUid(), mQosCallbackTracker, new ConnectivityService.Dependencies()); nai.everValidated = true; return nai; diff --git a/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java b/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java index ff8c632833f2..3adf08c19986 100644 --- a/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java +++ b/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java @@ -20,6 +20,7 @@ import static com.android.server.connectivity.NetworkNotificationManager.Notific import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyInt; +import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; @@ -35,6 +36,7 @@ import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.res.Resources; +import android.net.ConnectivityResources; import android.net.NetworkCapabilities; import android.net.NetworkInfo; import android.os.UserHandle; @@ -43,9 +45,10 @@ import android.telephony.TelephonyManager; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; -import com.android.internal.R; +import com.android.connectivity.resources.R; import com.android.server.connectivity.NetworkNotificationManager.NotificationType; +import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; @@ -119,11 +122,25 @@ public class NetworkNotificationManagerTest { when(mCtx.getSystemService(eq(Context.NOTIFICATION_SERVICE))) .thenReturn(mNotificationManager); when(mNetworkInfo.getExtraInfo()).thenReturn(TEST_EXTRA_INFO); + ConnectivityResources.setResourcesContextForTest(mCtx); when(mResources.getColor(anyInt(), any())).thenReturn(0xFF607D8B); + // Come up with some credible-looking transport names. The actual values do not matter. + String[] transportNames = new String[NetworkCapabilities.MAX_TRANSPORT + 1]; + for (int transport = 0; transport <= NetworkCapabilities.MAX_TRANSPORT; transport++) { + transportNames[transport] = NetworkCapabilities.transportNameOf(transport); + } + when(mResources.getStringArray(R.array.network_switch_type_name)) + .thenReturn(transportNames); + mManager = new NetworkNotificationManager(mCtx, mTelephonyManager); } + @After + public void tearDown() { + ConnectivityResources.setResourcesContextForTest(null); + } + private void verifyTitleByNetwork(final int id, final NetworkAgentInfo nai, final int title) { final String tag = NetworkNotificationManager.tagFor(id); mManager.showNotification(id, PRIVATE_DNS_BROKEN, nai, null, null, true); @@ -142,15 +159,15 @@ public class NetworkNotificationManagerTest { public void testTitleOfPrivateDnsBroken() { // Test the title of mobile data. verifyTitleByNetwork(100, mCellNai, R.string.mobile_no_internet); - reset(mResources); + clearInvocations(mResources); // Test the title of wifi. verifyTitleByNetwork(101, mWifiNai, R.string.wifi_no_internet); - reset(mResources); + clearInvocations(mResources); // Test the title of other networks. verifyTitleByNetwork(102, mVpnNai, R.string.other_networks_no_internet); - reset(mResources); + clearInvocations(mResources); } @Test diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java index b8f7fbca3983..6ad4900989f5 100644 --- a/tests/net/java/com/android/server/connectivity/VpnTest.java +++ b/tests/net/java/com/android/server/connectivity/VpnTest.java @@ -23,6 +23,7 @@ import static android.content.pm.UserInfo.FLAG_RESTRICTED; import static android.net.ConnectivityManager.NetworkCallback; import static android.net.INetd.IF_STATE_DOWN; import static android.net.INetd.IF_STATE_UP; +import static android.os.UserHandle.PER_USER_RANGE; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; @@ -74,7 +75,6 @@ import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkInfo.DetailedState; import android.net.RouteInfo; -import android.net.UidRange; import android.net.UidRangeParcel; import android.net.VpnManager; import android.net.VpnService; @@ -181,8 +181,7 @@ public class VpnTest { mPackages.put(PKGS[i], PKG_UIDS[i]); } } - private static final UidRange PRI_USER_RANGE = - UidRange.createForUser(UserHandle.of(primaryUser.id)); + private static final Range<Integer> PRI_USER_RANGE = uidRangeForUser(primaryUser.id); @Mock(answer = Answers.RETURNS_DEEP_STUBS) private Context mContext; @Mock private UserManager mUserManager; @@ -260,6 +259,21 @@ public class VpnTest { .thenReturn(tunnelResp); } + private Set<Range<Integer>> rangeSet(Range<Integer> ... ranges) { + final Set<Range<Integer>> range = new ArraySet<>(); + for (Range<Integer> r : ranges) range.add(r); + + return range; + } + + private static Range<Integer> uidRangeForUser(int userId) { + return new Range<Integer>(userId * PER_USER_RANGE, (userId + 1) * PER_USER_RANGE - 1); + } + + private Range<Integer> uidRange(int start, int stop) { + return new Range<Integer>(start, stop); + } + @Test public void testRestrictedProfilesAreAddedToVpn() { setMockedUsers(primaryUser, secondaryUser, restrictedProfileA, restrictedProfileB); @@ -268,12 +282,10 @@ public class VpnTest { // Assume the user can have restricted profiles. doReturn(true).when(mUserManager).canHaveRestrictedProfile(); - final Set<UidRange> ranges = + final Set<Range<Integer>> ranges = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id, null, null); - assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] { - PRI_USER_RANGE, UidRange.createForUser(UserHandle.of(restrictedProfileA.id)) - })), ranges); + assertEquals(rangeSet(PRI_USER_RANGE, uidRangeForUser(restrictedProfileA.id)), ranges); } @Test @@ -281,10 +293,10 @@ public class VpnTest { setMockedUsers(primaryUser, managedProfileA); final Vpn vpn = createVpn(primaryUser.id); - final Set<UidRange> ranges = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id, + final Set<Range<Integer>> ranges = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id, null, null); - assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] { PRI_USER_RANGE })), ranges); + assertEquals(rangeSet(PRI_USER_RANGE), ranges); } @Test @@ -292,35 +304,38 @@ public class VpnTest { setMockedUsers(primaryUser, restrictedProfileA, managedProfileA); final Vpn vpn = createVpn(primaryUser.id); - final Set<UidRange> ranges = new ArraySet<>(); + final Set<Range<Integer>> ranges = new ArraySet<>(); vpn.addUserToRanges(ranges, primaryUser.id, null, null); - assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] { PRI_USER_RANGE })), ranges); + assertEquals(rangeSet(PRI_USER_RANGE), ranges); } @Test public void testUidAllowAndDenylist() throws Exception { final Vpn vpn = createVpn(primaryUser.id); - final UidRange user = PRI_USER_RANGE; + final Range<Integer> user = PRI_USER_RANGE; + final int userStart = user.getLower(); + final int userStop = user.getUpper(); final String[] packages = {PKGS[0], PKGS[1], PKGS[2]}; // Allowed list - final Set<UidRange> allow = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id, - Arrays.asList(packages), null); - assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] { - new UidRange(user.start + PKG_UIDS[0], user.start + PKG_UIDS[0]), - new UidRange(user.start + PKG_UIDS[1], user.start + PKG_UIDS[2]) - })), allow); + final Set<Range<Integer>> allow = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id, + Arrays.asList(packages), null /* disallowedApplications */); + assertEquals(rangeSet( + uidRange(userStart + PKG_UIDS[0], userStart + PKG_UIDS[0]), + uidRange(userStart + PKG_UIDS[1], userStart + PKG_UIDS[2])), + allow); // Denied list - final Set<UidRange> disallow = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id, - null, Arrays.asList(packages)); - assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] { - new UidRange(user.start, user.start + PKG_UIDS[0] - 1), - new UidRange(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[1] - 1), - /* Empty range between UIDS[1] and UIDS[2], should be excluded, */ - new UidRange(user.start + PKG_UIDS[2] + 1, user.stop) - })), disallow); + final Set<Range<Integer>> disallow = + vpn.createUserAndRestrictedProfilesRanges(primaryUser.id, + null /* allowedApplications */, Arrays.asList(packages)); + assertEquals(rangeSet( + uidRange(userStart, userStart + PKG_UIDS[0] - 1), + uidRange(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[1] - 1), + /* Empty range between UIDS[1] and UIDS[2], should be excluded, */ + uidRange(userStart + PKG_UIDS[2] + 1, userStop)), + disallow); } @Test @@ -350,84 +365,86 @@ public class VpnTest { @Test public void testLockdownChangingPackage() throws Exception { final Vpn vpn = createVpn(primaryUser.id); - final UidRange user = PRI_USER_RANGE; - + final Range<Integer> user = PRI_USER_RANGE; + final int userStart = user.getLower(); + final int userStop = user.getUpper(); // Set always-on without lockdown. assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false, null)); // Set always-on with lockdown. assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, null)); verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { - new UidRangeParcel(user.start, user.start + PKG_UIDS[1] - 1), - new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.stop) + new UidRangeParcel(userStart, userStart + PKG_UIDS[1] - 1), + new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStop) })); // Switch to another app. assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true, null)); verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] { - new UidRangeParcel(user.start, user.start + PKG_UIDS[1] - 1), - new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.stop) + new UidRangeParcel(userStart, userStart + PKG_UIDS[1] - 1), + new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStop) })); verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { - new UidRangeParcel(user.start, user.start + PKG_UIDS[3] - 1), - new UidRangeParcel(user.start + PKG_UIDS[3] + 1, user.stop) + new UidRangeParcel(userStart, userStart + PKG_UIDS[3] - 1), + new UidRangeParcel(userStart + PKG_UIDS[3] + 1, userStop) })); } @Test public void testLockdownAllowlist() throws Exception { final Vpn vpn = createVpn(primaryUser.id); - final UidRange user = PRI_USER_RANGE; - + final Range<Integer> user = PRI_USER_RANGE; + final int userStart = user.getLower(); + final int userStop = user.getUpper(); // Set always-on with lockdown and allow app PKGS[2] from lockdown. assertTrue(vpn.setAlwaysOnPackage( PKGS[1], true, Collections.singletonList(PKGS[2]))); - verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { - new UidRangeParcel(user.start, user.start + PKG_UIDS[1] - 1), - new UidRangeParcel(user.start + PKG_UIDS[2] + 1, user.stop) + verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { + new UidRangeParcel(userStart, userStart + PKG_UIDS[1] - 1), + new UidRangeParcel(userStart + PKG_UIDS[2] + 1, userStop) })); // Change allowed app list to PKGS[3]. assertTrue(vpn.setAlwaysOnPackage( PKGS[1], true, Collections.singletonList(PKGS[3]))); verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] { - new UidRangeParcel(user.start + PKG_UIDS[2] + 1, user.stop) + new UidRangeParcel(userStart + PKG_UIDS[2] + 1, userStop) })); verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { - new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.start + PKG_UIDS[3] - 1), - new UidRangeParcel(user.start + PKG_UIDS[3] + 1, user.stop) + new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStart + PKG_UIDS[3] - 1), + new UidRangeParcel(userStart + PKG_UIDS[3] + 1, userStop) })); // Change the VPN app. assertTrue(vpn.setAlwaysOnPackage( PKGS[0], true, Collections.singletonList(PKGS[3]))); verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] { - new UidRangeParcel(user.start, user.start + PKG_UIDS[1] - 1), - new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.start + PKG_UIDS[3] - 1) + new UidRangeParcel(userStart, userStart + PKG_UIDS[1] - 1), + new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStart + PKG_UIDS[3] - 1) })); verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { - new UidRangeParcel(user.start, user.start + PKG_UIDS[0] - 1), - new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[3] - 1) + new UidRangeParcel(userStart, userStart + PKG_UIDS[0] - 1), + new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[3] - 1) })); // Remove the list of allowed packages. assertTrue(vpn.setAlwaysOnPackage(PKGS[0], true, null)); verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] { - new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[3] - 1), - new UidRangeParcel(user.start + PKG_UIDS[3] + 1, user.stop) + new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[3] - 1), + new UidRangeParcel(userStart + PKG_UIDS[3] + 1, userStop) })); verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { - new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.stop), + new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStop), })); // Add the list of allowed packages. assertTrue(vpn.setAlwaysOnPackage( PKGS[0], true, Collections.singletonList(PKGS[1]))); verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] { - new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.stop) + new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStop) })); verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { - new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[1] - 1), - new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.stop) + new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[1] - 1), + new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStop) })); // Try allowing a package with a comma, should be rejected. @@ -439,12 +456,12 @@ public class VpnTest { assertTrue(vpn.setAlwaysOnPackage( PKGS[0], true, Arrays.asList("com.foo.app", PKGS[2], "com.bar.app"))); verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] { - new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[1] - 1), - new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.stop) + new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[1] - 1), + new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStop) })); verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { - new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[2] - 1), - new UidRangeParcel(user.start + PKG_UIDS[2] + 1, user.stop) + new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[2] - 1), + new UidRangeParcel(userStart + PKG_UIDS[2] + 1, userStop) })); } @@ -452,7 +469,7 @@ public class VpnTest { public void testLockdownRuleRepeatability() throws Exception { final Vpn vpn = createVpn(primaryUser.id); final UidRangeParcel[] primaryUserRangeParcel = new UidRangeParcel[] { - new UidRangeParcel(PRI_USER_RANGE.start, PRI_USER_RANGE.stop)}; + new UidRangeParcel(PRI_USER_RANGE.getLower(), PRI_USER_RANGE.getUpper())}; // Given legacy lockdown is already enabled, vpn.setLockdown(true); verify(mConnectivityManager, times(1)).setRequireVpnForUids(true, @@ -484,7 +501,7 @@ public class VpnTest { public void testLockdownRuleReversibility() throws Exception { final Vpn vpn = createVpn(primaryUser.id); final UidRangeParcel[] entireUser = { - new UidRangeParcel(PRI_USER_RANGE.start, PRI_USER_RANGE.stop) + new UidRangeParcel(PRI_USER_RANGE.getLower(), PRI_USER_RANGE.getUpper()) }; final UidRangeParcel[] exceptPkg0 = { new UidRangeParcel(entireUser[0].start, entireUser[0].start + PKG_UIDS[0] - 1), @@ -1026,7 +1043,11 @@ public class VpnTest { .thenReturn(new Network[] { new Network(101) }); when(mConnectivityManager.registerNetworkAgent(any(), any(), any(), any(), - anyInt(), any(), anyInt())).thenReturn(new Network(102)); + any(), any(), anyInt())).thenAnswer(invocation -> { + // The runner has registered an agent and is now ready. + legacyRunnerReady.open(); + return new Network(102); + }); final Vpn vpn = startLegacyVpn(createVpn(primaryUser.id), profile); final TestDeps deps = (TestDeps) vpn.mDeps; try { @@ -1048,7 +1069,7 @@ public class VpnTest { ArgumentCaptor<NetworkCapabilities> ncCaptor = ArgumentCaptor.forClass(NetworkCapabilities.class); verify(mConnectivityManager, timeout(10_000)).registerNetworkAgent(any(), any(), - lpCaptor.capture(), ncCaptor.capture(), anyInt(), any(), anyInt()); + lpCaptor.capture(), ncCaptor.capture(), any(), any(), anyInt()); // In this test the expected address is always v4 so /32. // Note that the interface needs to be specified because RouteInfo objects stored in diff --git a/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java b/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java index 5b17aadc50a6..8a0c923d5fb0 100644 --- a/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java +++ b/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java @@ -109,16 +109,6 @@ public class VcnGatewayConnectionConfigTest { } @Test - public void testBuilderRequiresNonEmptyUnderlyingCaps() { - try { - newBuilder().addExposedCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET).build(); - - fail("Expected exception due to invalid required underlying capabilities"); - } catch (IllegalArgumentException e) { - } - } - - @Test public void testBuilderRequiresNonNullRetryInterval() { try { newBuilder().setRetryInterval(null); diff --git a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java index a02002752c38..a9d5822be226 100644 --- a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java +++ b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java @@ -32,9 +32,8 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.anyBoolean; import static org.mockito.Mockito.argThat; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doNothing; @@ -74,7 +73,7 @@ import android.telephony.TelephonyManager; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; -import com.android.internal.util.LocationPermissionChecker; +import com.android.net.module.util.LocationPermissionChecker; import com.android.server.VcnManagementService.VcnCallback; import com.android.server.VcnManagementService.VcnStatusCallbackInfo; import com.android.server.vcn.TelephonySubscriptionTracker; @@ -656,7 +655,7 @@ public class VcnManagementServiceTest { .setNetworkSpecifier(new TelephonyNetworkSpecifier(TEST_SUBSCRIPTION_ID)); } else if (transport == TRANSPORT_WIFI) { WifiInfo wifiInfo = mock(WifiInfo.class); - when(wifiInfo.makeCopy(anyBoolean())).thenReturn(wifiInfo); + when(wifiInfo.makeCopy(anyLong())).thenReturn(wifiInfo); when(mMockDeps.getSubIdForWifiInfo(eq(wifiInfo))).thenReturn(TEST_SUBSCRIPTION_ID); ncBuilder diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java index 0e5f5e43f282..ca6448ca9b8c 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java +++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java @@ -188,7 +188,7 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection any(), lpCaptor.capture(), ncCaptor.capture(), - anyInt(), + any(), any(), anyInt()); verify(mIpSecSvc) |