Merge "Use source for keystore/keymint interfaces."
diff --git a/StubLibraries.bp b/StubLibraries.bp
index d866116..fd614a7e3 100644
--- a/StubLibraries.bp
+++ b/StubLibraries.bp
@@ -422,10 +422,6 @@
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 @@
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 565ed95..15e5e84 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.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 @@
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/core/api/current.txt b/core/api/current.txt
index 0e7ecef..07bebbe 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -7999,13 +7999,13 @@
}
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 @@
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 @@
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 @@
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 @@
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[]);
}
@@ -39095,7 +39096,6 @@
method public static boolean isConfigForIdentifiedCarrier(android.os.PersistableBundle);
method public void notifyConfigChangedForSubId(int);
field public static final String ACTION_CARRIER_CONFIG_CHANGED = "android.telephony.action.CARRIER_CONFIG_CHANGED";
- field public static final int CARRIER_NR_AVAILABILITY_NONE = 0; // 0x0
field public static final int CARRIER_NR_AVAILABILITY_NSA = 1; // 0x1
field public static final int CARRIER_NR_AVAILABILITY_SA = 2; // 0x2
field public static final int DATA_CYCLE_THRESHOLD_DISABLED = -2; // 0xfffffffe
@@ -39156,7 +39156,7 @@
field public static final String KEY_CARRIER_INSTANT_LETTERING_LENGTH_LIMIT_INT = "carrier_instant_lettering_length_limit_int";
field public static final String KEY_CARRIER_NAME_OVERRIDE_BOOL = "carrier_name_override_bool";
field public static final String KEY_CARRIER_NAME_STRING = "carrier_name_string";
- field public static final String KEY_CARRIER_NR_AVAILABILITY_INT = "carrier_nr_availability_int";
+ field public static final String KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY = "carrier_nr_availabilities_int_array";
field public static final String KEY_CARRIER_RCS_PROVISIONING_REQUIRED_BOOL = "carrier_rcs_provisioning_required_bool";
field public static final String KEY_CARRIER_SETTINGS_ACTIVITY_COMPONENT_NAME_STRING = "carrier_settings_activity_component_name_string";
field public static final String KEY_CARRIER_SETTINGS_ENABLE_BOOL = "carrier_settings_enable_bool";
@@ -39225,6 +39225,7 @@
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 +39305,7 @@
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 +39348,7 @@
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 +40908,10 @@
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);
}
@@ -41018,6 +41025,7 @@
method @Deprecated public String iccTransmitApduBasicChannel(int, int, int, int, int, String);
method @Deprecated public String iccTransmitApduLogicalChannel(int, int, int, int, int, int, String);
method public boolean isConcurrentVoiceAndDataSupported();
+ method public boolean isDataCapable();
method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_NETWORK_STATE, android.Manifest.permission.READ_PHONE_STATE, "android.permission.READ_PRIVILEGED_PHONE_STATE"}) public boolean isDataConnectionAllowed();
method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_NETWORK_STATE, android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isDataEnabled();
method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_NETWORK_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isDataEnabledForReason(int);
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt
index 992b57f..f155a5f 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -22,6 +22,10 @@
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 @@
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 @@
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 @@
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 da56f45..92c18c6 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -113,6 +113,7 @@
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.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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
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
@@ -10229,6 +10334,7 @@
field public static final String CAPABILITY_ALLOWED_NETWORK_TYPES_USED = "CAPABILITY_ALLOWED_NETWORK_TYPES_USED";
field public static final String CAPABILITY_NR_DUAL_CONNECTIVITY_CONFIGURATION_AVAILABLE = "CAPABILITY_NR_DUAL_CONNECTIVITY_CONFIGURATION_AVAILABLE";
field public static final String CAPABILITY_SECONDARY_LINK_BANDWIDTH_VISIBLE = "CAPABILITY_SECONDARY_LINK_BANDWIDTH_VISIBLE";
+ field public static final String CAPABILITY_THERMAL_MITIGATION_DATA_THROTTLING = "CAPABILITY_THERMAL_MITIGATION_DATA_THROTTLING";
field public static final int CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES = -2; // 0xfffffffe
field public static final int CARRIER_PRIVILEGE_STATUS_HAS_ACCESS = 1; // 0x1
field public static final int CARRIER_PRIVILEGE_STATUS_NO_ACCESS = 0; // 0x0
@@ -10382,6 +10488,16 @@
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 a0ff97e..11df058 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -996,6 +996,8 @@
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 098d8b6..9f1132b 100644
--- a/core/java/android/app/usage/NetworkStatsManager.java
+++ b/core/java/android/app/usage/NetworkStatsManager.java
@@ -24,6 +24,7 @@
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 @@
* 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 @@
* @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 @@
* 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 @@
* @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 @@
* 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 @@
* @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 @@
/**
* 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 @@
/**
* 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 @@
* <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 @@
* @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 @@
* <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 @@
* @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 7281d50..de77848 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 @@
* @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 @@
* @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 @@
* @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 @@
* @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 @@
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 6a068ee..afdb3fe 100644
--- a/core/java/android/apphibernation/IAppHibernationService.aidl
+++ b/core/java/android/apphibernation/IAppHibernationService.aidl
@@ -25,4 +25,5 @@
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 cc0b22a..38863c2 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -52,6 +52,8 @@
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 @@
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 89030bc..c30b8af 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -1002,6 +1002,24 @@
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 @@
private static volatile IBluetooth sService;
private final String mAddress;
+ @AddressType private final int mAddressType;
/*package*/
@UnsupportedAppUsage
@@ -1064,6 +1083,7 @@
}
mAddress = address;
+ mAddressType = ADDRESS_TYPE_PUBLIC;
}
@Override
@@ -1279,7 +1299,6 @@
* 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 @@
* @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 @@
* <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 @@
}
/**
- * 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 0d0c6ab..08d694e 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 {
- public byte[] getLeBluetoothDeviceAddress() {
- return mLeBluetoothDeviceAddress;
+ 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);
}
/**
- * 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.
+ * 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
*/
- public void setLeBluetoothDeviceAddress(byte[] leBluetoothDeviceAddress) {
- mLeBluetoothDeviceAddress = leBluetoothDeviceAddress;
- }
-
- public byte[] getSecurityManagerTk() {
- return mSecurityManagerTk;
+ @NonNull
+ @SystemApi
+ public static LeBuilder createLeBuilder(@NonNull byte[] confirmationHash,
+ @NonNull byte[] deviceAddressWithType, @LeRole int leDeviceRole) {
+ return new LeBuilder(confirmationHash, deviceAddressWithType, leDeviceRole);
}
/**
- * 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.
+ * Builds an {@link OobData} object and validates that the required combination
+ * of values are present to create the LE specific OobData type.
+ *
+ * @hide
*/
- public void setSecurityManagerTk(byte[] securityManagerTk) {
- mSecurityManagerTk = securityManagerTk;
+ @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;
+ }
}
- public byte[] getLeSecureConnectionsConfirmation() {
- return mLeSecureConnectionsConfirmation;
+ /**
+ * 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;
+ }
+
+ /**
+ * @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;
+ }
}
- public void setLeSecureConnectionsConfirmation(byte[] leSecureConnectionsConfirmation) {
- mLeSecureConnectionsConfirmation = leSecureConnectionsConfirmation;
+ // 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;
}
- public byte[] getLeSecureConnectionsRandom() {
- return mLeSecureConnectionsRandom;
+ /**
+ * @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;
}
- public void setLeSecureConnectionsRandom(byte[] leSecureConnectionsRandom) {
- mLeSecureConnectionsRandom = leSecureConnectionsRandom;
+ /**
+ * @return byte array representing the randomizerHash value
+ * which is used to verify the identity of the controller.
+ *
+ * @hide
+ */
+ @NonNull
+ @SystemApi
+ public byte[] getRandomizerHash() {
+ return mRandomizerHash;
}
- public OobData() {
+ /**
+ * @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;
+ }
+
+ /**
+ * @return Temporary Key used for LE pairing.
+ *
+ * @hide
+ */
+ @Nullable
+ @SystemApi
+ public byte[] getLeTemporaryKey() {
+ return mLeTemporaryKey;
+ }
+
+ /**
+ * @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;
+ }
+
+ /**
+ * @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;
+ }
+
+ /**
+ * @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;
+ }
+
+ /**
+ * Classic Security Constructor
+ */
+ private OobData(@NonNull byte[] classicLength, @NonNull byte[] deviceAddressWithType,
+ @NonNull byte[] confirmationHash) {
+ mClassicLength = classicLength;
+ mDeviceAddressWithType = deviceAddressWithType;
+ mConfirmationHash = confirmationHash;
+ mLeDeviceRole = -1; // Satisfy final
+ }
+
+ /**
+ * 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 @@
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 7511fd0..8672150 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 @@
@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 @@
/** @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 @@
mManufacturerId = manufacturerId;
mManufacturerData = manufacturerData;
mManufacturerDataMask = manufacturerDataMask;
+ mAddressType = addressType;
+ mIrk = irk;
}
@Override
@@ -280,6 +291,23 @@
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 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 @@
*
* @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 @@
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 504118e..368d1ee 100644
--- a/core/java/android/bluetooth/le/ScanSettings.java
+++ b/core/java/android/bluetooth/le/ScanSettings.java
@@ -52,6 +52,16 @@
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 @@
* @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 32aa037..d21462e 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -744,7 +744,7 @@
// 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 @@
* 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 @@
* @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 aa61279..fe9ed27 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -4099,7 +4099,8 @@
* @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 7f834af..933dee3 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -2024,7 +2024,9 @@
// 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 dfb1e99..00c6913 100644
--- a/core/java/android/net/INetworkPolicyListener.aidl
+++ b/core/java/android/net/INetworkPolicyListener.aidl
@@ -25,4 +25,5 @@
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 9bf791b..171c6a2 100644
--- a/core/java/android/net/INetworkPolicyManager.aidl
+++ b/core/java/android/net/INetworkPolicyManager.aidl
@@ -62,6 +62,7 @@
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 1c56954..10be02c 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -23,6 +23,7 @@
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.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.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 @@
* @hide
*/
@TestApi
+@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
@SystemService(Context.NETWORK_POLICY_SERVICE)
public class NetworkPolicyManager {
@@ -198,12 +203,171 @@
})
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;
+ /**
+ * Flag to indicate that app is exempt from certain metered network restrictions because of it
+ * being a system component.
+ *
+ * @hide
+ */
+ public static final int ALLOWED_METERED_REASON_SYSTEM = 1 << 17;
+ /**
+ * Flag to indicate that app is exempt from certain metered network restrictions because of it
+ * being in the foreground.
+ *
+ * @hide
+ */
+ public static final int ALLOWED_METERED_REASON_FOREGROUND = 1 << 18;
+
+ /** @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 +482,7 @@
}
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 +495,7 @@
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 +543,26 @@
}
/**
+ * 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 +644,8 @@
* @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 +684,8 @@
*
* @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 +695,15 @@
}
/**
- * 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 +875,142 @@
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 +1065,7 @@
@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 77754d1..5f65d46 100644
--- a/core/java/android/net/VpnManager.java
+++ b/core/java/android/net/VpnManager.java
@@ -86,13 +86,21 @@
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 9f83b21..d4e8e2d 100644
--- a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
+++ b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
@@ -52,13 +52,12 @@
* 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 @@
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 @@
*
* @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 @@
* @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 @@
* @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 062438c..b73fdbf 100644
--- a/core/java/android/net/vcn/VcnManager.java
+++ b/core/java/android/net/vcn/VcnManager.java
@@ -448,7 +448,7 @@
* @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 d7d3e58..189a8ac 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -138,7 +138,7 @@
*/
@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 @@
}
/**
+ * 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 8c2ca6d..9d16f18 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 @@
* @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 9cb76c1..753abea 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -5284,7 +5284,8 @@
* 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 0ae5ed7..bbb1d0ca 100644
--- a/core/java/android/telephony/PhoneStateListener.java
+++ b/core/java/android/telephony/PhoneStateListener.java
@@ -21,7 +21,6 @@
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 @@
// 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 @@
// 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 a2584cae..e49c82c 100644
--- a/core/java/android/telephony/TelephonyCallback.java
+++ b/core/java/android/telephony/TelephonyCallback.java
@@ -24,7 +24,6 @@
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 @@
/**
* 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 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 @@
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 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 @@
/**
* 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 @@
@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 @@
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 15d1a59..b111ec3 100644
--- a/core/java/android/telephony/TelephonyRegistryManager.java
+++ b/core/java/android/telephony/TelephonyRegistryManager.java
@@ -825,24 +825,40 @@
}
/**
- * 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 @@
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 718076b..64570a8 100644
--- a/core/java/android/widget/OWNERS
+++ b/core/java/android/widget/OWNERS
@@ -5,6 +5,8 @@
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 7ade05c..e6c911e 100644
--- a/core/java/com/android/internal/app/OWNERS
+++ b/core/java/com/android/internal/app/OWNERS
@@ -3,6 +3,9 @@
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 c220428..5fea76a 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.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.InputStreamReader;
import java.security.Provider;
import java.security.Security;
-import java.util.Optional;
/**
* Startup class for the zygote process.
@@ -227,17 +225,7 @@
// 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 ee94ef8..b90722c 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.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 @@
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 8d69158..0e35c84 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.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 @@
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 d67bd7a..0000000
--- 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 276cad9..bbd738b 100644
--- a/core/java/com/android/internal/util/Protocol.java
+++ b/core/java/com/android/internal/util/Protocol.java
@@ -59,8 +59,6 @@
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 0000000..edfb211
--- /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 065c79b..452f55a 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -1419,6 +1419,42 @@
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 @@
(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 04faebc..6374305 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 @@
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 0000000..edb6c04
--- /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 0041f19..57b9f71 100644
--- a/core/proto/android/net/networkrequest.proto
+++ b/core/proto/android/net/networkrequest.proto
@@ -20,8 +20,8 @@
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 e97b1a8..64cf75d 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/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 b64e685..0000000
--- 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 0000000..dd313aa
--- /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 2f352e9..61e7d0a 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 22a79ed..0f6f15d 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 fc75463..ad24b79 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 7175f56..0000000
--- 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 354d83c..653e690 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -451,6 +451,7 @@
<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 937f01c..a08f390 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -207,7 +207,7 @@
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/keystore/AttestationUtils.java b/keystore/java/android/security/keystore/AttestationUtils.java
index 11c3689..1eb8541 100644
--- a/keystore/java/android/security/keystore/AttestationUtils.java
+++ b/keystore/java/android/security/keystore/AttestationUtils.java
@@ -287,6 +287,8 @@
keyStore.deleteEntry(keystoreAlias);
return certificateChain;
+ } catch (SecurityException e) {
+ throw e;
} catch (Exception e) {
throw new DeviceIdAttestationException("Unable to perform attestation", e);
}
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java b/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java
index 2ee952c..9d8a5ef 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java
@@ -123,8 +123,9 @@
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 @@
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 @@
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 fa852e3..ba6d22f 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java
@@ -145,23 +145,15 @@
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 446e81e..c6ab119 100644
--- a/libs/hwui/Properties.cpp
+++ b/libs/hwui/Properties.cpp
@@ -124,7 +124,7 @@
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 d3ecb54d..6ea208e 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -160,7 +160,7 @@
/**
* 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 1b05c3b..b265ebf 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -2077,6 +2077,65 @@
}
/**
+ * 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 @@
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 f65dfdd..517e192 100644
--- a/media/jni/Android.bp
+++ b/media/jni/Android.bp
@@ -19,6 +19,7 @@
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 694b939..3976086e 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -287,7 +287,10 @@
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 @@
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 @@
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_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 8b84bf3..309d71c 100644
--- a/media/jni/soundpool/StreamManager.cpp
+++ b/media/jni/soundpool/StreamManager.cpp
@@ -43,6 +43,14 @@
// 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 @@
: 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 @@
});
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::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 @@
}
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 @@
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 81ac69e..85b468c 100644
--- a/media/jni/soundpool/StreamManager.h
+++ b/media/jni/soundpool/StreamManager.h
@@ -437,6 +437,14 @@
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 @@
// 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 6fab9e4..550e324 100644
--- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java
@@ -86,7 +86,7 @@
@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 @@
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 78a02d7..43ca739 100644
--- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/ProvisionObserver.java
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/ProvisionObserver.java
@@ -49,7 +49,7 @@
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/TEST_MAPPING b/packages/Connectivity/TEST_MAPPING
new file mode 100644
index 0000000..94f9232
--- /dev/null
+++ b/packages/Connectivity/TEST_MAPPING
@@ -0,0 +1,19 @@
+{
+ "imports": [
+ {
+ "path": "frameworks/base/core/java/android/net"
+ },
+ {
+ "path": "packages/modules/NetworkStack"
+ },
+ {
+ "path": "packages/modules/CaptivePortalLogin"
+ },
+ {
+ "path": "packages/modules/Connectivity"
+ },
+ {
+ "path": "packages/modules/Connectivity/Tethering"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/packages/Connectivity/framework/Android.bp b/packages/Connectivity/framework/Android.bp
index 9da27d2..017ff51 100644
--- a/packages/Connectivity/framework/Android.bp
+++ b/packages/Connectivity/framework/Android.bp
@@ -23,7 +23,25 @@
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 @@
],
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/src/android/net/IOnSetOemNetworkPreferenceListener.aidl b/packages/Connectivity/framework/aidl-export/android/net/NetworkScore.aidl
similarity index 79%
copy from packages/Connectivity/framework/src/android/net/IOnSetOemNetworkPreferenceListener.aidl
copy to packages/Connectivity/framework/aidl-export/android/net/NetworkScore.aidl
index 7979afc..af12dcf 100644
--- a/packages/Connectivity/framework/src/android/net/IOnSetOemNetworkPreferenceListener.aidl
+++ b/packages/Connectivity/framework/aidl-export/android/net/NetworkScore.aidl
@@ -1,6 +1,5 @@
/**
- *
- * Copyright (C) 2021 The Android Open Source Project
+ * 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.
@@ -17,7 +16,5 @@
package android.net;
-/** @hide */
-oneway interface IOnSetOemNetworkPreferenceListener {
- void onComplete();
-}
+parcelable NetworkScore;
+
diff --git a/packages/Connectivity/framework/api/current.txt b/packages/Connectivity/framework/api/current.txt
index 243e4ca..e415e01 100644
--- a/packages/Connectivity/framework/api/current.txt
+++ b/packages/Connectivity/framework/api/current.txt
@@ -87,6 +87,7 @@
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 @@
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 4b33366..aa7a0ac 100644
--- a/packages/Connectivity/framework/api/module-lib-current.txt
+++ b/packages/Connectivity/framework/api/module-lib-current.txt
@@ -6,11 +6,26 @@
}
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 @@
}
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 @@
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 a98f14e..703fca4 100644
--- a/packages/Connectivity/framework/api/system-current.txt
+++ b/packages/Connectivity/framework/api/system-current.txt
@@ -18,7 +18,7 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
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 0000000..37b4dec1
--- /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 0000000..0959840
--- /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 eafda4d..82dbd0f 100644
--- a/packages/Connectivity/framework/src/android/net/CaptivePortalData.java
+++ b/packages/Connectivity/framework/src/android/net/CaptivePortalData.java
@@ -42,7 +42,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
* 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 @@
* Get the venue friendly name
*/
@Nullable
- public String getVenueFriendlyName() {
+ public CharSequence getVenueFriendlyName() {
return mVenueFriendlyName;
}
diff --git a/packages/Connectivity/framework/src/android/net/ConnectivityDiagnosticsManager.java b/packages/Connectivity/framework/src/android/net/ConnectivityDiagnosticsManager.java
index 5234494..3598ebc 100644
--- a/packages/Connectivity/framework/src/android/net/ConnectivityDiagnosticsManager.java
+++ b/packages/Connectivity/framework/src/android/net/ConnectivityDiagnosticsManager.java
@@ -28,7 +28,6 @@
import android.os.RemoteException;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.Preconditions;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -70,8 +69,8 @@
/** @hide */
public ConnectivityDiagnosticsManager(Context context, IConnectivityManager service) {
- mContext = Preconditions.checkNotNull(context, "missing context");
- mService = Preconditions.checkNotNull(service, "missing IConnectivityManager");
+ mContext = Objects.requireNonNull(context, "missing context");
+ mService = Objects.requireNonNull(service, "missing IConnectivityManager");
}
/** @hide */
diff --git a/packages/Connectivity/framework/src/android/net/ConnectivityManager.java b/packages/Connectivity/framework/src/android/net/ConnectivityManager.java
index 8c66db9..30ccb20 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.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,18 @@
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 +804,27 @@
/**
* @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 +839,6 @@
private final Context mContext;
- private INetworkPolicyManager mNPManager;
private final TetheringManager mTetheringManager;
/**
@@ -907,8 +911,8 @@
/**
* @hide
- * TODO: Expose for SystemServer when becomes a module.
*/
+ @SystemApi(client = MODULE_LIBRARIES)
public void systemReady() {
try {
mService.systemReady();
@@ -963,6 +967,33 @@
}
/**
+ * 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.
*
@@ -1742,7 +1773,9 @@
// Map from type to transports.
final int NOT_FOUND = -1;
final int transport = sLegacyTypeToTransport.get(type, NOT_FOUND);
- Preconditions.checkArgument(transport != NOT_FOUND, "unknown legacy type: " + type);
+ if (transport == NOT_FOUND) {
+ throw new IllegalArgumentException("unknown legacy type: " + type);
+ }
nc.addTransportType(transport);
// Map from type to capabilities.
@@ -1847,8 +1880,8 @@
}
private PacketKeepalive(Network network, PacketKeepaliveCallback callback) {
- Preconditions.checkNotNull(network, "network cannot be null");
- Preconditions.checkNotNull(callback, "callback cannot be null");
+ Objects.requireNonNull(network, "network cannot be null");
+ Objects.requireNonNull(callback, "callback cannot be null");
mNetwork = network;
mExecutor = Executors.newSingleThreadExecutor();
mCallback = new ISocketKeepaliveCallback.Stub() {
@@ -2223,7 +2256,9 @@
*/
public void removeDefaultNetworkActiveListener(@NonNull OnNetworkActiveListener l) {
INetworkActivityListener rl = mNetworkActivityListeners.get(l);
- Preconditions.checkArgument(rl != null, "Listener was not registered.");
+ if (rl == null) {
+ throw new IllegalArgumentException("Listener was not registered.");
+ }
try {
mService.registerNetworkActivityListener(rl);
} catch (RemoteException e) {
@@ -2251,8 +2286,8 @@
* {@hide}
*/
public ConnectivityManager(Context context, IConnectivityManager service) {
- mContext = Preconditions.checkNotNull(context, "missing context");
- mService = Preconditions.checkNotNull(service, "missing IConnectivityManager");
+ mContext = Objects.requireNonNull(context, "missing context");
+ mService = Objects.requireNonNull(service, "missing IConnectivityManager");
mTetheringManager = (TetheringManager) mContext.getSystemService(Context.TETHERING_SERVICE);
sInstance = this;
}
@@ -2519,7 +2554,7 @@
@RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
public void startTethering(int type, boolean showProvisioningUi,
final OnStartTetheringCallback callback, Handler handler) {
- Preconditions.checkNotNull(callback, "OnStartTetheringCallback cannot be null.");
+ Objects.requireNonNull(callback, "OnStartTetheringCallback cannot be null.");
final Executor executor = new Executor() {
@Override
@@ -2612,7 +2647,7 @@
public void registerTetheringEventCallback(
@NonNull @CallbackExecutor Executor executor,
@NonNull final OnTetheringEventCallback callback) {
- Preconditions.checkNotNull(callback, "OnTetheringEventCallback cannot be null.");
+ Objects.requireNonNull(callback, "OnTetheringEventCallback cannot be null.");
final TetheringEventCallback tetherCallback =
new TetheringEventCallback() {
@@ -2910,7 +2945,7 @@
public void getLatestTetheringEntitlementResult(int type, boolean showEntitlementUi,
@NonNull @CallbackExecutor Executor executor,
@NonNull final OnTetheringEntitlementResultListener listener) {
- Preconditions.checkNotNull(listener, "TetheringEntitlementResultListener cannot be null.");
+ Objects.requireNonNull(listener, "TetheringEntitlementResultListener cannot be null.");
ResultReceiver wrappedListener = new ResultReceiver(null) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
@@ -3003,8 +3038,9 @@
* 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 +3055,8 @@
* if no global HTTP proxy is set.
* @hide
*/
+ @SystemApi(client = MODULE_LIBRARIES)
+ @Nullable
public ProxyInfo getGlobalProxy() {
try {
return mService.getGlobalProxy();
@@ -3205,10 +3243,6 @@
}
}
- // 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.
@@ -3218,20 +3252,8 @@
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.
- * @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, 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) {
@@ -3296,7 +3318,9 @@
}
public NetworkCallback(@Flag int flags) {
- Preconditions.checkArgument((flags & VALID_FLAGS) == flags);
+ if ((flags & VALID_FLAGS) != flags) {
+ throw new IllegalArgumentException("Invalid flags");
+ }
mFlags = flags;
}
@@ -3531,29 +3555,28 @@
}
}
- 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) {
@@ -3583,7 +3606,7 @@
}
CallbackHandler(Handler handler) {
- this(Preconditions.checkNotNull(handler, "Handler cannot be null.").getLooper());
+ this(Objects.requireNonNull(handler, "Handler cannot be null.").getLooper());
}
@Override
@@ -3681,9 +3704,9 @@
int timeoutMs, NetworkRequest.Type reqType, int legacyType, CallbackHandler handler) {
printStackTrace();
checkCallbackNotNull(callback);
- Preconditions.checkArgument(
- reqType == TRACK_DEFAULT || reqType == TRACK_SYSTEM_DEFAULT || need != null,
- "null NetworkCapabilities");
+ if (reqType != TRACK_DEFAULT && reqType != TRACK_SYSTEM_DEFAULT && need == null) {
+ throw new IllegalArgumentException("null NetworkCapabilities");
+ }
final NetworkRequest request;
final String callingPackageName = mContext.getOpPackageName();
try {
@@ -4030,15 +4053,17 @@
}
private static void checkPendingIntentNotNull(PendingIntent intent) {
- Preconditions.checkNotNull(intent, "PendingIntent cannot be null.");
+ Objects.requireNonNull(intent, "PendingIntent cannot be null.");
}
private static void checkCallbackNotNull(NetworkCallback callback) {
- Preconditions.checkNotNull(callback, "null NetworkCallback");
+ Objects.requireNonNull(callback, "null NetworkCallback");
}
private static void checkTimeout(int timeoutMs) {
- Preconditions.checkArgumentPositive(timeoutMs, "timeoutMs must be strictly positive.");
+ if (timeoutMs <= 0) {
+ throw new IllegalArgumentException("timeoutMs must be strictly positive.");
+ }
}
/**
@@ -4249,15 +4274,33 @@
}
/**
- * @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);
}
/**
@@ -4300,8 +4343,9 @@
// Find all requests associated to this callback and stop callback triggers immediately.
// Callback is reusable immediately. http://b/20701525, http://b/35921499.
synchronized (sCallbacks) {
- Preconditions.checkArgument(networkCallback.networkRequest != null,
- "NetworkCallback was not registered");
+ if (networkCallback.networkRequest == null) {
+ throw new IllegalArgumentException("NetworkCallback was not registered");
+ }
if (networkCallback.networkRequest == ALREADY_UNREGISTERED) {
Log.d(TAG, "NetworkCallback was already unregistered");
return;
@@ -4352,8 +4396,13 @@
*
* @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 +4424,14 @@
*
* @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 +4449,13 @@
*
* @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 +4466,20 @@
/**
* 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 +4593,10 @@
* 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 +4674,7 @@
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 +4799,6 @@
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 +4809,7 @@
*/
public @RestrictBackgroundStatus int getRestrictBackgroundStatus() {
try {
- return getNetworkPolicyManager().getRestrictBackgroundByCaller();
+ return mService.getRestrictBackgroundStatusByCaller();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -4879,20 +4939,20 @@
* {@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 +5117,6 @@
}
/**
- * 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 +5138,16 @@
@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 +5159,56 @@
}
}
+ /**
+ * 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 +5221,25 @@
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 0000000..18f0de0
--- /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 0000000..bbd8393
--- /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 f9393e3..3300fa8 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.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.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.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 @@
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 @@
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
similarity index 94%
rename from packages/Connectivity/framework/src/com/android/connectivity/aidl/INetworkAgent.aidl
rename to packages/Connectivity/framework/src/android/net/INetworkAgent.aidl
index 64b5567..1f66e18 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
similarity index 90%
rename from packages/Connectivity/framework/src/com/android/connectivity/aidl/INetworkAgentRegistry.aidl
rename to packages/Connectivity/framework/src/android/net/INetworkAgentRegistry.aidl
index f0193db..c5464d3 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 @@
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
similarity index 92%
rename from packages/Connectivity/framework/src/android/net/IOnSetOemNetworkPreferenceListener.aidl
rename to packages/Connectivity/framework/src/android/net/IOnCompleteListener.aidl
index 7979afc..4bb89f6c 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 0000000..6b7e75c
--- /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/MacAddress.java b/packages/Connectivity/framework/src/android/net/MacAddress.java
index c83c23a..26a504a 100644
--- a/packages/Connectivity/framework/src/android/net/MacAddress.java
+++ b/packages/Connectivity/framework/src/android/net/MacAddress.java
@@ -25,7 +25,6 @@
import android.os.Parcel;
import android.os.Parcelable;
-import com.android.internal.util.Preconditions;
import com.android.net.module.util.MacAddressUtils;
import java.lang.annotation.Retention;
@@ -34,6 +33,7 @@
import java.net.UnknownHostException;
import java.security.SecureRandom;
import java.util.Arrays;
+import java.util.Objects;
/**
* Representation of a MAC address.
@@ -229,7 +229,7 @@
* @hide
*/
public static @NonNull byte[] byteAddrFromStringAddr(String addr) {
- Preconditions.checkNotNull(addr);
+ Objects.requireNonNull(addr);
String[] parts = addr.split(":");
if (parts.length != ETHER_ADDR_LEN) {
throw new IllegalArgumentException(addr + " was not a valid MAC address");
@@ -275,7 +275,7 @@
// Internal conversion function equivalent to longAddrFromByteAddr(byteAddrFromStringAddr(addr))
// that avoids the allocation of an intermediary byte[].
private static long longAddrFromStringAddr(String addr) {
- Preconditions.checkNotNull(addr);
+ Objects.requireNonNull(addr);
String[] parts = addr.split(":");
if (parts.length != ETHER_ADDR_LEN) {
throw new IllegalArgumentException(addr + " was not a valid MAC address");
@@ -364,8 +364,8 @@
*
*/
public boolean matches(@NonNull MacAddress baseAddress, @NonNull MacAddress mask) {
- Preconditions.checkNotNull(baseAddress);
- Preconditions.checkNotNull(mask);
+ Objects.requireNonNull(baseAddress);
+ Objects.requireNonNull(mask);
return (mAddr & mask.mAddr) == (baseAddress.mAddr & mask.mAddr);
}
diff --git a/packages/Connectivity/framework/src/android/net/Network.java b/packages/Connectivity/framework/src/android/net/Network.java
index 46141e0..0741414 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.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 @@
* @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 @@
* 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 @@
// 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 27aa15d..3863ed1 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.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 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 @@
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 @@
* @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 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 @@
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 @@
}
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 @@
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 664c265..5e50a64 100644
--- a/packages/Connectivity/framework/src/android/net/NetworkAgentConfig.java
+++ b/packages/Connectivity/framework/src/android/net/NetworkAgentConfig.java
@@ -50,7 +50,8 @@
* 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 058f3c9..c9c0940 100644
--- a/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java
+++ b/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java
@@ -19,9 +19,11 @@
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,10 +34,10 @@
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;
-import com.android.internal.util.Preconditions;
import com.android.net.module.util.CollectionUtils;
import com.android.net.module.util.NetworkCapabilitiesUtils;
@@ -63,6 +65,68 @@
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 +141,31 @@
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 +177,13 @@
* @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 +213,12 @@
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 +674,8 @@
* 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 +1521,8 @@
* @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 +1531,34 @@
* 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
+ */
+ @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> getUids() {
- return null == mUids ? null : new ArraySet<>(mUids);
+ public @Nullable Set<UidRange> getUidRanges() {
+ if (mUids == null) return null;
+
+ return new ArraySet<>(mUids);
}
/**
@@ -2099,8 +2173,9 @@
}
private static void checkValidTransportType(@Transport int transport) {
- Preconditions.checkArgument(
- isValidTransport(transport), "Invalid TransportType " + transport);
+ if (!isValidTransport(transport)) {
+ throw new IllegalArgumentException("Invalid TransportType " + transport);
+ }
}
private static boolean isValidCapability(@NetworkCapabilities.NetCapability int capability) {
@@ -2108,8 +2183,9 @@
}
private static void checkValidCapability(@NetworkCapabilities.NetCapability int capability) {
- Preconditions.checkArgument(isValidCapability(capability),
- "NetworkCapability " + capability + "out of range");
+ if (!isValidCapability(capability)) {
+ throw new IllegalArgumentException("NetworkCapability " + capability + "out of range");
+ }
}
/**
@@ -2338,6 +2414,23 @@
}
/**
+ * 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 +2748,21 @@
}
/**
+ * 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 3fd95ee..cf131f0 100644
--- a/packages/Connectivity/framework/src/android/net/NetworkRequest.java
+++ b/packages/Connectivity/framework/src/android/net/NetworkRequest.java
@@ -36,6 +36,7 @@
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.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 @@
REQUEST,
BACKGROUND_REQUEST,
TRACK_SYSTEM_DEFAULT,
- TRACK_BEST,
+ LISTEN_FOR_BEST,
};
/**
@@ -277,11 +279,14 @@
* 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 @@
}
/**
+ * 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 0000000..eadcb2d
--- /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/NetworkUtils.java b/packages/Connectivity/framework/src/android/net/NetworkUtils.java
index c0f2628..c4bebc0 100644
--- a/packages/Connectivity/framework/src/android/net/NetworkUtils.java
+++ b/packages/Connectivity/framework/src/android/net/NetworkUtils.java
@@ -323,22 +323,7 @@
*/
@UnsupportedAppUsage
public static String trimV4AddrZeros(String addr) {
- if (addr == null) return null;
- String[] octets = addr.split("\\.");
- if (octets.length != 4) return addr;
- StringBuilder builder = new StringBuilder(16);
- String result = null;
- for (int i = 0; i < 4; i++) {
- try {
- if (octets[i].length() > 3) return addr;
- builder.append(Integer.parseInt(octets[i]));
- } catch (NumberFormatException e) {
- return addr;
- }
- if (i < 3) builder.append('.');
- }
- result = builder.toString();
- return result;
+ return Inet4AddressUtils.trimAddressZeros(addr);
}
/**
diff --git a/packages/Connectivity/framework/src/android/net/OemNetworkPreferences.java b/packages/Connectivity/framework/src/android/net/OemNetworkPreferences.java
index 48bd297..5a76cd6 100644
--- a/packages/Connectivity/framework/src/android/net/OemNetworkPreferences.java
+++ b/packages/Connectivity/framework/src/android/net/OemNetworkPreferences.java
@@ -73,6 +73,14 @@
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 bcfdd7e..ca6d012 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 @@
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/StaticIpConfiguration.java b/packages/Connectivity/framework/src/android/net/StaticIpConfiguration.java
index ce54597..7904f7a 100644
--- a/packages/Connectivity/framework/src/android/net/StaticIpConfiguration.java
+++ b/packages/Connectivity/framework/src/android/net/StaticIpConfiguration.java
@@ -24,7 +24,6 @@
import android.os.Parcel;
import android.os.Parcelable;
-import com.android.internal.util.Preconditions;
import com.android.net.module.util.InetAddressUtils;
import java.net.InetAddress;
@@ -153,7 +152,7 @@
* @return The {@link Builder} for chaining.
*/
public @NonNull Builder setDnsServers(@NonNull Iterable<InetAddress> dnsServers) {
- Preconditions.checkNotNull(dnsServers);
+ Objects.requireNonNull(dnsServers);
mDnsServers = dnsServers;
return this;
}
diff --git a/packages/Connectivity/framework/src/android/net/TestNetworkManager.java b/packages/Connectivity/framework/src/android/net/TestNetworkManager.java
index a174a7b..a7a6235 100644
--- a/packages/Connectivity/framework/src/android/net/TestNetworkManager.java
+++ b/packages/Connectivity/framework/src/android/net/TestNetworkManager.java
@@ -21,10 +21,9 @@
import android.os.IBinder;
import android.os.RemoteException;
-import com.android.internal.util.Preconditions;
-
import java.util.Arrays;
import java.util.Collection;
+import java.util.Objects;
/**
* Class that allows creation and management of per-app, test-only networks
@@ -50,7 +49,7 @@
/** @hide */
public TestNetworkManager(@NonNull ITestNetworkManager service) {
- mService = Preconditions.checkNotNull(service, "missing ITestNetworkManager");
+ mService = Objects.requireNonNull(service, "missing ITestNetworkManager");
}
/**
@@ -93,7 +92,7 @@
*/
public void setupTestNetwork(
@NonNull LinkProperties lp, boolean isMetered, @NonNull IBinder binder) {
- Preconditions.checkNotNull(lp, "Invalid LinkProperties");
+ Objects.requireNonNull(lp, "Invalid LinkProperties");
setupTestNetwork(lp.getInterfaceName(), lp, isMetered, new int[0], binder);
}
diff --git a/packages/Connectivity/framework/src/android/net/TestNetworkSpecifier.java b/packages/Connectivity/framework/src/android/net/TestNetworkSpecifier.java
index b7470a5..117457d 100644
--- a/packages/Connectivity/framework/src/android/net/TestNetworkSpecifier.java
+++ b/packages/Connectivity/framework/src/android/net/TestNetworkSpecifier.java
@@ -23,8 +23,6 @@
import android.os.Parcelable;
import android.text.TextUtils;
-import com.android.internal.util.Preconditions;
-
import java.util.Objects;
/**
@@ -43,7 +41,9 @@
private final String mInterfaceName;
public TestNetworkSpecifier(@NonNull String interfaceName) {
- Preconditions.checkStringNotEmpty(interfaceName);
+ if (TextUtils.isEmpty(interfaceName)) {
+ throw new IllegalArgumentException("Empty interfaceName");
+ }
mInterfaceName = interfaceName;
}
diff --git a/packages/Connectivity/framework/src/android/net/TransportInfo.java b/packages/Connectivity/framework/src/android/net/TransportInfo.java
index aa4bbb0..fa889ea 100644
--- a/packages/Connectivity/framework/src/android/net/TransportInfo.java
+++ b/packages/Connectivity/framework/src/android/net/TransportInfo.java
@@ -29,35 +29,47 @@
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 26518d3..bc67c74 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.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 @@
}
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 c510079..cd8f4c0 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.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 @@
*/
@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 @@
@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 bf5b26e..85b24713 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 @@
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 @@
*/
@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 @@
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 @@
* @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 bfc4563..8d7a0b3 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 @@
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 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 739ddad..0b42a00 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.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.TelephonyManager;
import android.util.Log;
-import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import java.util.Arrays;
@@ -64,6 +64,7 @@
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 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 @@
* 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 @@
* 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 856f3b8..1330e71 100644
--- a/packages/Connectivity/service/Android.bp
+++ b/packages/Connectivity/service/Android.bp
@@ -60,6 +60,7 @@
"services.core",
"services.net",
"unsupportedappusage",
+ "ServiceConnectivityResources",
],
static_libs: [
"modules-utils-os",
@@ -67,6 +68,7 @@
"net-utils-framework-common",
"netd-client",
"PlatformProperties",
+ "service-connectivity-protos",
],
apex_available: [
"//apex_available:platform",
@@ -75,6 +77,21 @@
}
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 0000000..fa4501a
--- /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 0000000..2c30302
--- /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
new file mode 100644
index 0000000..74977e6
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/drawable-hdpi/stat_notify_rssi_in_range.png
Binary files differ
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
new file mode 100644
index 0000000..62e4fe9
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/drawable-mdpi/stat_notify_rssi_in_range.png
Binary files differ
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
new file mode 100644
index 0000000..c0586d8
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/drawable-xhdpi/stat_notify_rssi_in_range.png
Binary files differ
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
new file mode 100644
index 0000000..86c34ed
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/drawable-xxhdpi/stat_notify_rssi_in_range.png
Binary files differ
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 0000000..a271ca5
--- /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 0000000..68720d5
--- /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 0000000..78d9283
--- /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 0000000..8698a7e
--- /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 0000000..10b234a
--- /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 0000000..d75a204
--- /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 0000000..11e4957
--- /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 0000000..6b0b1f1
--- /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 0000000..6427bd0
--- /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 0000000..74d4cd6
--- /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 0000000..19f6e1a
--- /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 0000000..c55684d
--- /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 0000000..fa8c411
--- /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 0000000..f7be6df
--- /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 0000000..1e7b80c
--- /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 0000000..89647fdb
--- /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 0000000..d29e2ec
--- /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 0000000..d29e2ec
--- /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 0000000..d29e2ec
--- /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 0000000..d29e2ec
--- /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 0000000..cd69133
--- /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 0000000..9102dc0
--- /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 0000000..4c15566
--- /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 0000000..398223a
--- /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 0000000..dd70316
--- /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 0000000..46a946c
--- /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 0000000..dd94441
--- /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 0000000..02ef50b
--- /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 0000000..08c9d81
--- /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 0000000..9f98055
--- /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 0000000..4ae5a2c
--- /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 0000000..eff1b60
--- /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 0000000..52bfb93
--- /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 0000000..2ff59b5
--- /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 0000000..b35d31c
--- /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 0000000..27d7d89
--- /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 0000000..97f42dc
--- /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 0000000..7836101
--- /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 0000000..f322b99
--- /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 0000000..1aa3216
--- /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 0000000..61d21b5
--- /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 0000000..969aaef
--- /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 0000000..da3c337
--- /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 0000000..3b5e047
--- /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 0000000..874bd75
--- /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 0000000..1ace4dc
--- /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 0000000..3db497e
--- /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 0000000..c639c1f
--- /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 0000000..5774603
--- /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 0000000..7e7025f
--- /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 0000000..7e7025f
--- /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 0000000..7e7025f
--- /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 0000000..053c7cf
--- /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 0000000..3e80cf1
--- /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 0000000..214fc0c
--- /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 0000000..c4b1998
--- /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 0000000..529d0bd
--- /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 0000000..50590fa
--- /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 0000000..b89d198
--- /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 0000000..bdcfa3b
--- /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 0000000..8ecff6e
--- /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 0000000..6ec1f9d
--- /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 0000000..e948193
--- /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 0000000..038328f
--- /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 0000000..fe37405
--- /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 0000000..69060f7
--- /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 0000000..fe37405
--- /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 0000000..227b7be
--- /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 0000000..18acf81
--- /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 0000000..6307c2b
--- /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 0000000..e894fef
--- /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 0000000..954b324
--- /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 0000000..bd5d052
--- /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 0000000..8bedbff
--- /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 0000000..b3f1763
--- /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 0000000..9674654
--- /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 0000000..12604cb
--- /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 0000000..84a8640
--- /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 0000000..1616e51
--- /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 0000000..3bf1ce4
--- /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 0000000..5c326e5
--- /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 0000000..d1382da
--- /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 0000000..3c031ad
--- /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 0000000..7518db3
--- /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 0000000..d2284d4
--- /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 0000000..813482b
--- /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 0000000..676404f
--- /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 0000000..f355138
--- /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 0000000..55fefb7
--- /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 0000000..71674e4
--- /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 0000000..25e19ce
--- /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 0000000..b2fa5f5
--- /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 a7b419b..5caa11b 100644
--- a/packages/Connectivity/service/jarjar-rules.txt
+++ b/packages/Connectivity/service/jarjar-rules.txt
@@ -12,3 +12,6 @@
# 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/framework/src/android/net/IOnSetOemNetworkPreferenceListener.aidl b/packages/Connectivity/service/proto/connectivityproto.proto
similarity index 69%
copy from packages/Connectivity/framework/src/android/net/IOnSetOemNetworkPreferenceListener.aidl
copy to packages/Connectivity/service/proto/connectivityproto.proto
index 7979afc..a992d7c 100644
--- a/packages/Connectivity/framework/src/android/net/IOnSetOemNetworkPreferenceListener.aidl
+++ b/packages/Connectivity/service/proto/connectivityproto.proto
@@ -1,12 +1,11 @@
-/**
- *
+/*
* 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
+ * 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,
@@ -15,9 +14,7 @@
* limitations under the License.
*/
-package android.net;
+syntax = "proto2";
-/** @hide */
-oneway interface IOnSetOemNetworkPreferenceListener {
- void onComplete();
-}
+// 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 ad459a4..40a457f 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.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.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 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 3bb3a0c..7f12cc8 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 @@
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 com.android.settingslib.R;
import com.android.settingslib.core.lifecycle.Lifecycle;
-import java.net.InetAddress;
import java.util.Iterator;
/**
@@ -93,19 +93,19 @@
* @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 092cbf3..60bcf37 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 @@
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 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 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 6568bff..268603f 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 @@
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 3fed29a..b7ce2a3 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 f1ab2aa..c40afbfe 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -81,9 +81,18 @@
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 2dcf82f..611a37d 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 @@
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 @@
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 aab0553..992ef26 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -453,6 +453,7 @@
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 @@
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 @@
if (mBluetoothAirplaneModeListener != null) {
mBluetoothAirplaneModeListener.start(mBluetoothModeChangeHelper);
}
- mBluetoothDeviceConfigListener = new BluetoothDeviceConfigListener(this);
+ registerForProvisioningStateChange();
+ mBluetoothDeviceConfigListener = new BluetoothDeviceConfigListener(this, DBG);
}
/**
@@ -2219,12 +2250,25 @@
}
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 eac9f4d..6fcb3f7 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_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_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.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.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.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.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.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 @@
/**
* 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 @@
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 @@
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 @@
protected INetd mNetd;
private NetworkStatsManager mStatsManager;
private NetworkPolicyManager mPolicyManager;
- private NetworkPolicyManagerInternal mPolicyManagerInternal;
private final NetdCallback mNetdCallback;
/**
@@ -487,16 +510,6 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
* 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 @@
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 @@
}
/**
+ * 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
// 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 @@
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 @@
createWithLocationInfoSanitizedIfNecessaryWhenParceled(
nc,
false /* includeLocationSensitiveInfo */,
- mDeps.getCallingUid(), callingPackageName,
+ getCallingPid(), mDeps.getCallingUid(), callingPackageName,
callingAttributionTag));
}
}
@@ -1818,7 +1873,7 @@
return createWithLocationInfoSanitizedIfNecessaryWhenParceled(
getNetworkCapabilitiesInternal(network),
false /* includeLocationSensitiveInfo */,
- mDeps.getCallingUid(), callingPackageName, callingAttributionTag);
+ getCallingPid(), mDeps.getCallingUid(), callingPackageName, callingAttributionTag);
}
@VisibleForTesting
@@ -1837,40 +1892,137 @@
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 @@
// 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 @@
}
}
+ @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 @@
}
}
- 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 @@
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 @@
} 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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
? 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 @@
// 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 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
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 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 @@
@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.
@@ -5964,10 +6116,15 @@
private NetworkCapabilities copyDefaultNetworkCapabilitiesForUid(
@NonNull final NetworkCapabilities netCapToCopy, @NonNull final int requestorUid,
@NonNull final String requestorPackageName) {
+ // These capabilities are for a TRACK_DEFAULT callback, so:
+ // 1. Remove NET_CAPABILITY_VPN, because it's (currently!) the only difference between
+ // mDefaultRequest and a per-UID default request.
+ // TODO: stop depending on the fact that these two unrelated things happen to be the same
+ // 2. Always set the UIDs to mAsUid. restrictRequestUidsForCallerAndSetRequestorInfo will
+ // not do this in the case of a privileged application.
final NetworkCapabilities netCap = new NetworkCapabilities(netCapToCopy);
netCap.removeCapability(NET_CAPABILITY_NOT_VPN);
netCap.setSingleUid(requestorUid);
- netCap.setUids(new ArraySet<>());
restrictRequestUidsForCallerAndSetRequestorInfo(
netCap, requestorUid, requestorPackageName);
return netCap;
@@ -6048,7 +6205,7 @@
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 +6236,6 @@
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 +6246,7 @@
* 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 +6254,12 @@
*/
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 +6271,7 @@
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 +6279,8 @@
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 +6646,7 @@
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 +6661,11 @@
}
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 +6902,8 @@
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 +7011,8 @@
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 +7248,7 @@
putParcelable(
bundle,
createWithLocationInfoSanitizedIfNecessaryWhenParceled(
- nc, includeLocationSensitiveInfo, nri.mUid,
+ nc, includeLocationSensitiveInfo, nri.mPid, nri.mUid,
nrForCallback.getRequestorPackageName(),
nri.mCallingAttributionTag));
putParcelable(bundle, linkPropertiesRestrictedForCallerPermissions(
@@ -7118,7 +7269,7 @@
putParcelable(
bundle,
createWithLocationInfoSanitizedIfNecessaryWhenParceled(
- netCap, includeLocationSensitiveInfo, nri.mUid,
+ netCap, includeLocationSensitiveInfo, nri.mPid, nri.mUid,
nrForCallback.getRequestorPackageName(),
nri.mCallingAttributionTag));
break;
@@ -7853,7 +8004,7 @@
}
}
- 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 +8026,8 @@
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 +8045,14 @@
*
* @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 +8060,11 @@
? 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 +8074,20 @@
}
/**
- * 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 +8227,15 @@
@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 +8317,11 @@
// 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 +8434,7 @@
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 +9026,13 @@
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 +9073,13 @@
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 +9247,143 @@
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 +9402,26 @@
* 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 +9440,22 @@
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 +9559,8 @@
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 10d6570..3ea0ce1 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -643,7 +643,7 @@
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 00d8b0f..351e616 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.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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 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 @@
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 dce919d..78ffcbd 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.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 @@
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 @@
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 @@
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 @@
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 @@
cutListToSize(mPreciseDataConnectionStates, mNumPhones);
cutListToSize(mBarringInfo, mNumPhones);
cutListToSize(mPhysicalChannelConfigs, mNumPhones);
+ cutListToSize(mLinkCapacityEstimateLists, mNumPhones);
return;
}
@@ -571,6 +581,9 @@
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 @@
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 @@
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 @@
}
}
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 @@
*
* @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 @@
&& 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 @@
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 @@
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 @@
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 @@
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 1ef93f4..6c18cde 100644
--- a/services/core/java/com/android/server/VcnManagementService.java
+++ b/services/core/java/com/android/server/VcnManagementService.java
@@ -64,7 +64,7 @@
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/VpnManagerService.java b/services/core/java/com/android/server/VpnManagerService.java
index 56aabc20..d756c1f 100644
--- a/services/core/java/com/android/server/VpnManagerService.java
+++ b/services/core/java/com/android/server/VpnManagerService.java
@@ -352,7 +352,10 @@
@Override
public void startLegacyVpn(VpnProfile profile) {
int user = UserHandle.getUserId(mDeps.getCallingUid());
- final LinkProperties egress = mCm.getActiveLinkProperties();
+ // Note that if the caller is not system (uid >= Process.FIRST_APPLICATION_UID),
+ // the code might not work well since getActiveNetwork might return null if the uid is
+ // blocked by NetworkPolicyManagerService.
+ final LinkProperties egress = mCm.getLinkProperties(mCm.getActiveNetwork());
if (egress == null) {
throw new IllegalStateException("Missing active network connection");
}
diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java
index a847847..a37115d 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -75,7 +75,8 @@
// 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 dd0e1f6..ca4b9c3 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 @@
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 bd08b62..cc5a25a 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 @@
// 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 @@
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 @@
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 be17b1b..54b3e64 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 @@
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 @@
"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 1c38c86..90d9409 100644
--- a/services/core/java/com/android/server/am/OWNERS
+++ b/services/core/java/com/android/server/am/OWNERS
@@ -30,6 +30,10 @@
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 968cf5f..b3373d0 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 @@
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 @@
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 @@
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 @@
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 @@
}
/**
+ * 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 @@
}
@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 ed3a223..6776f49 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 java.io.IOException;
import java.io.RandomAccessFile;
+import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
@@ -80,27 +81,29 @@
private static final String PIPE_NAME = "pipe:clipboard";
private static final String PIPE_DEVICE = "/dev/qemu_pipe";
- private void openPipe() {
+ 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 boolean 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);
- } catch (IOException e) {
+ final RandomAccessFile pipe = new RandomAccessFile(PIPE_DEVICE, "rw");
try {
- if (mPipe != null) mPipe.close();
- } catch (IOException ee) {}
- mPipe = null;
+ pipe.write(createOpenHandshake());
+ mPipe = pipe;
+ return true;
+ } catch (IOException ignore) {
+ pipe.close();
+ }
+ } catch (IOException ignore) {
}
+ return false;
}
public HostClipboardMonitor(HostClipboardCallback cb) {
@@ -114,8 +117,7 @@
// There's no guarantee that QEMU pipes will be ready at the moment
// this method is invoked. We simply try to get the pipe open and
// retry on failure indefinitely.
- while (mPipe == null) {
- openPipe();
+ while ((mPipe == null) && !openPipe()) {
Thread.sleep(100);
}
int size = mPipe.readInt();
@@ -158,7 +160,7 @@
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 0fb6fec..325a2cd 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 @@
/**
* 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 4f6b530..ffeb77d 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 @@
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 PrivateDnsConfig getPrivateDnsConfig() {
- return getPrivateDnsConfig(mContentResolver);
+ return getPrivateDnsConfig(mContext);
}
public void removeNetwork(Network network) {
@@ -479,13 +483,6 @@
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 0000000..028cfee
--- /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 ef76734..a25b89a 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 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 803cc9d..103ab95 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.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.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.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 @@
// 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 @@
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 @@
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 @@
}
@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 @@
@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 @@
break;
case LISTEN:
+ case LISTEN_FOR_BEST:
case TRACK_DEFAULT:
case TRACK_SYSTEM_DEFAULT:
break;
@@ -841,30 +846,6 @@
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 @@
// 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 508739f..0c0d459 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.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.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 @@
// 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 @@
(NotificationManager) c.createContextAsUser(UserHandle.ALL, 0 /* flags */)
.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationTypeMap = new SparseIntArray();
+ mResources = new ConnectivityResources(mContext).get();
}
@VisibleForTesting
@@ -113,20 +117,19 @@
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 @@
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 @@
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 @@
.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 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 0000000..dd2815d
--- /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 8b9c836..f572b46 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.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 @@
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 124c374..30e0c7e 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 @@
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.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 @@
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 @@
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 @@
}
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 @@
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 @@
}
/**
- * 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 @@
* @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 @@
}
/**
- * 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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
}
/**
- * 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 @@
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 @@
// 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 @@
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 fa03e59..47eb3eb 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 @@
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 294d7e2..0215188 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.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.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 @@
@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 aee0947..46c80e7 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -56,6 +56,25 @@
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_FOREGROUND;
+import static android.net.NetworkPolicyManager.ALLOWED_METERED_REASON_MASK;
+import static android.net.NetworkPolicyManager.ALLOWED_METERED_REASON_SYSTEM;
+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 +263,7 @@
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 +434,14 @@
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 +588,10 @@
/** 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 +2910,18 @@
}
@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 +3115,16 @@
@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 +3593,7 @@
* 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 +3966,7 @@
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 +3987,7 @@
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 +3999,31 @@
}
}
+ 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 +4144,21 @@
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 +4603,11 @@
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 +4632,16 @@
}
}
+ 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_METERED_REASON_SYSTEM : 0);
+ newAllowedReasons |= (isForeground ? ALLOWED_METERED_REASON_FOREGROUND : 0);
+ newAllowedReasons |= (isAllowed ? ALLOWED_METERED_REASON_USER_EXEMPTED : 0);
+
if (LOGV) {
Log.v(TAG, "updateRuleForRestrictBackgroundUL(" + uid + ")"
+ ": isForeground=" +isForeground
@@ -4619,6 +4714,18 @@
// 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 +4799,12 @@
// 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 +4817,20 @@
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 +4862,18 @@
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 +4903,57 @@
}
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 +5110,19 @@
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 +5854,56 @@
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 = (blockedReasons & ALLOWED_METERED_REASON_MASK);
+ }
+ if ((allowedReasons & ALLOWED_METERED_REASON_SYSTEM) != 0) {
+ effectiveBlockedReasons = (blockedReasons & ~ALLOWED_METERED_REASON_MASK);
+ }
+ if ((allowedReasons & ALLOWED_REASON_FOREGROUND) != 0) {
+ effectiveBlockedReasons &= ~BLOCKED_REASON_BATTERY_SAVER;
+ effectiveBlockedReasons &= ~BLOCKED_REASON_DOZE;
+ effectiveBlockedReasons &= ~BLOCKED_REASON_APP_STANDBY;
+ }
+ if ((allowedReasons & ALLOWED_METERED_REASON_FOREGROUND) != 0) {
+ 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 9c4c510..cc6a824 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 @@
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 b39a6b4..5d8b75d 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.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.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 @@
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 @@
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 06b54b5..4038bf2 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 @@
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 @@
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 @@
}
} 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 0000000..c8dc1b1
--- /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 349561d..37f3175 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 @@
* 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 @@
&& 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 9c3a394..5b48abb 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.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 @@
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 @@
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 fd2d8e1..beebb31 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.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.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 @@
/**
* 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 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 @@
}
}
+ 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 @@
@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 @@
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 @@
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 69a153f..9589505 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.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 @@
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 @@
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 7e6b7cd..e060171 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.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 @@
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 816a6a0..f55a983 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 @@
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 729fa71..d18043f 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_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 6badafa..736a6f6 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 @@
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 7bde760..46ec65d 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -332,8 +332,6 @@
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 @@
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 @@
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
similarity index 84%
rename from services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java
rename to services/tests/mockingservicestests/src/com/android/server/pm/dex/DexManagerTests.java
index ee0a16a..2e0cadf 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.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 @@
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 @@
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 @@
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 @@
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 0000000..5492dc8
--- /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 0000000..e95633a
--- /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 0000000..e95633a
--- /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 0000000..e95633a
--- /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 0000000..e95633a
--- /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 0000000..e95633a
--- /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 1c96838..1b8ab21 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 @@
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 @@
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 @@
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 @@
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 a38745f..d9af51f 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 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 @@
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 @@
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 @@
.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 c295177..6413026 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.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 javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
@SmallTest
@@ -77,7 +77,7 @@
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 @@
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 @@
.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 ac74470..f4e74ba 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.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 @@
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 @@
.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 9813ab7..60052f7 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.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 @@
@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 @@
@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 @@
@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 @@
@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 @@
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 @@
.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 0000000..13d75a7
--- /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 9b8a2a8..324e592 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 @@
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 @@
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 @@
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 @@
}
@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 @@
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 @@
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 @@
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 @@
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 0727e5a..a894178 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 @@
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 @@
mUncryptSocket = uncryptSocket;
mLockSettingsInternal = lockSettingsInternal;
mIBootControl = bootControl;
+ mIMetricsReporter = metricsReporter;
}
@Override
@@ -94,14 +96,45 @@
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 @@
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 ec7d4bd..647a2a2 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.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 @@
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 dc05488..ae1984e 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -42,8 +42,6 @@
import com.android.internal.telephony.ICarrierConfigLoader;
import com.android.telephony.Rlog;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
import java.util.concurrent.TimeUnit;
/**
@@ -110,31 +108,17 @@
*/
public static final int USSD_OVER_IMS_ONLY = 3;
- /** @hide */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(prefix = { "CARRIER_NR_AVAILABILITY_" }, value = {
- CARRIER_NR_AVAILABILITY_NONE,
- CARRIER_NR_AVAILABILITY_NSA,
- CARRIER_NR_AVAILABILITY_SA,
- })
- public @interface DeviceNrCapability {}
-
- /**
- * Indicates CARRIER_NR_AVAILABILITY_NONE determine that the carrier does not enable 5G NR.
- */
- public static final int CARRIER_NR_AVAILABILITY_NONE = 0;
-
/**
* Indicates CARRIER_NR_AVAILABILITY_NSA determine that the carrier enable the non-standalone
* (NSA) mode of 5G NR.
*/
- public static final int CARRIER_NR_AVAILABILITY_NSA = 1 << 0;
+ public static final int CARRIER_NR_AVAILABILITY_NSA = 1;
/**
* Indicates CARRIER_NR_AVAILABILITY_SA determine that the carrier enable the standalone (SA)
* mode of 5G NR.
*/
- public static final int CARRIER_NR_AVAILABILITY_SA = 1 << 1;
+ public static final int CARRIER_NR_AVAILABILITY_SA = 2;
private final Context mContext;
@@ -1807,23 +1791,20 @@
"show_precise_failed_cause_bool";
/**
- * Bit-field integer to determine whether the carrier enable the non-standalone (NSA) mode of
- * 5G NR, standalone (SA) mode of 5G NR
+ * A list of carrier nr availability is used to determine whether the carrier enable the
+ * non-standalone (NSA) mode of 5G NR, standalone (SA) mode of 5G NR
*
- * <UL>
- * <LI>CARRIER_NR_AVAILABILITY_NONE: non-NR = 0 </LI>
- * <LI>CARRIER_NR_AVAILABILITY_NSA: NSA = 1 << 0</LI>
- * <LI>CARRIER_NR_AVAILABILITY_SA: SA = 1 << 1</LI>
- * </UL>
- * <p> The value of this key must be bitwise OR of
- * {@link #CARRIER_NR_AVAILABILITY_NONE}, {@link #CARRIER_NR_AVAILABILITY_NSA},
- * {@link #CARRIER_NR_AVAILABILITY_SA}.
+ * <p> The value of list is
+ * {@link #CARRIER_NR_AVAILABILITY_NSA}, or {@link #CARRIER_NR_AVAILABILITY_SA}.
*
- * <p> For example, if both NSA and SA are used, the value of key is 3 (1 << 0 | 1 << 1).
- * If the carrier doesn't support 5G NR, the value of key is 0 (non-NR).
- * If the key is invalid or not configured, a default value 3 (NSA|SA = 3) will apply.
+ * <p> For example, if both NSA and SA are used, the list value is {
+ * {@link #CARRIER_NR_AVAILABILITY_NSA},{@link #CARRIER_NR_AVAILABILITY_SA}}.
+ * If the carrier doesn't support 5G NR, the value is the empty array.
+ * If the key is invalid or not configured, the default value {
+ * {@link #CARRIER_NR_AVAILABILITY_NSA},{@link #CARRIER_NR_AVAILABILITY_SA}} will apply.
*/
- public static final String KEY_CARRIER_NR_AVAILABILITY_INT = "carrier_nr_availability_int";
+ public static final String KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY =
+ "carrier_nr_availabilities_int_array";
/**
* Boolean to decide whether LTE is enabled.
@@ -2898,6 +2879,18 @@
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 +4249,14 @@
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 +4619,8 @@
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);
@@ -4631,8 +4634,8 @@
sDefaults.putString(KEY_SHOW_CARRIER_DATA_ICON_PATTERN_STRING, "");
sDefaults.putBoolean(KEY_HIDE_LTE_PLUS_DATA_ICON_BOOL, true);
sDefaults.putInt(KEY_LTE_PLUS_THRESHOLD_BANDWIDTH_KHZ_INT, 20000);
- sDefaults.putInt(KEY_CARRIER_NR_AVAILABILITY_INT,
- CARRIER_NR_AVAILABILITY_NSA | CARRIER_NR_AVAILABILITY_SA);
+ sDefaults.putIntArray(KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY,
+ new int[]{CARRIER_NR_AVAILABILITY_NSA, CARRIER_NR_AVAILABILITY_SA});
sDefaults.putBoolean(KEY_LTE_ENABLED_BOOL, true);
sDefaults.putBoolean(KEY_SUPPORT_TDSCDMA_BOOL, false);
sDefaults.putStringArray(KEY_SUPPORT_TDSCDMA_ROAMING_NETWORKS_STRING_ARRAY, null);
@@ -4811,6 +4814,7 @@
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 597fe8f..957f683 100644
--- a/telephony/java/android/telephony/DataSpecificRegistrationInfo.java
+++ b/telephony/java/android/telephony/DataSpecificRegistrationInfo.java
@@ -68,22 +68,22 @@
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 @@
isDcNrRestricted = dsri.isDcNrRestricted;
isNrAvailable = dsri.isNrAvailable;
isEnDcAvailable = dsri.isEnDcAvailable;
- mLteVopsSupportInfo = dsri.mLteVopsSupportInfo;
+ mVopsSupportInfo = dsri.mVopsSupportInfo;
}
private DataSpecificRegistrationInfo(/* @NonNull */ Parcel source) {
@@ -105,7 +105,7 @@
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 @@
dest.writeBoolean(isDcNrRestricted);
dest.writeBoolean(isNrAvailable);
dest.writeBoolean(isEnDcAvailable);
- mLteVopsSupportInfo.writeToParcel(dest, flags);
+ dest.writeParcelable(mVopsSupportInfo, flags);
}
@Override
@@ -131,15 +131,15 @@
.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 @@
&& 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 @@
/**
* @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/DataThrottlingRequest.java b/telephony/java/android/telephony/DataThrottlingRequest.java
index f50bb58..2827e8d 100644
--- a/telephony/java/android/telephony/DataThrottlingRequest.java
+++ b/telephony/java/android/telephony/DataThrottlingRequest.java
@@ -17,6 +17,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.RequiresFeature;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -52,6 +53,9 @@
* @hide
*/
@SystemApi
+ @RequiresFeature(
+ enforcement = "android.telephony.TelephonyManager#isRadioInterfaceCapabilitySupported",
+ value = TelephonyManager.CAPABILITY_THERMAL_MITIGATION_DATA_THROTTLING)
public static final int DATA_THROTTLING_ACTION_THROTTLE_SECONDARY_CARRIER = 1;
/**
@@ -63,6 +67,9 @@
* @hide
*/
@SystemApi
+ @RequiresFeature(
+ enforcement = "android.telephony.TelephonyManager#isRadioInterfaceCapabilitySupported",
+ value = TelephonyManager.CAPABILITY_THERMAL_MITIGATION_DATA_THROTTLING)
public static final int DATA_THROTTLING_ACTION_THROTTLE_PRIMARY_CARRIER = 2;
/**
@@ -76,6 +83,9 @@
* @hide
*/
@SystemApi
+ @RequiresFeature(
+ enforcement = "android.telephony.TelephonyManager#isRadioInterfaceCapabilitySupported",
+ value = TelephonyManager.CAPABILITY_THERMAL_MITIGATION_DATA_THROTTLING)
public static final int DATA_THROTTLING_ACTION_HOLD = 3;
/**
diff --git a/packages/Connectivity/framework/src/android/net/IOnSetOemNetworkPreferenceListener.aidl b/telephony/java/android/telephony/LinkCapacityEstimate.aidl
similarity index 76%
copy from packages/Connectivity/framework/src/android/net/IOnSetOemNetworkPreferenceListener.aidl
copy to telephony/java/android/telephony/LinkCapacityEstimate.aidl
index 7979afc..286f33f 100644
--- a/packages/Connectivity/framework/src/android/net/IOnSetOemNetworkPreferenceListener.aidl
+++ b/telephony/java/android/telephony/LinkCapacityEstimate.aidl
@@ -1,12 +1,11 @@
-/**
- *
+/*
* 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
+ * 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,
@@ -15,9 +14,6 @@
* limitations under the License.
*/
-package android.net;
+package android.telephony;
-/** @hide */
-oneway interface IOnSetOemNetworkPreferenceListener {
- void onComplete();
-}
+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 0000000..deeb809
--- /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 83e41bf..87761e2 100644
--- a/telephony/java/android/telephony/LteVopsSupportInfo.java
+++ b/telephony/java/android/telephony/LteVopsSupportInfo.java
@@ -21,7 +21,7 @@
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 @@
* @hide
*/
@SystemApi
-public final class LteVopsSupportInfo implements Parcelable {
+public final class LteVopsSupportInfo extends VopsSupportInfo {
/**@hide*/
@Retention(RetentionPolicy.SOURCE)
@@ -42,7 +42,10 @@
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 @@
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 @@
new Creator<LteVopsSupportInfo>() {
@Override
public LteVopsSupportInfo createFromParcel(Parcel in) {
+ // Skip the type info.
+ in.readInt();
return new LteVopsSupportInfo(in);
}
@@ -133,6 +163,11 @@
}
};
+ /** @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 a78f813..5fb60d7 100644
--- a/telephony/java/android/telephony/NetworkRegistrationInfo.java
+++ b/telephony/java/android/telephony/NetworkRegistrationInfo.java
@@ -293,11 +293,12 @@
@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/packages/Connectivity/framework/src/android/net/IOnSetOemNetworkPreferenceListener.aidl b/telephony/java/android/telephony/NrVopsSupportInfo.aidl
similarity index 69%
copy from packages/Connectivity/framework/src/android/net/IOnSetOemNetworkPreferenceListener.aidl
copy to telephony/java/android/telephony/NrVopsSupportInfo.aidl
index 7979afc..460a589 100644
--- a/packages/Connectivity/framework/src/android/net/IOnSetOemNetworkPreferenceListener.aidl
+++ b/telephony/java/android/telephony/NrVopsSupportInfo.aidl
@@ -1,12 +1,11 @@
-/**
- *
- * Copyright (C) 2021 The Android Open Source Project
+/*
+ * 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
+ * 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,
@@ -15,9 +14,6 @@
* limitations under the License.
*/
-package android.net;
+package android.telephony;
-/** @hide */
-oneway interface IOnSetOemNetworkPreferenceListener {
- void onComplete();
-}
+parcelable NrVopsSupportInfo;
diff --git a/telephony/java/android/telephony/NrVopsSupportInfo.java b/telephony/java/android/telephony/NrVopsSupportInfo.java
new file mode 100644
index 0000000..155ee38
--- /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 b958bff..ce5a8cc 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -2127,7 +2127,7 @@
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 364c9be..bae032c 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -129,6 +129,8 @@
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 @@
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 @@
@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 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 @@
* {@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 @@
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 @@
}
/**
+ * 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}).
@@ -11859,12 +11897,6 @@
* "Data capable" means that this device supports packet-switched
* data connections over the telephony network.
* <p>
- * Note: the meaning of this flag is subtly different from the
- * PackageManager.FEATURE_TELEPHONY system feature, which is available
- * on any device with a telephony radio, even if the device is
- * voice-only.
- *
- * @hide
*/
public boolean isDataCapable() {
if (mContext == null) return true;
@@ -12079,6 +12111,7 @@
NETWORK_TYPE_BITMASK_LTE,
NETWORK_TYPE_BITMASK_LTE_CA,
NETWORK_TYPE_BITMASK_NR,
+ NETWORK_TYPE_BITMASK_IWLAN
})
public @interface NetworkTypeBitMask {}
@@ -13981,33 +14014,6 @@
}
/**
- * 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
@@ -14428,12 +14434,23 @@
public static final String CAPABILITY_NR_DUAL_CONNECTIVITY_CONFIGURATION_AVAILABLE =
"CAPABILITY_NR_DUAL_CONNECTIVITY_CONFIGURATION_AVAILABLE";
+ /**
+ * Indicates whether a data throttling request sent with {@link #sendThermalMitigationRequest}
+ * is supported. See comments on {@link #sendThermalMitigationRequest} for more information.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final String CAPABILITY_THERMAL_MITIGATION_DATA_THROTTLING =
+ "CAPABILITY_THERMAL_MITIGATION_DATA_THROTTLING";
+
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@StringDef(prefix = "CAPABILITY_", value = {
CAPABILITY_SECONDARY_LINK_BANDWIDTH_VISIBLE,
CAPABILITY_ALLOWED_NETWORK_TYPES_USED,
- CAPABILITY_NR_DUAL_CONNECTIVITY_CONFIGURATION_AVAILABLE
+ CAPABILITY_NR_DUAL_CONNECTIVITY_CONFIGURATION_AVAILABLE,
+ CAPABILITY_THERMAL_MITIGATION_DATA_THROTTLING,
})
public @interface RadioInterfaceCapability {}
@@ -14543,11 +14560,24 @@
* and can be used at any time during data throttling to hold onto the current level of data
* throttling.
*
+ * <p> If {@link android.telephony.TelephonyManager#isRadioInterfaceCapabilitySupported}({@link
+ * #CAPABILITY_THERMAL_MITIGATION_DATA_THROTTLING}) returns false, then sending a {@link
+ * DataThrottlingRequest#DATA_THROTTLING_ACTION_HOLD}, {@link
+ * DataThrottlingRequest#DATA_THROTTLING_ACTION_THROTTLE_SECONDARY_CARRIER}, or {@link
+ * DataThrottlingRequest#DATA_THROTTLING_ACTION_THROTTLE_PRIMARY_CARRIER} will result in {@link
+ * IllegalArgumentException} being thrown. However, on devices that do not
+ * support data throttling, {@link
+ * DataThrottlingRequest#DATA_THROTTLING_ACTION_NO_DATA_THROTTLING} can still be requested in
+ * order to undo the mitigations above it (i.e {@link
+ * ThermalMitigationRequest#THERMAL_MITIGATION_ACTION_VOICE_ONLY} and/or {@link
+ * ThermalMitigationRequest#THERMAL_MITIGATION_ACTION_RADIO_OFF}).
+ *
* @param thermalMitigationRequest Thermal mitigation request. See {@link
* ThermalMitigationRequest} for details.
*
* @throws IllegalStateException if the Telephony process is not currently available.
- * @throws IllegalArgumentException if the thermalMitigationRequest had invalid parameters.
+ * @throws IllegalArgumentException if the thermalMitigationRequest had invalid parameters or
+ * if the device's modem does not support data throttling.
*
* @hide
*/
@@ -14601,6 +14631,11 @@
*/
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 +14962,9 @@
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/packages/Connectivity/framework/src/android/net/IOnSetOemNetworkPreferenceListener.aidl b/telephony/java/android/telephony/VopsSupportInfo.aidl
similarity index 69%
copy from packages/Connectivity/framework/src/android/net/IOnSetOemNetworkPreferenceListener.aidl
copy to telephony/java/android/telephony/VopsSupportInfo.aidl
index 7979afc..31c608f 100644
--- a/packages/Connectivity/framework/src/android/net/IOnSetOemNetworkPreferenceListener.aidl
+++ b/telephony/java/android/telephony/VopsSupportInfo.aidl
@@ -1,12 +1,11 @@
-/**
- *
- * Copyright (C) 2021 The Android Open Source Project
+/*
+ * 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
+ * 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,
@@ -15,9 +14,6 @@
* limitations under the License.
*/
-package android.net;
+package android.telephony;
-/** @hide */
-oneway interface IOnSetOemNetworkPreferenceListener {
- void onComplete();
-}
+parcelable VopsSupportInfo;
diff --git a/telephony/java/android/telephony/VopsSupportInfo.java b/telephony/java/android/telephony/VopsSupportInfo.java
new file mode 100644
index 0000000..f89bfa9
--- /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 51857a7..609d111 100644
--- a/telephony/java/android/telephony/data/SliceInfo.java
+++ b/telephony/java/android/telephony/data/SliceInfo.java
@@ -29,7 +29,12 @@
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 f74484b..45702c31 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.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.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 @@
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 @@
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 7f0318a..e1a424f 100644
--- a/tests/net/Android.bp
+++ b/tests/net/Android.bp
@@ -79,6 +79,7 @@
"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 0dfec75..d40b88c 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_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.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.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 @@
@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,55 +353,6 @@
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();
- return new NetworkCapabilities()
- .addCapability(NET_CAPABILITY_INTERNET)
- .addCapability(NET_CAPABILITY_EIMS)
- .addCapability(NET_CAPABILITY_NOT_METERED)
- .setSSID(TEST_SSID)
- .setTransportInfo(wifiInfo)
- .setRequestorPackageName("com.android.test")
- .setRequestorUid(9304);
- }
-
- @Test
- public void testParcelNetworkCapabilitiesWithLocationSensitiveFields() {
- assumeTrue(isAtLeastS());
-
- final NetworkCapabilities netCap = createNetworkCapabilitiesWithWifiInfo();
- final NetworkCapabilities netCapWithLocationSensitiveFields =
- new NetworkCapabilities(netCap, true);
-
- assertParcelingIsLossless(netCapWithLocationSensitiveFields);
- testParcelSane(netCapWithLocationSensitiveFields);
-
- assertEquals(netCapWithLocationSensitiveFields,
- parcelingRoundTrip(netCapWithLocationSensitiveFields));
- }
-
- @Test
- public void testParcelNetworkCapabilitiesWithoutLocationSensitiveFields() {
- 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);
@@ -389,6 +363,45 @@
}
}
+ private static NetworkCapabilities createNetworkCapabilitiesWithTransportInfo() {
+ return new NetworkCapabilities()
+ .addCapability(NET_CAPABILITY_INTERNET)
+ .addCapability(NET_CAPABILITY_EIMS)
+ .addCapability(NET_CAPABILITY_NOT_METERED)
+ .setSSID(TEST_SSID)
+ .setTransportInfo(new TestTransportInfo())
+ .setRequestorPackageName("com.android.test")
+ .setRequestorUid(9304);
+ }
+
+ @Test
+ public void testNetworkCapabilitiesCopyWithNoRedactions() {
+ assumeTrue(isAtLeastS());
+
+ 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 testNetworkCapabilitiesCopyWithoutLocationSensitiveFields() {
+ assumeTrue(isAtLeastS());
+
+ 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
public void testOemPaid() {
NetworkCapabilities nc = new NetworkCapabilities();
@@ -540,12 +553,16 @@
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 @@
} 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 @@
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 @@
} 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 @@
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 2a2dc56..db49e0b 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 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 @@
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 01d8186..e2d43cb 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.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 @@
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 d04c87b..b7a42ec 100644
--- a/tests/net/java/android/net/VpnTransportInfoTest.java
+++ b/tests/net/java/android/net/VpnTransportInfoTest.java
@@ -42,7 +42,13 @@
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 8ea226d..b62bdbc 100644
--- a/tests/net/java/android/net/util/KeepaliveUtilsTest.kt
+++ b/tests/net/java/android/net/util/KeepaliveUtilsTest.kt
@@ -18,6 +18,7 @@
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_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 @@
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 @@
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 c1315f6..25aa626 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.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.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 @@
@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 @@
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 @@
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 2c8c8a6..ed9a44b 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_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.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_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.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.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.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.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.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.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 @@
// 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 @@
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 @@
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 @@
@Mock NetworkPolicyManager mNetworkPolicyManager;
@Mock VpnProfileStore mVpnProfileStore;
@Mock SystemConfigManager mSystemConfigManager;
+ @Mock Resources mResources;
private ArgumentCaptor<ResolverParamsParcel> mResolverParamsParcelCaptor =
ArgumentCaptor.forClass(ResolverParamsParcel.class);
@@ -471,7 +489,7 @@
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 @@
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 @@
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 @@
@Override
public Resources getResources() {
- return mResources;
+ return mInternalResources;
}
@Override
@@ -1082,6 +1107,10 @@
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 void setUids(Set<UidRange> uids) {
- mNetworkCapabilities.setUids(uids);
+ mNetworkCapabilities.setUids(UidRange.toIntRanges(uids));
if (mAgentRegistered) {
mMockNetworkAgent.setNetworkCapabilities(mNetworkCapabilities, true);
}
@@ -1349,28 +1378,13 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
}).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 @@
@After
public void tearDown() throws Exception {
unregisterDefaultNetworkCallbacks();
+ maybeTearDownEnterpriseNetwork();
setAlwaysOnNetworks(false);
if (mCellNetworkAgent != null) {
mCellNetworkAgent.disconnect();
@@ -1588,6 +1649,7 @@
waitForIdle();
FakeSettingsProvider.clearSettingsProvider();
+ ConnectivityResources.setResourcesContextForTest(null);
mCsHandlerThread.quitSafely();
mAlarmManagerThread.quitSafely();
@@ -1776,7 +1838,8 @@
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 @@
.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 @@
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 @@
@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 @@
assertTrue(mPolicyTracker.shouldNotifyWifiUnvalidated());
}
+ @Ignore("Refactoring in progress b/178071397")
@Test
public void testAvoidBadWifi() throws Exception {
final ContentResolver cr = mServiceContext.getContentResolver();
@@ -4307,7 +4372,7 @@
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 @@
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 @@
// 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 @@
@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 @@
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 @@
// 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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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();
@@ -7419,6 +7487,9 @@
final NetworkRequest vpnUidRequest = new NetworkRequest.Builder().build();
registerNetworkCallbackAsUid(vpnUidRequest, vpnUidCallback, VPN_UID);
+ final TestNetworkCallback vpnUidDefaultCallback = new TestNetworkCallback();
+ registerDefaultNetworkCallbackAsUid(vpnUidDefaultCallback, VPN_UID);
+
final int uid = Process.myUid();
final int userId = UserHandle.getUserId(uid);
final ArrayList<String> allowList = new ArrayList<>();
@@ -7437,6 +7508,7 @@
callback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiNetworkAgent);
defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiNetworkAgent);
vpnUidCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+ vpnUidDefaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
assertNull(mCm.getActiveNetwork());
assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
@@ -7449,6 +7521,7 @@
callback.expectBlockedStatusCallback(false, mWiFiNetworkAgent);
defaultCallback.expectBlockedStatusCallback(false, mWiFiNetworkAgent);
vpnUidCallback.assertNoCallback();
+ vpnUidDefaultCallback.assertNoCallback();
expectNetworkRejectNonSecureVpn(inOrder, false, firstHalf, secondHalf);
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
@@ -7463,6 +7536,7 @@
callback.assertNoCallback();
defaultCallback.assertNoCallback();
vpnUidCallback.assertNoCallback();
+ vpnUidDefaultCallback.assertNoCallback();
// The following requires that the UID of this test package is greater than VPN_UID. This
// is always true in practice because a plain AOSP build with no apps installed has almost
@@ -7483,6 +7557,7 @@
callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
defaultCallback.assertNoCallback();
vpnUidCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
+ vpnUidDefaultCallback.assertNoCallback();
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
@@ -7503,6 +7578,7 @@
defaultCallback.expectBlockedStatusCallback(true, mWiFiNetworkAgent);
assertBlockedCallbackInAnyOrder(callback, true, mWiFiNetworkAgent, mCellNetworkAgent);
vpnUidCallback.assertNoCallback();
+ vpnUidDefaultCallback.assertNoCallback();
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
assertNull(mCm.getActiveNetwork());
assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
@@ -7514,6 +7590,7 @@
defaultCallback.expectBlockedStatusCallback(false, mWiFiNetworkAgent);
assertBlockedCallbackInAnyOrder(callback, false, mWiFiNetworkAgent, mCellNetworkAgent);
vpnUidCallback.assertNoCallback();
+ vpnUidDefaultCallback.assertNoCallback();
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
@@ -7528,6 +7605,7 @@
callback.assertNoCallback();
defaultCallback.assertNoCallback();
vpnUidCallback.assertNoCallback();
+ vpnUidDefaultCallback.assertNoCallback();
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
@@ -7539,6 +7617,7 @@
callback.assertNoCallback();
defaultCallback.assertNoCallback();
vpnUidCallback.assertNoCallback();
+ vpnUidDefaultCallback.assertNoCallback();
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
@@ -7551,6 +7630,7 @@
defaultCallback.expectBlockedStatusCallback(true, mWiFiNetworkAgent);
assertBlockedCallbackInAnyOrder(callback, true, mWiFiNetworkAgent, mCellNetworkAgent);
vpnUidCallback.assertNoCallback();
+ vpnUidDefaultCallback.assertNoCallback();
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
assertNull(mCm.getActiveNetwork());
assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
@@ -7561,6 +7641,7 @@
assertUidRangesUpdatedForMyUid(true);
defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
vpnUidCallback.assertNoCallback(); // vpnUidCallback has NOT_VPN capability.
+ vpnUidDefaultCallback.assertNoCallback(); // VPN does not apply to VPN_UID
assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
@@ -7571,11 +7652,14 @@
mMockVpn.disconnect();
defaultCallback.expectCallback(CallbackEntry.LOST, mMockVpn);
defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiNetworkAgent);
+ vpnUidCallback.assertNoCallback();
+ vpnUidDefaultCallback.assertNoCallback();
assertNull(mCm.getActiveNetwork());
mCm.unregisterNetworkCallback(callback);
mCm.unregisterNetworkCallback(defaultCallback);
mCm.unregisterNetworkCallback(vpnUidCallback);
+ mCm.unregisterNetworkCallback(vpnUidDefaultCallback);
}
private void setupLegacyLockdownVpn() {
@@ -7597,7 +7681,7 @@
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 +8069,6 @@
// 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 +8554,12 @@
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 +8643,7 @@
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 +8671,7 @@
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 +8687,7 @@
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 +8702,7 @@
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 +8754,7 @@
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 +8859,34 @@
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 +8900,13 @@
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 +8916,15 @@
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 +8934,15 @@
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 +8953,15 @@
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 +8971,15 @@
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 +8989,11 @@
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 +9016,11 @@
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 +9030,196 @@
// 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 +9418,8 @@
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 +9779,7 @@
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 +9977,7 @@
.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 +10160,11 @@
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 +10194,17 @@
// 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 +10371,12 @@
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 +10388,9 @@
if (null != mSystemDefaultNetworkCallback) {
mCm.unregisterNetworkCallback(mSystemDefaultNetworkCallback);
}
+ if (null != mProfileDefaultNetworkCallback) {
+ mCm.unregisterNetworkCallback(mProfileDefaultNetworkCallback);
+ }
}
private void setupMultipleDefaultNetworksForOemNetworkPreferenceNotCurrentUidTest(
@@ -10174,7 +10446,7 @@
oemPrefListener.expectOnComplete();
}
- private static class TestOemListenerCallback implements IOnSetOemNetworkPreferenceListener {
+ private static class TestOemListenerCallback implements IOnCompleteListener {
final CompletableFuture<Object> mDone = new CompletableFuture<>();
@Override
@@ -11112,11 +11384,494 @@
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 a10a3c8..5ec1119 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.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 @@
@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(mTracker.isTypeSupported(UNSUPPORTED_TYPE))
+ 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))
+ }
}
@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 5760211..692c50f 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 @@
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 @@
@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 @@
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 0000000..eb3b4df
--- /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 1c0ba4f..9ab60a4 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.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 @@
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 ff8c632..3adf08c 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 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.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 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 @@
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 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 b8f7fbc..6ad4900 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.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.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 @@
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 @@
.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 @@
// 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 @@
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 @@
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 @@
@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 @@
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 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 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 @@
.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 @@
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 5b17aad..8a0c923 100644
--- a/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java
+++ b/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java
@@ -109,16 +109,6 @@
}
@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 a0200275..a9d5822 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.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 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 @@
.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 0e5f5e4..ca6448c 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 @@
any(),
lpCaptor.capture(),
ncCaptor.capture(),
- anyInt(),
+ any(),
any(),
anyInt());
verify(mIpSecSvc)