summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apex/jobscheduler/framework/java/android/app/job/JobInfo.java8
-rw-r--r--cmds/bootanimation/BootAnimation.cpp2
-rw-r--r--cmds/statsd/OWNERS10
-rw-r--r--cmds/statsd/src/OWNERS6
-rw-r--r--core/api/current.txt10
-rw-r--r--core/api/system-current.txt179
-rw-r--r--core/java/android/app/Activity.java4
-rw-r--r--core/java/android/bluetooth/BluetoothLeAudio.java451
-rw-r--r--core/java/android/bluetooth/BluetoothProfile.java9
-rw-r--r--core/java/android/hardware/hdmi/HdmiDeviceInfo.java15
-rw-r--r--core/java/android/net/ConnectivityManager.java2
-rw-r--r--core/java/android/net/NetworkAgent.java44
-rw-r--r--core/java/android/net/NetworkCapabilities.java5
-rw-r--r--core/java/android/net/NetworkProvider.java7
-rw-r--r--core/java/android/os/UserManager.java43
-rw-r--r--core/java/android/os/VibrationEffect.java3
-rw-r--r--core/java/android/os/storage/VolumeInfo.java15
-rw-r--r--core/java/android/security/keymaster/KeymasterDefs.java425
-rw-r--r--core/jni/android_media_AudioSystem.cpp17
-rw-r--r--core/proto/OWNERS18
-rw-r--r--core/res/AndroidManifest.xml6
-rw-r--r--core/tests/hdmitests/Android.bp1
-rwxr-xr-xcore/tests/hdmitests/src/android/hardware/hdmi/HdmiDeviceInfoTest.java75
-rw-r--r--data/etc/privapp-permissions-platform.xml1
-rw-r--r--libs/hwui/renderthread/EglManager.cpp9
-rw-r--r--media/jni/audioeffect/android_media_AudioEffect.cpp2
-rw-r--r--media/jni/soundpool/android_media_SoundPool.cpp2
-rw-r--r--packages/Shell/AndroidManifest.xml1
-rw-r--r--packages/SystemUI/OWNERS22
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java280
-rw-r--r--services/core/java/com/android/server/OWNERS3
-rw-r--r--services/core/java/com/android/server/StorageManagerService.java5
-rw-r--r--services/core/java/com/android/server/TestNetworkService.java45
-rw-r--r--services/core/java/com/android/server/UserspaceRebootLogger.java10
-rw-r--r--services/core/java/com/android/server/connectivity/NetworkAgentInfo.java16
-rw-r--r--services/core/java/com/android/server/connectivity/PermissionMonitor.java2
-rw-r--r--services/core/java/com/android/server/connectivity/Vpn.java254
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java5
-rw-r--r--services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java6
-rw-r--r--services/core/java/com/android/server/locksettings/LockSettingsService.java21
-rw-r--r--services/core/java/com/android/server/locksettings/SyntheticPasswordCrypto.java24
-rw-r--r--services/core/java/com/android/server/media/MediaKeyDispatcher.java3
-rw-r--r--services/core/java/com/android/server/media/MediaSessionService.java24
-rw-r--r--services/core/java/com/android/server/media/SessionPolicyProvider.java3
-rw-r--r--services/core/java/com/android/server/pm/PreferredComponent.java31
-rw-r--r--services/core/java/com/android/server/pm/PreferredIntentResolver.java21
-rw-r--r--services/core/java/com/android/server/pm/Settings.java3
-rw-r--r--services/core/java/com/android/server/timedetector/TimeDetectorService.java2
-rw-r--r--services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java66
-rw-r--r--services/core/java/com/android/server/timedetector/TimeDetectorStrategyCallbackImpl.java17
-rw-r--r--services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java97
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java101
-rw-r--r--services/wifi/java/android/net/wifi/WifiApiServiceInfo.aidl23
-rw-r--r--telephony/java/android/telephony/CallForwardingInfo.java2
-rw-r--r--telephony/java/android/telephony/CarrierConfigManager.java27
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java33
-rw-r--r--telephony/java/android/telephony/ims/DelegateMessageCallback.java2
-rw-r--r--telephony/java/android/telephony/ims/DelegateRegistrationState.java54
-rw-r--r--telephony/java/android/telephony/ims/DelegateRequest.java6
-rw-r--r--telephony/java/android/telephony/ims/DelegateStateCallback.java15
-rw-r--r--telephony/java/android/telephony/ims/FeatureTagState.java10
-rw-r--r--telephony/java/android/telephony/ims/ImsExternalCallState.java6
-rw-r--r--telephony/java/android/telephony/ims/ImsSsData.java6
-rw-r--r--telephony/java/android/telephony/ims/RcsContactUceCapability.java13
-rw-r--r--telephony/java/android/telephony/ims/SipDelegateConnection.java5
-rw-r--r--telephony/java/android/telephony/ims/SipDelegateImsConfiguration.java55
-rw-r--r--telephony/java/android/telephony/ims/SipDelegateManager.java24
-rw-r--r--telephony/java/android/telephony/ims/SipMessage.java26
-rw-r--r--telephony/java/android/telephony/ims/aidl/ISipDelegate.aidl2
-rw-r--r--telephony/java/android/telephony/ims/aidl/SipDelegateAidlWrapper.java11
-rw-r--r--telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java2
-rw-r--r--telephony/java/android/telephony/ims/stub/DelegateConnectionMessageCallback.java4
-rw-r--r--telephony/java/android/telephony/ims/stub/DelegateConnectionStateCallback.java2
-rw-r--r--telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java3
-rw-r--r--telephony/java/android/telephony/ims/stub/SipDelegate.java4
-rw-r--r--telephony/java/android/telephony/ims/stub/SipTransportImplBase.java9
-rw-r--r--telephony/java/com/android/internal/telephony/ITelephony.aidl7
-rw-r--r--telephony/java/com/android/internal/telephony/RILConstants.java1
-rw-r--r--tests/BootImageProfileTest/TEST_MAPPING7
-rw-r--r--tests/net/common/java/android/net/OemNetworkPreferencesTest.java8
-rw-r--r--tests/net/java/com/android/server/ConnectivityServiceTest.java175
-rw-r--r--tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java2
-rw-r--r--tests/net/java/com/android/server/connectivity/VpnTest.java141
85 files changed, 2207 insertions, 913 deletions
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobInfo.java b/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
index c2d530d00058..24b8055b9a57 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
@@ -462,11 +462,11 @@ public class JobInfo implements Parcelable {
public @NetworkType int getNetworkType() {
if (networkRequest == null) {
return NETWORK_TYPE_NONE;
- } else if (networkRequest.networkCapabilities.hasCapability(NET_CAPABILITY_NOT_METERED)) {
+ } else if (networkRequest.hasCapability(NET_CAPABILITY_NOT_METERED)) {
return NETWORK_TYPE_UNMETERED;
- } else if (networkRequest.networkCapabilities.hasCapability(NET_CAPABILITY_NOT_ROAMING)) {
+ } else if (networkRequest.hasCapability(NET_CAPABILITY_NOT_ROAMING)) {
return NETWORK_TYPE_NOT_ROAMING;
- } else if (networkRequest.networkCapabilities.hasTransport(TRANSPORT_CELLULAR)) {
+ } else if (networkRequest.hasTransport(TRANSPORT_CELLULAR)) {
return NETWORK_TYPE_CELLULAR;
} else {
return NETWORK_TYPE_ANY;
@@ -1513,7 +1513,7 @@ public class JobInfo implements Parcelable {
}
// We can't serialize network specifiers
if (mIsPersisted && mNetworkRequest != null
- && mNetworkRequest.networkCapabilities.getNetworkSpecifier() != null) {
+ && mNetworkRequest.getNetworkSpecifier() != null) {
throw new IllegalArgumentException(
"Network specifiers aren't supported for persistent jobs");
}
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 5bcf30771436..2c7ee212b7b5 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -582,6 +582,7 @@ bool BootAnimation::threadLoop() {
result = movie();
}
+ mCallbacks->shutdown();
eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
eglDestroyContext(mDisplay, mContext);
eglDestroySurface(mDisplay, mSurface);
@@ -668,7 +669,6 @@ void BootAnimation::checkExit() {
int exitnow = atoi(value);
if (exitnow) {
requestExit();
- mCallbacks->shutdown();
}
}
diff --git a/cmds/statsd/OWNERS b/cmds/statsd/OWNERS
index a61babf32e58..4e4e11988b62 100644
--- a/cmds/statsd/OWNERS
+++ b/cmds/statsd/OWNERS
@@ -1,9 +1 @@
-jeffreyhuang@google.com
-joeo@google.com
-jtnguyen@google.com
-muhammadq@google.com
-ruchirr@google.com
-singhtejinder@google.com
-tsaichristine@google.com
-yaochen@google.com
-yro@google.com
+baligh@google.com
diff --git a/cmds/statsd/src/OWNERS b/cmds/statsd/src/OWNERS
deleted file mode 100644
index 0f3ddf7388d9..000000000000
--- a/cmds/statsd/src/OWNERS
+++ /dev/null
@@ -1,6 +0,0 @@
-# Temporary OWNERS Block to assist with migration
-# bug: 167962588
-per-file *atoms.proto = set noparent
-per-file *atom_field_options.proto = set noparent
-per-file *atoms.proto = baligh@google.com, yro@google.com, singhtejinder@google.com, jeffreyhuang@google.com
-per-file *atom_field_options.proto = baligh@google.com, yro@google.com, singhtejinder@google.com, jeffreyhuang@google.com
diff --git a/core/api/current.txt b/core/api/current.txt
index a20b58efb53f..b579d2cfc1db 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -9051,6 +9051,15 @@ package android.bluetooth {
field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothHidDeviceAppSdpSettings> CREATOR;
}
+ public final class BluetoothLeAudio implements java.lang.AutoCloseable android.bluetooth.BluetoothProfile {
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public void close();
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) protected void finalize();
+ method @NonNull public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public int getConnectionState(@NonNull android.bluetooth.BluetoothDevice);
+ method @NonNull public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(@NonNull int[]);
+ field public static final String ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED = "android.bluetooth.action.LE_AUDIO_CONNECTION_STATE_CHANGED";
+ }
+
public final class BluetoothManager {
method public android.bluetooth.BluetoothAdapter getAdapter();
method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices(int);
@@ -45091,6 +45100,7 @@ package android.telephony {
}
public static final class CarrierConfigManager.Ims {
+ field public static final String KEY_ENABLE_PRESENCE_PUBLISH_BOOL = "ims.enable_presence_publish_bool";
field public static final String KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL = "ims.ims_single_registration_required_bool";
field public static final String KEY_PREFIX = "ims.";
field public static final String KEY_WIFI_OFF_DEFERRING_TIME_MILLIS_INT = "ims.wifi_off_deferring_time_millis_int";
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index f6b1d0627312..44917df36e2b 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -5986,6 +5986,7 @@ package android.net {
field @Deprecated public static final int TETHER_ERROR_NO_ERROR = 0; // 0x0
field @Deprecated public static final int TETHER_ERROR_PROVISION_FAILED = 11; // 0xb
field public static final int TYPE_NONE = -1; // 0xffffffff
+ field @Deprecated public static final int TYPE_PROXY = 16; // 0x10
field @Deprecated public static final int TYPE_WIFI_P2P = 13; // 0xd
}
@@ -6175,6 +6176,7 @@ package android.net {
method public final void sendNetworkCapabilities(@NonNull android.net.NetworkCapabilities);
method public final void sendNetworkScore(@IntRange(from=0, to=99) int);
method public final void sendSocketKeepaliveEvent(int, int);
+ method public final void setUnderlyingNetworks(@Nullable java.util.List<android.net.Network>);
method public void unregister();
field public static final int VALIDATION_STATUS_NOT_VALID = 2; // 0x2
field public static final int VALIDATION_STATUS_VALID = 1; // 0x1
@@ -10152,6 +10154,7 @@ package android.telephony {
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSimCardState(int);
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Locale getSimLocale();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getSupportedRadioAccessFamily();
+ method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<android.telephony.RadioAccessSpecifier> getSystemSelectionChannels();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public java.util.List<android.telephony.TelephonyHistogram> getTelephonyHistograms();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.UiccSlotInfo[] getUiccSlotsInfo();
method @Nullable public android.os.Bundle getVisualVoicemailSettings();
@@ -10692,6 +10695,61 @@ package android.telephony.ims {
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.AudioCodecAttributes> CREATOR;
}
+ public interface DelegateMessageCallback {
+ method public void onMessageReceived(@NonNull android.telephony.ims.SipMessage);
+ method public void onMessageSendFailure(@NonNull String, int);
+ method public void onMessageSent(@NonNull String);
+ }
+
+ public final class DelegateRegistrationState implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public java.util.Set<android.telephony.ims.FeatureTagState> getDeregisteredFeatureTags();
+ method @NonNull public java.util.Set<android.telephony.ims.FeatureTagState> getDeregisteringFeatureTags();
+ method @NonNull public java.util.Set<java.lang.String> getRegisteredFeatureTags();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.DelegateRegistrationState> CREATOR;
+ field public static final int DEREGISTERED_REASON_NOT_PROVISIONED = 1; // 0x1
+ field public static final int DEREGISTERED_REASON_NOT_REGISTERED = 2; // 0x2
+ field public static final int DEREGISTERED_REASON_UNKNOWN = 0; // 0x0
+ field public static final int DEREGISTERING_REASON_DESTROY_PENDING = 6; // 0x6
+ field public static final int DEREGISTERING_REASON_FEATURE_TAGS_CHANGING = 5; // 0x5
+ field public static final int DEREGISTERING_REASON_PDN_CHANGE = 3; // 0x3
+ field public static final int DEREGISTERING_REASON_PROVISIONING_CHANGE = 4; // 0x4
+ }
+
+ public static final class DelegateRegistrationState.Builder {
+ ctor public DelegateRegistrationState.Builder();
+ method @NonNull public android.telephony.ims.DelegateRegistrationState.Builder addDeregisteredFeatureTag(@NonNull String, int);
+ method @NonNull public android.telephony.ims.DelegateRegistrationState.Builder addDeregisteringFeatureTag(@NonNull String, int);
+ method @NonNull public android.telephony.ims.DelegateRegistrationState.Builder addRegisteredFeatureTag(@NonNull String);
+ method @NonNull public android.telephony.ims.DelegateRegistrationState.Builder addRegisteredFeatureTags(@NonNull java.util.Set<java.lang.String>);
+ method @NonNull public android.telephony.ims.DelegateRegistrationState build();
+ }
+
+ public final class DelegateRequest implements android.os.Parcelable {
+ ctor public DelegateRequest(@NonNull java.util.Set<java.lang.String>);
+ method public int describeContents();
+ method @NonNull public java.util.Set<java.lang.String> getFeatureTags();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.DelegateRequest> CREATOR;
+ }
+
+ public interface DelegateStateCallback {
+ method public void onCreated(@NonNull android.telephony.ims.stub.SipDelegate, @Nullable java.util.Set<android.telephony.ims.FeatureTagState>);
+ method public void onDestroyed(int);
+ method public void onFeatureTagRegistrationChanged(@NonNull android.telephony.ims.DelegateRegistrationState);
+ method public void onImsConfigurationChanged(@NonNull android.telephony.ims.SipDelegateImsConfiguration);
+ }
+
+ public final class FeatureTagState implements android.os.Parcelable {
+ ctor public FeatureTagState(@NonNull String, int);
+ method public int describeContents();
+ method @NonNull public String getFeatureTag();
+ method public int getState();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.FeatureTagState> CREATOR;
+ }
+
public final class ImsCallForwardInfo implements android.os.Parcelable {
ctor public ImsCallForwardInfo(int, int, int, int, @NonNull String, int);
method public int describeContents();
@@ -11212,8 +11270,107 @@ package android.telephony.ims {
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.RtpHeaderExtensionType> CREATOR;
}
+ public interface SipDelegateConnection {
+ method public void notifyMessageReceiveError(@NonNull String, int);
+ method public void notifyMessageReceived(@NonNull String);
+ method public void sendMessage(@NonNull android.telephony.ims.SipMessage, long);
+ }
+
+ public final class SipDelegateImsConfiguration implements android.os.Parcelable {
+ method public boolean containsKey(@NonNull String);
+ method @NonNull public android.os.PersistableBundle copyBundle();
+ method public int describeContents();
+ method public boolean getBoolean(@NonNull String, boolean);
+ method public int getInt(@NonNull String, int);
+ method @Nullable public String getString(@NonNull String);
+ method public long getVersion();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.SipDelegateImsConfiguration> CREATOR;
+ field public static final String IPTYPE_IPV4 = "IPV4";
+ field public static final String IPTYPE_IPV6 = "IPV6";
+ field public static final String KEY_SIP_CONFIG_AUTHENTICATION_HEADER_STRING = "sip_config_auhentication_header_string";
+ field public static final String KEY_SIP_CONFIG_AUTHENTICATION_NONCE_STRING = "sip_config_authentication_nonce_string";
+ field public static final String KEY_SIP_CONFIG_HOME_DOMAIN_STRING = "sip_config_home_domain_string";
+ field public static final String KEY_SIP_CONFIG_IMEI_STRING = "sip_config_imei_string";
+ field public static final String KEY_SIP_CONFIG_IPTYPE_STRING = "sip_config_iptype_string";
+ field public static final String KEY_SIP_CONFIG_IS_COMPACT_FORM_ENABLED_BOOL = "sip_config_is_compact_form_enabled_bool";
+ field public static final String KEY_SIP_CONFIG_IS_GRUU_ENABLED_BOOL = "sip_config_is_gruu_enabled_bool";
+ field public static final String KEY_SIP_CONFIG_IS_IPSEC_ENABLED_BOOL = "sip_config_is_ipsec_enabled_bool";
+ field public static final String KEY_SIP_CONFIG_IS_KEEPALIVE_ENABLED_BOOL = "sip_config_is_keepalive_enabled_bool";
+ field public static final String KEY_SIP_CONFIG_IS_NAT_ENABLED_BOOL = "sip_config_is_nat_enabled_bool";
+ field public static final String KEY_SIP_CONFIG_MAX_PAYLOAD_SIZE_ON_UDP_INT = "sip_config_udp_max_payload_size_int";
+ field public static final String KEY_SIP_CONFIG_PATH_HEADER_STRING = "sip_config_path_header_string";
+ field public static final String KEY_SIP_CONFIG_P_ACCESS_NETWORK_INFO_HEADER_STRING = "sip_config_p_access_network_info_header_string";
+ field public static final String KEY_SIP_CONFIG_P_ASSOCIATED_URI_HEADER_STRING = "sip_config_p_associated_uri_header_string";
+ field public static final String KEY_SIP_CONFIG_P_LAST_ACCESS_NETWORK_INFO_HEADER_STRING = "sip_config_p_last_access_network_info_header_string";
+ field public static final String KEY_SIP_CONFIG_SECURITY_VERIFY_HEADER_STRING = "sip_config_security_verify_header_string";
+ field public static final String KEY_SIP_CONFIG_SERVER_DEFAULT_IPADDRESS_STRING = "sip_config_server_default_ipaddress_string";
+ field public static final String KEY_SIP_CONFIG_SERVER_DEFAULT_PORT_INT = "sip_config_server_default_port_int";
+ field public static final String KEY_SIP_CONFIG_SERVER_IPSEC_CLIENT_PORT_INT = "sip_config_server_ipsec_client_port_int";
+ field public static final String KEY_SIP_CONFIG_SERVER_IPSEC_OLD_CLIENT_PORT_INT = "sip_config_server_ipsec_old_client_port_int";
+ field public static final String KEY_SIP_CONFIG_SERVER_IPSEC_SERVER_PORT_INT = "sip_config_server_ipsec_server_port_int";
+ field public static final String KEY_SIP_CONFIG_SERVICE_ROUTE_HEADER_STRING = "sip_config_service_route_header_string";
+ field public static final String KEY_SIP_CONFIG_TRANSPORT_TYPE_STRING = "sip_config_protocol_type_string";
+ field public static final String KEY_SIP_CONFIG_UE_DEFAULT_IPADDRESS_STRING = "sip_config_ue_default_ipaddress_string";
+ field public static final String KEY_SIP_CONFIG_UE_DEFAULT_PORT_INT = "sip_config_ue_default_port_int";
+ field public static final String KEY_SIP_CONFIG_UE_IPSEC_CLIENT_PORT_INT = "sip_config_ue_ipsec_client_port_int";
+ field public static final String KEY_SIP_CONFIG_UE_IPSEC_OLD_CLIENT_PORT_INT = "sip_config_ue_ipsec_old_client_port_int";
+ field public static final String KEY_SIP_CONFIG_UE_IPSEC_SERVER_PORT_INT = "sip_config_ue_ipsec_server_port_int";
+ field public static final String KEY_SIP_CONFIG_UE_PRIVATE_USER_ID_STRING = "sip_config_ue_private_user_id_string";
+ field public static final String KEY_SIP_CONFIG_UE_PUBLIC_GRUU_STRING = "sip_config_ue_public_gruu_string";
+ field public static final String KEY_SIP_CONFIG_UE_PUBLIC_IPADDRESS_WITH_NAT_STRING = "sip_config_ue_public_ipaddress_with_nat_string";
+ field public static final String KEY_SIP_CONFIG_UE_PUBLIC_PORT_WITH_NAT_INT = "sip_config_ue_public_port_with_nat_int";
+ field public static final String KEY_SIP_CONFIG_UE_PUBLIC_USER_ID_STRING = "sip_config_ue_public_user_id_string";
+ field public static final String KEY_SIP_CONFIG_URI_USER_PART_STRING = "sip_config_uri_user_part_string";
+ field public static final String SIP_TRANSPORT_TCP = "TCP";
+ field public static final String SIP_TRANSPORT_UDP = "UDP";
+ }
+
+ public static final class SipDelegateImsConfiguration.Builder {
+ ctor public SipDelegateImsConfiguration.Builder(int);
+ ctor public SipDelegateImsConfiguration.Builder(@NonNull android.telephony.ims.SipDelegateImsConfiguration);
+ method @NonNull public android.telephony.ims.SipDelegateImsConfiguration.Builder addBoolean(@NonNull String, boolean);
+ method @NonNull public android.telephony.ims.SipDelegateImsConfiguration.Builder addInt(@NonNull String, int);
+ method @NonNull public android.telephony.ims.SipDelegateImsConfiguration.Builder addString(@NonNull String, @NonNull String);
+ method @NonNull public android.telephony.ims.SipDelegateImsConfiguration build();
+ }
+
public class SipDelegateManager {
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void createSipDelegate(@NonNull android.telephony.ims.DelegateRequest, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.stub.DelegateConnectionStateCallback, @NonNull android.telephony.ims.stub.DelegateConnectionMessageCallback) throws android.telephony.ims.ImsException;
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void destroySipDelegate(@NonNull android.telephony.ims.SipDelegateConnection, int);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isSupported() throws android.telephony.ims.ImsException;
+ field public static final int DENIED_REASON_INVALID = 4; // 0x4
+ field public static final int DENIED_REASON_IN_USE_BY_ANOTHER_DELEGATE = 1; // 0x1
+ field public static final int DENIED_REASON_NOT_ALLOWED = 2; // 0x2
+ field public static final int DENIED_REASON_SINGLE_REGISTRATION_NOT_ALLOWED = 3; // 0x3
+ field public static final int DENIED_REASON_UNKNOWN = 0; // 0x0
+ field public static final int MESSAGE_FAILURE_REASON_DELEGATE_CLOSED = 2; // 0x2
+ field public static final int MESSAGE_FAILURE_REASON_DELEGATE_DEAD = 1; // 0x1
+ field public static final int MESSAGE_FAILURE_REASON_INTERNAL_DELEGATE_STATE_TRANSITION = 11; // 0xb
+ field public static final int MESSAGE_FAILURE_REASON_INVALID_BODY_CONTENT = 5; // 0x5
+ field public static final int MESSAGE_FAILURE_REASON_INVALID_FEATURE_TAG = 6; // 0x6
+ field public static final int MESSAGE_FAILURE_REASON_INVALID_HEADER_FIELDS = 4; // 0x4
+ field public static final int MESSAGE_FAILURE_REASON_INVALID_START_LINE = 3; // 0x3
+ field public static final int MESSAGE_FAILURE_REASON_NETWORK_NOT_AVAILABLE = 8; // 0x8
+ field public static final int MESSAGE_FAILURE_REASON_NOT_REGISTERED = 9; // 0x9
+ field public static final int MESSAGE_FAILURE_REASON_STALE_IMS_CONFIGURATION = 10; // 0xa
+ field public static final int MESSAGE_FAILURE_REASON_TAG_NOT_ENABLED_FOR_DELEGATE = 7; // 0x7
+ field public static final int MESSAGE_FAILURE_REASON_UNKNOWN = 0; // 0x0
+ field public static final int SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP = 2; // 0x2
+ field public static final int SIP_DELEGATE_DESTROY_REASON_SERVICE_DEAD = 1; // 0x1
+ field public static final int SIP_DELEGATE_DESTROY_REASON_SUBSCRIPTION_TORN_DOWN = 4; // 0x4
+ field public static final int SIP_DELEGATE_DESTROY_REASON_UNKNOWN = 0; // 0x0
+ field public static final int SIP_DELEGATE_DESTROY_REASON_USER_DISABLED_RCS = 3; // 0x3
+ }
+
+ public final class SipMessage implements android.os.Parcelable {
+ ctor public SipMessage(@NonNull String, @NonNull String, @NonNull byte[]);
+ method public int describeContents();
+ method @NonNull public byte[] getContent();
+ method @NonNull public String getHeaderSection();
+ method @NonNull public String getStartLine();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.SipMessage> CREATOR;
}
}
@@ -11307,6 +11464,19 @@ package android.telephony.ims.feature {
package android.telephony.ims.stub {
+ public interface DelegateConnectionMessageCallback {
+ method public void onMessageReceived(@NonNull android.telephony.ims.SipMessage);
+ method public void onMessageSendFailure(@NonNull String, int);
+ method public void onMessageSent(@NonNull String);
+ }
+
+ public interface DelegateConnectionStateCallback {
+ method public void onCreated(@NonNull android.telephony.ims.SipDelegateConnection);
+ method public void onDestroyed(int);
+ method public void onFeatureTagStatusChanged(@NonNull android.telephony.ims.DelegateRegistrationState, @NonNull java.util.Set<android.telephony.ims.FeatureTagState>);
+ method public void onImsConfigurationChanged(@NonNull android.telephony.ims.SipDelegateImsConfiguration);
+ }
+
public class ImsCallSessionImplBase implements java.lang.AutoCloseable {
ctor public ImsCallSessionImplBase();
method public void accept(int, android.telephony.ims.ImsStreamMediaProfile);
@@ -11467,8 +11637,17 @@ package android.telephony.ims.stub {
method public int updateColr(int);
}
+ public interface SipDelegate {
+ method public void closeDialog(@NonNull String);
+ method public void notifyMessageReceiveError(@NonNull String, int);
+ method public void notifyMessageReceived(@NonNull String);
+ method public void sendMessage(@NonNull android.telephony.ims.SipMessage, long);
+ }
+
public class SipTransportImplBase {
ctor public SipTransportImplBase(@NonNull java.util.concurrent.Executor);
+ method public void createSipDelegate(int, @NonNull android.telephony.ims.DelegateRequest, @NonNull android.telephony.ims.DelegateStateCallback, @NonNull android.telephony.ims.DelegateMessageCallback);
+ method public void destroySipDelegate(@NonNull android.telephony.ims.stub.SipDelegate, int);
}
}
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index bd09eacfebd1..4c16072cefd3 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -5195,8 +5195,8 @@ public class Activity extends ContextThemeWrapper
* result callbacks including {@link #onRequestPermissionsResult(int, String[], int[])}.
* </p>
* <p>
- * The <a href="https://github.com/googlesamples/android-RuntimePermissions">
- * RuntimePermissions</a> sample app demonstrates how to use this method to
+ * The <a href="https://github.com/android/permissions-samples">
+ * RuntimePermissions</a> sample apps demonstrate how to use this method to
* request permissions at run time.
* </p>
*
diff --git a/core/java/android/bluetooth/BluetoothLeAudio.java b/core/java/android/bluetooth/BluetoothLeAudio.java
new file mode 100644
index 000000000000..3f00fa6f4181
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothLeAudio.java
@@ -0,0 +1,451 @@
+/*
+ * Copyright 2020 HIMSA II K/S - www.himsa.com.
+ * Represented by EHIMA - www.ehima.com
+ *
+ * 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.bluetooth;
+
+import android.Manifest;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
+import android.content.Context;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.CloseGuard;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This class provides the public APIs to control the LeAudio profile.
+ *
+ * <p>BluetoothLeAudio is a proxy object for controlling the Bluetooth LE Audio
+ * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get
+ * the BluetoothLeAudio proxy object.
+ *
+ * <p> Android only supports one set of connected Bluetooth LeAudio device at a time. Each
+ * method is protected with its appropriate permission.
+ */
+public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable {
+ private static final String TAG = "BluetoothLeAudio";
+ private static final boolean DBG = false;
+ private static final boolean VDBG = false;
+
+ private CloseGuard mCloseGuard;
+
+ /**
+ * Intent used to broadcast the change in connection state of the LeAudio
+ * profile. Please note that in the binaural case, there will be two different LE devices for
+ * the left and right side and each device will have their own connection state changes.
+ *
+ * <p>This intent will have 3 extras:
+ * <ul>
+ * <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
+ * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li>
+ * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
+ * </ul>
+ *
+ * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
+ * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
+ * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
+ * receive.
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED =
+ "android.bluetooth.action.LE_AUDIO_CONNECTION_STATE_CHANGED";
+
+ /**
+ * Intent used to broadcast the selection of a connected device as active.
+ *
+ * <p>This intent will have one extra:
+ * <ul>
+ * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. It can
+ * be null if no device is active. </li>
+ * </ul>
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
+ * receive.
+ *
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED =
+ "android.bluetooth.action.LE_AUDIO_ACTIVE_DEVICE_CHANGED";
+
+ /**
+ * This represents an invalid group ID.
+ *
+ * @hide
+ */
+ public static final int GROUP_ID_INVALID = IBluetoothLeAudio.LE_AUDIO_GROUP_ID_INVALID;
+
+ private BluetoothAdapter mAdapter;
+ private final BluetoothProfileConnector<IBluetoothLeAudio> mProfileConnector =
+ new BluetoothProfileConnector(this, BluetoothProfile.LE_AUDIO, "BluetoothLeAudio",
+ IBluetoothLeAudio.class.getName()) {
+ @Override
+ public IBluetoothLeAudio getServiceInterface(IBinder service) {
+ return IBluetoothLeAudio.Stub.asInterface(Binder.allowBlocking(service));
+ }
+ };
+
+ /**
+ * Create a BluetoothLeAudio proxy object for interacting with the local
+ * Bluetooth LeAudio service.
+ */
+ /*package*/ BluetoothLeAudio(Context context, ServiceListener listener) {
+ mAdapter = BluetoothAdapter.getDefaultAdapter();
+ mProfileConnector.connect(context, listener);
+ mCloseGuard = new CloseGuard();
+ mCloseGuard.open("close");
+ }
+
+ /**
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+ public void close() {
+ mProfileConnector.disconnect();
+ }
+
+ private IBluetoothLeAudio getService() {
+ return mProfileConnector.getService();
+ }
+
+ @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+ protected void finalize() {
+ if (mCloseGuard != null) {
+ mCloseGuard.warnIfOpen();
+ }
+ close();
+ }
+
+ /**
+ * Initiate connection to a profile of the remote bluetooth device.
+ *
+ * <p> This API returns false in scenarios like the profile on the
+ * device is already connected or Bluetooth is not turned on.
+ * When this API returns true, it is guaranteed that
+ * connection state intent for the profile will be broadcasted with
+ * the state. Users can get the connection state of the profile
+ * from this intent.
+ *
+ *
+ * @param device Remote Bluetooth Device
+ * @return false on immediate error, true otherwise
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+ public boolean connect(@Nullable BluetoothDevice device) {
+ if (DBG) log("connect(" + device + ")");
+ try {
+ final IBluetoothLeAudio service = getService();
+ if (service != null && mAdapter.isEnabled() && isValidDevice(device)) {
+ return service.connect(device);
+ }
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
+ return false;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return false;
+ }
+ }
+
+ /**
+ * Initiate disconnection from a profile
+ *
+ * <p> This API will return false in scenarios like the profile on the
+ * Bluetooth device is not in connected state etc. When this API returns,
+ * true, it is guaranteed that the connection state change
+ * intent will be broadcasted with the state. Users can get the
+ * disconnection state of the profile from this intent.
+ *
+ * <p> If the disconnection is initiated by a remote device, the state
+ * will transition from {@link #STATE_CONNECTED} to
+ * {@link #STATE_DISCONNECTED}. If the disconnect is initiated by the
+ * host (local) device the state will transition from
+ * {@link #STATE_CONNECTED} to state {@link #STATE_DISCONNECTING} to
+ * state {@link #STATE_DISCONNECTED}. The transition to
+ * {@link #STATE_DISCONNECTING} can be used to distinguish between the
+ * two scenarios.
+ *
+ *
+ * @param device Remote Bluetooth Device
+ * @return false on immediate error, true otherwise
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+ public boolean disconnect(@Nullable BluetoothDevice device) {
+ if (DBG) log("disconnect(" + device + ")");
+ try {
+ final IBluetoothLeAudio service = getService();
+ if (service != null && mAdapter.isEnabled() && isValidDevice(device)) {
+ return service.disconnect(device);
+ }
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
+ return false;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return false;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public @NonNull List<BluetoothDevice> getConnectedDevices() {
+ if (VDBG) log("getConnectedDevices()");
+ try {
+ final IBluetoothLeAudio service = getService();
+ if (service != null && mAdapter.isEnabled()) {
+ return service.getConnectedDevices();
+ }
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
+ return new ArrayList<BluetoothDevice>();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return new ArrayList<BluetoothDevice>();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public @NonNull List<BluetoothDevice> getDevicesMatchingConnectionStates(
+ @NonNull int[] states) {
+ if (VDBG) log("getDevicesMatchingStates()");
+ try {
+ final IBluetoothLeAudio service = getService();
+ if (service != null && mAdapter.isEnabled()) {
+ return service.getDevicesMatchingConnectionStates(states);
+ }
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
+ return new ArrayList<BluetoothDevice>();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return new ArrayList<BluetoothDevice>();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
+ public @BtProfileState int getConnectionState(@NonNull BluetoothDevice device) {
+ if (VDBG) log("getState(" + device + ")");
+ try {
+ final IBluetoothLeAudio service = getService();
+ if (service != null && mAdapter.isEnabled()
+ && isValidDevice(device)) {
+ return service.getConnectionState(device);
+ }
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
+ return BluetoothProfile.STATE_DISCONNECTED;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return BluetoothProfile.STATE_DISCONNECTED;
+ }
+ }
+
+ /**
+ * Select a connected device as active.
+ *
+ * The active device selection is per profile. An active device's
+ * purpose is profile-specific. For example, LeAudio audio
+ * streaming is to the active LeAudio device. If a remote device
+ * is not connected, it cannot be selected as active.
+ *
+ * <p> This API returns false in scenarios like the profile on the
+ * device is not connected or Bluetooth is not turned on.
+ * When this API returns true, it is guaranteed that the
+ * {@link #ACTION_LEAUDIO_ACTIVE_DEVICE_CHANGED} intent will be broadcasted
+ * with the active device.
+ *
+ *
+ * @param device the remote Bluetooth device. Could be null to clear
+ * the active device and stop streaming audio to a Bluetooth device.
+ * @return false on immediate error, true otherwise
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+ public boolean setActiveDevice(@Nullable BluetoothDevice device) {
+ if (DBG) log("setActiveDevice(" + device + ")");
+ try {
+ final IBluetoothLeAudio service = getService();
+ if (service != null && mAdapter.isEnabled()
+ && ((device == null) || isValidDevice(device))) {
+ service.setActiveDevice(device);
+ return true;
+ }
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
+ return false;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return false;
+ }
+ }
+
+ /**
+ * Get the connected LeAudio devices that are active
+ *
+ * @return the list of active devices. Returns empty list on error.
+ * @hide
+ */
+ @NonNull
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
+ public List<BluetoothDevice> getActiveDevices() {
+ if (VDBG) log("getActiveDevices()");
+ try {
+ final IBluetoothLeAudio service = getService();
+ if (service != null && mAdapter.isEnabled()) {
+ return service.getActiveDevices();
+ }
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
+ return new ArrayList<>();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return new ArrayList<>();
+ }
+ }
+
+ /**
+ * Get device group id. Devices with same group id belong to same group (i.e left and right
+ * earbud)
+ * @param device LE Audio capable device
+ * @return group id that this device currently belongs to
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
+ public int getGroupId(@NonNull BluetoothDevice device) {
+ if (VDBG) log("getGroupId()");
+ try {
+ final IBluetoothLeAudio service = getService();
+ if (service != null && mAdapter.isEnabled()) {
+ return service.getGroupId(device);
+ }
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
+ return GROUP_ID_INVALID;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return GROUP_ID_INVALID;
+ }
+ }
+
+ /**
+ * Set connection policy of the profile
+ *
+ * <p> The device should already be paired.
+ * Connection policy can be one of {@link #CONNECTION_POLICY_ALLOWED},
+ * {@link #CONNECTION_POLICY_FORBIDDEN}, {@link #CONNECTION_POLICY_UNKNOWN}
+ *
+ * @param device Paired bluetooth device
+ * @param connectionPolicy is the connection policy to set to for this profile
+ * @return true if connectionPolicy is set, false on error
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+ public boolean setConnectionPolicy(@NonNull BluetoothDevice device,
+ @ConnectionPolicy int connectionPolicy) {
+ if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
+ try {
+ final IBluetoothLeAudio service = getService();
+ if (service != null && mAdapter.isEnabled()
+ && isValidDevice(device)) {
+ if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
+ && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
+ return false;
+ }
+ return service.setConnectionPolicy(device, connectionPolicy);
+ }
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
+ return false;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return false;
+ }
+ }
+
+ /**
+ * Get the connection policy of the profile.
+ *
+ * <p> The connection policy can be any of:
+ * {@link #CONNECTION_POLICY_ALLOWED}, {@link #CONNECTION_POLICY_FORBIDDEN},
+ * {@link #CONNECTION_POLICY_UNKNOWN}
+ *
+ * @param device Bluetooth device
+ * @return connection policy of the device
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+ public @ConnectionPolicy int getConnectionPolicy(@Nullable BluetoothDevice device) {
+ if (VDBG) log("getConnectionPolicy(" + device + ")");
+ try {
+ final IBluetoothLeAudio service = getService();
+ if (service != null && mAdapter.isEnabled()
+ && isValidDevice(device)) {
+ return service.getConnectionPolicy(device);
+ }
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
+ return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
+ }
+ }
+
+
+ /**
+ * Helper for converting a state to a string.
+ *
+ * For debug use only - strings are not internationalized.
+ *
+ * @hide
+ */
+ public static String stateToString(int state) {
+ switch (state) {
+ case STATE_DISCONNECTED:
+ return "disconnected";
+ case STATE_CONNECTING:
+ return "connecting";
+ case STATE_CONNECTED:
+ return "connected";
+ case STATE_DISCONNECTING:
+ return "disconnecting";
+ default:
+ return "<unknown state " + state + ">";
+ }
+ }
+
+ private boolean isValidDevice(@Nullable BluetoothDevice device) {
+ if (device == null) return false;
+
+ if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
+ return false;
+ }
+
+ private static void log(String msg) {
+ Log.d(TAG, msg);
+ }
+}
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
index db851c4f33b9..c31b04e81456 100644
--- a/core/java/android/bluetooth/BluetoothProfile.java
+++ b/core/java/android/bluetooth/BluetoothProfile.java
@@ -207,12 +207,19 @@ public interface BluetoothProfile {
int HEARING_AID = 21;
/**
+ * LE Audio Device
+ *
+ * @hide
+ */
+ int LE_AUDIO = 22;
+
+ /**
* Max profile ID. This value should be updated whenever a new profile is added to match
* the largest value assigned to a profile.
*
* @hide
*/
- int MAX_PROFILE_ID = 21;
+ int MAX_PROFILE_ID = 22;
/**
* Default priority for devices that we try to auto-connect to and
diff --git a/core/java/android/hardware/hdmi/HdmiDeviceInfo.java b/core/java/android/hardware/hdmi/HdmiDeviceInfo.java
index 55b07268d201..6b2bab4f5a4f 100644
--- a/core/java/android/hardware/hdmi/HdmiDeviceInfo.java
+++ b/core/java/android/hardware/hdmi/HdmiDeviceInfo.java
@@ -513,4 +513,19 @@ public class HdmiDeviceInfo implements Parcelable {
&& mDeviceId == other.mDeviceId
&& mAdopterId == other.mAdopterId;
}
+
+ @Override
+ public int hashCode() {
+ return java.util.Objects.hash(
+ mHdmiDeviceType,
+ mPhysicalAddress,
+ mPortId,
+ mLogicalAddress,
+ mDeviceType,
+ mVendorId,
+ mDevicePowerStatus,
+ mDisplayName,
+ mDeviceId,
+ mAdopterId);
+ }
}
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index c28a901fba75..cf5d4e579f85 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -684,7 +684,7 @@ public class ConnectivityManager {
* {@hide}
*/
@Deprecated
- @UnsupportedAppUsage
+ @SystemApi
public static final int TYPE_PROXY = 16;
/**
diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java
index 44ebff99f3e9..0676ad4e2322 100644
--- a/core/java/android/net/NetworkAgent.java
+++ b/core/java/android/net/NetworkAgent.java
@@ -40,6 +40,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.time.Duration;
import java.util.ArrayList;
+import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -174,6 +175,14 @@ public abstract class NetworkAgent {
public static final int EVENT_NETWORK_SCORE_CHANGED = BASE + 4;
/**
+ * Sent by the NetworkAgent to ConnectivityService to pass the current
+ * list of underlying networks.
+ * obj = array of Network objects
+ * @hide
+ */
+ public static final int EVENT_UNDERLYING_NETWORKS_CHANGED = BASE + 5;
+
+ /**
* Sent by ConnectivityService to the NetworkAgent to inform the agent of the
* networks status - whether we could use the network or could not, due to
* either a bad network configuration (no internet link) or captive portal.
@@ -217,7 +226,13 @@ public abstract class NetworkAgent {
* The key for the redirect URL in the Bundle argument of {@code CMD_REPORT_NETWORK_STATUS}.
* @hide
*/
- public static String REDIRECT_URL_KEY = "redirect URL";
+ public static final String REDIRECT_URL_KEY = "redirect URL";
+
+ /**
+ * Bundle key for the underlying networks in {@code EVENT_UNDERLYING_NETWORKS_CHANGED}.
+ * @hide
+ */
+ public static final String UNDERLYING_NETWORKS_KEY = "underlyingNetworks";
/**
* Sent by the NetworkAgent to ConnectivityService to indicate this network was
@@ -650,6 +665,33 @@ public abstract class NetworkAgent {
}
/**
+ * Must be called by the agent when the network's underlying networks change.
+ *
+ * <p>{@code networks} is one of the following:
+ * <ul>
+ * <li><strong>a non-empty array</strong>: an array of one or more {@link Network}s, in
+ * decreasing preference order. For example, if this VPN uses both wifi and mobile (cellular)
+ * networks to carry app traffic, but prefers or uses wifi more than mobile, wifi should appear
+ * first in the array.</li>
+ * <li><strong>an empty array</strong>: a zero-element array, meaning that the VPN has no
+ * underlying network connection, and thus, app traffic will not be sent or received.</li>
+ * <li><strong>null</strong>: (default) signifies that the VPN uses whatever is the system's
+ * default network. I.e., it doesn't use the {@code bindSocket} or {@code bindDatagramSocket}
+ * APIs mentioned above to send traffic over specific channels.</li>
+ * </ul>
+ *
+ * @param underlyingNetworks the new list of underlying networks.
+ * @see {@link VpnService.Builder#setUnderlyingNetworks(Network[])}
+ */
+ public final void setUnderlyingNetworks(@Nullable List<Network> underlyingNetworks) {
+ final ArrayList<Network> underlyingArray = (underlyingNetworks != null)
+ ? new ArrayList<>(underlyingNetworks) : null;
+ final Bundle bundle = new Bundle();
+ bundle.putParcelableArrayList(UNDERLYING_NETWORKS_KEY, underlyingArray);
+ queueOrSendMessage(EVENT_UNDERLYING_NETWORKS_CHANGED, bundle);
+ }
+
+ /**
* Inform ConnectivityService that this agent has now connected.
* Call {@link #unregister} to disconnect.
*/
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index 40bb8bf11d0b..8dad11ffa731 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -712,6 +712,7 @@ public final class NetworkCapabilities implements Parcelable {
if (ArrayUtils.contains(originalAdministratorUids, creatorUid)) {
setAdministratorUids(new int[] {creatorUid});
}
+ // There is no need to clear the UIDs, they have already been cleared by clearAll() above.
}
/**
@@ -805,7 +806,9 @@ public final class NetworkCapabilities implements Parcelable {
*/
private static final int TEST_NETWORKS_ALLOWED_TRANSPORTS = 1 << TRANSPORT_TEST
// Test ethernet networks can be created with EthernetManager#setIncludeTestInterfaces
- | 1 << TRANSPORT_ETHERNET;
+ | 1 << TRANSPORT_ETHERNET
+ // Test VPN networks can be created but their UID ranges must be empty.
+ | 1 << TRANSPORT_VPN;
/**
* Adds the given transport type to this {@code NetworkCapability} instance.
diff --git a/core/java/android/net/NetworkProvider.java b/core/java/android/net/NetworkProvider.java
index d31218d9b67b..a17a49897d39 100644
--- a/core/java/android/net/NetworkProvider.java
+++ b/core/java/android/net/NetworkProvider.java
@@ -51,13 +51,6 @@ public class NetworkProvider {
public static final int ID_NONE = -1;
/**
- * A hardcoded ID for NetworkAgents representing VPNs. These agents are not created by any
- * provider, so they use this constant for clarity instead of NONE.
- * @hide only used by ConnectivityService.
- */
- public static final int ID_VPN = -2;
-
- /**
* The first providerId value that will be allocated.
* @hide only used by ConnectivityService.
*/
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 8926b2740d6e..67d5f5f205cc 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -3172,28 +3172,55 @@ public class UserManager {
}
/**
- * Returns information for all users on this device, including ones marked for deletion.
- * To retrieve only users that are alive, use {@link #getUsers(boolean)}.
+ * Returns information for all fully-created users on this device, including ones marked for
+ * deletion.
+ *
+ * <p>To retrieve only users that are not marked for deletion, use {@link #getAliveUsers()}.
+ *
+ * <p>To retrieve *all* users (including partial and pre-created users), use
+ * {@link #getUsers(boolean, boolean, boolean)) getUsers(false, false, false)}.
+ *
+ * <p>To retrieve a more specific list of users, use
+ * {@link #getUsers(boolean, boolean, boolean)}.
+ *
+ * @return the list of users that were created.
*
- * @return the list of users that exist on the device.
* @hide
*/
@UnsupportedAppUsage
@RequiresPermission(android.Manifest.permission.MANAGE_USERS)
public List<UserInfo> getUsers() {
- return getUsers(/* excludeDying= */ false);
+ return getUsers(/*excludePartial= */ true, /* excludeDying= */ false,
+ /* excludePreCreated= */ true);
}
/**
- * Returns information for all users on this device. Requires
- * {@link android.Manifest.permission#MANAGE_USERS} permission.
+ * Returns information for all "usable" users on this device (i.e, it excludes users that are
+ * marked for deletion, pre-created users, etc...).
+ *
+ * <p>To retrieve all fully-created users, use {@link #getUsers()}.
+ *
+ * <p>To retrieve a more specific list of users, use
+ * {@link #getUsers(boolean, boolean, boolean)}.
*
- * @param excludeDying specify if the list should exclude users being
- * removed.
* @return the list of users that were created.
* @hide
*/
+ @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+ public @NonNull List<UserInfo> getAliveUsers() {
+ return getUsers(/*excludePartial= */ true, /* excludeDying= */ true,
+ /* excludePreCreated= */ true);
+ }
+
+ /**
+ * @deprecated use {@link #getAliveUsers()} for {@code getUsers(true)}, or
+ * {@link #getUsers()} for @code getUsers(false)}.
+ *
+ * @hide
+ */
+ @Deprecated
@UnsupportedAppUsage
+ @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
public @NonNull List<UserInfo> getUsers(boolean excludeDying) {
return getUsers(/*excludePartial= */ true, excludeDying,
/* excludePreCreated= */ true);
diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java
index 8be4bfde2fa6..769a34eed1dc 100644
--- a/core/java/android/os/VibrationEffect.java
+++ b/core/java/android/os/VibrationEffect.java
@@ -1083,8 +1083,7 @@ public abstract class VibrationEffect implements Parcelable {
*
* @param primitiveId The primitive to add
* @param scale The scale to apply to the intensity of the primitive.
- * @param delay The amount of time, in milliseconds, to wait between playing the prior
- * primitive and this one
+ * @param delay The amount of time in milliseconds to wait before playing this primitive
* @return The {@link Composition} object to enable adding multiple primitives in one chain.
*/
@NonNull
diff --git a/core/java/android/os/storage/VolumeInfo.java b/core/java/android/os/storage/VolumeInfo.java
index e6bb08836aee..3edc154656c3 100644
--- a/core/java/android/os/storage/VolumeInfo.java
+++ b/core/java/android/os/storage/VolumeInfo.java
@@ -200,6 +200,21 @@ public class VolumeInfo implements Parcelable {
internalPath = parcel.readString8();
}
+ public VolumeInfo(VolumeInfo volumeInfo) {
+ this.id = volumeInfo.id;
+ this.type = volumeInfo.type;
+ this.disk = volumeInfo.disk;
+ this.partGuid = volumeInfo.partGuid;
+ this.mountFlags = volumeInfo.mountFlags;
+ this.mountUserId = volumeInfo.mountUserId;
+ this.state = volumeInfo.state;
+ this.fsType = volumeInfo.fsType;
+ this.fsUuid = volumeInfo.fsUuid;
+ this.fsLabel = volumeInfo.fsLabel;
+ this.path = volumeInfo.path;
+ this.internalPath = volumeInfo.internalPath;
+ }
+
@UnsupportedAppUsage
public static @NonNull String getEnvironmentForState(int state) {
final String envState = sStateToEnvironment.get(state);
diff --git a/core/java/android/security/keymaster/KeymasterDefs.java b/core/java/android/security/keymaster/KeymasterDefs.java
index 18921639f55d..6ef9e7e3d9b8 100644
--- a/core/java/android/security/keymaster/KeymasterDefs.java
+++ b/core/java/android/security/keymaster/KeymasterDefs.java
@@ -16,6 +16,19 @@
package android.security.keymaster;
+import android.hardware.keymint.Algorithm;
+import android.hardware.keymint.BlockMode;
+import android.hardware.keymint.Digest;
+import android.hardware.keymint.ErrorCode;
+import android.hardware.keymint.HardwareAuthenticatorType;
+import android.hardware.keymint.KeyFormat;
+import android.hardware.keymint.KeyOrigin;
+import android.hardware.keymint.KeyPurpose;
+import android.hardware.keymint.PaddingMode;
+import android.hardware.keymint.SecurityLevel;
+import android.hardware.keymint.Tag;
+import android.hardware.keymint.TagType;
+
import java.util.HashMap;
import java.util.Map;
@@ -30,206 +43,284 @@ public final class KeymasterDefs {
private KeymasterDefs() {}
// Tag types.
- public static final int KM_INVALID = 0 << 28;
- public static final int KM_ENUM = 1 << 28;
- public static final int KM_ENUM_REP = 2 << 28;
- public static final int KM_UINT = 3 << 28;
- public static final int KM_UINT_REP = 4 << 28;
- public static final int KM_ULONG = 5 << 28;
- public static final int KM_DATE = 6 << 28;
- public static final int KM_BOOL = 7 << 28;
- public static final int KM_BIGNUM = 8 << 28;
- public static final int KM_BYTES = 9 << 28;
- public static final int KM_ULONG_REP = 10 << 28;
+ public static final int KM_INVALID = TagType.INVALID;
+ public static final int KM_ENUM = TagType.ENUM;
+ public static final int KM_ENUM_REP = TagType.ENUM_REP;
+ public static final int KM_UINT = TagType.UINT;
+ public static final int KM_UINT_REP = TagType.UINT_REP;
+ public static final int KM_ULONG = TagType.ULONG;
+ public static final int KM_DATE = TagType.DATE;
+ public static final int KM_BOOL = TagType.BOOL;
+ public static final int KM_BIGNUM = TagType.BIGNUM;
+ public static final int KM_BYTES = TagType.BYTES;
+ public static final int KM_ULONG_REP = TagType.ULONG_REP;
// Tag values.
- public static final int KM_TAG_INVALID = KM_INVALID | 0;
- public static final int KM_TAG_PURPOSE = KM_ENUM_REP | 1;
- public static final int KM_TAG_ALGORITHM = KM_ENUM | 2;
- public static final int KM_TAG_KEY_SIZE = KM_UINT | 3;
- public static final int KM_TAG_BLOCK_MODE = KM_ENUM_REP | 4;
- public static final int KM_TAG_DIGEST = KM_ENUM_REP | 5;
- public static final int KM_TAG_PADDING = KM_ENUM_REP | 6;
- public static final int KM_TAG_CALLER_NONCE = KM_BOOL | 7;
- public static final int KM_TAG_MIN_MAC_LENGTH = KM_UINT | 8;
+ public static final int KM_TAG_INVALID = Tag.INVALID; // KM_INVALID | 0;
+ public static final int KM_TAG_PURPOSE = Tag.PURPOSE; // KM_ENUM_REP | 1;
+ public static final int KM_TAG_ALGORITHM = Tag.ALGORITHM; // KM_ENUM | 2;
+ public static final int KM_TAG_KEY_SIZE = Tag.KEY_SIZE; // KM_UINT | 3;
+ public static final int KM_TAG_BLOCK_MODE = Tag.BLOCK_MODE; // KM_ENUM_REP | 4;
+ public static final int KM_TAG_DIGEST = Tag.DIGEST; // KM_ENUM_REP | 5;
+ public static final int KM_TAG_PADDING = Tag.PADDING; // KM_ENUM_REP | 6;
+ public static final int KM_TAG_CALLER_NONCE = Tag.CALLER_NONCE; // KM_BOOL | 7;
+ public static final int KM_TAG_MIN_MAC_LENGTH = Tag.MIN_MAC_LENGTH; // KM_UINT | 8;
- public static final int KM_TAG_RESCOPING_ADD = KM_ENUM_REP | 101;
- public static final int KM_TAG_RESCOPING_DEL = KM_ENUM_REP | 102;
- public static final int KM_TAG_BLOB_USAGE_REQUIREMENTS = KM_ENUM | 705;
+ public static final int KM_TAG_BLOB_USAGE_REQUIREMENTS =
+ Tag.BLOB_USAGE_REQUIREMENTS; // KM_ENUM | 705;
- public static final int KM_TAG_RSA_PUBLIC_EXPONENT = KM_ULONG | 200;
- public static final int KM_TAG_INCLUDE_UNIQUE_ID = KM_BOOL | 202;
+ public static final int KM_TAG_RSA_PUBLIC_EXPONENT = Tag.RSA_PUBLIC_EXPONENT; // KM_ULONG | 200;
+ public static final int KM_TAG_INCLUDE_UNIQUE_ID = Tag.INCLUDE_UNIQUE_ID; // KM_BOOL | 202;
- public static final int KM_TAG_ACTIVE_DATETIME = KM_DATE | 400;
- public static final int KM_TAG_ORIGINATION_EXPIRE_DATETIME = KM_DATE | 401;
- public static final int KM_TAG_USAGE_EXPIRE_DATETIME = KM_DATE | 402;
- public static final int KM_TAG_MIN_SECONDS_BETWEEN_OPS = KM_UINT | 403;
- public static final int KM_TAG_MAX_USES_PER_BOOT = KM_UINT | 404;
+ public static final int KM_TAG_ACTIVE_DATETIME = Tag.ACTIVE_DATETIME; // KM_DATE | 400;
+ public static final int KM_TAG_ORIGINATION_EXPIRE_DATETIME =
+ Tag.ORIGINATION_EXPIRE_DATETIME; // KM_DATE | 401;
+ public static final int KM_TAG_USAGE_EXPIRE_DATETIME =
+ Tag.USAGE_EXPIRE_DATETIME; // KM_DATE | 402;
+ public static final int KM_TAG_MIN_SECONDS_BETWEEN_OPS =
+ Tag.MIN_SECONDS_BETWEEN_OPS; // KM_UINT | 403;
+ public static final int KM_TAG_MAX_USES_PER_BOOT = Tag.MAX_USES_PER_BOOT; // KM_UINT | 404;
- public static final int KM_TAG_ALL_USERS = KM_BOOL | 500;
- public static final int KM_TAG_USER_ID = KM_UINT | 501;
- public static final int KM_TAG_USER_SECURE_ID = KM_ULONG_REP | 502;
- public static final int KM_TAG_NO_AUTH_REQUIRED = KM_BOOL | 503;
- public static final int KM_TAG_USER_AUTH_TYPE = KM_ENUM | 504;
- public static final int KM_TAG_AUTH_TIMEOUT = KM_UINT | 505;
- public static final int KM_TAG_ALLOW_WHILE_ON_BODY = KM_BOOL | 506;
- public static final int KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED = KM_BOOL | 507;
- public static final int KM_TAG_TRUSTED_CONFIRMATION_REQUIRED = KM_BOOL | 508;
- public static final int KM_TAG_UNLOCKED_DEVICE_REQUIRED = KM_BOOL | 509;
+ public static final int KM_TAG_USER_ID = Tag.USER_ID; // KM_UINT | 501;
+ public static final int KM_TAG_USER_SECURE_ID = Tag.USER_SECURE_ID; // KM_ULONG_REP | 502;
+ public static final int KM_TAG_NO_AUTH_REQUIRED = Tag.NO_AUTH_REQUIRED; // KM_BOOL | 503;
+ public static final int KM_TAG_USER_AUTH_TYPE = Tag.USER_AUTH_TYPE; // KM_ENUM | 504;
+ public static final int KM_TAG_AUTH_TIMEOUT = Tag.AUTH_TIMEOUT; // KM_UINT | 505;
+ public static final int KM_TAG_ALLOW_WHILE_ON_BODY = Tag.ALLOW_WHILE_ON_BODY; // KM_BOOL | 506;
+ public static final int KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED =
+ Tag.TRUSTED_USER_PRESENCE_REQUIRED; // KM_BOOL | 507;
+ public static final int KM_TAG_TRUSTED_CONFIRMATION_REQUIRED =
+ Tag.TRUSTED_CONFIRMATION_REQUIRED; // KM_BOOL | 508;
+ public static final int KM_TAG_UNLOCKED_DEVICE_REQUIRED =
+ Tag.UNLOCKED_DEVICE_REQUIRED; // KM_BOOL | 509;
- public static final int KM_TAG_ALL_APPLICATIONS = KM_BOOL | 600;
- public static final int KM_TAG_APPLICATION_ID = KM_BYTES | 601;
+ public static final int KM_TAG_APPLICATION_ID = Tag.APPLICATION_ID; // KM_BYTES | 601;
- public static final int KM_TAG_CREATION_DATETIME = KM_DATE | 701;
- public static final int KM_TAG_ORIGIN = KM_ENUM | 702;
- public static final int KM_TAG_ROLLBACK_RESISTANT = KM_BOOL | 703;
- public static final int KM_TAG_ROOT_OF_TRUST = KM_BYTES | 704;
- public static final int KM_TAG_UNIQUE_ID = KM_BYTES | 707;
- public static final int KM_TAG_ATTESTATION_CHALLENGE = KM_BYTES | 708;
- public static final int KM_TAG_ATTESTATION_ID_BRAND = KM_BYTES | 710;
- public static final int KM_TAG_ATTESTATION_ID_DEVICE = KM_BYTES | 711;
- public static final int KM_TAG_ATTESTATION_ID_PRODUCT = KM_BYTES | 712;
- public static final int KM_TAG_ATTESTATION_ID_SERIAL = KM_BYTES | 713;
- public static final int KM_TAG_ATTESTATION_ID_IMEI = KM_BYTES | 714;
- public static final int KM_TAG_ATTESTATION_ID_MEID = KM_BYTES | 715;
- public static final int KM_TAG_ATTESTATION_ID_MANUFACTURER = KM_BYTES | 716;
- public static final int KM_TAG_ATTESTATION_ID_MODEL = KM_BYTES | 717;
- public static final int KM_TAG_VENDOR_PATCHLEVEL = KM_UINT | 718;
- public static final int KM_TAG_BOOT_PATCHLEVEL = KM_UINT | 719;
- public static final int KM_TAG_DEVICE_UNIQUE_ATTESTATION = KM_BOOL | 720;
+ public static final int KM_TAG_CREATION_DATETIME = Tag.CREATION_DATETIME; // KM_DATE | 701;
+ public static final int KM_TAG_ORIGIN = Tag.ORIGIN; // KM_ENUM | 702;
+ public static final int KM_TAG_ROLLBACK_RESISTANT = Tag.ROLLBACK_RESISTANCE; // KM_BOOL | 703;
+ public static final int KM_TAG_ROOT_OF_TRUST = Tag.ROOT_OF_TRUST; // KM_BYTES | 704;
+ public static final int KM_TAG_UNIQUE_ID = Tag.UNIQUE_ID; // KM_BYTES | 707;
+ public static final int KM_TAG_ATTESTATION_CHALLENGE =
+ Tag.ATTESTATION_CHALLENGE; // KM_BYTES | 708;
+ public static final int KM_TAG_ATTESTATION_ID_BRAND =
+ Tag.ATTESTATION_ID_BRAND; // KM_BYTES | 710;
+ public static final int KM_TAG_ATTESTATION_ID_DEVICE =
+ Tag.ATTESTATION_ID_DEVICE; // KM_BYTES | 711;
+ public static final int KM_TAG_ATTESTATION_ID_PRODUCT =
+ Tag.ATTESTATION_ID_PRODUCT; // KM_BYTES | 712;
+ public static final int KM_TAG_ATTESTATION_ID_SERIAL =
+ Tag.ATTESTATION_ID_SERIAL; // KM_BYTES | 713;
+ public static final int KM_TAG_ATTESTATION_ID_IMEI =
+ Tag.ATTESTATION_ID_IMEI; // KM_BYTES | 714;
+ public static final int KM_TAG_ATTESTATION_ID_MEID =
+ Tag.ATTESTATION_ID_MEID; // KM_BYTES | 715;
+ public static final int KM_TAG_ATTESTATION_ID_MANUFACTURER =
+ Tag.ATTESTATION_ID_MANUFACTURER; // KM_BYTES | 716;
+ public static final int KM_TAG_ATTESTATION_ID_MODEL =
+ Tag.ATTESTATION_ID_MODEL; // KM_BYTES | 717;
+ public static final int KM_TAG_VENDOR_PATCHLEVEL =
+ Tag.VENDOR_PATCHLEVEL; // KM_UINT | 718;
+ public static final int KM_TAG_BOOT_PATCHLEVEL =
+ Tag.BOOT_PATCHLEVEL; // KM_UINT | 719;
+ public static final int KM_TAG_DEVICE_UNIQUE_ATTESTATION =
+ Tag.DEVICE_UNIQUE_ATTESTATION; // KM_BOOL | 720;
- public static final int KM_TAG_ASSOCIATED_DATA = KM_BYTES | 1000;
- public static final int KM_TAG_NONCE = KM_BYTES | 1001;
- public static final int KM_TAG_AUTH_TOKEN = KM_BYTES | 1002;
- public static final int KM_TAG_MAC_LENGTH = KM_UINT | 1003;
+ public static final int KM_TAG_ASSOCIATED_DATA = Tag.ASSOCIATED_DATA; // KM_BYTES | 1000;
+ public static final int KM_TAG_NONCE = Tag.NONCE; // KM_BYTES | 1001;
+ public static final int KM_TAG_MAC_LENGTH = Tag.MAC_LENGTH; // KM_UINT | 1003;
// Algorithm values.
- public static final int KM_ALGORITHM_RSA = 1;
- public static final int KM_ALGORITHM_EC = 3;
- public static final int KM_ALGORITHM_AES = 32;
- public static final int KM_ALGORITHM_3DES = 33;
- public static final int KM_ALGORITHM_HMAC = 128;
+ public static final int KM_ALGORITHM_RSA = Algorithm.RSA;
+ public static final int KM_ALGORITHM_EC = Algorithm.EC;
+ public static final int KM_ALGORITHM_AES = Algorithm.AES;
+ public static final int KM_ALGORITHM_3DES = Algorithm.TRIPLE_DES;
+ public static final int KM_ALGORITHM_HMAC = Algorithm.HMAC;
// Block modes.
- public static final int KM_MODE_ECB = 1;
- public static final int KM_MODE_CBC = 2;
- public static final int KM_MODE_CTR = 3;
- public static final int KM_MODE_GCM = 32;
+ public static final int KM_MODE_ECB = BlockMode.ECB;
+ public static final int KM_MODE_CBC = BlockMode.CBC;
+ public static final int KM_MODE_CTR = BlockMode.CTR;
+ public static final int KM_MODE_GCM = BlockMode.GCM;
// Padding modes.
- public static final int KM_PAD_NONE = 1;
- public static final int KM_PAD_RSA_OAEP = 2;
- public static final int KM_PAD_RSA_PSS = 3;
- public static final int KM_PAD_RSA_PKCS1_1_5_ENCRYPT = 4;
- public static final int KM_PAD_RSA_PKCS1_1_5_SIGN = 5;
- public static final int KM_PAD_PKCS7 = 64;
+ public static final int KM_PAD_NONE = PaddingMode.NONE;
+ public static final int KM_PAD_RSA_OAEP = PaddingMode.RSA_OAEP;
+ public static final int KM_PAD_RSA_PSS = PaddingMode.RSA_PSS;
+ public static final int KM_PAD_RSA_PKCS1_1_5_ENCRYPT = PaddingMode.RSA_PKCS1_1_5_ENCRYPT;
+ public static final int KM_PAD_RSA_PKCS1_1_5_SIGN = PaddingMode.RSA_PKCS1_1_5_SIGN;
+ public static final int KM_PAD_PKCS7 = PaddingMode.PKCS7;
// Digest modes.
- public static final int KM_DIGEST_NONE = 0;
- public static final int KM_DIGEST_MD5 = 1;
- public static final int KM_DIGEST_SHA1 = 2;
- public static final int KM_DIGEST_SHA_2_224 = 3;
- public static final int KM_DIGEST_SHA_2_256 = 4;
- public static final int KM_DIGEST_SHA_2_384 = 5;
- public static final int KM_DIGEST_SHA_2_512 = 6;
+ public static final int KM_DIGEST_NONE = Digest.NONE;
+ public static final int KM_DIGEST_MD5 = Digest.MD5;
+ public static final int KM_DIGEST_SHA1 = Digest.SHA1;
+ public static final int KM_DIGEST_SHA_2_224 = Digest.SHA_2_224;
+ public static final int KM_DIGEST_SHA_2_256 = Digest.SHA_2_256;
+ public static final int KM_DIGEST_SHA_2_384 = Digest.SHA_2_384;
+ public static final int KM_DIGEST_SHA_2_512 = Digest.SHA_2_512;
// Key origins.
- public static final int KM_ORIGIN_GENERATED = 0;
- public static final int KM_ORIGIN_IMPORTED = 2;
- public static final int KM_ORIGIN_UNKNOWN = 3;
- public static final int KM_ORIGIN_SECURELY_IMPORTED = 4;
+ public static final int KM_ORIGIN_GENERATED = KeyOrigin.GENERATED;
+ public static final int KM_ORIGIN_DERIVED = KeyOrigin.DERIVED;
+ public static final int KM_ORIGIN_IMPORTED = KeyOrigin.IMPORTED;
+ public static final int KM_ORIGIN_UNKNOWN = KeyOrigin.RESERVED;
+ public static final int KM_ORIGIN_SECURELY_IMPORTED = KeyOrigin.SECURELY_IMPORTED;
// Key usability requirements.
public static final int KM_BLOB_STANDALONE = 0;
public static final int KM_BLOB_REQUIRES_FILE_SYSTEM = 1;
// Operation Purposes.
- public static final int KM_PURPOSE_ENCRYPT = 0;
- public static final int KM_PURPOSE_DECRYPT = 1;
- public static final int KM_PURPOSE_SIGN = 2;
- public static final int KM_PURPOSE_VERIFY = 3;
- public static final int KM_PURPOSE_WRAP = 5;
+ public static final int KM_PURPOSE_ENCRYPT = KeyPurpose.ENCRYPT;
+ public static final int KM_PURPOSE_DECRYPT = KeyPurpose.DECRYPT;
+ public static final int KM_PURPOSE_SIGN = KeyPurpose.SIGN;
+ public static final int KM_PURPOSE_VERIFY = KeyPurpose.VERIFY;
+ public static final int KM_PURPOSE_WRAP = KeyPurpose.WRAP_KEY;
// Key formats.
- public static final int KM_KEY_FORMAT_X509 = 0;
- public static final int KM_KEY_FORMAT_PKCS8 = 1;
- public static final int KM_KEY_FORMAT_RAW = 3;
+ public static final int KM_KEY_FORMAT_X509 = KeyFormat.X509;
+ public static final int KM_KEY_FORMAT_PKCS8 = KeyFormat.PKCS8;
+ public static final int KM_KEY_FORMAT_RAW = KeyFormat.RAW;
// User authenticators.
- public static final int HW_AUTH_PASSWORD = 1 << 0;
- public static final int HW_AUTH_BIOMETRIC = 1 << 1;
+ public static final int HW_AUTH_PASSWORD = HardwareAuthenticatorType.PASSWORD;
+ public static final int HW_AUTH_BIOMETRIC = HardwareAuthenticatorType.FINGERPRINT;
// Security Levels.
- public static final int KM_SECURITY_LEVEL_SOFTWARE = 0;
- public static final int KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT = 1;
- public static final int KM_SECURITY_LEVEL_STRONGBOX = 2;
+ public static final int KM_SECURITY_LEVEL_SOFTWARE = SecurityLevel.SOFTWARE;
+ public static final int KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT =
+ SecurityLevel.TRUSTED_ENVIRONMENT;
+ public static final int KM_SECURITY_LEVEL_STRONGBOX = SecurityLevel.STRONGBOX;
// Error codes.
- public static final int KM_ERROR_OK = 0;
- public static final int KM_ERROR_ROOT_OF_TRUST_ALREADY_SET = -1;
- public static final int KM_ERROR_UNSUPPORTED_PURPOSE = -2;
- public static final int KM_ERROR_INCOMPATIBLE_PURPOSE = -3;
- public static final int KM_ERROR_UNSUPPORTED_ALGORITHM = -4;
- public static final int KM_ERROR_INCOMPATIBLE_ALGORITHM = -5;
- public static final int KM_ERROR_UNSUPPORTED_KEY_SIZE = -6;
- public static final int KM_ERROR_UNSUPPORTED_BLOCK_MODE = -7;
- public static final int KM_ERROR_INCOMPATIBLE_BLOCK_MODE = -8;
- public static final int KM_ERROR_UNSUPPORTED_MAC_LENGTH = -9;
- public static final int KM_ERROR_UNSUPPORTED_PADDING_MODE = -10;
- public static final int KM_ERROR_INCOMPATIBLE_PADDING_MODE = -11;
- public static final int KM_ERROR_UNSUPPORTED_DIGEST = -12;
- public static final int KM_ERROR_INCOMPATIBLE_DIGEST = -13;
- public static final int KM_ERROR_INVALID_EXPIRATION_TIME = -14;
- public static final int KM_ERROR_INVALID_USER_ID = -15;
- public static final int KM_ERROR_INVALID_AUTHORIZATION_TIMEOUT = -16;
- public static final int KM_ERROR_UNSUPPORTED_KEY_FORMAT = -17;
- public static final int KM_ERROR_INCOMPATIBLE_KEY_FORMAT = -18;
- public static final int KM_ERROR_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM = -19;
- public static final int KM_ERROR_UNSUPPORTED_KEY_VERIFICATION_ALGORITHM = -20;
- public static final int KM_ERROR_INVALID_INPUT_LENGTH = -21;
- public static final int KM_ERROR_KEY_EXPORT_OPTIONS_INVALID = -22;
- public static final int KM_ERROR_DELEGATION_NOT_ALLOWED = -23;
- public static final int KM_ERROR_KEY_NOT_YET_VALID = -24;
- public static final int KM_ERROR_KEY_EXPIRED = -25;
- public static final int KM_ERROR_KEY_USER_NOT_AUTHENTICATED = -26;
- public static final int KM_ERROR_OUTPUT_PARAMETER_NULL = -27;
- public static final int KM_ERROR_INVALID_OPERATION_HANDLE = -28;
- public static final int KM_ERROR_INSUFFICIENT_BUFFER_SPACE = -29;
- public static final int KM_ERROR_VERIFICATION_FAILED = -30;
- public static final int KM_ERROR_TOO_MANY_OPERATIONS = -31;
- public static final int KM_ERROR_UNEXPECTED_NULL_POINTER = -32;
- public static final int KM_ERROR_INVALID_KEY_BLOB = -33;
- public static final int KM_ERROR_IMPORTED_KEY_NOT_ENCRYPTED = -34;
- public static final int KM_ERROR_IMPORTED_KEY_DECRYPTION_FAILED = -35;
- public static final int KM_ERROR_IMPORTED_KEY_NOT_SIGNED = -36;
- public static final int KM_ERROR_IMPORTED_KEY_VERIFICATION_FAILED = -37;
- public static final int KM_ERROR_INVALID_ARGUMENT = -38;
- public static final int KM_ERROR_UNSUPPORTED_TAG = -39;
- public static final int KM_ERROR_INVALID_TAG = -40;
- public static final int KM_ERROR_MEMORY_ALLOCATION_FAILED = -41;
- public static final int KM_ERROR_INVALID_RESCOPING = -42;
- public static final int KM_ERROR_IMPORT_PARAMETER_MISMATCH = -44;
- public static final int KM_ERROR_SECURE_HW_ACCESS_DENIED = -45;
- public static final int KM_ERROR_OPERATION_CANCELLED = -46;
- public static final int KM_ERROR_CONCURRENT_ACCESS_CONFLICT = -47;
- public static final int KM_ERROR_SECURE_HW_BUSY = -48;
- public static final int KM_ERROR_SECURE_HW_COMMUNICATION_FAILED = -49;
- public static final int KM_ERROR_UNSUPPORTED_EC_FIELD = -50;
- public static final int KM_ERROR_MISSING_NONCE = -51;
- public static final int KM_ERROR_INVALID_NONCE = -52;
- public static final int KM_ERROR_MISSING_MAC_LENGTH = -53;
- public static final int KM_ERROR_KEY_RATE_LIMIT_EXCEEDED = -54;
- public static final int KM_ERROR_CALLER_NONCE_PROHIBITED = -55;
- public static final int KM_ERROR_KEY_MAX_OPS_EXCEEDED = -56;
- public static final int KM_ERROR_INVALID_MAC_LENGTH = -57;
- public static final int KM_ERROR_MISSING_MIN_MAC_LENGTH = -58;
- public static final int KM_ERROR_UNSUPPORTED_MIN_MAC_LENGTH = -59;
- public static final int KM_ERROR_CANNOT_ATTEST_IDS = -66;
- public static final int KM_ERROR_HARDWARE_TYPE_UNAVAILABLE = -68;
- public static final int KM_ERROR_DEVICE_LOCKED = -72;
- public static final int KM_ERROR_UNIMPLEMENTED = -100;
- public static final int KM_ERROR_VERSION_MISMATCH = -101;
- public static final int KM_ERROR_UNKNOWN_ERROR = -1000;
+ public static final int KM_ERROR_OK = ErrorCode.OK;
+ public static final int KM_ERROR_ROOT_OF_TRUST_ALREADY_SET =
+ ErrorCode.ROOT_OF_TRUST_ALREADY_SET; // -1;
+ public static final int KM_ERROR_UNSUPPORTED_PURPOSE =
+ ErrorCode.UNSUPPORTED_PURPOSE; // -2;
+ public static final int KM_ERROR_INCOMPATIBLE_PURPOSE =
+ ErrorCode.INCOMPATIBLE_PURPOSE; // -3;
+ public static final int KM_ERROR_UNSUPPORTED_ALGORITHM =
+ ErrorCode.UNSUPPORTED_ALGORITHM; // -4;
+ public static final int KM_ERROR_INCOMPATIBLE_ALGORITHM =
+ ErrorCode.INCOMPATIBLE_ALGORITHM; // -5;
+ public static final int KM_ERROR_UNSUPPORTED_KEY_SIZE =
+ ErrorCode.UNSUPPORTED_KEY_SIZE; // -6;
+ public static final int KM_ERROR_UNSUPPORTED_BLOCK_MODE =
+ ErrorCode.UNSUPPORTED_BLOCK_MODE; // -7;
+ public static final int KM_ERROR_INCOMPATIBLE_BLOCK_MODE =
+ ErrorCode.INCOMPATIBLE_BLOCK_MODE; // -8;
+ public static final int KM_ERROR_UNSUPPORTED_MAC_LENGTH =
+ ErrorCode.UNSUPPORTED_MAC_LENGTH; // -9;
+ public static final int KM_ERROR_UNSUPPORTED_PADDING_MODE =
+ ErrorCode.UNSUPPORTED_PADDING_MODE; // -10;
+ public static final int KM_ERROR_INCOMPATIBLE_PADDING_MODE =
+ ErrorCode.INCOMPATIBLE_PADDING_MODE; // -11;
+ public static final int KM_ERROR_UNSUPPORTED_DIGEST =
+ ErrorCode.UNSUPPORTED_DIGEST; // -12;
+ public static final int KM_ERROR_INCOMPATIBLE_DIGEST =
+ ErrorCode.INCOMPATIBLE_DIGEST; // -13;
+ public static final int KM_ERROR_INVALID_EXPIRATION_TIME =
+ ErrorCode.INVALID_EXPIRATION_TIME; // -14;
+ public static final int KM_ERROR_INVALID_USER_ID =
+ ErrorCode.INVALID_USER_ID; // -15;
+ public static final int KM_ERROR_INVALID_AUTHORIZATION_TIMEOUT =
+ ErrorCode.INVALID_AUTHORIZATION_TIMEOUT; // -16;
+ public static final int KM_ERROR_UNSUPPORTED_KEY_FORMAT =
+ ErrorCode.UNSUPPORTED_KEY_FORMAT; // -17;
+ public static final int KM_ERROR_INCOMPATIBLE_KEY_FORMAT =
+ ErrorCode.INCOMPATIBLE_KEY_FORMAT; // -18;
+ public static final int KM_ERROR_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM =
+ ErrorCode.UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM; // -19;
+ public static final int KM_ERROR_UNSUPPORTED_KEY_VERIFICATION_ALGORITHM =
+ ErrorCode.UNSUPPORTED_KEY_VERIFICATION_ALGORITHM; // -20;
+ public static final int KM_ERROR_INVALID_INPUT_LENGTH =
+ ErrorCode.INVALID_INPUT_LENGTH; // -21;
+ public static final int KM_ERROR_KEY_EXPORT_OPTIONS_INVALID =
+ ErrorCode.KEY_EXPORT_OPTIONS_INVALID; // -22;
+ public static final int KM_ERROR_DELEGATION_NOT_ALLOWED =
+ ErrorCode.DELEGATION_NOT_ALLOWED; // -23;
+ public static final int KM_ERROR_KEY_NOT_YET_VALID =
+ ErrorCode.KEY_NOT_YET_VALID; // -24;
+ public static final int KM_ERROR_KEY_EXPIRED =
+ ErrorCode.KEY_EXPIRED; // -25;
+ public static final int KM_ERROR_KEY_USER_NOT_AUTHENTICATED =
+ ErrorCode.KEY_USER_NOT_AUTHENTICATED; // -26;
+ public static final int KM_ERROR_OUTPUT_PARAMETER_NULL =
+ ErrorCode.OUTPUT_PARAMETER_NULL; // -27;
+ public static final int KM_ERROR_INVALID_OPERATION_HANDLE =
+ ErrorCode.INVALID_OPERATION_HANDLE; // -28;
+ public static final int KM_ERROR_INSUFFICIENT_BUFFER_SPACE =
+ ErrorCode.INSUFFICIENT_BUFFER_SPACE; // -29;
+ public static final int KM_ERROR_VERIFICATION_FAILED =
+ ErrorCode.VERIFICATION_FAILED; // -30;
+ public static final int KM_ERROR_TOO_MANY_OPERATIONS =
+ ErrorCode.TOO_MANY_OPERATIONS; // -31;
+ public static final int KM_ERROR_UNEXPECTED_NULL_POINTER =
+ ErrorCode.UNEXPECTED_NULL_POINTER; // -32;
+ public static final int KM_ERROR_INVALID_KEY_BLOB =
+ ErrorCode.INVALID_KEY_BLOB; // -33;
+ public static final int KM_ERROR_IMPORTED_KEY_NOT_ENCRYPTED =
+ ErrorCode.IMPORTED_KEY_NOT_ENCRYPTED; // -34;
+ public static final int KM_ERROR_IMPORTED_KEY_DECRYPTION_FAILED =
+ ErrorCode.IMPORTED_KEY_DECRYPTION_FAILED; // -35;
+ public static final int KM_ERROR_IMPORTED_KEY_NOT_SIGNED =
+ ErrorCode.IMPORTED_KEY_NOT_SIGNED; // -36;
+ public static final int KM_ERROR_IMPORTED_KEY_VERIFICATION_FAILED =
+ ErrorCode.IMPORTED_KEY_VERIFICATION_FAILED; // -37;
+ public static final int KM_ERROR_INVALID_ARGUMENT =
+ ErrorCode.INVALID_ARGUMENT; // -38;
+ public static final int KM_ERROR_UNSUPPORTED_TAG =
+ ErrorCode.UNSUPPORTED_TAG; // -39;
+ public static final int KM_ERROR_INVALID_TAG =
+ ErrorCode.INVALID_TAG; // -40;
+ public static final int KM_ERROR_MEMORY_ALLOCATION_FAILED =
+ ErrorCode.MEMORY_ALLOCATION_FAILED; // -41;
+ public static final int KM_ERROR_IMPORT_PARAMETER_MISMATCH =
+ ErrorCode.IMPORT_PARAMETER_MISMATCH; // -44;
+ public static final int KM_ERROR_SECURE_HW_ACCESS_DENIED =
+ ErrorCode.SECURE_HW_ACCESS_DENIED; // -45;
+ public static final int KM_ERROR_OPERATION_CANCELLED =
+ ErrorCode.OPERATION_CANCELLED; // -46;
+ public static final int KM_ERROR_CONCURRENT_ACCESS_CONFLICT =
+ ErrorCode.CONCURRENT_ACCESS_CONFLICT; // -47;
+ public static final int KM_ERROR_SECURE_HW_BUSY =
+ ErrorCode.SECURE_HW_BUSY; // -48;
+ public static final int KM_ERROR_SECURE_HW_COMMUNICATION_FAILED =
+ ErrorCode.SECURE_HW_COMMUNICATION_FAILED; // -49;
+ public static final int KM_ERROR_UNSUPPORTED_EC_FIELD =
+ ErrorCode.UNSUPPORTED_EC_FIELD; // -50;
+ public static final int KM_ERROR_MISSING_NONCE =
+ ErrorCode.MISSING_NONCE; // -51;
+ public static final int KM_ERROR_INVALID_NONCE =
+ ErrorCode.INVALID_NONCE; // -52;
+ public static final int KM_ERROR_MISSING_MAC_LENGTH =
+ ErrorCode.MISSING_MAC_LENGTH; // -53;
+ public static final int KM_ERROR_KEY_RATE_LIMIT_EXCEEDED =
+ ErrorCode.KEY_RATE_LIMIT_EXCEEDED; // -54;
+ public static final int KM_ERROR_CALLER_NONCE_PROHIBITED =
+ ErrorCode.CALLER_NONCE_PROHIBITED; // -55;
+ public static final int KM_ERROR_KEY_MAX_OPS_EXCEEDED =
+ ErrorCode.KEY_MAX_OPS_EXCEEDED; // -56;
+ public static final int KM_ERROR_INVALID_MAC_LENGTH =
+ ErrorCode.INVALID_MAC_LENGTH; // -57;
+ public static final int KM_ERROR_MISSING_MIN_MAC_LENGTH =
+ ErrorCode.MISSING_MIN_MAC_LENGTH; // -58;
+ public static final int KM_ERROR_UNSUPPORTED_MIN_MAC_LENGTH =
+ ErrorCode.UNSUPPORTED_MIN_MAC_LENGTH; // -59;
+ public static final int KM_ERROR_CANNOT_ATTEST_IDS =
+ ErrorCode.CANNOT_ATTEST_IDS; // -66;
+ public static final int KM_ERROR_HARDWARE_TYPE_UNAVAILABLE =
+ ErrorCode.HARDWARE_TYPE_UNAVAILABLE; // -68;
+ public static final int KM_ERROR_DEVICE_LOCKED =
+ ErrorCode.DEVICE_LOCKED; // -72;
+ public static final int KM_ERROR_UNIMPLEMENTED =
+ ErrorCode.UNIMPLEMENTED; // -100;
+ public static final int KM_ERROR_VERSION_MISMATCH =
+ ErrorCode.VERSION_MISMATCH; // -101;
+ public static final int KM_ERROR_UNKNOWN_ERROR =
+ ErrorCode.UNKNOWN_ERROR; // -1000;
public static final Map<Integer, String> sErrorCodeToString = new HashMap<Integer, String>();
static {
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 1f625443c96e..7493e39538dc 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -336,7 +336,7 @@ static jint getVectorOfAudioDeviceTypeAddr(JNIEnv *env, jintArray deviceTypes,
return (jint)AUDIO_JAVA_BAD_VALUE;
}
const char *address = env->GetStringUTFChars((jstring)addrJobj, NULL);
- AudioDeviceTypeAddr dev = AudioDeviceTypeAddr(typesPtr[i], address);
+ AudioDeviceTypeAddr dev = AudioDeviceTypeAddr((audio_devices_t)typesPtr[i], address);
audioDeviceTypeAddrVector.add(dev);
env->ReleaseStringUTFChars((jstring)addrJobj, address);
}
@@ -818,7 +818,8 @@ static void convertAudioGainConfigToNative(JNIEnv *env,
bool useInMask)
{
nAudioGainConfig->index = env->GetIntField(jAudioGainConfig, gAudioGainConfigFields.mIndex);
- nAudioGainConfig->mode = env->GetIntField(jAudioGainConfig, gAudioGainConfigFields.mMode);
+ nAudioGainConfig->mode =
+ (audio_gain_mode_t)env->GetIntField(jAudioGainConfig, gAudioGainConfigFields.mMode);
ALOGV("convertAudioGainConfigToNative got gain index %d", nAudioGainConfig->index);
jint jMask = env->GetIntField(jAudioGainConfig, gAudioGainConfigFields.mChannelMask);
audio_channel_mask_t nMask;
@@ -938,8 +939,8 @@ static jint convertAudioPortConfigToNativeWithDevicePort(JNIEnv *env,
jobject jAudioDevicePort = env->GetObjectField(jAudioPortConfig,
gAudioPortConfigFields.mPort);
- nAudioPortConfig->ext.device.type = env->GetIntField(jAudioDevicePort,
- gAudioPortFields.mType);
+ nAudioPortConfig->ext.device.type =
+ (audio_devices_t)env->GetIntField(jAudioDevicePort, gAudioPortFields.mType);
jstring jDeviceAddress = (jstring)env->GetObjectField(jAudioDevicePort,
gAudioPortFields.mAddress);
const char *nDeviceAddress = env->GetStringUTFChars(jDeviceAddress, NULL);
@@ -2332,7 +2333,7 @@ static jint android_media_AudioSystem_setSupportedSystemUsages(JNIEnv *env, jobj
static jint
android_media_AudioSystem_setAllowedCapturePolicy(JNIEnv *env, jobject thiz, jint uid, jint flags) {
- return AudioSystem::setAllowedCapturePolicy(uid, flags);
+ return AudioSystem::setAllowedCapturePolicy(uid, static_cast<audio_flags_mask_t>(flags));
}
static jint
@@ -2367,8 +2368,10 @@ android_media_AudioSystem_setPreferredDeviceForStrategy(JNIEnv *env, jobject thi
const char *c_address = env->GetStringUTFChars(deviceAddress, NULL);
int status = check_AudioSystem_Command(
- AudioSystem::setPreferredDeviceForStrategy((product_strategy_t) strategy,
- AudioDeviceTypeAddr(deviceType, c_address)));
+ AudioSystem::setPreferredDeviceForStrategy((product_strategy_t)strategy,
+ AudioDeviceTypeAddr((audio_devices_t)
+ deviceType,
+ c_address)));
env->ReleaseStringUTFChars(deviceAddress, c_address);
return (jint) status;
}
diff --git a/core/proto/OWNERS b/core/proto/OWNERS
index 5eeeb048e6d6..748b4b4f5743 100644
--- a/core/proto/OWNERS
+++ b/core/proto/OWNERS
@@ -26,17 +26,7 @@ hyunyoungs@google.com
# Graphics stats
jreck@google.com
-# Temporary Block to assist in migration
-# Bug: 143080132
-per-file *enums.proto = baligh@google.com, yro@google.com, jeffreyhuang@google.com
-per-file *media_output_enum.proto = baligh@google.com, yro@google.com, jeffreyhuang@google.com
-per-file *networkcapabilities.proto = baligh@google.com, yro@google.com, jeffreyhuang@google.com
-per-file *data_stall_event.proto = baligh@google.com, yro@google.com, jeffreyhuang@google.com
-per-file *procstats_enum.proto = baligh@google.com, yro@google.com, jeffreyhuang@google.com
-per-file *usb.proto = baligh@google.com, yro@google.com, jeffreyhuang@google.com
-per-file *network_stack.proto = baligh@google.com, yro@google.com, jeffreyhuang@google.com
-per-file *tethering.proto = baligh@google.com, yro@google.com, jeffreyhuang@google.com
-per-file *dns_resolver.proto = baligh@google.com, yro@google.com, jeffreyhuang@google.com
-per-file *device_policy.proto = baligh@google.com, yro@google.com, jeffreyhuang@google.com
-per-file *launcher.proto = baligh@google.com, yro@google.com, jeffreyhuang@google.com
-per-file *mediametrics.proto = baligh@google.com, yro@google.com, jeffreyhuang@google.com
+# Accessibility
+pweaver@google.com
+hongmingjin@google.com
+cbrower@google.com
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index a417f0c708b2..e6619f58f273 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -3032,6 +3032,12 @@
<permission android:name="android.permission.DUMP"
android:protectionLevel="signature|privileged|development" />
+ <!-- Allows an application to start tracing for InputMethod and WindowManager.
+ <p>Not for use by third-party applications.
+ @hide -->
+ <permission android:name="android.permission.CONTROL_UI_TRACING"
+ android:protectionLevel="signature|privileged|development" />
+
<!-- Allows an application to read the low-level system log files.
<p>Not for use by third-party applications, because
Log entries can contain the user's private information. -->
diff --git a/core/tests/hdmitests/Android.bp b/core/tests/hdmitests/Android.bp
index 2194d4b030ce..4755e0ea5259 100644
--- a/core/tests/hdmitests/Android.bp
+++ b/core/tests/hdmitests/Android.bp
@@ -19,6 +19,7 @@ android_test {
static_libs: [
"androidx.test.rules",
"frameworks-base-testutils",
+ "guava-android-testlib",
"truth-prebuilt",
],
libs: ["android.test.runner"],
diff --git a/core/tests/hdmitests/src/android/hardware/hdmi/HdmiDeviceInfoTest.java b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiDeviceInfoTest.java
new file mode 100755
index 000000000000..4c0de629c464
--- /dev/null
+++ b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiDeviceInfoTest.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.hdmi;
+
+import androidx.test.filters.SmallTest;
+
+import com.google.common.testing.EqualsTester;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Tests for {@link HdmiDeviceInfo} */
+@RunWith(JUnit4.class)
+@SmallTest
+public class HdmiDeviceInfoTest {
+
+ @Test
+ public void testEquals() {
+ int logicalAddr = 0x00;
+ int phyAddr = 0x1000;
+ int portId = 1;
+ int deviceType = 0;
+ int vendorId = 0x123456;
+ String displayName = "test device";
+ int powerStatus = HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY;
+ int deviceId = 3;
+ int adopterId = 2;
+
+ new EqualsTester()
+ .addEqualityGroup(new HdmiDeviceInfo())
+ .addEqualityGroup(
+ new HdmiDeviceInfo(phyAddr, portId), new HdmiDeviceInfo(phyAddr, portId))
+ .addEqualityGroup(
+ new HdmiDeviceInfo(phyAddr, portId, adopterId, deviceId),
+ new HdmiDeviceInfo(phyAddr, portId, adopterId, deviceId))
+ .addEqualityGroup(
+ new HdmiDeviceInfo(
+ logicalAddr, phyAddr, portId, deviceType, vendorId, displayName),
+ new HdmiDeviceInfo(
+ logicalAddr, phyAddr, portId, deviceType, vendorId, displayName))
+ .addEqualityGroup(
+ new HdmiDeviceInfo(
+ logicalAddr,
+ phyAddr,
+ portId,
+ deviceType,
+ vendorId,
+ displayName,
+ powerStatus),
+ new HdmiDeviceInfo(
+ logicalAddr,
+ phyAddr,
+ portId,
+ deviceType,
+ vendorId,
+ displayName,
+ powerStatus))
+ .testEquals();
+ }
+}
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 0806e7151997..ce6deeab87fa 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -316,6 +316,7 @@ applications that come with the platform
<permission name="android.permission.DELETE_CACHE_FILES"/>
<permission name="android.permission.DELETE_PACKAGES"/>
<permission name="android.permission.DUMP"/>
+ <permission name="android.permission.CONTROL_UI_TRACING"/>
<permission name="android.permission.ACTIVITY_EMBEDDING"/>
<permission name="android.permission.FORCE_STOP_PACKAGES"/>
<permission name="android.permission.GET_APP_OPS_STATS"/>
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index 5e0471c08d67..7982ab664c1b 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -208,8 +208,12 @@ EGLConfig EglManager::loadFP16Config(EGLDisplay display, SwapBehavior swapBehavi
return config;
}
+extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
+
void EglManager::initExtensions() {
auto extensions = StringUtils::split(eglQueryString(mEglDisplay, EGL_EXTENSIONS));
+ auto extensionsAndroid =
+ StringUtils::split(eglQueryStringImplementationANDROID(mEglDisplay, EGL_EXTENSIONS));
// For our purposes we don't care if EGL_BUFFER_AGE is a result of
// EGL_EXT_buffer_age or EGL_KHR_partial_update as our usage is covered
@@ -228,9 +232,12 @@ void EglManager::initExtensions() {
EglExtensions.displayP3 = extensions.has("EGL_EXT_gl_colorspace_display_p3_passthrough");
EglExtensions.contextPriority = extensions.has("EGL_IMG_context_priority");
EglExtensions.surfacelessContext = extensions.has("EGL_KHR_surfaceless_context");
- EglExtensions.nativeFenceSync = extensions.has("EGL_ANDROID_native_fence_sync");
EglExtensions.fenceSync = extensions.has("EGL_KHR_fence_sync");
EglExtensions.waitSync = extensions.has("EGL_KHR_wait_sync");
+
+ // EGL_ANDROID_native_fence_sync is not exposed to applications, so access
+ // this through the private Android-specific query instead.
+ EglExtensions.nativeFenceSync = extensionsAndroid.has("EGL_ANDROID_native_fence_sync");
}
bool EglManager::hasEglContext() {
diff --git a/media/jni/audioeffect/android_media_AudioEffect.cpp b/media/jni/audioeffect/android_media_AudioEffect.cpp
index 96961ac21a2d..d55e9d0efffd 100644
--- a/media/jni/audioeffect/android_media_AudioEffect.cpp
+++ b/media/jni/audioeffect/android_media_AudioEffect.cpp
@@ -331,7 +331,7 @@ android_media_AudioEffect_native_setup(JNIEnv *env, jobject thiz, jobject weak_t
}
if (deviceType != AUDIO_DEVICE_NONE) {
- device.mType = deviceType;
+ device.mType = (audio_devices_t)deviceType;
ScopedUtfChars address(env, deviceAddress);
device.mAddress = address.c_str();
}
diff --git a/media/jni/soundpool/android_media_SoundPool.cpp b/media/jni/soundpool/android_media_SoundPool.cpp
index ca3cc8552990..26725f87bfdc 100644
--- a/media/jni/soundpool/android_media_SoundPool.cpp
+++ b/media/jni/soundpool/android_media_SoundPool.cpp
@@ -200,7 +200,7 @@ android_media_SoundPool_native_setup(JNIEnv *env, jobject thiz, jobject weakRef,
paa->usage = (audio_usage_t) env->GetIntField(jaa, javaAudioAttrFields.fieldUsage);
paa->content_type =
(audio_content_type_t) env->GetIntField(jaa, javaAudioAttrFields.fieldContentType);
- paa->flags = env->GetIntField(jaa, javaAudioAttrFields.fieldFlags);
+ paa->flags = (audio_flags_mask_t) env->GetIntField(jaa, javaAudioAttrFields.fieldFlags);
ALOGV("android_media_SoundPool_native_setup");
auto *ap = new SoundPool(maxChannels, paa);
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index a9279971ce1e..fa4da2826b54 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -70,6 +70,7 @@
<uses-permission android:name="android.permission.SET_PROCESS_LIMIT" />
<uses-permission android:name="android.permission.SET_ALWAYS_FINISH" />
<uses-permission android:name="android.permission.DUMP" />
+ <uses-permission android:name="android.permission.CONTROL_UI_TRACING" />
<uses-permission android:name="android.permission.SIGNAL_PERSISTENT_PROCESSES" />
<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
<!-- Internal permissions granted to the shell. -->
diff --git a/packages/SystemUI/OWNERS b/packages/SystemUI/OWNERS
index 17d2f9c89c30..f884270eaba8 100644
--- a/packages/SystemUI/OWNERS
+++ b/packages/SystemUI/OWNERS
@@ -2,8 +2,11 @@ set noparent
dsandler@android.com
+aaliomer@google.com
adamcohen@google.com
+alexflo@google.com
asc@google.com
+awickham@google.com
beverlyt@google.com
brockman@google.com
cinek@google.com
@@ -11,11 +14,16 @@ cwren@google.com
dupin@google.com
ethibodeau@google.com
evanlaird@google.com
+gwasserman@google.com
hwwang@google.com
hyunyoungs@google.com
jaggies@google.com
+jamesoleary@google.com
+jeffdq@google.com
jjaggi@google.com
+jonmiranda@google.com
joshmcgrath@google.com
+joshtrask@google.com
juliacr@google.com
juliatuttle@google.com
kchyn@google.com
@@ -24,28 +32,38 @@ kprevas@google.com
lynhan@google.com
madym@google.com
mankoff@google.com
+mett@google.com
+mkephart@google.com
+mpietal@google.com
mrcasey@google.com
mrenouf@google.com
nbenbernou@google.com
nesciosquid@google.com
ogunwale@google.com
peanutbutter@google.com
+pinyaoting@google.com
pixel@google.com
roosa@google.com
+santie@google.com
snoeberger@google.com
+sreyasr@google.com
steell@google.com
+sfufa@google.com
stwu@google.com
sunnygoyal@google.com
susikp@google.com
+thiruram@google.com
tracyzhou@google.com
tsuji@google.com
twickham@google.com
+vadimt@google.com
+victortulias@google.com
winsonc@google.com
+xuqiu@google.com
zakcohen@google.com
#Android Auto
hseog@google.com
#Android TV
-rgl@google.com
-
+rgl@google.com \ No newline at end of file
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index f7de5c023b4f..9b006d050c02 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -41,6 +41,7 @@ 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_FOREGROUND;
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
@@ -2771,6 +2772,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
networkCapabilities = new NetworkCapabilities(networkCapabilities);
networkCapabilities.restrictCapabilitesForTestNetwork(nai.creatorUid);
}
+ processCapabilitiesFromAgent(nai, networkCapabilities);
updateCapabilities(nai.getCurrentScore(), nai, networkCapabilities);
break;
}
@@ -2809,6 +2811,31 @@ public class ConnectivityService extends IConnectivityManager.Stub
mKeepaliveTracker.handleEventSocketKeepalive(nai, msg);
break;
}
+ case NetworkAgent.EVENT_UNDERLYING_NETWORKS_CHANGED: {
+ if (!nai.supportsUnderlyingNetworks()) {
+ Log.wtf(TAG, "Non-virtual networks cannot have underlying networks");
+ break;
+ }
+ final ArrayList<Network> underlying;
+ try {
+ underlying = ((Bundle) msg.obj).getParcelableArrayList(
+ NetworkAgent.UNDERLYING_NETWORKS_KEY);
+ } catch (NullPointerException | ClassCastException e) {
+ break;
+ }
+ final Network[] oldUnderlying = nai.declaredUnderlyingNetworks;
+ nai.declaredUnderlyingNetworks = (underlying != null)
+ ? underlying.toArray(new Network[0]) : null;
+
+ if (!Arrays.equals(oldUnderlying, nai.declaredUnderlyingNetworks)) {
+ if (DBG) {
+ log(nai.toShortString() + " changed underlying networks to "
+ + Arrays.toString(nai.declaredUnderlyingNetworks));
+ }
+ updateCapabilities(nai.getCurrentScore(), nai, nai.networkCapabilities);
+ notifyIfacesChangedForNetworkStats();
+ }
+ }
}
}
@@ -3394,7 +3421,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
mLegacyTypeTracker.remove(nai, wasDefault);
if (!nai.networkCapabilities.hasTransport(TRANSPORT_VPN)) {
- updateAllVpnsCapabilities();
+ propagateUnderlyingNetworkCapabilities();
}
rematchAllNetworksAndRequests();
mLingerMonitor.noteDisconnect(nai);
@@ -4704,10 +4731,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (mLockdownEnabled) {
return new VpnInfo[0];
}
-
List<VpnInfo> infoList = new ArrayList<>();
- for (int i = 0; i < mVpns.size(); i++) {
- VpnInfo info = createVpnInfo(mVpns.valueAt(i));
+ for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
+ VpnInfo info = createVpnInfo(nai);
if (info != null) {
infoList.add(info);
}
@@ -4720,13 +4746,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
* @return VPN information for accounting, or null if we can't retrieve all required
* information, e.g underlying ifaces.
*/
- @Nullable
- private VpnInfo createVpnInfo(Vpn vpn) {
- VpnInfo info = vpn.getVpnInfo();
- if (info == null) {
- return null;
- }
- Network[] underlyingNetworks = vpn.getUnderlyingNetworks();
+ private VpnInfo createVpnInfo(NetworkAgentInfo nai) {
+ if (!nai.isVPN()) return null;
+
+ Network[] underlyingNetworks = nai.declaredUnderlyingNetworks;
// see VpnService.setUnderlyingNetworks()'s javadoc about how to interpret
// the underlyingNetworks list.
if (underlyingNetworks == null) {
@@ -4735,23 +4758,33 @@ public class ConnectivityService extends IConnectivityManager.Stub
underlyingNetworks = new Network[] { defaultNai.network };
}
}
- if (underlyingNetworks != null && underlyingNetworks.length > 0) {
- List<String> interfaces = new ArrayList<>();
- for (Network network : underlyingNetworks) {
- LinkProperties lp = getLinkProperties(network);
- if (lp != null) {
- for (String iface : lp.getAllInterfaceNames()) {
- if (!TextUtils.isEmpty(iface)) {
- interfaces.add(iface);
- }
- }
+
+ if (ArrayUtils.isEmpty(underlyingNetworks)) return null;
+
+ List<String> interfaces = new ArrayList<>();
+ for (Network network : underlyingNetworks) {
+ NetworkAgentInfo underlyingNai = getNetworkAgentInfoForNetwork(network);
+ if (underlyingNai == null) continue;
+ LinkProperties lp = underlyingNai.linkProperties;
+ for (String iface : lp.getAllInterfaceNames()) {
+ if (!TextUtils.isEmpty(iface)) {
+ interfaces.add(iface);
}
}
- if (!interfaces.isEmpty()) {
- info.underlyingIfaces = interfaces.toArray(new String[interfaces.size()]);
- }
}
- return info.underlyingIfaces == null ? null : info;
+
+ if (interfaces.isEmpty()) return null;
+
+ VpnInfo info = new VpnInfo();
+ info.ownerUid = nai.networkCapabilities.getOwnerUid();
+ info.vpnIface = nai.linkProperties.getInterfaceName();
+ // Must be non-null or NetworkStatsService will crash.
+ // Cannot happen in production code because Vpn only registers the NetworkAgent after the
+ // tun or ipsec interface is created.
+ if (info.vpnIface == null) return null;
+ info.underlyingIfaces = interfaces.toArray(new String[0]);
+
+ return info;
}
/**
@@ -4774,33 +4807,19 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
/**
- * Ask all VPN objects to recompute and update their capabilities.
+ * Ask all networks with underlying networks to recompute and update their capabilities.
*
- * When underlying networks change, VPNs may have to update capabilities to reflect things
- * like the metered bit, their transports, and so on. This asks the VPN objects to update
- * their capabilities, and as this will cause them to send messages to the ConnectivityService
- * handler thread through their agent, this is asynchronous. When the capabilities objects
- * are computed they will be up-to-date as they are computed synchronously from here and
- * this is running on the ConnectivityService thread.
+ * When underlying networks change, such networks may have to update capabilities to reflect
+ * things like the metered bit, their transports, and so on. The capabilities are calculated
+ * immediately. This method runs on the ConnectivityService thread.
*/
- private void updateAllVpnsCapabilities() {
- Network defaultNetwork = getNetwork(getDefaultNetwork());
- synchronized (mVpns) {
- for (int i = 0; i < mVpns.size(); i++) {
- final Vpn vpn = mVpns.valueAt(i);
- NetworkCapabilities nc = vpn.updateCapabilities(defaultNetwork);
- updateVpnCapabilities(vpn, nc);
- }
- }
- }
-
- private void updateVpnCapabilities(Vpn vpn, @Nullable NetworkCapabilities nc) {
+ private void propagateUnderlyingNetworkCapabilities() {
ensureRunningOnConnectivityServiceThread();
- NetworkAgentInfo vpnNai = getNetworkAgentInfoForNetId(vpn.getNetId());
- if (vpnNai == null || nc == null) {
- return;
+ for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
+ if (nai.supportsUnderlyingNetworks()) {
+ updateCapabilities(nai.getCurrentScore(), nai, nai.networkCapabilities);
+ }
}
- updateCapabilities(vpnNai.getCurrentScore(), vpnNai, nc);
}
@Override
@@ -5113,7 +5132,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
}
- private void onUserStart(int userId) {
+ private void onUserStarted(int userId) {
synchronized (mVpns) {
Vpn userVpn = mVpns.get(userId);
if (userVpn != null) {
@@ -5128,7 +5147,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
}
- private void onUserStop(int userId) {
+ private void onUserStopped(int userId) {
synchronized (mVpns) {
Vpn userVpn = mVpns.get(userId);
if (userVpn == null) {
@@ -5142,28 +5161,22 @@ public class ConnectivityService extends IConnectivityManager.Stub
private void onUserAdded(int userId) {
mPermissionMonitor.onUserAdded(userId);
- Network defaultNetwork = getNetwork(getDefaultNetwork());
synchronized (mVpns) {
final int vpnsSize = mVpns.size();
for (int i = 0; i < vpnsSize; i++) {
Vpn vpn = mVpns.valueAt(i);
vpn.onUserAdded(userId);
- NetworkCapabilities nc = vpn.updateCapabilities(defaultNetwork);
- updateVpnCapabilities(vpn, nc);
}
}
}
private void onUserRemoved(int userId) {
mPermissionMonitor.onUserRemoved(userId);
- Network defaultNetwork = getNetwork(getDefaultNetwork());
synchronized (mVpns) {
final int vpnsSize = mVpns.size();
for (int i = 0; i < vpnsSize; i++) {
Vpn vpn = mVpns.valueAt(i);
vpn.onUserRemoved(userId);
- NetworkCapabilities nc = vpn.updateCapabilities(defaultNetwork);
- updateVpnCapabilities(vpn, nc);
}
}
}
@@ -5245,9 +5258,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (userId == UserHandle.USER_NULL) return;
if (Intent.ACTION_USER_STARTED.equals(action)) {
- onUserStart(userId);
+ onUserStarted(userId);
} else if (Intent.ACTION_USER_STOPPED.equals(action)) {
- onUserStop(userId);
+ onUserStopped(userId);
} else if (Intent.ACTION_USER_ADDED.equals(action)) {
onUserAdded(userId);
} else if (Intent.ACTION_USER_REMOVED.equals(action)) {
@@ -5959,13 +5972,29 @@ public class ConnectivityService extends IConnectivityManager.Stub
int currentScore, NetworkAgentConfig networkAgentConfig, int providerId) {
if (networkCapabilities.hasTransport(TRANSPORT_TEST)) {
enforceAnyPermissionOf(Manifest.permission.MANAGE_TEST_NETWORKS);
+ } else {
+ enforceNetworkFactoryPermission();
+ }
+
+ final int uid = Binder.getCallingUid();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ return registerNetworkAgentInternal(messenger, networkInfo, linkProperties,
+ networkCapabilities, currentScore, networkAgentConfig, providerId, uid);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ private Network registerNetworkAgentInternal(Messenger messenger, NetworkInfo networkInfo,
+ LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
+ int 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
// sees capabilities that may be malicious, which might prevent mistakes in the future.
networkCapabilities = new NetworkCapabilities(networkCapabilities);
- networkCapabilities.restrictCapabilitesForTestNetwork(Binder.getCallingUid());
- } else {
- enforceNetworkFactoryPermission();
+ networkCapabilities.restrictCapabilitesForTestNetwork(uid);
}
LinkProperties lp = new LinkProperties(linkProperties);
@@ -5976,9 +6005,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
final NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(),
new Network(mNetIdManager.reserveNetId()), new NetworkInfo(networkInfo), lp, nc,
currentScore, mContext, mTrackerHandler, new NetworkAgentConfig(networkAgentConfig),
- this, mNetd, mDnsResolver, mNMS, providerId, Binder.getCallingUid());
+ this, mNetd, mDnsResolver, mNMS, providerId, uid);
// Make sure the LinkProperties and NetworkCapabilities reflect what the agent info says.
+ processCapabilitiesFromAgent(nai, nc);
nai.getAndSetNetworkCapabilities(mixInCapabilities(nai, nc));
processLinkPropertiesFromAgent(nai, nai.linkProperties);
@@ -5986,13 +6016,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
final String name = TextUtils.isEmpty(extraInfo)
? nai.networkCapabilities.getSsid() : extraInfo;
if (DBG) log("registerNetworkAgent " + nai);
- final long token = Binder.clearCallingIdentity();
- try {
- mDeps.getNetworkStack().makeNetworkMonitor(
- nai.network, name, new NetworkMonitorCallbacks(nai));
- } finally {
- Binder.restoreCallingIdentity(token);
- }
+ mDeps.getNetworkStack().makeNetworkMonitor(
+ nai.network, name, new NetworkMonitorCallbacks(nai));
// NetworkAgentInfo registration will finish when the NetworkMonitor is created.
// If the network disconnects or sends any other event before that, messages are deferred by
// NetworkAgent until nai.asyncChannel.connect(), which will be called when finalizing the
@@ -6019,6 +6044,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
updateUids(nai, null, nai.networkCapabilities);
}
+ /**
+ * Called when receiving LinkProperties directly from a NetworkAgent.
+ * Stores into |nai| any data coming from the agent that might also be written to the network's
+ * LinkProperties by ConnectivityService itself. This ensures that the data provided by the
+ * agent is not lost when updateLinkProperties is called.
+ */
private void processLinkPropertiesFromAgent(NetworkAgentInfo nai, LinkProperties lp) {
lp.ensureDirectlyConnectedRoutes();
nai.clatd.setNat64PrefixFromRa(lp.getNat64Prefix());
@@ -6315,6 +6346,83 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
/**
+ * Called when receiving NetworkCapabilities directly from a NetworkAgent.
+ * Stores into |nai| any data coming from the agent that might also be written to the network's
+ * NetworkCapabilities by ConnectivityService itself. This ensures that the data provided by the
+ * agent is not lost when updateCapabilities is called.
+ */
+ private void processCapabilitiesFromAgent(NetworkAgentInfo nai, NetworkCapabilities nc) {
+ nai.declaredMetered = !nc.hasCapability(NET_CAPABILITY_NOT_METERED);
+ }
+
+ /** Modifies |caps| based on the capabilities of the specified underlying networks. */
+ @VisibleForTesting
+ void applyUnderlyingCapabilities(@Nullable Network[] underlyingNetworks,
+ @NonNull NetworkCapabilities caps, boolean declaredMetered) {
+ final Network defaultNetwork = getNetwork(getDefaultNetwork());
+ if (underlyingNetworks == null && defaultNetwork != null) {
+ // null underlying networks means to track the default.
+ underlyingNetworks = new Network[] { defaultNetwork };
+ }
+ int[] transportTypes = new int[] { NetworkCapabilities.TRANSPORT_VPN };
+ int downKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
+ int upKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
+ boolean metered = declaredMetered; // metered if any underlying is metered, or agentMetered
+ boolean roaming = false; // roaming if any underlying is roaming
+ boolean congested = false; // congested if any underlying is congested
+ boolean suspended = true; // suspended if all underlying are suspended
+
+ boolean hadUnderlyingNetworks = false;
+ if (null != underlyingNetworks) {
+ for (Network underlyingNetwork : underlyingNetworks) {
+ final NetworkAgentInfo underlying =
+ getNetworkAgentInfoForNetwork(underlyingNetwork);
+ if (underlying == null) continue;
+
+ final NetworkCapabilities underlyingCaps = underlying.networkCapabilities;
+ hadUnderlyingNetworks = true;
+ for (int underlyingType : underlyingCaps.getTransportTypes()) {
+ transportTypes = ArrayUtils.appendInt(transportTypes, underlyingType);
+ }
+
+ // Merge capabilities of this underlying network. For bandwidth, assume the
+ // worst case.
+ downKbps = NetworkCapabilities.minBandwidth(downKbps,
+ underlyingCaps.getLinkDownstreamBandwidthKbps());
+ upKbps = NetworkCapabilities.minBandwidth(upKbps,
+ underlyingCaps.getLinkUpstreamBandwidthKbps());
+ // If this underlying network is metered, the VPN is metered (it may cost money
+ // to send packets on this network).
+ metered |= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_METERED);
+ // If this underlying network is roaming, the VPN is roaming (the billing structure
+ // is different than the usual, local one).
+ roaming |= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_ROAMING);
+ // If this underlying network is congested, the VPN is congested (the current
+ // condition of the network affects the performance of this network).
+ congested |= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_CONGESTED);
+ // If this network is not suspended, the VPN is not suspended (the VPN
+ // is able to transfer some data).
+ suspended &= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED);
+ }
+ }
+ if (!hadUnderlyingNetworks) {
+ // No idea what the underlying networks are; assume reasonable defaults
+ metered = true;
+ roaming = false;
+ congested = false;
+ suspended = false;
+ }
+
+ caps.setTransportTypes(transportTypes);
+ caps.setLinkDownstreamBandwidthKbps(downKbps);
+ caps.setLinkUpstreamBandwidthKbps(upKbps);
+ caps.setCapability(NET_CAPABILITY_NOT_METERED, !metered);
+ caps.setCapability(NET_CAPABILITY_NOT_ROAMING, !roaming);
+ caps.setCapability(NET_CAPABILITY_NOT_CONGESTED, !congested);
+ caps.setCapability(NET_CAPABILITY_NOT_SUSPENDED, !suspended);
+ }
+
+ /**
* Augments the NetworkCapabilities passed in by a NetworkAgent with capabilities that are
* maintained here that the NetworkAgent is not aware of (e.g., validated, captive portal,
* and foreground status).
@@ -6367,6 +6475,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
newNc.addCapability(NET_CAPABILITY_NOT_ROAMING);
}
+ if (nai.supportsUnderlyingNetworks()) {
+ applyUnderlyingCapabilities(nai.declaredUnderlyingNetworks, newNc, nai.declaredMetered);
+ }
+
return newNc;
}
@@ -6446,7 +6558,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (!newNc.hasTransport(TRANSPORT_VPN)) {
// Tell VPNs about updated capabilities, since they may need to
// bubble those changes through.
- updateAllVpnsCapabilities();
+ propagateUnderlyingNetworkCapabilities();
}
if (!newNc.equalsTransportTypes(prevNc)) {
@@ -6766,7 +6878,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
? newNetwork.linkProperties.getTcpBufferSizes() : null);
notifyIfacesChangedForNetworkStats();
// Fix up the NetworkCapabilities of any VPNs that don't specify underlying networks.
- updateAllVpnsCapabilities();
+ propagateUnderlyingNetworkCapabilities();
}
private void processListenRequests(@NonNull final NetworkAgentInfo nai) {
@@ -7228,7 +7340,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
// onCapabilitiesUpdated being sent in updateAllVpnCapabilities below as
// the VPN would switch from its default, blank capabilities to those
// that reflect the capabilities of its underlying networks.
- updateAllVpnsCapabilities();
+ propagateUnderlyingNetworkCapabilities();
}
networkAgent.created = true;
}
@@ -7270,8 +7382,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
// doing.
updateSignalStrengthThresholds(networkAgent, "CONNECT", null);
- if (networkAgent.isVPN()) {
- updateAllVpnsCapabilities();
+ if (networkAgent.supportsUnderlyingNetworks()) {
+ propagateUnderlyingNetworkCapabilities();
}
// Consider network even though it is not yet validated.
@@ -7528,13 +7640,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
throwIfLockdownEnabled();
success = mVpns.get(user).setUnderlyingNetworks(networks);
}
- if (success) {
- mHandler.post(() -> {
- // Update VPN's capabilities based on updated underlying network set.
- updateAllVpnsCapabilities();
- notifyIfacesChangedForNetworkStats();
- });
- }
return success;
}
@@ -8210,13 +8315,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
return false;
}
- final Network[] underlyingNetworks;
- synchronized (mVpns) {
- final Vpn vpn = getVpnIfOwner(callbackUid);
- underlyingNetworks = (vpn == null) ? null : vpn.getUnderlyingNetworks();
- }
- if (underlyingNetworks != null) {
- if (Arrays.asList(underlyingNetworks).contains(nai.network)) return true;
+ for (NetworkAgentInfo virtual : mNetworkAgentInfos.values()) {
+ if (virtual.supportsUnderlyingNetworks()
+ && virtual.networkCapabilities.getOwnerUid() == callbackUid
+ && ArrayUtils.contains(virtual.declaredUnderlyingNetworks, nai.network)) {
+ return true;
+ }
}
// Administrator UIDs also contains the Owner UID
diff --git a/services/core/java/com/android/server/OWNERS b/services/core/java/com/android/server/OWNERS
index 8099f8f37bc7..3d1e709ab3bd 100644
--- a/services/core/java/com/android/server/OWNERS
+++ b/services/core/java/com/android/server/OWNERS
@@ -7,3 +7,6 @@ per-file VibratorService.java, DisplayThread.java = ogunwale@google.com
# Zram writeback
per-file ZramWriteback.java = minchan@google.com, rajekumar@google.com, srnvs@google.com
+
+# Userspace reboot
+per-file UserspaceRebootLogger.java = ioffe@google.com, tomcherry@google.com
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 1147db511a87..70ef44c3edb3 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -1391,12 +1391,13 @@ class StorageManagerService extends IStorageManager.Stub
final int oldState = vol.state;
final int newState = state;
vol.state = newState;
+ final VolumeInfo vInfo = new VolumeInfo(vol);
final SomeArgs args = SomeArgs.obtain();
- args.arg1 = vol;
+ args.arg1 = vInfo;
args.arg2 = oldState;
args.arg3 = newState;
mHandler.obtainMessage(H_VOLUME_STATE_CHANGED, args).sendToTarget();
- onVolumeStateChangedLocked(vol, oldState, newState);
+ onVolumeStateChangedLocked(vInfo, oldState, newState);
}
}
}
diff --git a/services/core/java/com/android/server/TestNetworkService.java b/services/core/java/com/android/server/TestNetworkService.java
index d6bd5a1d7c4c..a45466d98563 100644
--- a/services/core/java/com/android/server/TestNetworkService.java
+++ b/services/core/java/com/android/server/TestNetworkService.java
@@ -29,9 +29,9 @@ import android.net.IpPrefix;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.NetworkAgent;
+import android.net.NetworkAgentConfig;
import android.net.NetworkCapabilities;
-import android.net.NetworkInfo;
-import android.net.NetworkInfo.DetailedState;
+import android.net.NetworkProvider;
import android.net.RouteInfo;
import android.net.StringNetworkSpecifier;
import android.net.TestNetworkInterface;
@@ -62,7 +62,8 @@ import java.util.concurrent.atomic.AtomicInteger;
/** @hide */
class TestNetworkService extends ITestNetworkManager.Stub {
@NonNull private static final String TAG = TestNetworkService.class.getSimpleName();
- @NonNull private static final String TEST_NETWORK_TYPE = "TEST_NETWORK";
+ @NonNull private static final String TEST_NETWORK_LOGTAG = "TestNetworkAgent";
+ @NonNull private static final String TEST_NETWORK_PROVIDER_NAME = TAG;
@NonNull private static final AtomicInteger sTestTunIndex = new AtomicInteger();
@NonNull private final Context mContext;
@@ -72,6 +73,9 @@ class TestNetworkService extends ITestNetworkManager.Stub {
@NonNull private final HandlerThread mHandlerThread;
@NonNull private final Handler mHandler;
+ @NonNull private final ConnectivityManager mCm;
+ @NonNull private final NetworkProvider mNetworkProvider;
+
// Native method stubs
private static native int jniCreateTunTap(boolean isTun, @NonNull String iface);
@@ -85,6 +89,10 @@ class TestNetworkService extends ITestNetworkManager.Stub {
mContext = Objects.requireNonNull(context, "missing Context");
mNMS = Objects.requireNonNull(netManager, "missing INetworkManagementService");
mNetd = Objects.requireNonNull(NetdService.getInstance(), "could not get netd instance");
+ mCm = mContext.getSystemService(ConnectivityManager.class);
+ mNetworkProvider = new NetworkProvider(mContext, mHandler.getLooper(),
+ TEST_NETWORK_PROVIDER_NAME);
+ mCm.registerNetworkProvider(mNetworkProvider);
}
/**
@@ -150,9 +158,6 @@ class TestNetworkService extends ITestNetworkManager.Stub {
private static final int NETWORK_SCORE = 1; // Use a low, non-zero score.
private final int mUid;
- @NonNull private final NetworkInfo mNi;
- @NonNull private final NetworkCapabilities mNc;
- @NonNull private final LinkProperties mLp;
@GuardedBy("mBinderLock")
@NonNull
@@ -161,20 +166,18 @@ class TestNetworkService extends ITestNetworkManager.Stub {
@NonNull private final Object mBinderLock = new Object();
private TestNetworkAgent(
- @NonNull Looper looper,
@NonNull Context context,
- @NonNull NetworkInfo ni,
+ @NonNull Looper looper,
+ @NonNull NetworkAgentConfig config,
@NonNull NetworkCapabilities nc,
@NonNull LinkProperties lp,
int uid,
- @NonNull IBinder binder)
+ @NonNull IBinder binder,
+ @NonNull NetworkProvider np)
throws RemoteException {
- super(looper, context, TEST_NETWORK_TYPE, ni, nc, lp, NETWORK_SCORE);
+ super(context, looper, TEST_NETWORK_LOGTAG, nc, lp, NETWORK_SCORE, config, np);
mUid = uid;
- mNi = ni;
- mNc = nc;
- mLp = lp;
synchronized (mBinderLock) {
mBinder = binder; // Binder null-checks in create()
@@ -203,9 +206,7 @@ class TestNetworkService extends ITestNetworkManager.Stub {
}
private void teardown() {
- mNi.setDetailedState(DetailedState.DISCONNECTED, null, null);
- mNi.setIsAvailable(false);
- sendNetworkInfo(mNi);
+ unregister();
// Synchronize on mBinderLock to ensure that unlinkToDeath is never called more than
// once (otherwise it could throw an exception)
@@ -238,11 +239,6 @@ class TestNetworkService extends ITestNetworkManager.Stub {
Objects.requireNonNull(context, "missing Context");
// iface and binder validity checked by caller
- // Build network info with special testing type
- NetworkInfo ni = new NetworkInfo(ConnectivityManager.TYPE_TEST, 0, TEST_NETWORK_TYPE, "");
- ni.setDetailedState(DetailedState.CONNECTED, null, null);
- ni.setIsAvailable(true);
-
// Build narrow set of NetworkCapabilities, useful only for testing
NetworkCapabilities nc = new NetworkCapabilities();
nc.clearAll(); // Remove default capabilities.
@@ -290,7 +286,12 @@ class TestNetworkService extends ITestNetworkManager.Stub {
lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null, iface));
}
- return new TestNetworkAgent(looper, context, ni, nc, lp, callingUid, binder);
+ final TestNetworkAgent agent = new TestNetworkAgent(context, looper,
+ new NetworkAgentConfig.Builder().build(), nc, lp, callingUid, binder,
+ mNetworkProvider);
+ agent.register();
+ agent.markConnected();
+ return agent;
}
/**
diff --git a/services/core/java/com/android/server/UserspaceRebootLogger.java b/services/core/java/com/android/server/UserspaceRebootLogger.java
index 2403b637581f..89327b50883c 100644
--- a/services/core/java/com/android/server/UserspaceRebootLogger.java
+++ b/services/core/java/com/android/server/UserspaceRebootLogger.java
@@ -59,7 +59,7 @@ public final class UserspaceRebootLogger {
*/
public static void noteUserspaceRebootWasRequested() {
if (!PowerManager.isRebootingUserspaceSupportedImpl()) {
- Slog.wtf(TAG, "Userspace reboot is not supported.");
+ Slog.wtf(TAG, "noteUserspaceRebootWasRequested: Userspace reboot is not supported.");
return;
}
@@ -77,7 +77,7 @@ public final class UserspaceRebootLogger {
*/
public static void noteUserspaceRebootSuccess() {
if (!PowerManager.isRebootingUserspaceSupportedImpl()) {
- Slog.wtf(TAG, "Userspace reboot is not supported.");
+ Slog.wtf(TAG, "noteUserspaceRebootSuccess: Userspace reboot is not supported.");
return;
}
@@ -88,11 +88,11 @@ public final class UserspaceRebootLogger {
/**
* Returns {@code true} if {@code UserspaceRebootReported} atom should be logged.
*
- * <p>This call should only be made on devices supporting userspace reboot.
+ * <p>On devices that do not support userspace reboot this method will always return {@code
+ * false}.
*/
public static boolean shouldLogUserspaceRebootEvent() {
if (!PowerManager.isRebootingUserspaceSupportedImpl()) {
- Slog.wtf(TAG, "Userspace reboot is not supported.");
return false;
}
@@ -110,7 +110,7 @@ public final class UserspaceRebootLogger {
*/
public static void logEventAsync(boolean userUnlocked, Executor executor) {
if (!PowerManager.isRebootingUserspaceSupportedImpl()) {
- Slog.wtf(TAG, "Userspace reboot is not supported.");
+ Slog.wtf(TAG, "logEventAsync: Userspace reboot is not supported.");
return;
}
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index a9f62d91592d..3270dd55218c 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -132,6 +132,16 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
// TODO: make this private with a getter.
public NetworkCapabilities networkCapabilities;
public final NetworkAgentConfig networkAgentConfig;
+
+ // Underlying networks declared by the agent. Only set if supportsUnderlyingNetworks is true.
+ // The networks in this list might be declared by a VPN app using setUnderlyingNetworks and are
+ // not guaranteed to be current or correct, or even to exist.
+ public @Nullable Network[] declaredUnderlyingNetworks;
+
+ // Whether this network is always metered even if its underlying networks are unmetered.
+ // Only relevant if #supportsUnderlyingNetworks is true.
+ public boolean declaredMetered;
+
// Indicates if netd has been told to create this Network. From this point on the appropriate
// routing rules are setup and routes are added so packets can begin flowing over the Network.
// This is a sticky bit; once set it is never cleared.
@@ -474,10 +484,16 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
networkCapabilities);
}
+ /** Whether this network is a VPN. */
public boolean isVPN() {
return networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN);
}
+ /** Whether this network might have underlying networks. Currently only true for VPNs. */
+ public boolean supportsUnderlyingNetworks() {
+ 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
diff --git a/services/core/java/com/android/server/connectivity/PermissionMonitor.java b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
index a75a80a606eb..4c63eb488118 100644
--- a/services/core/java/com/android/server/connectivity/PermissionMonitor.java
+++ b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
@@ -174,7 +174,7 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse
netdPermsUids.put(uid, netdPermsUids.get(uid) | otherNetdPerms);
}
- List<UserInfo> users = mUserManager.getUsers(true); // exclude dying users
+ List<UserInfo> users = mUserManager.getAliveUsers();
if (users != null) {
for (UserInfo user : users) {
mUsers.add(user.id);
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index ff1a9c0ab35f..3445275b76dd 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -18,10 +18,7 @@ package com.android.server.connectivity;
import static android.Manifest.permission.BIND_VPN_SERVICE;
import static android.net.ConnectivityManager.NETID_UNSET;
-import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
-import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
-import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
import static android.net.RouteInfo.RTN_THROW;
import static android.net.RouteInfo.RTN_UNREACHABLE;
@@ -111,8 +108,6 @@ import com.android.internal.net.LegacyVpnInfo;
import com.android.internal.net.VpnConfig;
import com.android.internal.net.VpnInfo;
import com.android.internal.net.VpnProfile;
-import com.android.internal.util.ArrayUtils;
-import com.android.server.ConnectivityService;
import com.android.server.DeviceIdleInternal;
import com.android.server.LocalServices;
import com.android.server.net.BaseNetworkObserver;
@@ -123,7 +118,6 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.math.BigInteger;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
@@ -153,36 +147,13 @@ import java.util.concurrent.atomic.AtomicInteger;
public class Vpn {
private static final String NETWORKTYPE = "VPN";
private static final String TAG = "Vpn";
+ private static final String VPN_PROVIDER_NAME_BASE = "VpnNetworkProvider:";
private static final boolean LOGD = true;
// Length of time (in milliseconds) that an app hosting an always-on VPN is placed on
// the device idle allowlist during service launch and VPN bootstrap.
private static final long VPN_LAUNCH_IDLE_ALLOWLIST_DURATION_MS = 60 * 1000;
- // Settings for how much of the address space should be routed so that Vpn considers
- // "most" of the address space is routed. This is used to determine whether this Vpn
- // should be marked with the INTERNET capability.
- private static final long MOST_IPV4_ADDRESSES_COUNT;
- private static final BigInteger MOST_IPV6_ADDRESSES_COUNT;
- static {
- // 85% of the address space must be routed for Vpn to consider this VPN to provide
- // INTERNET access.
- final int howManyPercentIsMost = 85;
-
- final long twoPower32 = 1L << 32;
- MOST_IPV4_ADDRESSES_COUNT = twoPower32 * howManyPercentIsMost / 100;
- final BigInteger twoPower128 = BigInteger.ONE.shiftLeft(128);
- MOST_IPV6_ADDRESSES_COUNT = twoPower128
- .multiply(BigInteger.valueOf(howManyPercentIsMost))
- .divide(BigInteger.valueOf(100));
- }
- // How many routes to evaluate before bailing and declaring this Vpn should provide
- // the INTERNET capability. This is necessary because computing the address space is
- // O(n²) and this is running in the system service, so a limit is needed to alleviate
- // the risk of attack.
- // This is taken as a total of IPv4 + IPV6 routes for simplicity, but the algorithm
- // is actually O(n²)+O(n²).
- private static final int MAX_ROUTES_TO_EVALUATE = 150;
private static final String LOCKDOWN_ALLOWLIST_SETTING_NAME =
Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN_WHITELIST;
/**
@@ -199,6 +170,7 @@ public class Vpn {
// automated reconnection
private final Context mContext;
+ private final ConnectivityManager mConnectivityManager;
// The context is for specific user which is created from mUserId
private final Context mUserIdContext;
@VisibleForTesting final Dependencies mDeps;
@@ -219,6 +191,7 @@ public class Vpn {
private final INetworkManagementService mNetd;
@VisibleForTesting
protected VpnConfig mConfig;
+ private final NetworkProvider mNetworkProvider;
@VisibleForTesting
protected NetworkAgent mNetworkAgent;
private final Looper mLooper;
@@ -402,6 +375,7 @@ public class Vpn {
int userId, @NonNull KeyStore keyStore, SystemServices systemServices,
Ikev2SessionCreator ikev2SessionCreator) {
mContext = context;
+ mConnectivityManager = mContext.getSystemService(ConnectivityManager.class);
mUserIdContext = context.createContextAsUser(UserHandle.of(userId), 0 /* flags */);
mDeps = deps;
mNetd = netService;
@@ -420,13 +394,16 @@ public class Vpn {
Log.wtf(TAG, "Problem registering observer", e);
}
+ mNetworkProvider = new NetworkProvider(context, looper, VPN_PROVIDER_NAME_BASE + mUserId);
+ // This constructor is called in onUserStart and registers the provider. The provider
+ // will be unregistered in onUserStop.
+ mConnectivityManager.registerNetworkProvider(mNetworkProvider);
mLegacyState = LegacyVpnInfo.STATE_DISCONNECTED;
mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_VPN, 0 /* subtype */, NETWORKTYPE,
"" /* subtypeName */);
mNetworkCapabilities = new NetworkCapabilities();
mNetworkCapabilities.addTransportType(NetworkCapabilities.TRANSPORT_VPN);
mNetworkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN);
- updateCapabilities(null /* defaultNetwork */);
loadAlwaysOnPackage(keyStore);
}
@@ -444,110 +421,44 @@ public class Vpn {
* Update current state, dispatching event to listeners.
*/
@VisibleForTesting
+ @GuardedBy("this")
protected void updateState(DetailedState detailedState, String reason) {
if (LOGD) Log.d(TAG, "setting state=" + detailedState + ", reason=" + reason);
mLegacyState = LegacyVpnInfo.stateFromNetworkInfo(detailedState);
mNetworkInfo.setDetailedState(detailedState, reason, null);
- if (mNetworkAgent != null) {
- mNetworkAgent.sendNetworkInfo(mNetworkInfo);
+ // TODO : only accept transitions when the agent is in the correct state (non-null for
+ // CONNECTED, DISCONNECTED and FAILED, null for CONNECTED).
+ // This will require a way for tests to pretend the VPN is connected that's not
+ // calling this method with CONNECTED.
+ // It will also require audit of where the code calls this method with DISCONNECTED
+ // with a null agent, which it was doing historically to make sure the agent is
+ // disconnected as this was a no-op if the agent was null.
+ switch (detailedState) {
+ case CONNECTED:
+ if (null != mNetworkAgent) {
+ mNetworkAgent.markConnected();
+ }
+ break;
+ case DISCONNECTED:
+ case FAILED:
+ if (null != mNetworkAgent) {
+ mNetworkAgent.unregister();
+ mNetworkAgent = null;
+ }
+ break;
+ case CONNECTING:
+ if (null != mNetworkAgent) {
+ throw new IllegalStateException("VPN can only go to CONNECTING state when"
+ + " the agent is null.");
+ }
+ break;
+ default:
+ throw new IllegalArgumentException("Illegal state argument " + detailedState);
}
updateAlwaysOnNotification(detailedState);
}
/**
- * Updates {@link #mNetworkCapabilities} based on current underlying networks and returns a
- * defensive copy.
- *
- * <p>Does not propagate updated capabilities to apps.
- *
- * @param defaultNetwork underlying network for VPNs following platform's default
- */
- public synchronized NetworkCapabilities updateCapabilities(@Nullable Network defaultNetwork) {
- if (mConfig == null) {
- // VPN is not running.
- return null;
- }
-
- Network[] underlyingNetworks = mConfig.underlyingNetworks;
- if (underlyingNetworks == null && defaultNetwork != null) {
- // null underlying networks means to track the default.
- underlyingNetworks = new Network[] { defaultNetwork };
- }
- // Only apps targeting Q and above can explicitly declare themselves as metered.
- final boolean isAlwaysMetered = mIsPackageTargetingAtLeastQ && mConfig.isMetered;
-
- applyUnderlyingCapabilities(
- mContext.getSystemService(ConnectivityManager.class),
- underlyingNetworks,
- mNetworkCapabilities,
- isAlwaysMetered);
-
- return new NetworkCapabilities(mNetworkCapabilities);
- }
-
- @VisibleForTesting
- public static void applyUnderlyingCapabilities(
- ConnectivityManager cm,
- Network[] underlyingNetworks,
- NetworkCapabilities caps,
- boolean isAlwaysMetered) {
- int[] transportTypes = new int[] { NetworkCapabilities.TRANSPORT_VPN };
- int downKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
- int upKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
- boolean metered = isAlwaysMetered; // metered if any underlying is metered, or alwaysMetered
- boolean roaming = false; // roaming if any underlying is roaming
- boolean congested = false; // congested if any underlying is congested
- boolean suspended = true; // suspended if all underlying are suspended
-
- boolean hadUnderlyingNetworks = false;
- if (null != underlyingNetworks) {
- for (Network underlying : underlyingNetworks) {
- // TODO(b/124469351): Get capabilities directly from ConnectivityService instead.
- final NetworkCapabilities underlyingCaps = cm.getNetworkCapabilities(underlying);
- if (underlyingCaps == null) continue;
- hadUnderlyingNetworks = true;
- for (int underlyingType : underlyingCaps.getTransportTypes()) {
- transportTypes = ArrayUtils.appendInt(transportTypes, underlyingType);
- }
-
- // Merge capabilities of this underlying network. For bandwidth, assume the
- // worst case.
- downKbps = NetworkCapabilities.minBandwidth(downKbps,
- underlyingCaps.getLinkDownstreamBandwidthKbps());
- upKbps = NetworkCapabilities.minBandwidth(upKbps,
- underlyingCaps.getLinkUpstreamBandwidthKbps());
- // If this underlying network is metered, the VPN is metered (it may cost money
- // to send packets on this network).
- metered |= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_METERED);
- // If this underlying network is roaming, the VPN is roaming (the billing structure
- // is different than the usual, local one).
- roaming |= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_ROAMING);
- // If this underlying network is congested, the VPN is congested (the current
- // condition of the network affects the performance of this network).
- congested |= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_CONGESTED);
- // If this network is not suspended, the VPN is not suspended (the VPN
- // is able to transfer some data).
- suspended &= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED);
- }
- }
- if (!hadUnderlyingNetworks) {
- // No idea what the underlying networks are; assume the safer defaults
- metered = true;
- roaming = false;
- congested = false;
- suspended = false;
- }
-
- caps.setTransportTypes(transportTypes);
- caps.setLinkDownstreamBandwidthKbps(downKbps);
- caps.setLinkUpstreamBandwidthKbps(upKbps);
- caps.setCapability(NET_CAPABILITY_NOT_METERED, !metered);
- caps.setCapability(NET_CAPABILITY_NOT_ROAMING, !roaming);
- caps.setCapability(NET_CAPABILITY_NOT_CONGESTED, !congested);
- caps.setCapability(NET_CAPABILITY_NOT_SUSPENDED, !suspended);
- }
-
- /**
* Chooses whether to force all connections to go though VPN.
*
* Used to enable/disable legacy VPN lockdown.
@@ -1017,7 +928,7 @@ public class Vpn {
}
mConfig = null;
- updateState(DetailedState.IDLE, "prepare");
+ updateState(DetailedState.DISCONNECTED, "prepare");
setVpnForcedLocked(mLockdown);
} finally {
Binder.restoreCallingIdentity(token);
@@ -1253,7 +1164,7 @@ public class Vpn {
mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
mLegacyState = LegacyVpnInfo.STATE_CONNECTING;
- mNetworkInfo.setDetailedState(DetailedState.CONNECTING, null, null);
+ updateState(DetailedState.CONNECTING, "agentConnect");
NetworkAgentConfig networkAgentConfig = new NetworkAgentConfig();
networkAgentConfig.allowBypass = mConfig.allowBypass && !mLockdown;
@@ -1262,20 +1173,34 @@ public class Vpn {
mNetworkCapabilities.setAdministratorUids(new int[] {mOwnerUID});
mNetworkCapabilities.setUids(createUserAndRestrictedProfilesRanges(mUserId,
mConfig.allowedApplications, mConfig.disallowedApplications));
- final long token = Binder.clearCallingIdentity();
- try {
- mNetworkAgent = new NetworkAgent(mLooper, mContext, NETWORKTYPE /* logtag */,
- mNetworkInfo, mNetworkCapabilities, lp,
- ConnectivityConstants.VPN_DEFAULT_SCORE, networkAgentConfig,
- NetworkProvider.ID_VPN) {
- @Override
- public void unwanted() {
- // We are user controlled, not driven by NetworkRequest.
- }
- };
- } finally {
- Binder.restoreCallingIdentity(token);
+
+ // Only apps targeting Q and above can explicitly declare themselves as metered.
+ // These VPNs are assumed metered unless they state otherwise.
+ if (mIsPackageTargetingAtLeastQ && mConfig.isMetered) {
+ mNetworkCapabilities.removeCapability(NET_CAPABILITY_NOT_METERED);
+ } else {
+ mNetworkCapabilities.addCapability(NET_CAPABILITY_NOT_METERED);
}
+
+ mNetworkAgent = new NetworkAgent(mContext, mLooper, NETWORKTYPE /* logtag */,
+ mNetworkCapabilities, lp,
+ ConnectivityConstants.VPN_DEFAULT_SCORE, networkAgentConfig, mNetworkProvider) {
+ @Override
+ public void unwanted() {
+ // We are user controlled, not driven by NetworkRequest.
+ }
+ };
+ Binder.withCleanCallingIdentity(() -> {
+ try {
+ mNetworkAgent.register();
+ } catch (final Exception e) {
+ // If register() throws, don't keep an unregistered agent.
+ mNetworkAgent = null;
+ throw e;
+ }
+ });
+ mNetworkAgent.setUnderlyingNetworks((mConfig.underlyingNetworks != null)
+ ? Arrays.asList(mConfig.underlyingNetworks) : null);
mNetworkInfo.setIsAvailable(true);
updateState(DetailedState.CONNECTED, "agentConnect");
}
@@ -1291,19 +1216,12 @@ public class Vpn {
private void agentDisconnect(NetworkAgent networkAgent) {
if (networkAgent != null) {
- NetworkInfo networkInfo = new NetworkInfo(mNetworkInfo);
- networkInfo.setIsAvailable(false);
- networkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
- networkAgent.sendNetworkInfo(networkInfo);
+ networkAgent.unregister();
}
}
private void agentDisconnect() {
- if (mNetworkInfo.isConnected()) {
- mNetworkInfo.setIsAvailable(false);
- updateState(DetailedState.DISCONNECTED, "agentDisconnect");
- mNetworkAgent = null;
- }
+ updateState(DetailedState.DISCONNECTED, "agentDisconnect");
}
/**
@@ -1392,6 +1310,8 @@ public class Vpn {
&& updateLinkPropertiesInPlaceIfPossible(mNetworkAgent, oldConfig)) {
// Keep mNetworkAgent unchanged
} else {
+ // Initialize the state for a new agent, while keeping the old one connected
+ // in case this new connection fails.
mNetworkAgent = null;
updateState(DetailedState.CONNECTING, "establish");
// Set up forwarding and DNS rules.
@@ -1483,7 +1403,7 @@ public class Vpn {
final long token = Binder.clearCallingIdentity();
List<UserInfo> users;
try {
- users = UserManager.get(mContext).getUsers(true);
+ users = UserManager.get(mContext).getAliveUsers();
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -1575,12 +1495,13 @@ public class Vpn {
try {
addUserToRanges(existingRanges, userId, mConfig.allowedApplications,
mConfig.disallowedApplications);
- // ConnectivityService will call {@link #updateCapabilities} and apply
- // those for VPN network.
mNetworkCapabilities.setUids(existingRanges);
} catch (Exception e) {
Log.wtf(TAG, "Failed to add restricted user to owner", e);
}
+ if (mNetworkAgent != null) {
+ mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
+ }
}
setVpnForcedLocked(mLockdown);
}
@@ -1603,12 +1524,13 @@ public class Vpn {
final List<UidRange> removedRanges =
uidRangesForUser(userId, existingRanges);
existingRanges.removeAll(removedRanges);
- // ConnectivityService will call {@link #updateCapabilities} and
- // apply those for VPN network.
mNetworkCapabilities.setUids(existingRanges);
} catch (Exception e) {
Log.wtf(TAG, "Failed to remove restricted user to owner", e);
}
+ if (mNetworkAgent != null) {
+ mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
+ }
}
setVpnForcedLocked(mLockdown);
}
@@ -1625,6 +1547,9 @@ public class Vpn {
// Quit any active connections
agentDisconnect();
+
+ // The provider has been registered in the constructor, which is called in onUserStart.
+ mConnectivityManager.unregisterNetworkProvider(mNetworkProvider);
}
/**
@@ -1857,6 +1782,8 @@ public class Vpn {
}
}
}
+ mNetworkAgent.setUnderlyingNetworks((mConfig.underlyingNetworks != null)
+ ? Arrays.asList(mConfig.underlyingNetworks) : null);
return true;
}
@@ -2399,7 +2326,6 @@ public class Vpn {
// When restricted to test networks, select any network with TRANSPORT_TEST. Since the
// creator of the profile and the test network creator both have MANAGE_TEST_NETWORKS,
// this is considered safe.
- final ConnectivityManager cm = ConnectivityManager.from(mContext);
final NetworkRequest req;
if (mProfile.isRestrictedToTestNetworks()) {
@@ -2418,7 +2344,7 @@ public class Vpn {
.build();
}
- cm.requestNetwork(req, mNetworkCallback);
+ mConnectivityManager.requestNetwork(req, mNetworkCallback);
}
private boolean isActiveNetwork(@Nullable Network network) {
@@ -2705,8 +2631,7 @@ public class Vpn {
resetIkeState();
- final ConnectivityManager cm = ConnectivityManager.from(mContext);
- cm.unregisterNetworkCallback(mNetworkCallback);
+ mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
mExecutor.shutdown();
}
@@ -2787,13 +2712,12 @@ public class Vpn {
mProfile = profile;
if (!TextUtils.isEmpty(mOuterInterface)) {
- final ConnectivityManager cm = ConnectivityManager.from(mContext);
- for (Network network : cm.getAllNetworks()) {
- final LinkProperties lp = cm.getLinkProperties(network);
+ for (Network network : mConnectivityManager.getAllNetworks()) {
+ final LinkProperties lp = mConnectivityManager.getLinkProperties(network);
if (lp != null && lp.getAllInterfaceNames().contains(mOuterInterface)) {
- final NetworkInfo networkInfo = cm.getNetworkInfo(network);
- if (networkInfo != null) {
- mOuterConnection.set(networkInfo.getType());
+ final NetworkInfo netInfo = mConnectivityManager.getNetworkInfo(network);
+ if (netInfo != null) {
+ mOuterConnection.set(netInfo.getType());
break;
}
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 804cc92cca08..b2d694b20d80 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -1569,10 +1569,11 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
// When the device is not unplugged but reawaken from standby, we check if the System
// Audio Control Feature is enabled or not then decide if turning SAM on/off accordingly.
if (getAvrDeviceInfo() != null && portId == getAvrDeviceInfo().getPortId()) {
+ HdmiLogger.debug("Port ID:%d, 5v=%b", portId, connected);
if (!connected) {
setSystemAudioMode(false);
- } else if (mSystemAudioControlFeatureEnabled != mService.isSystemAudioActivated()){
- setSystemAudioMode(mSystemAudioControlFeatureEnabled);
+ } else {
+ onNewAvrAdded(getAvrDeviceInfo());
}
}
diff --git a/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java b/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java
index 6633789ffc06..db93ad0617ff 100644
--- a/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java
+++ b/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java
@@ -102,12 +102,12 @@ final class SetArcTransmissionStateAction extends HdmiCecFeatureAction {
}
private void setArcStatus(boolean enabled) {
- boolean wasEnabled = tv().setArcStatus(enabled);
- Slog.i(TAG, "Change arc status [old:" + wasEnabled + ", new:" + enabled + "]");
+ tv().setArcStatus(enabled);
+ Slog.i(TAG, "Change arc status to " + enabled);
// If enabled before and set to "disabled" and send <Report Arc Terminated> to
// av reciever.
- if (!enabled && wasEnabled) {
+ if (!enabled) {
sendCommand(HdmiCecMessageBuilder.buildReportArcTerminated(getSourceAddress(),
mAvrAddress));
}
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index cef5cb6c6e30..4563a2de19c1 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -154,6 +154,7 @@ import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Objects;
+import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -261,7 +262,13 @@ public class LockSettingsService extends ILockSettings.Stub {
@Override
public void onStart() {
- AndroidKeyStoreProvider.install();
+ Optional<Boolean> keystore2_enabled =
+ android.sysprop.Keystore2Properties.keystore2_enabled();
+ if (keystore2_enabled.isPresent() && keystore2_enabled.get()) {
+ android.security.keystore2.AndroidKeyStoreProvider.install();
+ } else {
+ AndroidKeyStoreProvider.install();
+ }
mLockSettingsService = new LockSettingsService(getContext());
publishBinderService("lock_settings", mLockSettingsService);
}
@@ -542,7 +549,8 @@ public class LockSettingsService extends ILockSettings.Stub {
public @NonNull ManagedProfilePasswordCache getManagedProfilePasswordCache() {
try {
- java.security.KeyStore ks = java.security.KeyStore.getInstance("AndroidKeyStore");
+ java.security.KeyStore ks = java.security.KeyStore.getInstance(
+ SyntheticPasswordCrypto.androidKeystoreProviderName());
ks.load(null);
return new ManagedProfilePasswordCache(ks, getUserManager());
} catch (Exception e) {
@@ -1284,7 +1292,8 @@ public class LockSettingsService extends ILockSettings.Stub {
byte[] encryptedPassword = Arrays.copyOfRange(storedData, PROFILE_KEY_IV_SIZE,
storedData.length);
byte[] decryptionResult;
- java.security.KeyStore keyStore = java.security.KeyStore.getInstance("AndroidKeyStore");
+ java.security.KeyStore keyStore = java.security.KeyStore.getInstance(
+ SyntheticPasswordCrypto.androidKeystoreProviderName());
keyStore.load(null);
SecretKey decryptionKey = (SecretKey) keyStore.getKey(
LockPatternUtils.PROFILE_KEY_NAME_DECRYPT + userId, null);
@@ -1743,7 +1752,8 @@ public class LockSettingsService extends ILockSettings.Stub {
KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES);
keyGenerator.init(new SecureRandom());
SecretKey secretKey = keyGenerator.generateKey();
- java.security.KeyStore keyStore = java.security.KeyStore.getInstance("AndroidKeyStore");
+ java.security.KeyStore keyStore = java.security.KeyStore.getInstance(
+ SyntheticPasswordCrypto.androidKeystoreProviderName());
keyStore.load(null);
try {
keyStore.setEntry(
@@ -2299,7 +2309,8 @@ public class LockSettingsService extends ILockSettings.Stub {
private void removeKeystoreProfileKey(int targetUserId) {
Slog.i(TAG, "Remove keystore profile key for user: " + targetUserId);
try {
- java.security.KeyStore keyStore = java.security.KeyStore.getInstance("AndroidKeyStore");
+ java.security.KeyStore keyStore = java.security.KeyStore.getInstance(
+ SyntheticPasswordCrypto.androidKeystoreProviderName());
keyStore.load(null);
keyStore.deleteEntry(LockPatternUtils.PROFILE_KEY_NAME_ENCRYPT + targetUserId);
keyStore.deleteEntry(LockPatternUtils.PROFILE_KEY_NAME_DECRYPT + targetUserId);
diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordCrypto.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordCrypto.java
index 9246311fcdc7..6d420a95e26c 100644
--- a/services/core/java/com/android/server/locksettings/SyntheticPasswordCrypto.java
+++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordCrypto.java
@@ -18,6 +18,7 @@ package com.android.server.locksettings;
import android.security.keystore.KeyProperties;
import android.security.keystore.KeyProtection;
+import android.security.keystore2.AndroidKeyStoreProvider;
import android.util.Slog;
import java.io.ByteArrayOutputStream;
@@ -125,7 +126,7 @@ public class SyntheticPasswordCrypto {
public static byte[] decryptBlobV1(String keyAlias, byte[] blob, byte[] applicationId) {
try {
- KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
+ KeyStore keyStore = KeyStore.getInstance(androidKeystoreProviderName());
keyStore.load(null);
SecretKey decryptionKey = (SecretKey) keyStore.getKey(keyAlias, null);
@@ -140,9 +141,24 @@ public class SyntheticPasswordCrypto {
}
}
+ /**
+ * TODO This function redirects keystore access to the legacy keystore during a transitional
+ * phase during which not all calling code has been adjusted to use Keystore 2.0.
+ * This can be reverted to a constant of "AndroidKeyStore" when b/171305684 is complete.
+ * The specific bug for this component is b/171305115.
+ */
+ static String androidKeystoreProviderName() {
+ if (AndroidKeyStoreProvider.isInstalled()) {
+ return "AndroidKeyStoreLegacy";
+ } else {
+ return "AndroidKeystore";
+ }
+
+ }
+
public static byte[] decryptBlob(String keyAlias, byte[] blob, byte[] applicationId) {
try {
- KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
+ KeyStore keyStore = KeyStore.getInstance(androidKeystoreProviderName());
keyStore.load(null);
SecretKey decryptionKey = (SecretKey) keyStore.getKey(keyAlias, null);
@@ -166,7 +182,7 @@ public class SyntheticPasswordCrypto {
KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES);
keyGenerator.init(AES_KEY_LENGTH * 8, new SecureRandom());
SecretKey secretKey = keyGenerator.generateKey();
- KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
+ KeyStore keyStore = KeyStore.getInstance(androidKeystoreProviderName());
keyStore.load(null);
KeyProtection.Builder builder = new KeyProtection.Builder(KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
@@ -196,7 +212,7 @@ public class SyntheticPasswordCrypto {
public static void destroyBlobKey(String keyAlias) {
KeyStore keyStore;
try {
- keyStore = KeyStore.getInstance("AndroidKeyStore");
+ keyStore = KeyStore.getInstance(androidKeystoreProviderName());
keyStore.load(null);
keyStore.deleteEntry(keyAlias);
Slog.i(TAG, "SP key deleted: " + keyAlias);
diff --git a/services/core/java/com/android/server/media/MediaKeyDispatcher.java b/services/core/java/com/android/server/media/MediaKeyDispatcher.java
index 5933723f01b6..fc7c82ac5fd1 100644
--- a/services/core/java/com/android/server/media/MediaKeyDispatcher.java
+++ b/services/core/java/com/android/server/media/MediaKeyDispatcher.java
@@ -20,6 +20,7 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.PendingIntent;
+import android.content.Context;
import android.media.session.ISessionManager;
import android.media.session.MediaSession;
import android.os.Binder;
@@ -60,7 +61,7 @@ public abstract class MediaKeyDispatcher {
private Map<Integer, Integer> mOverriddenKeyEvents;
- public MediaKeyDispatcher() {
+ public MediaKeyDispatcher(Context context) {
// Constructor used for reflection
mOverriddenKeyEvents = new HashMap<>();
mOverriddenKeyEvents.put(KeyEvent.KEYCODE_MEDIA_PLAY, 0);
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index b02b90092b7a..9dde4c83e2a2 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -96,7 +96,6 @@ import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
-import java.util.Map;
/**
* System implementation of MediaSessionManager
@@ -152,7 +151,6 @@ public class MediaSessionService extends SystemService implements Monitor {
private SessionPolicyProvider mCustomSessionPolicyProvider;
private MediaKeyDispatcher mCustomMediaKeyDispatcher;
- private Map<Integer, Integer> mOverriddenKeyEventsMap;
public MediaSessionService(Context context) {
super(context);
@@ -771,7 +769,6 @@ public class MediaSessionService extends SystemService implements Monitor {
private void instantiateCustomDispatcher(String nameFromTesting) {
synchronized (mLock) {
mCustomMediaKeyDispatcher = null;
- mOverriddenKeyEventsMap = null;
String customDispatcherClassName = (nameFromTesting == null)
? mContext.getResources().getString(R.string.config_customMediaKeyDispatcher)
@@ -779,9 +776,10 @@ public class MediaSessionService extends SystemService implements Monitor {
try {
if (!TextUtils.isEmpty(customDispatcherClassName)) {
Class customDispatcherClass = Class.forName(customDispatcherClassName);
- Constructor constructor = customDispatcherClass.getDeclaredConstructor();
- mCustomMediaKeyDispatcher = (MediaKeyDispatcher) constructor.newInstance();
- mOverriddenKeyEventsMap = mCustomMediaKeyDispatcher.getOverriddenKeyEvents();
+ Constructor constructor =
+ customDispatcherClass.getDeclaredConstructor(Context.class);
+ mCustomMediaKeyDispatcher =
+ (MediaKeyDispatcher) constructor.newInstance(mContext);
}
} catch (ClassNotFoundException | InstantiationException | InvocationTargetException
| IllegalAccessException | NoSuchMethodException e) {
@@ -801,9 +799,10 @@ public class MediaSessionService extends SystemService implements Monitor {
try {
if (!TextUtils.isEmpty(customProviderClassName)) {
Class customProviderClass = Class.forName(customProviderClassName);
- Constructor constructor = customProviderClass.getDeclaredConstructor();
+ Constructor constructor =
+ customProviderClass.getDeclaredConstructor(Context.class);
mCustomSessionPolicyProvider =
- (SessionPolicyProvider) constructor.newInstance();
+ (SessionPolicyProvider) constructor.newInstance(mContext);
}
} catch (ClassNotFoundException | InstantiationException | InvocationTargetException
| IllegalAccessException | NoSuchMethodException e) {
@@ -2398,9 +2397,12 @@ public class MediaSessionService extends SystemService implements Monitor {
return;
}
- int overriddenKeyEvents = (mCustomMediaKeyDispatcher == null) ? 0
- : mCustomMediaKeyDispatcher.getOverriddenKeyEvents()
- .get(keyEvent.getKeyCode());
+ int overriddenKeyEvents = 0;
+ if (mCustomMediaKeyDispatcher != null
+ && mCustomMediaKeyDispatcher.getOverriddenKeyEvents() != null) {
+ overriddenKeyEvents = mCustomMediaKeyDispatcher.getOverriddenKeyEvents()
+ .get(keyEvent.getKeyCode());
+ }
cancelTrackingIfNeeded(packageName, pid, uid, asSystemService, keyEvent,
needWakeLock, opPackageName, stream, musicOnly, overriddenKeyEvents);
if (!needTracking(keyEvent, overriddenKeyEvents)) {
diff --git a/services/core/java/com/android/server/media/SessionPolicyProvider.java b/services/core/java/com/android/server/media/SessionPolicyProvider.java
index 5f02a075344e..332c85adec01 100644
--- a/services/core/java/com/android/server/media/SessionPolicyProvider.java
+++ b/services/core/java/com/android/server/media/SessionPolicyProvider.java
@@ -18,6 +18,7 @@ package com.android.server.media;
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.content.Context;
import android.media.session.MediaSession;
import java.lang.annotation.Retention;
@@ -54,7 +55,7 @@ public abstract class SessionPolicyProvider {
*/
static final int SESSION_POLICY_IGNORE_BUTTON_SESSION = 1 << 1;
- public SessionPolicyProvider() {
+ public SessionPolicyProvider(Context context) {
// Constructor used for reflection
}
diff --git a/services/core/java/com/android/server/pm/PreferredComponent.java b/services/core/java/com/android/server/pm/PreferredComponent.java
index c312fc0eca2f..a0b2e86e6a1d 100644
--- a/services/core/java/com/android/server/pm/PreferredComponent.java
+++ b/services/core/java/com/android/server/pm/PreferredComponent.java
@@ -254,6 +254,37 @@ public class PreferredComponent {
return numMatch == NS;
}
+ public boolean sameSet(PreferredComponent pc) {
+ if (mSetPackages == null || pc == null || pc.mSetPackages == null
+ || !sameComponent(pc.mComponent)) {
+ return false;
+ }
+ final int otherPackageCount = pc.mSetPackages.length;
+ final int packageCount = mSetPackages.length;
+ if (otherPackageCount != packageCount) {
+ return false;
+ }
+ for (int i = 0; i < packageCount; i++) {
+ if (!mSetPackages[i].equals(pc.mSetPackages[i])
+ || !mSetClasses[i].equals(pc.mSetClasses[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /** Returns true if the preferred component represents the provided ComponentName. */
+ private boolean sameComponent(ComponentName comp) {
+ if (mComponent == null || comp == null) {
+ return false;
+ }
+ if (mComponent.getPackageName().equals(comp.getPackageName())
+ && mComponent.getClassName().equals(comp.getClassName())) {
+ return true;
+ }
+ return false;
+ }
+
public boolean isSuperset(List<ResolveInfo> query, boolean excludeSetupWizardPackage) {
if (mSetPackages == null) {
return query == null;
diff --git a/services/core/java/com/android/server/pm/PreferredIntentResolver.java b/services/core/java/com/android/server/pm/PreferredIntentResolver.java
index a261e29b05a7..ff3df130a3cc 100644
--- a/services/core/java/com/android/server/pm/PreferredIntentResolver.java
+++ b/services/core/java/com/android/server/pm/PreferredIntentResolver.java
@@ -22,6 +22,7 @@ import android.content.IntentFilter;
import java.io.PrintWriter;
import com.android.server.IntentResolver;
+import java.util.ArrayList;
public class PreferredIntentResolver
extends IntentResolver<PreferredActivity, PreferredActivity> {
@@ -45,4 +46,24 @@ public class PreferredIntentResolver
protected IntentFilter getIntentFilter(@NonNull PreferredActivity input) {
return input;
}
+
+ public boolean shouldAddPreferredActivity(PreferredActivity pa) {
+ ArrayList<PreferredActivity> pal = findFilters(pa);
+ if (pal == null || pal.isEmpty()) {
+ return true;
+ }
+ if (!pa.mPref.mAlways) {
+ return false;
+ }
+ final int activityCount = pal.size();
+ for (int i = 0; i < activityCount; i++) {
+ PreferredActivity cur = pal.get(i);
+ if (cur.mPref.mAlways
+ && cur.mPref.mMatch == (pa.mPref.mMatch & IntentFilter.MATCH_CATEGORY_MASK)
+ && cur.mPref.sameSet(pa.mPref)) {
+ return false;
+ }
+ }
+ return true;
+ }
}
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 0f5d9781c612..79e5b276ac64 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -1410,8 +1410,7 @@ public final class Settings {
PreferredActivity pa = new PreferredActivity(parser);
if (pa.mPref.getParseError() == null) {
final PreferredIntentResolver resolver = editPreferredActivitiesLPw(userId);
- ArrayList<PreferredActivity> pal = resolver.findFilters(pa);
- if (pal == null || pal.size() == 0 || pa.mPref.mAlways) {
+ if (resolver.shouldAddPreferredActivity(pa)) {
resolver.addFilter(pa);
}
} else {
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorService.java b/services/core/java/com/android/server/timedetector/TimeDetectorService.java
index c63f306ec84f..6dac6b1773c4 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorService.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorService.java
@@ -125,7 +125,7 @@ public final class TimeDetectorService extends ITimeDetectorService.Stub {
/** Internal method for handling the auto time setting being changed. */
@VisibleForTesting
public void handleAutoTimeDetectionChanged() {
- mHandler.post(mTimeDetectorStrategy::handleAutoTimeDetectionChanged);
+ mHandler.post(mTimeDetectorStrategy::handleAutoTimeConfigChanged);
}
@Override
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java b/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java
index 13f0ab605b3a..abd4c8c63a07 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java
@@ -16,6 +16,7 @@
package com.android.server.timedetector;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.timedetector.ManualTimeSuggestion;
@@ -24,6 +25,8 @@ import android.app.timedetector.TelephonyTimeSuggestion;
import android.os.TimestampedValue;
import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
/**
* The interface for the class that implements the time detection algorithm used by the
@@ -37,22 +40,41 @@ import java.io.PrintWriter;
*/
public interface TimeDetectorStrategy {
- /** Process the suggested time from telephony sources. */
+ @IntDef({ ORIGIN_TELEPHONY, ORIGIN_MANUAL, ORIGIN_NETWORK })
+ @Retention(RetentionPolicy.SOURCE)
+ @interface Origin {}
+
+ /** Used when a time value originated from a telephony signal. */
+ @Origin
+ int ORIGIN_TELEPHONY = 1;
+
+ /** Used when a time value originated from a user / manual settings. */
+ @Origin
+ int ORIGIN_MANUAL = 2;
+
+ /** Used when a time value originated from a network signal. */
+ @Origin
+ int ORIGIN_NETWORK = 3;
+
+ /** Processes the suggested time from telephony sources. */
void suggestTelephonyTime(@NonNull TelephonyTimeSuggestion timeSuggestion);
/**
- * Process the suggested manually entered time. Returns {@code false} if the suggestion was
+ * Processes the suggested manually entered time. Returns {@code false} if the suggestion was
* invalid, or the device configuration prevented the suggestion being used, {@code true} if the
* suggestion was accepted. A suggestion that is valid but does not change the time because it
* matches the current device time is considered accepted.
*/
boolean suggestManualTime(@NonNull ManualTimeSuggestion timeSuggestion);
- /** Process the suggested time from network sources. */
+ /** Processes the suggested time from network sources. */
void suggestNetworkTime(@NonNull NetworkTimeSuggestion timeSuggestion);
- /** Handle the auto-time setting being toggled on or off. */
- void handleAutoTimeDetectionChanged();
+ /**
+ * Handles the auto-time configuration changing For example, when the auto-time setting is
+ * toggled on or off.
+ */
+ void handleAutoTimeConfigChanged();
/** Dump debug information. */
void dump(@NonNull PrintWriter pw, @Nullable String[] args);
@@ -67,4 +89,38 @@ public interface TimeDetectorStrategy {
return (referenceClockMillisNow - timeValue.getReferenceTimeMillis())
+ timeValue.getValue();
}
+
+ /**
+ * Converts one of the {@code ORIGIN_} constants to a human readable string suitable for config
+ * and debug usage. Throws an {@link IllegalArgumentException} if the value is unrecognized.
+ */
+ static String originToString(@Origin int origin) {
+ switch (origin) {
+ case ORIGIN_MANUAL:
+ return "manual";
+ case ORIGIN_NETWORK:
+ return "network";
+ case ORIGIN_TELEPHONY:
+ return "telephony";
+ default:
+ throw new IllegalArgumentException("origin=" + origin);
+ }
+ }
+
+ /**
+ * Converts a human readable config string to one of the {@code ORIGIN_} constants.
+ * Throws an {@link IllegalArgumentException} if the value is unrecognized.
+ */
+ static @Origin int stringToOrigin(String originString) {
+ switch (originString) {
+ case "manual":
+ return ORIGIN_MANUAL;
+ case "network":
+ return ORIGIN_NETWORK;
+ case "telephony":
+ return ORIGIN_TELEPHONY;
+ default:
+ throw new IllegalArgumentException("originString=" + originString);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyCallbackImpl.java b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyCallbackImpl.java
index 6bd107fffeaa..5b6de0518999 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyCallbackImpl.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyCallbackImpl.java
@@ -16,6 +16,8 @@
package com.android.server.timedetector;
+import static com.android.server.timedetector.TimeDetectorStrategy.stringToOrigin;
+
import android.annotation.NonNull;
import android.app.AlarmManager;
import android.content.ContentResolver;
@@ -58,6 +60,7 @@ public final class TimeDetectorStrategyCallbackImpl implements TimeDetectorStrat
@NonNull private final ContentResolver mContentResolver;
@NonNull private final PowerManager.WakeLock mWakeLock;
@NonNull private final AlarmManager mAlarmManager;
+ @NonNull private final int[] mOriginPriorities;
public TimeDetectorStrategyCallbackImpl(@NonNull Context context) {
mContext = Objects.requireNonNull(context);
@@ -72,6 +75,15 @@ public final class TimeDetectorStrategyCallbackImpl implements TimeDetectorStrat
mSystemClockUpdateThresholdMillis =
SystemProperties.getInt("ro.sys.time_detector_update_diff",
SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS_DEFAULT);
+
+ // TODO(b/172230856): Obtain these values from configuration.
+ String[] originStrings = { "telephony", "network" };
+ int[] origins = new int[originStrings.length];
+ for (int i = 0; i < originStrings.length; i++) {
+ int origin = stringToOrigin(originStrings[i]);
+ origins[i] = origin;
+ }
+ mOriginPriorities = origins;
}
@Override
@@ -94,6 +106,11 @@ public final class TimeDetectorStrategyCallbackImpl implements TimeDetectorStrat
}
@Override
+ public int[] getAutoOriginPriorities() {
+ return mOriginPriorities;
+ }
+
+ @Override
public void acquireWakeLock() {
if (mWakeLock.isHeld()) {
Slog.wtf(TAG, "WakeLock " + mWakeLock + " already held");
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
index a889bdfe17b6..36a3ddd73d89 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
@@ -16,7 +16,8 @@
package com.android.server.timedetector;
-import android.annotation.IntDef;
+import static com.android.server.timedetector.TimeDetectorStrategy.originToString;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.AlarmManager;
@@ -34,9 +35,8 @@ import com.android.server.timezonedetector.ArrayMapWithHistory;
import com.android.server.timezonedetector.ReferenceWithHistory;
import java.io.PrintWriter;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
import java.time.Instant;
+import java.util.Arrays;
/**
* An implementation of {@link TimeDetectorStrategy} that passes telephony and manual suggestions to
@@ -64,22 +64,6 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
static final long MAX_UTC_TIME_AGE_MILLIS =
TELEPHONY_BUCKET_COUNT * TELEPHONY_BUCKET_SIZE_MILLIS;
- @IntDef({ ORIGIN_TELEPHONY, ORIGIN_MANUAL, ORIGIN_NETWORK })
- @Retention(RetentionPolicy.SOURCE)
- public @interface Origin {}
-
- /** Used when a time value originated from a telephony signal. */
- @Origin
- private static final int ORIGIN_TELEPHONY = 1;
-
- /** Used when a time value originated from a user / manual settings. */
- @Origin
- private static final int ORIGIN_MANUAL = 2;
-
- /** Used when a time value originated from a network signal. */
- @Origin
- private static final int ORIGIN_NETWORK = 3;
-
/**
* CLOCK_PARANOIA: The maximum difference allowed between the expected system clock time and the
* actual system clock time before a warning is logged. Used to help identify situations where
@@ -153,6 +137,12 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
@NonNull
Instant autoTimeLowerBound();
+ /**
+ * Returns the order to look at time suggestions when automatically detecting time.
+ * See {@code #ORIGIN_} constants
+ */
+ @Origin int[] getAutoOriginPriorities();
+
/** Acquire a suitable wake lock. Must be followed by {@link #releaseWakeLock()} */
void acquireWakeLock();
@@ -237,12 +227,12 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
}
@Override
- public synchronized void handleAutoTimeDetectionChanged() {
+ public synchronized void handleAutoTimeConfigChanged() {
boolean enabled = mCallback.isAutoTimeDetectionEnabled();
// When automatic time detection is enabled we update the system clock instantly if we can.
// Conversely, when automatic time detection is disabled we leave the clock as it is.
if (enabled) {
- String reason = "Auto time zone detection setting enabled.";
+ String reason = "Auto time zone detection config changed.";
doAutoTimeDetection(reason);
} else {
// CLOCK_PARANOIA: We are losing "control" of the system clock so we cannot predict what
@@ -365,33 +355,44 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
return;
}
- // Android devices currently prioritize any telephony over network signals. There are
- // carrier compliance tests that would need to be changed before we could ignore NITZ or
- // prefer NTP generally. This check is cheap on devices without telephony hardware.
- TelephonyTimeSuggestion bestTelephonySuggestion = findBestTelephonySuggestion();
- if (bestTelephonySuggestion != null) {
- final TimestampedValue<Long> newUtcTime = bestTelephonySuggestion.getUtcTime();
- String cause = "Found good telephony suggestion."
- + ", bestTelephonySuggestion=" + bestTelephonySuggestion
- + ", detectionReason=" + detectionReason;
- setSystemClockIfRequired(ORIGIN_TELEPHONY, newUtcTime, cause);
- return;
- }
+ // Try the different origins one at a time.
+ int[] originPriorities = mCallback.getAutoOriginPriorities();
+ for (int origin : originPriorities) {
+ TimestampedValue<Long> newUtcTime = null;
+ String cause = null;
+ if (origin == ORIGIN_TELEPHONY) {
+ TelephonyTimeSuggestion bestTelephonySuggestion = findBestTelephonySuggestion();
+ if (bestTelephonySuggestion != null) {
+ newUtcTime = bestTelephonySuggestion.getUtcTime();
+ cause = "Found good telephony suggestion."
+ + ", bestTelephonySuggestion=" + bestTelephonySuggestion
+ + ", detectionReason=" + detectionReason;
+ }
+ } else if (origin == ORIGIN_NETWORK) {
+ NetworkTimeSuggestion networkSuggestion = findLatestValidNetworkSuggestion();
+ if (networkSuggestion != null) {
+ newUtcTime = networkSuggestion.getUtcTime();
+ cause = "Found good network suggestion."
+ + ", networkSuggestion=" + networkSuggestion
+ + ", detectionReason=" + detectionReason;
+ }
+ } else {
+ Slog.w(LOG_TAG, "Unknown or unsupported origin=" + origin
+ + " in " + Arrays.toString(originPriorities)
+ + ": Skipping");
+ }
- // There is no good telephony suggestion, try network.
- NetworkTimeSuggestion networkSuggestion = findLatestValidNetworkSuggestion();
- if (networkSuggestion != null) {
- final TimestampedValue<Long> newUtcTime = networkSuggestion.getUtcTime();
- String cause = "Found good network suggestion."
- + ", networkSuggestion=" + networkSuggestion
- + ", detectionReason=" + detectionReason;
- setSystemClockIfRequired(ORIGIN_NETWORK, newUtcTime, cause);
- return;
+ // Update the system clock if a good suggestion has been found.
+ if (newUtcTime != null) {
+ setSystemClockIfRequired(origin, newUtcTime, cause);
+ return;
+ }
}
if (DBG) {
- Slog.d(LOG_TAG, "Could not determine time: No best telephony or network suggestion."
- + " detectionReason=" + detectionReason);
+ Slog.d(LOG_TAG, "Could not determine time: No suggestion found in"
+ + " originPriorities=" + Arrays.toString(originPriorities)
+ + ", detectionReason=" + detectionReason);
}
}
@@ -476,7 +477,7 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
// Validate first.
TimestampedValue<Long> utcTime = timeSuggestion.getUtcTime();
if (!validateSuggestionUtcTime(elapsedRealtimeMillis, utcTime)) {
- Slog.w(LOG_TAG, "Existing suggestion found to be invalid "
+ Slog.w(LOG_TAG, "Existing suggestion found to be invalid"
+ " elapsedRealtimeMillis=" + elapsedRealtimeMillis
+ ", timeSuggestion=" + timeSuggestion);
return TELEPHONY_INVALID_SCORE;
@@ -525,7 +526,7 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
if (!mCallback.isAutoTimeDetectionEnabled()) {
if (DBG) {
Slog.d(LOG_TAG, "Auto time detection is not enabled."
- + " origin=" + origin
+ + " origin=" + originToString(origin)
+ ", time=" + time
+ ", cause=" + cause);
}
@@ -535,7 +536,7 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
if (mCallback.isAutoTimeDetectionEnabled()) {
if (DBG) {
Slog.d(LOG_TAG, "Auto time detection is enabled."
- + " origin=" + origin
+ + " origin=" + originToString(origin)
+ ", time=" + time
+ ", cause=" + cause);
}
@@ -557,7 +558,7 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
@GuardedBy("this")
private boolean setSystemClockUnderWakeLock(
- int origin, @NonNull TimestampedValue<Long> newTime, @NonNull Object cause) {
+ @Origin int origin, @NonNull TimestampedValue<Long> newTime, @NonNull String cause) {
long elapsedRealtimeMillis = mCallback.elapsedRealtimeMillis();
boolean isOriginAutomatic = isOriginAutomatic(origin);
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 39aa60bce2bc..0d2f57ed5622 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -3246,7 +3246,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
int numTaskContainers = display.getTaskDisplayAreaCount();
for (int tdaNdx = 0; tdaNdx < numTaskContainers; tdaNdx++) {
final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx);
- final int numStacks = display.getStackCount();
+ final int numStacks = taskDisplayArea.getStackCount();
for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
final ActivityStack stack = taskDisplayArea.getStackAt(stackNdx);
stack.finishVoiceTask(session);
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
index 02031bc4f210..22addf948a53 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
@@ -242,7 +242,7 @@ public class TimeDetectorServiceTest {
}
@Override
- public void handleAutoTimeDetectionChanged() {
+ public void handleAutoTimeConfigChanged() {
mHandleAutoTimeDetectionChangedCalled = true;
}
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
index 217de55fb400..c23fb8028224 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
@@ -16,6 +16,9 @@
package com.android.server.timedetector;
+import static com.android.server.timedetector.TimeDetectorStrategy.ORIGIN_NETWORK;
+import static com.android.server.timedetector.TimeDetectorStrategy.ORIGIN_TELEPHONY;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
@@ -29,6 +32,8 @@ import android.os.TimestampedValue;
import androidx.test.runner.AndroidJUnit4;
+import com.android.server.timedetector.TimeDetectorStrategy.Origin;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -48,6 +53,9 @@ public class TimeDetectorStrategyImplTest {
123456789L /* realtimeClockMillis */,
createUtcTime(2010, 5, 23, 12, 0, 0));
+ // This is the traditional ordering for time detection on Android.
+ private static final @Origin int [] PROVIDERS_PRIORITY = { ORIGIN_TELEPHONY, ORIGIN_NETWORK };
+
/**
* An arbitrary time, very different from the {@link #ARBITRARY_CLOCK_INITIALIZATION_INFO}
* time. Can be used as the basis for time suggestions.
@@ -488,11 +496,8 @@ public class TimeDetectorStrategyImplTest {
.assertLatestTelephonySuggestion(slotIndex, telephonyTimeSuggestion);
}
- /**
- * Manual suggestions should be ignored if auto time is enabled.
- */
@Test
- public void testSuggestManualTime_autoTimeEnabled() {
+ public void manualTimeSuggestion_isIgnored_whenAutoTimeEnabled() {
mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
.pokeAutoTimeDetectionEnabled(true);
@@ -505,7 +510,7 @@ public class TimeDetectorStrategyImplTest {
}
@Test
- public void suggestManualTime_ignoresTimeLowerBound() {
+ public void manualTimeSuggestion_ignoresTimeLowerBound() {
mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
.pokeAutoTimeDetectionEnabled(false);
Instant suggestedTime = TIME_LOWER_BOUND.minus(Duration.ofDays(1));
@@ -658,6 +663,73 @@ public class TimeDetectorStrategyImplTest {
.assertLatestNetworkSuggestion(null);
}
+ @Test
+ public void whenAllTimeSuggestionsAreAvailable_higherPriorityWins_lowerPriorityComesFirst() {
+ mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+ .pokeAutoTimeDetectionEnabled(true);
+
+ Instant networkTime = ARBITRARY_TEST_TIME;
+ Instant telephonyTime = ARBITRARY_TEST_TIME.plus(Duration.ofDays(30));
+
+ NetworkTimeSuggestion networkTimeSuggestion =
+ mScript.generateNetworkTimeSuggestion(networkTime);
+ TelephonyTimeSuggestion telephonyTimeSuggestion =
+ mScript.generateTelephonyTimeSuggestion(ARBITRARY_SLOT_INDEX, telephonyTime);
+
+ mScript.simulateNetworkTimeSuggestion(networkTimeSuggestion)
+ .simulateTelephonyTimeSuggestion(telephonyTimeSuggestion)
+ .assertLatestNetworkSuggestion(networkTimeSuggestion)
+ .assertLatestTelephonySuggestion(ARBITRARY_SLOT_INDEX, telephonyTimeSuggestion)
+ .verifySystemClockWasSetAndResetCallTracking(telephonyTime.toEpochMilli());
+ }
+
+ @Test
+ public void whenAllTimeSuggestionsAreAvailable_higherPriorityWins_higherPriorityComesFirst() {
+ mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+ .pokeAutoTimeDetectionEnabled(true);
+
+ Instant networkTime = ARBITRARY_TEST_TIME;
+ Instant telephonyTime = ARBITRARY_TEST_TIME.plus(Duration.ofDays(30));
+
+ NetworkTimeSuggestion networkTimeSuggestion =
+ mScript.generateNetworkTimeSuggestion(networkTime);
+ TelephonyTimeSuggestion telephonyTimeSuggestion =
+ mScript.generateTelephonyTimeSuggestion(ARBITRARY_SLOT_INDEX, telephonyTime);
+
+ mScript.simulateTelephonyTimeSuggestion(telephonyTimeSuggestion)
+ .simulateNetworkTimeSuggestion(networkTimeSuggestion)
+ .assertLatestNetworkSuggestion(networkTimeSuggestion)
+ .assertLatestTelephonySuggestion(ARBITRARY_SLOT_INDEX, telephonyTimeSuggestion)
+ .verifySystemClockWasSetAndResetCallTracking(telephonyTime.toEpochMilli());
+ }
+
+ @Test
+ public void whenHighestPrioritySuggestionIsNotAvailable_fallbacksToNext() {
+ mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+ .pokeAutoTimeDetectionEnabled(true);
+
+ NetworkTimeSuggestion timeSuggestion =
+ mScript.generateNetworkTimeSuggestion(ARBITRARY_TEST_TIME);
+
+ mScript.simulateNetworkTimeSuggestion(timeSuggestion)
+ .assertLatestNetworkSuggestion(timeSuggestion)
+ .verifySystemClockWasSetAndResetCallTracking(ARBITRARY_TEST_TIME.toEpochMilli());
+ }
+
+ @Test
+ public void suggestionsFromSourceNotListedInPrioritiesList_areIgnored() {
+ mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+ .pokeAutoTimeDetectionEnabled(true)
+ .pokeAutoOriginPriorities(new int[]{ORIGIN_TELEPHONY});
+
+ NetworkTimeSuggestion timeSuggestion = mScript.generateNetworkTimeSuggestion(
+ ARBITRARY_TEST_TIME);
+
+ mScript.simulateNetworkTimeSuggestion(timeSuggestion)
+ .assertLatestNetworkSuggestion(timeSuggestion)
+ .verifySystemClockWasNotSetAndResetCallTracking();
+ }
+
/**
* A fake implementation of TimeDetectorStrategy.Callback. Besides tracking changes and behaving
* like the real thing should, it also asserts preconditions.
@@ -668,6 +740,7 @@ public class TimeDetectorStrategyImplTest {
private long mElapsedRealtimeMillis;
private long mSystemClockMillis;
private int mSystemClockUpdateThresholdMillis = 2000;
+ private int[] mAutoOriginPriorities = PROVIDERS_PRIORITY;
// Tracking operations.
private boolean mSystemClockWasSet;
@@ -688,6 +761,11 @@ public class TimeDetectorStrategyImplTest {
}
@Override
+ public int[] getAutoOriginPriorities() {
+ return mAutoOriginPriorities;
+ }
+
+ @Override
public void acquireWakeLock() {
if (mWakeLockAcquired) {
fail("Wake lock already acquired");
@@ -736,6 +814,10 @@ public class TimeDetectorStrategyImplTest {
mAutoTimeDetectionEnabled = enabled;
}
+ void pokeAutoOriginPriorities(@Origin int[] autoOriginPriorities) {
+ mAutoOriginPriorities = autoOriginPriorities;
+ }
+
long peekElapsedRealtimeMillis() {
return mElapsedRealtimeMillis;
}
@@ -804,6 +886,11 @@ public class TimeDetectorStrategyImplTest {
return this;
}
+ Script pokeAutoOriginPriorities(@Origin int[] autoOriginPriorites) {
+ mFakeCallback.pokeAutoOriginPriorities(autoOriginPriorites);
+ return this;
+ }
+
long peekElapsedRealtimeMillis() {
return mFakeCallback.peekElapsedRealtimeMillis();
}
@@ -836,7 +923,7 @@ public class TimeDetectorStrategyImplTest {
Script simulateAutoTimeDetectionToggle() {
mFakeCallback.simulateAutoTimeZoneDetectionToggle();
- mTimeDetectorStrategy.handleAutoTimeDetectionChanged();
+ mTimeDetectorStrategy.handleAutoTimeConfigChanged();
return this;
}
@@ -870,7 +957,7 @@ public class TimeDetectorStrategyImplTest {
Script assertLatestTelephonySuggestion(int slotIndex, TelephonyTimeSuggestion expected) {
assertEquals(
"Expected to see " + expected + " at slotIndex=" + slotIndex + ", but got "
- + mTimeDetectorStrategy.getLatestTelephonySuggestion(slotIndex),
+ + mTimeDetectorStrategy.getLatestTelephonySuggestion(slotIndex),
expected, mTimeDetectorStrategy.getLatestTelephonySuggestion(slotIndex));
return this;
}
diff --git a/services/wifi/java/android/net/wifi/WifiApiServiceInfo.aidl b/services/wifi/java/android/net/wifi/WifiApiServiceInfo.aidl
deleted file mode 100644
index 45e4c69102f0..000000000000
--- a/services/wifi/java/android/net/wifi/WifiApiServiceInfo.aidl
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.wifi;
-
-/** @hide */
-parcelable WifiApiServiceInfo {
- String name;
- IBinder binder;
-}
diff --git a/telephony/java/android/telephony/CallForwardingInfo.java b/telephony/java/android/telephony/CallForwardingInfo.java
index 6ae6d002d990..aeac36e3a5f5 100644
--- a/telephony/java/android/telephony/CallForwardingInfo.java
+++ b/telephony/java/android/telephony/CallForwardingInfo.java
@@ -86,7 +86,7 @@ public final class CallForwardingInfo implements Parcelable {
* Call forwarding reason types
* @hide
*/
- @IntDef(flag = true, prefix = { "REASON_" }, value = {
+ @IntDef(prefix = { "REASON_" }, value = {
REASON_UNCONDITIONAL,
REASON_BUSY,
REASON_NO_REPLY,
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 92febd962958..27ea6902146f 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -2030,8 +2030,16 @@ public class CarrierConfigManager {
"allow_hold_call_during_emergency_bool";
/**
- * Flag indicating whether the carrier supports RCS presence indication for
- * User Capability Exchange (UCE). When presence is supported, the device should use the
+ * Flag indicating whether or not the carrier supports the periodic exchange of phone numbers
+ * in the user's address book with the carrier's presence server in order to retrieve the RCS
+ * capabilities for each contact used in the RCS User Capability Exchange (UCE) procedure. See
+ * RCC.71, section 3 for more information.
+ * <p>
+ * The flag {@link Ims#KEY_ENABLE_PRESENCE_PUBLISH_BOOL} must also be enabled if this flag is
+ * enabled, as sending a periodic SIP PUBLISH with this device's RCS capabilities is a
+ * requirement for capability exchange to begin.
+ * <p>
+ * When presence is supported, the device should use the
* {@link android.provider.ContactsContract.Data#CARRIER_PRESENCE} bit mask and set the
* {@link android.provider.ContactsContract.Data#CARRIER_PRESENCE_VT_CAPABLE} bit to indicate
* whether each contact supports video calling. The UI is made aware that presence is enabled
@@ -3847,12 +3855,27 @@ public class CarrierConfigManager {
public static final String KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL =
KEY_PREFIX + "ims_single_registration_required_bool";
+ /**
+ * A boolean flag specifying whether or not this carrier supports the device notifying the
+ * network of its RCS capabilities using the SIP PUBLISH procedure defined for User
+ * Capability Exchange (UCE). See RCC.71, section 3 for more information.
+ * <p>
+ * If this key's value is set to false, the procedure for RCS contact capability exchange
+ * via SIP SUBSCRIBE/NOTIFY will also be disabled internally, and
+ * {@link #KEY_USE_RCS_PRESENCE_BOOL} must also be set to false to ensure apps do not
+ * improperly think that capability exchange via SIP PUBLISH is enabled.
+ * <p> The default value for this key is {@code false}.
+ */
+ public static final String KEY_ENABLE_PRESENCE_PUBLISH_BOOL =
+ KEY_PREFIX + "enable_presence_publish_bool";
+
private Ims() {}
private static PersistableBundle getDefaults() {
PersistableBundle defaults = new PersistableBundle();
defaults.putInt(KEY_WIFI_OFF_DEFERRING_TIME_MILLIS_INT, 4000);
defaults.putBoolean(KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL, false);
+ defaults.putBoolean(KEY_ENABLE_PRESENCE_PUBLISH_BOOL, false);
return defaults;
}
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 4a7118ec3590..d156907af081 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -9436,7 +9436,7 @@ public class TelephonyManager {
}
/** @hide */
- @IntDef(flag = true, prefix = { "CDMA_SUBSCRIPTION_" }, value = {
+ @IntDef(prefix = { "CDMA_SUBSCRIPTION_" }, value = {
CDMA_SUBSCRIPTION_UNKNOWN,
CDMA_SUBSCRIPTION_RUIM_SIM,
CDMA_SUBSCRIPTION_NV
@@ -13030,6 +13030,37 @@ public class TelephonyManager {
}
/**
+ * Get which bands the modem's background scan is acting on, specified by
+ * {@link #setSystemSelectionChannels}.
+ *
+ * <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}).
+ *
+ * @return a list of {@link RadioAccessSpecifier}, or an empty list if no bands are specified.
+ * @throws IllegalStateException if the Telephony process is not currently available.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ public @NonNull List<RadioAccessSpecifier> getSystemSelectionChannels() {
+ try {
+ ITelephony service = getITelephony();
+ if (service != null) {
+ return service.getSystemSelectionChannels(getSubId());
+ } else {
+ throw new IllegalStateException("telephony service is null.");
+ }
+ } catch (RemoteException ex) {
+ if (!isSystemProcess()) {
+ ex.rethrowAsRuntimeException();
+ }
+ }
+ return new ArrayList<>();
+ }
+
+ /**
* Verifies whether the input MCC/MNC and MVNO correspond to the current carrier.
*
* @param mccmnc the carrier's mccmnc that you want to match
diff --git a/telephony/java/android/telephony/ims/DelegateMessageCallback.java b/telephony/java/android/telephony/ims/DelegateMessageCallback.java
index beec4a680d78..0d82a54a0f32 100644
--- a/telephony/java/android/telephony/ims/DelegateMessageCallback.java
+++ b/telephony/java/android/telephony/ims/DelegateMessageCallback.java
@@ -17,6 +17,7 @@
package android.telephony.ims;
import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.telephony.ims.stub.SipDelegate;
/**
@@ -30,6 +31,7 @@ import android.telephony.ims.stub.SipDelegate;
* </ul>
* @hide
*/
+@SystemApi
public interface DelegateMessageCallback {
/**
diff --git a/telephony/java/android/telephony/ims/DelegateRegistrationState.java b/telephony/java/android/telephony/ims/DelegateRegistrationState.java
index 4facfa77de21..3558a9b79ce0 100644
--- a/telephony/java/android/telephony/ims/DelegateRegistrationState.java
+++ b/telephony/java/android/telephony/ims/DelegateRegistrationState.java
@@ -18,14 +18,14 @@ package android.telephony.ims;
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.ArraySet;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.List;
import java.util.Objects;
import java.util.Set;
@@ -34,6 +34,7 @@ import java.util.Set;
* ImsService.
* @hide
*/
+@SystemApi
public final class DelegateRegistrationState implements Parcelable {
/**
@@ -114,14 +115,14 @@ public final class DelegateRegistrationState implements Parcelable {
})
public @interface DeregisteringReason {}
- private final ArrayList<String> mRegisteredTags = new ArrayList<>();
- private final ArrayList<FeatureTagState> mDeregisteringTags = new ArrayList<>();
- private final ArrayList<FeatureTagState> mDeregisteredTags = new ArrayList<>();
+ private ArraySet<String> mRegisteredTags = new ArraySet<>();
+ private final ArraySet<FeatureTagState> mDeregisteringTags = new ArraySet<>();
+ private final ArraySet<FeatureTagState> mDeregisteredTags = new ArraySet<>();
/**
* Builder used to create new instances of {@link DelegateRegistrationState}.
*/
- public static class Builder {
+ public static final class Builder {
private final DelegateRegistrationState mState;
@@ -135,10 +136,8 @@ public final class DelegateRegistrationState implements Parcelable {
* @param featureTag The IMS media feature tag included in the current IMS registration.
* @return The in-progress Builder instance for RegistrationState.
*/
- public Builder addRegisteredFeatureTag(@NonNull String featureTag) {
- if (!mState.mRegisteredTags.contains(featureTag)) {
- mState.mRegisteredTags.add(featureTag);
- }
+ public @NonNull Builder addRegisteredFeatureTag(@NonNull String featureTag) {
+ mState.mRegisteredTags.add(featureTag);
return this;
}
@@ -148,7 +147,8 @@ public final class DelegateRegistrationState implements Parcelable {
* @param featureTags The IMS media feature tags included in the current IMS registration.
* @return The in-progress Builder instance for RegistrationState.
*/
- public Builder addRegisteredFeatureTags(@NonNull Set<String> featureTags) {
+ @SuppressLint("MissingGetterMatchingBuilder")
+ public @NonNull Builder addRegisteredFeatureTags(@NonNull Set<String> featureTags) {
mState.mRegisteredTags.addAll(featureTags);
return this;
}
@@ -167,13 +167,9 @@ public final class DelegateRegistrationState implements Parcelable {
* The availability of the feature tag depends on the {@link DeregisteringReason}.
* @return The in-progress Builder instance for RegistrationState.
*/
- public Builder addDeregisteringFeatureTag(@NonNull String featureTag,
+ public @NonNull Builder addDeregisteringFeatureTag(@NonNull String featureTag,
@DeregisteringReason int reason) {
- boolean ftExists = mState.mDeregisteringTags.stream().anyMatch(
- f -> f.getFeatureTag().equals(featureTag));
- if (!ftExists) {
- mState.mDeregisteringTags.add(new FeatureTagState(featureTag, reason));
- }
+ mState.mDeregisteringTags.add(new FeatureTagState(featureTag, reason));
return this;
}
@@ -185,20 +181,16 @@ public final class DelegateRegistrationState implements Parcelable {
* @param reason The reason why the media feature tag has been deregistered.
* @return The in-progress Builder instance for RegistrationState.
*/
- public Builder addDeregisteredFeatureTag(@NonNull String featureTag,
+ public @NonNull Builder addDeregisteredFeatureTag(@NonNull String featureTag,
@DeregisteredReason int reason) {
- boolean ftExists = mState.mDeregisteredTags.stream().anyMatch(
- f -> f.getFeatureTag().equals(featureTag));
- if (!ftExists) {
- mState.mDeregisteredTags.add(new FeatureTagState(featureTag, reason));
- }
+ mState.mDeregisteredTags.add(new FeatureTagState(featureTag, reason));
return this;
}
/**
* @return the finalized instance.
*/
- public DelegateRegistrationState build() {
+ public @NonNull DelegateRegistrationState build() {
return mState;
}
}
@@ -212,7 +204,7 @@ public final class DelegateRegistrationState implements Parcelable {
* Used for unparcelling only.
*/
private DelegateRegistrationState(Parcel source) {
- source.readList(mRegisteredTags, null /*classloader*/);
+ mRegisteredTags = (ArraySet<String>) source.readArraySet(null);
readStateFromParcel(source, mDeregisteringTags);
readStateFromParcel(source, mDeregisteredTags);
}
@@ -268,7 +260,8 @@ public final class DelegateRegistrationState implements Parcelable {
return new ArraySet<>(mDeregisteredTags);
}
- public static final Creator<DelegateRegistrationState> CREATOR =
+
+ public static final @NonNull Creator<DelegateRegistrationState> CREATOR =
new Creator<DelegateRegistrationState>() {
@Override
public DelegateRegistrationState createFromParcel(Parcel source) {
@@ -287,13 +280,13 @@ public final class DelegateRegistrationState implements Parcelable {
}
@Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeList(mRegisteredTags);
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeArraySet(mRegisteredTags);
writeStateToParcel(dest, mDeregisteringTags);
writeStateToParcel(dest, mDeregisteredTags);
}
- private void writeStateToParcel(Parcel dest, List<FeatureTagState> state) {
+ private void writeStateToParcel(Parcel dest, Set<FeatureTagState> state) {
dest.writeInt(state.size());
for (FeatureTagState s : state) {
dest.writeString(s.getFeatureTag());
@@ -301,11 +294,12 @@ public final class DelegateRegistrationState implements Parcelable {
}
}
- private void readStateFromParcel(Parcel source, List<FeatureTagState> emptyState) {
+ private void readStateFromParcel(Parcel source, Set<FeatureTagState> emptyState) {
int len = source.readInt();
for (int i = 0; i < len; i++) {
String ft = source.readString();
int reason = source.readInt();
+
emptyState.add(new FeatureTagState(ft, reason));
}
}
diff --git a/telephony/java/android/telephony/ims/DelegateRequest.java b/telephony/java/android/telephony/ims/DelegateRequest.java
index 73d0840177dd..c322d924182a 100644
--- a/telephony/java/android/telephony/ims/DelegateRequest.java
+++ b/telephony/java/android/telephony/ims/DelegateRequest.java
@@ -17,6 +17,7 @@
package android.telephony.ims;
import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.ims.stub.SipDelegate;
@@ -31,6 +32,7 @@ import java.util.Set;
* SipDelegateConnection given back to the requesting application.
* @hide
*/
+@SystemApi
public final class DelegateRequest implements Parcelable {
private final ArrayList<String> mFeatureTags;
@@ -52,7 +54,7 @@ public final class DelegateRequest implements Parcelable {
* @return the list of IMS feature tag associated with this DelegateRequest in the format
* defined in RCC.07 section 2.6.1.3.
*/
- public Set<String> getFeatureTags() {
+ public @NonNull Set<String> getFeatureTags() {
return new ArraySet<>(mFeatureTags);
}
@@ -70,7 +72,7 @@ public final class DelegateRequest implements Parcelable {
}
@Override
- public void writeToParcel(Parcel dest, int flags) {
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeList(mFeatureTags);
}
diff --git a/telephony/java/android/telephony/ims/DelegateStateCallback.java b/telephony/java/android/telephony/ims/DelegateStateCallback.java
index 0f1afc42249e..fb659490d546 100644
--- a/telephony/java/android/telephony/ims/DelegateStateCallback.java
+++ b/telephony/java/android/telephony/ims/DelegateStateCallback.java
@@ -18,10 +18,11 @@ package android.telephony.ims;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.telephony.ims.stub.SipDelegate;
import android.telephony.ims.stub.SipTransportImplBase;
-import java.util.List;
+import java.util.Set;
/**
* Callback interface to notify a remote application of the following:
@@ -34,26 +35,24 @@ import java.util.List;
* </ul>
* @hide
*/
+@SystemApi
public interface DelegateStateCallback {
/**
* This must be called by the ImsService after {@link SipTransportImplBase#createSipDelegate} is
* called by the framework to notify the framework and remote application that the
* {@link SipDelegate} has been successfully created.
- *
- * @param delegate The SipDelegate created to service the DelegateRequest.
- * @param deniedTags A List of {@link FeatureTagState}, which contains the feature tags
+ * @param delegate The SipDelegate created to service the DelegateRequest.
+ * @param deniedTags A Set of {@link FeatureTagState}s, which contain the feature tags
* associated with this {@link SipDelegate} that have no access to send/receive SIP messages
* as well as a reason for why the feature tag is denied. For more information on the reason
* why the feature tag was denied access, see the
* {@link SipDelegateManager.DeniedReason} reasons. This is considered a permanent denial due
* to this {@link SipDelegate} not supporting a feature or this ImsService already
* implementing this feature elsewhere. If all features of this {@link SipDelegate} are
- * denied, {@link #onCreated(SipDelegate, List)} should still be called as the framework will
- * later call {@link SipTransportImplBase#destroySipDelegate(SipDelegate, int)} to clean the
- * delegate up.
+ * denied, this method should still be called.
*/
- void onCreated(@NonNull SipDelegate delegate, @Nullable List<FeatureTagState> deniedTags);
+ void onCreated(@NonNull SipDelegate delegate, @Nullable Set<FeatureTagState> deniedTags);
/**
* This must be called by the ImsService after the framework calls
diff --git a/telephony/java/android/telephony/ims/FeatureTagState.java b/telephony/java/android/telephony/ims/FeatureTagState.java
index 060be6f2510d..3622065c5fe8 100644
--- a/telephony/java/android/telephony/ims/FeatureTagState.java
+++ b/telephony/java/android/telephony/ims/FeatureTagState.java
@@ -17,6 +17,7 @@
package android.telephony.ims;
import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.ims.stub.DelegateConnectionStateCallback;
@@ -39,6 +40,7 @@ import java.util.Objects;
* currently available.
* @hide
*/
+@SystemApi
public final class FeatureTagState implements Parcelable {
private final String mFeatureTag;
@@ -48,8 +50,8 @@ public final class FeatureTagState implements Parcelable {
* Associate an IMS feature tag with its current state. See {@link DelegateRegistrationState}
* and {@link DelegateConnectionStateCallback#onFeatureTagStatusChanged(
* DelegateRegistrationState, List)} and
- * {@link DelegateStateCallback#onCreated(SipDelegate, List)} for examples on how and when this
- * is used.
+ * {@link DelegateStateCallback#onCreated(SipDelegate, java.util.Set)} for examples on how and
+ * when this is used.
*
* @param featureTag The IMS feature tag that is deregistered, in the process of
* deregistering, or denied.
@@ -93,12 +95,12 @@ public final class FeatureTagState implements Parcelable {
}
@Override
- public void writeToParcel(Parcel dest, int flags) {
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeString(mFeatureTag);
dest.writeInt(mState);
}
- public static final Creator<FeatureTagState> CREATOR = new Creator<FeatureTagState>() {
+ public static final @NonNull Creator<FeatureTagState> CREATOR = new Creator<FeatureTagState>() {
@Override
public FeatureTagState createFromParcel(Parcel source) {
return new FeatureTagState(source);
diff --git a/telephony/java/android/telephony/ims/ImsExternalCallState.java b/telephony/java/android/telephony/ims/ImsExternalCallState.java
index fdf636c323b6..c663e393fe06 100644
--- a/telephony/java/android/telephony/ims/ImsExternalCallState.java
+++ b/telephony/java/android/telephony/ims/ImsExternalCallState.java
@@ -49,8 +49,7 @@ public final class ImsExternalCallState implements Parcelable {
public static final int CALL_STATE_TERMINATED = 2;
/**@hide*/
- @IntDef(flag = true,
- value = {
+ @IntDef(value = {
CALL_STATE_CONFIRMED,
CALL_STATE_TERMINATED
},
@@ -59,8 +58,7 @@ public final class ImsExternalCallState implements Parcelable {
public @interface ExternalCallState {}
/**@hide*/
- @IntDef(flag = true,
- value = {
+ @IntDef(value = {
ImsCallProfile.CALL_TYPE_VOICE,
ImsCallProfile.CALL_TYPE_VT_TX,
ImsCallProfile.CALL_TYPE_VT_RX,
diff --git a/telephony/java/android/telephony/ims/ImsSsData.java b/telephony/java/android/telephony/ims/ImsSsData.java
index fb8e5d37875b..868dea6a3121 100644
--- a/telephony/java/android/telephony/ims/ImsSsData.java
+++ b/telephony/java/android/telephony/ims/ImsSsData.java
@@ -72,7 +72,7 @@ public final class ImsSsData implements Parcelable {
/**@hide*/
- @IntDef(flag = true, prefix = {"SS_"}, value = {
+ @IntDef(prefix = {"SS_"}, value = {
SS_ACTIVATION,
SS_DEACTIVATION,
SS_INTERROGATION,
@@ -89,7 +89,7 @@ public final class ImsSsData implements Parcelable {
public static final int SS_ERASURE = 4;
/**@hide*/
- @IntDef(flag = true, prefix = {"SS_"}, value = {
+ @IntDef(prefix = {"SS_"}, value = {
SS_ALL_TELE_AND_BEARER_SERVICES,
SS_ALL_TELESEVICES,
SS_TELEPHONY,
@@ -190,7 +190,7 @@ public final class ImsSsData implements Parcelable {
public static final int RESULT_SUCCESS = 0;
/** @hide */
- @IntDef(flag = true, prefix = { "SS_" }, value = {
+ @IntDef(prefix = { "SS_" }, value = {
SS_CFU,
SS_CF_BUSY,
SS_CF_NO_REPLY,
diff --git a/telephony/java/android/telephony/ims/RcsContactUceCapability.java b/telephony/java/android/telephony/ims/RcsContactUceCapability.java
index d12a6aef5186..5848be8b0bf2 100644
--- a/telephony/java/android/telephony/ims/RcsContactUceCapability.java
+++ b/telephony/java/android/telephony/ims/RcsContactUceCapability.java
@@ -105,10 +105,17 @@ public final class RcsContactUceCapability implements Parcelable {
public @interface RequestResult {}
/**
+ * The base class of {@link OptionsBuilder} and {@link PresenceBuilder}
+ */
+ public static abstract class RcsUcsCapabilityBuilder {
+ public abstract @NonNull RcsContactUceCapability build();
+ }
+
+ /**
* Builder to help construct {@link RcsContactUceCapability} instances when capabilities were
* queried through SIP OPTIONS.
*/
- public static class OptionsBuilder {
+ public static class OptionsBuilder extends RcsUcsCapabilityBuilder {
private final RcsContactUceCapability mCapabilities;
@@ -155,6 +162,7 @@ public final class RcsContactUceCapability implements Parcelable {
/**
* @return the constructed instance.
*/
+ @Override
public @NonNull RcsContactUceCapability build() {
return mCapabilities;
}
@@ -164,7 +172,7 @@ public final class RcsContactUceCapability implements Parcelable {
* Builder to help construct {@link RcsContactUceCapability} instances when capabilities were
* queried through a presence server.
*/
- public static class PresenceBuilder {
+ public static class PresenceBuilder extends RcsUcsCapabilityBuilder {
private final RcsContactUceCapability mCapabilities;
@@ -205,6 +213,7 @@ public final class RcsContactUceCapability implements Parcelable {
/**
* @return the RcsContactUceCapability instance.
*/
+ @Override
public @NonNull RcsContactUceCapability build() {
return mCapabilities;
}
diff --git a/telephony/java/android/telephony/ims/SipDelegateConnection.java b/telephony/java/android/telephony/ims/SipDelegateConnection.java
index 6bfdc2c6d48a..c3cc1edf590b 100644
--- a/telephony/java/android/telephony/ims/SipDelegateConnection.java
+++ b/telephony/java/android/telephony/ims/SipDelegateConnection.java
@@ -17,6 +17,7 @@
package android.telephony.ims;
import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.telephony.ims.stub.SipDelegate;
/**
@@ -36,6 +37,7 @@ import android.telephony.ims.stub.SipDelegate;
* @see SipDelegateManager#createSipDelegate
* @hide
*/
+@SystemApi
public interface SipDelegateConnection {
/**
@@ -47,9 +49,8 @@ public interface SipDelegateConnection {
* @param sipMessage The SipMessage to be sent.
* @param configVersion The SipDelegateImsConfiguration version used to construct the
* SipMessage. See {@link SipDelegateImsConfiguration#getVersion} for more
- * information on this parameter and why it is used.
*/
- void sendMessage(@NonNull SipMessage sipMessage, int configVersion);
+ void sendMessage(@NonNull SipMessage sipMessage, long configVersion);
/**
* Notify the {@link SipDelegate} that a SIP message received from
diff --git a/telephony/java/android/telephony/ims/SipDelegateImsConfiguration.java b/telephony/java/android/telephony/ims/SipDelegateImsConfiguration.java
index 8abd0ee94865..eddbb1002f20 100644
--- a/telephony/java/android/telephony/ims/SipDelegateImsConfiguration.java
+++ b/telephony/java/android/telephony/ims/SipDelegateImsConfiguration.java
@@ -17,7 +17,10 @@
package android.telephony.ims;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.StringDef;
+import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.PersistableBundle;
@@ -47,7 +50,8 @@ import java.lang.annotation.RetentionPolicy;
* update.
* @hide
*/
-public class SipDelegateImsConfiguration implements Parcelable {
+@SystemApi
+public final class SipDelegateImsConfiguration implements Parcelable {
/**
* IPV4 Address type.
@@ -354,7 +358,7 @@ public class SipDelegateImsConfiguration implements Parcelable {
/**
* Builder class to be used when constructing a new SipDelegateImsConfiguration.
*/
- public static class Builder {
+ public static final class Builder {
private final long mVersion;
private final PersistableBundle mBundle;
@@ -381,7 +385,10 @@ public class SipDelegateImsConfiguration implements Parcelable {
/**
* Put a string value into this configuration bundle for the given key.
*/
- public Builder putString(@StringConfigKey String key, String value) {
+ // getString is available below.
+ @SuppressLint("MissingGetterMatchingBuilder")
+ public @NonNull Builder addString(@NonNull @StringConfigKey String key,
+ @NonNull String value) {
mBundle.putString(key, value);
return this;
}
@@ -389,7 +396,9 @@ public class SipDelegateImsConfiguration implements Parcelable {
/**
* Replace the existing default value with a new value for a given key.
*/
- public Builder putInt(@IntConfigKey String key, int value) {
+ // getInt is available below.
+ @SuppressLint("MissingGetterMatchingBuilder")
+ public @NonNull Builder addInt(@NonNull @IntConfigKey String key, int value) {
mBundle.putInt(key, value);
return this;
}
@@ -397,7 +406,9 @@ public class SipDelegateImsConfiguration implements Parcelable {
/**
* Replace the existing default value with a new value for a given key.
*/
- public Builder putBoolean(@BooleanConfigKey String key, boolean value) {
+ // getBoolean is available below.
+ @SuppressLint("MissingGetterMatchingBuilder")
+ public @NonNull Builder addBoolean(@NonNull @BooleanConfigKey String key, boolean value) {
mBundle.putBoolean(key, value);
return this;
}
@@ -405,7 +416,7 @@ public class SipDelegateImsConfiguration implements Parcelable {
/**
* @return a new SipDelegateImsConfiguration from this Builder.
*/
- public SipDelegateImsConfiguration build() {
+ public @NonNull SipDelegateImsConfiguration build() {
return new SipDelegateImsConfiguration(mVersion, mBundle);
}
}
@@ -424,30 +435,38 @@ public class SipDelegateImsConfiguration implements Parcelable {
}
/**
+ * @return {@code true} if this configuration object has a an entry for the key specified,
+ * {@code false} if it does not.
+ */
+ public boolean containsKey(@NonNull String key) {
+ return mBundle.containsKey(key);
+ }
+
+ /**
* @return the string value associated with a given key or {@code null} if it doesn't exist.
*/
- public @StringConfigKey String getString(String key) {
+ public @Nullable @StringConfigKey String getString(@NonNull String key) {
return mBundle.getString(key);
}
/**
- * @return the Integer value associated with a given key or {@code null} if the value doesn't
- * exist.
+ * @return the integer value associated with a given key if it exists or the supplied default
+ * value if it does not.
*/
- public @IntConfigKey Integer getInt(String key) {
+ public @IntConfigKey int getInt(@NonNull String key, int defaultValue) {
if (!mBundle.containsKey(key)) {
- return null;
+ return defaultValue;
}
return mBundle.getInt(key);
}
/**
- * @return the Integer value associated with a given key or {@code null} if the value doesn't
- * exist.
+ * @return the boolean value associated with a given key or the supplied default value if the
+ * value doesn't exist in the bundle.
*/
- public @BooleanConfigKey Boolean getBoolen(String key) {
+ public @BooleanConfigKey boolean getBoolean(@NonNull String key, boolean defaultValue) {
if (!mBundle.containsKey(key)) {
- return null;
+ return defaultValue;
}
return mBundle.getBoolean(key);
}
@@ -455,7 +474,7 @@ public class SipDelegateImsConfiguration implements Parcelable {
/**
* @return a shallow copy of the full configuration.
*/
- public PersistableBundle copyBundle() {
+ public @NonNull PersistableBundle copyBundle() {
return new PersistableBundle(mBundle);
}
@@ -479,12 +498,12 @@ public class SipDelegateImsConfiguration implements Parcelable {
}
@Override
- public void writeToParcel(Parcel dest, int flags) {
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeLong(mVersion);
dest.writePersistableBundle(mBundle);
}
- public static final Creator<SipDelegateImsConfiguration> CREATOR =
+ public static final @NonNull Creator<SipDelegateImsConfiguration> CREATOR =
new Creator<SipDelegateImsConfiguration>() {
@Override
public SipDelegateImsConfiguration createFromParcel(Parcel source) {
diff --git a/telephony/java/android/telephony/ims/SipDelegateManager.java b/telephony/java/android/telephony/ims/SipDelegateManager.java
index 190a792b5a9a..2ec88ff27f93 100644
--- a/telephony/java/android/telephony/ims/SipDelegateManager.java
+++ b/telephony/java/android/telephony/ims/SipDelegateManager.java
@@ -54,7 +54,6 @@ public class SipDelegateManager {
* The SIP message has failed being sent or received for an unknown reason.
* <p>
* The caller should retry a message that failed with this response.
- * @hide
*/
public static final int MESSAGE_FAILURE_REASON_UNKNOWN = 0;
@@ -64,47 +63,40 @@ public class SipDelegateManager {
* <p>
* This is considered a permanent error and the system will automatically begin the teardown and
* destruction of the SipDelegate. No further messages should be sent on this transport.
- * @hide
*/
public static final int MESSAGE_FAILURE_REASON_DELEGATE_DEAD = 1;
/**
* The message has not been sent/received because the delegate is in the process of closing and
* has become unavailable. No further messages should be sent/received on this delegate.
- * @hide
*/
public static final int MESSAGE_FAILURE_REASON_DELEGATE_CLOSED = 2;
/**
* The SIP message has an invalid start line and the message can not be sent.
- * @hide
*/
public static final int MESSAGE_FAILURE_REASON_INVALID_START_LINE = 3;
/**
* One or more of the header fields in the header section of the outgoing SIP message is invalid
* and the SIP message can not be sent.
- * @hide
*/
public static final int MESSAGE_FAILURE_REASON_INVALID_HEADER_FIELDS = 4;
/**
* The body content of the SIP message is invalid and the message can not be sent.
- * @hide
*/
public static final int MESSAGE_FAILURE_REASON_INVALID_BODY_CONTENT = 5;
/**
* The feature tag associated with the outgoing message does not match any known feature tags
* and this message can not be sent.
- * @hide
*/
public static final int MESSAGE_FAILURE_REASON_INVALID_FEATURE_TAG = 6;
/**
* The feature tag associated with the outgoing message is not enabled for the associated
* SipDelegateConnection and can not be sent.
- * @hide
*/
public static final int MESSAGE_FAILURE_REASON_TAG_NOT_ENABLED_FOR_DELEGATE = 7;
@@ -113,7 +105,6 @@ public class SipDelegateManager {
* <p>
* This message should be retried when connectivity to the network is re-established. See
* {@link android.net.ConnectivityManager.NetworkCallback} for how this can be determined.
- * @hide
*/
public static final int MESSAGE_FAILURE_REASON_NETWORK_NOT_AVAILABLE = 8;
@@ -124,7 +115,6 @@ public class SipDelegateManager {
* This is considered a temporary failure, the message should not be retried until an IMS
* registration change callback is received via
* {@link DelegateConnectionStateCallback#onFeatureTagStatusChanged}
- * @hide
*/
public static final int MESSAGE_FAILURE_REASON_NOT_REGISTERED = 9;
@@ -135,7 +125,6 @@ public class SipDelegateManager {
* <p>
* The @link SipMessage} should be recreated using the newest
* {@link SipDelegateImsConfiguration} and sent again.
- * @hide
*/
public static final int MESSAGE_FAILURE_REASON_STALE_IMS_CONFIGURATION = 10;
@@ -146,7 +135,6 @@ public class SipDelegateManager {
* This is considered a temporary error and the {@link SipDelegateConnection} should resend the
* message once {@link DelegateRegistrationState#DEREGISTERING_REASON_FEATURE_TAGS_CHANGING} is
* no longer reported.
- * @hide
*/
public static final int MESSAGE_FAILURE_REASON_INTERNAL_DELEGATE_STATE_TRANSITION = 11;
@@ -171,7 +159,6 @@ public class SipDelegateManager {
/**
* Access to use this feature tag has been denied for an unknown reason.
- * @hide
*/
public static final int DENIED_REASON_UNKNOWN = 0;
@@ -179,14 +166,12 @@ public class SipDelegateManager {
* This feature tag is allowed to be used by this SipDelegateConnection, but it is in use by
* another SipDelegateConnection and can not be associated with this delegate. The feature tag
* will stay in this state until the feature tag is release by the other application.
- * @hide
*/
public static final int DENIED_REASON_IN_USE_BY_ANOTHER_DELEGATE = 1;
/**
* Access to use this feature tag has been denied because this application does not have the
* permissions required to access this feature tag.
- * @hide
*/
public static final int DENIED_REASON_NOT_ALLOWED = 2;
@@ -194,14 +179,12 @@ public class SipDelegateManager {
* Access to use this feature tag has been denied because single registration is not allowed by
* the carrier at this time. The application should fall back to dual registration if
* applicable.
- * @hide
*/
public static final int DENIED_REASON_SINGLE_REGISTRATION_NOT_ALLOWED = 3;
/**
* This feature tag is not recognized as a valid feature tag by the SipDelegate and has been
* denied.
- * @hide
*/
public static final int DENIED_REASON_INVALID = 4;
@@ -218,33 +201,28 @@ public class SipDelegateManager {
/**
* The SipDelegate has closed due to an unknown reason.
- * @hide
*/
public static final int SIP_DELEGATE_DESTROY_REASON_UNKNOWN = 0;
/**
* The SipDelegate has closed because the IMS service has died unexpectedly.
- * @hide
*/
public static final int SIP_DELEGATE_DESTROY_REASON_SERVICE_DEAD = 1;
/**
* The SipDelegate has closed because the IMS application has requested that the connection be
* destroyed.
- * @hide
*/
public static final int SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP = 2;
/**
* The SipDelegate has been closed due to the user disabling RCS.
- * @hide
*/
public static final int SIP_DELEGATE_DESTROY_REASON_USER_DISABLED_RCS = 3;
/**
* The SipDelegate has been closed due to the subscription associated with this delegate being
* torn down.
- * @hide
*/
public static final int SIP_DELEGATE_DESTROY_REASON_SUBSCRIPTION_TORN_DOWN = 4;
@@ -331,7 +309,6 @@ public class SipDelegateManager {
* SipDelegateConnection.
* @throws ImsException Thrown if there was a problem communicating with the ImsService
* associated with this SipDelegateManager. See {@link ImsException#getCode()}.
- * @hide
*/
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
public void createSipDelegate(@NonNull DelegateRequest request, @NonNull Executor executor,
@@ -366,7 +343,6 @@ public class SipDelegateManager {
* This will also clean up all related callbacks in the associated ImsService.
* @param delegateConnection The SipDelegateConnection to destroy.
* @param reason The reason for why this SipDelegateConnection was destroyed.
- * @hide
*/
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
public void destroySipDelegate(@NonNull SipDelegateConnection delegateConnection,
diff --git a/telephony/java/android/telephony/ims/SipMessage.java b/telephony/java/android/telephony/ims/SipMessage.java
index c3b1be2d7fc8..1539224dedcf 100644
--- a/telephony/java/android/telephony/ims/SipMessage.java
+++ b/telephony/java/android/telephony/ims/SipMessage.java
@@ -17,10 +17,14 @@
package android.telephony.ims;
import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
+import java.util.Arrays;
+import java.util.Objects;
+
/**
* Represents a partially encoded SIP message. See RFC 3261 for more information on how SIP
* messages are structured and used.
@@ -29,6 +33,7 @@ import android.os.Parcelable;
* verification and should not be used as a generic SIP message container.
* @hide
*/
+@SystemApi
public final class SipMessage implements Parcelable {
// Should not be set to true for production!
private static final boolean IS_DEBUGGING = Build.IS_ENG;
@@ -95,14 +100,14 @@ public final class SipMessage implements Parcelable {
}
@Override
- public void writeToParcel(Parcel dest, int flags) {
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeString(mStartLine);
dest.writeString(mHeaderSection);
dest.writeInt(mContent.length);
dest.writeByteArray(mContent);
}
- public static final Creator<SipMessage> CREATOR = new Creator<SipMessage>() {
+ public static final @NonNull Creator<SipMessage> CREATOR = new Creator<SipMessage>() {
@Override
public SipMessage createFromParcel(Parcel source) {
return new SipMessage(source);
@@ -152,4 +157,21 @@ public final class SipMessage implements Parcelable {
}
return startLine;
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ SipMessage that = (SipMessage) o;
+ return mStartLine.equals(that.mStartLine)
+ && mHeaderSection.equals(that.mHeaderSection)
+ && Arrays.equals(mContent, that.mContent);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = Objects.hash(mStartLine, mHeaderSection);
+ result = 31 * result + Arrays.hashCode(mContent);
+ return result;
+ }
}
diff --git a/telephony/java/android/telephony/ims/aidl/ISipDelegate.aidl b/telephony/java/android/telephony/ims/aidl/ISipDelegate.aidl
index 477ee958e1e8..5d6766a65155 100644
--- a/telephony/java/android/telephony/ims/aidl/ISipDelegate.aidl
+++ b/telephony/java/android/telephony/ims/aidl/ISipDelegate.aidl
@@ -23,7 +23,7 @@ import android.telephony.ims.SipMessage;
* {@hide}
*/
oneway interface ISipDelegate {
- void sendMessage(in SipMessage sipMessage, int configVersion);
+ void sendMessage(in SipMessage sipMessage, long configVersion);
void notifyMessageReceived(in String viaTransactionId);
void notifyMessageReceiveError(in String viaTransactionId, int reason);
diff --git a/telephony/java/android/telephony/ims/aidl/SipDelegateAidlWrapper.java b/telephony/java/android/telephony/ims/aidl/SipDelegateAidlWrapper.java
index a7f62cc32be1..522ad8160870 100644
--- a/telephony/java/android/telephony/ims/aidl/SipDelegateAidlWrapper.java
+++ b/telephony/java/android/telephony/ims/aidl/SipDelegateAidlWrapper.java
@@ -29,12 +29,13 @@ import android.telephony.ims.SipDelegateManager;
import android.telephony.ims.SipMessage;
import android.telephony.ims.stub.SipDelegate;
-import java.util.List;
+import java.util.ArrayList;
+import java.util.Set;
import java.util.concurrent.Executor;
/**
* Implementation of callbacks by wrapping the internal AIDL from telephony. Also implements
- * ISipDelegate internally when {@link DelegateStateCallback#onCreated(SipDelegate, List)} is called
+ * ISipDelegate internally when {@link DelegateStateCallback#onCreated(SipDelegate, Set)} is called
* in order to trampoline events back to telephony.
* @hide
*/
@@ -42,7 +43,7 @@ public class SipDelegateAidlWrapper implements DelegateStateCallback, DelegateMe
private final ISipDelegate.Stub mDelegateBinder = new ISipDelegate.Stub() {
@Override
- public void sendMessage(SipMessage sipMessage, int configVersion) {
+ public void sendMessage(SipMessage sipMessage, long configVersion) {
SipDelegate d = mDelegate;
final long token = Binder.clearCallingIdentity();
try {
@@ -136,10 +137,10 @@ public class SipDelegateAidlWrapper implements DelegateStateCallback, DelegateMe
@Override
public void onCreated(@NonNull SipDelegate delegate,
- @Nullable List<FeatureTagState> deniedTags) {
+ @Nullable Set<FeatureTagState> deniedTags) {
mDelegate = delegate;
try {
- mStateBinder.onCreated(mDelegateBinder, deniedTags);
+ mStateBinder.onCreated(mDelegateBinder, new ArrayList<>(deniedTags));
} catch (RemoteException e) {
// BinderDied will trigger destroySipDelegate, so just ignore this locally.
}
diff --git a/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java b/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java
index 3bd1a462b31a..29ba8e2d50c4 100644
--- a/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java
+++ b/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java
@@ -158,7 +158,7 @@ public class SipDelegateConnectionAidlWrapper implements SipDelegateConnection,
}
@Override
- public void sendMessage(SipMessage sipMessage, int configVersion) {
+ public void sendMessage(SipMessage sipMessage, long configVersion) {
try {
ISipDelegate conn = getSipDelegateBinder();
if (conn == null) {
diff --git a/telephony/java/android/telephony/ims/stub/DelegateConnectionMessageCallback.java b/telephony/java/android/telephony/ims/stub/DelegateConnectionMessageCallback.java
index 59f9601299b2..eefe8493aef1 100644
--- a/telephony/java/android/telephony/ims/stub/DelegateConnectionMessageCallback.java
+++ b/telephony/java/android/telephony/ims/stub/DelegateConnectionMessageCallback.java
@@ -17,6 +17,7 @@
package android.telephony.ims.stub;
import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.telephony.ims.SipDelegateConnection;
import android.telephony.ims.SipDelegateManager;
import android.telephony.ims.SipMessage;
@@ -26,6 +27,7 @@ import android.telephony.ims.SipMessage;
* messages as well as the result of sending a SIP message.
* @hide
*/
+@SystemApi
public interface DelegateConnectionMessageCallback {
/**
@@ -49,6 +51,6 @@ public interface DelegateConnectionMessageCallback {
* previously sent {@link SipMessage}.
* @param reason The reason for the failure.
*/
- void onMessageSendFailure(String viaTransactionId,
+ void onMessageSendFailure(@NonNull String viaTransactionId,
@SipDelegateManager.MessageFailureReason int reason);
}
diff --git a/telephony/java/android/telephony/ims/stub/DelegateConnectionStateCallback.java b/telephony/java/android/telephony/ims/stub/DelegateConnectionStateCallback.java
index 976180538b18..02218ead0ad7 100644
--- a/telephony/java/android/telephony/ims/stub/DelegateConnectionStateCallback.java
+++ b/telephony/java/android/telephony/ims/stub/DelegateConnectionStateCallback.java
@@ -17,6 +17,7 @@
package android.telephony.ims.stub;
import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.telephony.ims.DelegateRegistrationState;
import android.telephony.ims.DelegateRequest;
import android.telephony.ims.FeatureTagState;
@@ -58,6 +59,7 @@ import java.util.Set;
*
* @hide
*/
+@SystemApi
public interface DelegateConnectionStateCallback {
/**
diff --git a/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java
index a6f5c45445f5..153d687dd84f 100644
--- a/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java
@@ -49,8 +49,7 @@ public class ImsRegistrationImplBase {
* @hide
*/
// Defines the underlying radio technology type that we have registered for IMS over.
- @IntDef(flag = true,
- value = {
+ @IntDef(value = {
REGISTRATION_TECH_NONE,
REGISTRATION_TECH_LTE,
REGISTRATION_TECH_IWLAN
diff --git a/telephony/java/android/telephony/ims/stub/SipDelegate.java b/telephony/java/android/telephony/ims/stub/SipDelegate.java
index 3ec97095eb00..d7e7b62dd550 100644
--- a/telephony/java/android/telephony/ims/stub/SipDelegate.java
+++ b/telephony/java/android/telephony/ims/stub/SipDelegate.java
@@ -17,6 +17,7 @@
package android.telephony.ims.stub;
import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.telephony.ims.DelegateMessageCallback;
import android.telephony.ims.ImsService;
import android.telephony.ims.SipDelegateImsConfiguration;
@@ -40,6 +41,7 @@ import android.telephony.ims.SipMessage;
* {@link android.telephony.ims.DelegateStateCallback} for more information.
* @hide
*/
+@SystemApi
public interface SipDelegate {
/**
@@ -57,7 +59,7 @@ public interface SipDelegate {
* {@link DelegateMessageCallback#onMessageSendFailure} should be called with code
* {@link SipDelegateManager#MESSAGE_FAILURE_REASON_STALE_IMS_CONFIGURATION}.
*/
- void sendMessage(@NonNull SipMessage message, int configVersion);
+ void sendMessage(@NonNull SipMessage message, long configVersion);
/**
* The framework is requesting that routing resources associated with the SIP dialog using the
diff --git a/telephony/java/android/telephony/ims/stub/SipTransportImplBase.java b/telephony/java/android/telephony/ims/stub/SipTransportImplBase.java
index 93d438cf7f4d..1f74c09af0f6 100644
--- a/telephony/java/android/telephony/ims/stub/SipTransportImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/SipTransportImplBase.java
@@ -17,6 +17,7 @@
package android.telephony.ims.stub;
import android.annotation.NonNull;
+import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.os.Binder;
import android.os.IBinder;
@@ -32,7 +33,6 @@ import android.telephony.ims.aidl.SipDelegateAidlWrapper;
import android.util.Log;
import java.util.ArrayList;
-import java.util.List;
import java.util.Objects;
import java.util.concurrent.Executor;
@@ -99,7 +99,8 @@ public class SipTransportImplBase {
/**
* Called by the Telephony framework to request the creation of a new {@link SipDelegate}.
* <p>
- * The implementation must call {@link DelegateStateCallback#onCreated(SipDelegate, List)} with
+ * The implementation must call
+ * {@link DelegateStateCallback#onCreated(SipDelegate, java.util.Set)} with
* the {@link SipDelegate} that is associated with the {@link DelegateRequest}.
* <p>
* This method will be called on the Executor specified in
@@ -112,8 +113,9 @@ public class SipTransportImplBase {
* for the SipDelegate.
* @param mc A callback back to the remote application to be used to send SIP messages to the
* remote application and acknowledge the sending of outgoing SIP messages.
- * @hide
*/
+ // executor used is defined in the constructor.
+ @SuppressLint("ExecutorRegistration")
public void createSipDelegate(int subscriptionId, @NonNull DelegateRequest request,
@NonNull DelegateStateCallback dc, @NonNull DelegateMessageCallback mc) {
throw new UnsupportedOperationException("createSipDelegate not implemented!");
@@ -130,7 +132,6 @@ public class SipTransportImplBase {
* @param delegate The delegate to be destroyed.
* @param reason The reason the remote connection to this {@link SipDelegate} is being
* destroyed.
- * @hide
*/
public void destroySipDelegate(@NonNull SipDelegate delegate,
@SipDelegateManager.SipDelegateDestroyReason int reason) {
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 4895fffa5849..69525a887af9 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -856,6 +856,11 @@ interface ITelephony {
in int[] featureTypes, in String packageName);
/**
+ * @return true if the ImsService cleared any carrier ImsService overrides, false otherwise.
+ */
+ boolean clearCarrierImsServiceOverride(int slotIndex);
+
+ /**
* @return the package name of the carrier/device ImsService associated with this slot.
*/
String getBoundImsServicePackage(int slotIndex, boolean isCarrierImsService, int featureType);
@@ -2154,6 +2159,8 @@ interface ITelephony {
oneway void setSystemSelectionChannels(in List<RadioAccessSpecifier> specifiers,
int subId, IBooleanConsumer resultCallback);
+ List<RadioAccessSpecifier> getSystemSelectionChannels(int subId);
+
boolean isMvnoMatched(int subId, int mvnoType, String mvnoMatchData);
/**
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index 9d4072f1cf1c..a2361a7d34a1 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -519,6 +519,7 @@ public interface RILConstants {
int RIL_REQUEST_RELEASE_PDU_SESSION_ID = 216;
int RIL_REQUEST_START_HANDOVER = 217;
int RIL_REQUEST_CANCEL_HANDOVER = 218;
+ int RIL_REQUEST_GET_SYSTEM_SELECTION_CHANNELS = 219;
/* Responses begin */
int RIL_RESPONSE_ACKNOWLEDGEMENT = 800;
diff --git a/tests/BootImageProfileTest/TEST_MAPPING b/tests/BootImageProfileTest/TEST_MAPPING
new file mode 100644
index 000000000000..1b569f9455bf
--- /dev/null
+++ b/tests/BootImageProfileTest/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "BootImageProfileTest"
+ }
+ ]
+}
diff --git a/tests/net/common/java/android/net/OemNetworkPreferencesTest.java b/tests/net/common/java/android/net/OemNetworkPreferencesTest.java
index b77ed6ab5a29..cade5ba3771f 100644
--- a/tests/net/common/java/android/net/OemNetworkPreferencesTest.java
+++ b/tests/net/common/java/android/net/OemNetworkPreferencesTest.java
@@ -22,10 +22,13 @@ import static com.android.testutils.ParcelUtils.assertParcelSane;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import android.os.Build;
import android.util.SparseArray;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
+
+import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
+import com.android.testutils.DevSdkIgnoreRunner;
import org.junit.Before;
import org.junit.Test;
@@ -34,7 +37,8 @@ import org.junit.runner.RunWith;
import java.util.ArrayList;
import java.util.List;
-@RunWith(AndroidJUnit4.class)
+@IgnoreUpTo(Build.VERSION_CODES.R)
+@RunWith(DevSdkIgnoreRunner.class)
@SmallTest
public class OemNetworkPreferencesTest {
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 99f1985ff691..7a1cb25b2d3a 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -56,8 +56,10 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_IA;
import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS;
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
@@ -1058,7 +1060,9 @@ public class ConnectivityServiceTest {
public void setUids(Set<UidRange> uids) {
mNetworkCapabilities.setUids(uids);
- updateCapabilitiesInternal(null /* defaultNetwork */, true);
+ if (mAgentRegistered) {
+ mMockNetworkAgent.setNetworkCapabilities(mNetworkCapabilities, true);
+ }
}
public void setVpnType(int vpnType) {
@@ -1084,11 +1088,15 @@ public class ConnectivityServiceTest {
throws Exception {
if (mAgentRegistered) throw new IllegalStateException("already registered");
setUids(uids);
- mConfig.isMetered = isAlwaysMetered;
+ if (!isAlwaysMetered) mNetworkCapabilities.addCapability(NET_CAPABILITY_NOT_METERED);
mInterface = VPN_IFNAME;
mMockNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN, lp,
mNetworkCapabilities);
mMockNetworkAgent.waitForIdle(TIMEOUT_MS);
+ verify(mNetworkManagementService, times(1))
+ .addVpnUidRanges(eq(mMockVpn.getNetId()), eq(uids.toArray(new UidRange[0])));
+ verify(mNetworkManagementService, never())
+ .removeVpnUidRanges(eq(mMockVpn.getNetId()), any());
mAgentRegistered = true;
mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities());
mNetworkAgent = mMockNetworkAgent.getNetworkAgent();
@@ -1143,28 +1151,6 @@ public class ConnectivityServiceTest {
mMockNetworkAgent.sendLinkProperties(lp);
}
- private NetworkCapabilities updateCapabilitiesInternal(Network defaultNetwork,
- boolean sendToConnectivityService) {
- if (!mAgentRegistered) return null;
- super.updateCapabilities(defaultNetwork);
- // Because super.updateCapabilities will update the capabilities of the agent but
- // not the mock agent, the mock agent needs to know about them.
- copyCapabilitiesToNetworkAgent(sendToConnectivityService);
- return new NetworkCapabilities(mNetworkCapabilities);
- }
-
- private void copyCapabilitiesToNetworkAgent(boolean sendToConnectivityService) {
- if (null != mMockNetworkAgent) {
- mMockNetworkAgent.setNetworkCapabilities(mNetworkCapabilities,
- sendToConnectivityService);
- }
- }
-
- @Override
- public NetworkCapabilities updateCapabilities(Network defaultNetwork) {
- return updateCapabilitiesInternal(defaultNetwork, false);
- }
-
public void disconnect() {
if (mMockNetworkAgent != null) mMockNetworkAgent.disconnect();
mAgentRegistered = false;
@@ -1249,7 +1235,7 @@ public class ConnectivityServiceTest {
MockitoAnnotations.initMocks(this);
when(mMetricsService.defaultNetworkMetrics()).thenReturn(mDefaultNetworkMetrics);
- when(mUserManager.getUsers(eq(true))).thenReturn(
+ when(mUserManager.getAliveUsers()).thenReturn(
Arrays.asList(new UserInfo[] {
new UserInfo(VPN_USER, "", 0),
}));
@@ -5053,6 +5039,13 @@ public class ConnectivityServiceTest {
waitForIdle();
expectForceUpdateIfaces(wifiAndVpn, null);
reset(mStatsService);
+
+ // Passing in null again means follow the default network again.
+ mService.setUnderlyingNetworksForVpn(null);
+ waitForIdle();
+ expectForceUpdateIfaces(wifiAndVpn, WIFI_IFNAME, Process.myUid(), VPN_IFNAME,
+ new String[]{WIFI_IFNAME});
+ reset(mStatsService);
}
@Test
@@ -5407,6 +5400,106 @@ public class ConnectivityServiceTest {
}
@Test
+ public void testApplyUnderlyingCapabilities() throws Exception {
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+ mCellNetworkAgent.connect(false /* validated */);
+ mWiFiNetworkAgent.connect(false /* validated */);
+
+ final NetworkCapabilities cellNc = new NetworkCapabilities()
+ .addTransportType(TRANSPORT_CELLULAR)
+ .addCapability(NET_CAPABILITY_INTERNET)
+ .addCapability(NET_CAPABILITY_NOT_CONGESTED)
+ .setLinkDownstreamBandwidthKbps(10);
+ final NetworkCapabilities wifiNc = new NetworkCapabilities()
+ .addTransportType(TRANSPORT_WIFI)
+ .addCapability(NET_CAPABILITY_INTERNET)
+ .addCapability(NET_CAPABILITY_NOT_METERED)
+ .addCapability(NET_CAPABILITY_NOT_ROAMING)
+ .addCapability(NET_CAPABILITY_NOT_CONGESTED)
+ .addCapability(NET_CAPABILITY_NOT_SUSPENDED)
+ .setLinkUpstreamBandwidthKbps(20);
+ mCellNetworkAgent.setNetworkCapabilities(cellNc, true /* sendToConnectivityService */);
+ mWiFiNetworkAgent.setNetworkCapabilities(wifiNc, true /* sendToConnectivityService */);
+ waitForIdle();
+
+ final Network mobile = mCellNetworkAgent.getNetwork();
+ final Network wifi = mWiFiNetworkAgent.getNetwork();
+
+ final NetworkCapabilities initialCaps = new NetworkCapabilities();
+ initialCaps.addCapability(NET_CAPABILITY_INTERNET);
+ initialCaps.removeCapability(NET_CAPABILITY_NOT_VPN);
+
+ final NetworkCapabilities withNoUnderlying = new NetworkCapabilities();
+ withNoUnderlying.addCapability(NET_CAPABILITY_INTERNET);
+ withNoUnderlying.addCapability(NET_CAPABILITY_NOT_CONGESTED);
+ withNoUnderlying.addCapability(NET_CAPABILITY_NOT_ROAMING);
+ withNoUnderlying.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
+ withNoUnderlying.addTransportType(TRANSPORT_VPN);
+ withNoUnderlying.removeCapability(NET_CAPABILITY_NOT_VPN);
+
+ final NetworkCapabilities withMobileUnderlying = new NetworkCapabilities(withNoUnderlying);
+ withMobileUnderlying.addTransportType(TRANSPORT_CELLULAR);
+ withMobileUnderlying.removeCapability(NET_CAPABILITY_NOT_ROAMING);
+ withMobileUnderlying.removeCapability(NET_CAPABILITY_NOT_SUSPENDED);
+ withMobileUnderlying.setLinkDownstreamBandwidthKbps(10);
+
+ final NetworkCapabilities withWifiUnderlying = new NetworkCapabilities(withNoUnderlying);
+ withWifiUnderlying.addTransportType(TRANSPORT_WIFI);
+ withWifiUnderlying.addCapability(NET_CAPABILITY_NOT_METERED);
+ withWifiUnderlying.setLinkUpstreamBandwidthKbps(20);
+
+ final NetworkCapabilities withWifiAndMobileUnderlying =
+ new NetworkCapabilities(withNoUnderlying);
+ withWifiAndMobileUnderlying.addTransportType(TRANSPORT_CELLULAR);
+ withWifiAndMobileUnderlying.addTransportType(TRANSPORT_WIFI);
+ withWifiAndMobileUnderlying.removeCapability(NET_CAPABILITY_NOT_METERED);
+ withWifiAndMobileUnderlying.removeCapability(NET_CAPABILITY_NOT_ROAMING);
+ withWifiAndMobileUnderlying.setLinkDownstreamBandwidthKbps(10);
+ withWifiAndMobileUnderlying.setLinkUpstreamBandwidthKbps(20);
+
+ NetworkCapabilities caps = new NetworkCapabilities(initialCaps);
+ final boolean notDeclaredMetered = false;
+ mService.applyUnderlyingCapabilities(new Network[]{}, caps, notDeclaredMetered);
+ assertEquals(withNoUnderlying, caps);
+
+ caps = new NetworkCapabilities(initialCaps);
+ mService.applyUnderlyingCapabilities(new Network[]{null}, caps, notDeclaredMetered);
+ assertEquals(withNoUnderlying, caps);
+
+ caps = new NetworkCapabilities(initialCaps);
+ mService.applyUnderlyingCapabilities(new Network[]{mobile}, caps, notDeclaredMetered);
+ assertEquals(withMobileUnderlying, caps);
+
+ mService.applyUnderlyingCapabilities(new Network[]{wifi}, caps, notDeclaredMetered);
+ assertEquals(withWifiUnderlying, caps);
+
+ final boolean isDeclaredMetered = true;
+ withWifiUnderlying.removeCapability(NET_CAPABILITY_NOT_METERED);
+ caps = new NetworkCapabilities(initialCaps);
+ mService.applyUnderlyingCapabilities(new Network[]{wifi}, caps, isDeclaredMetered);
+ assertEquals(withWifiUnderlying, caps);
+
+ caps = new NetworkCapabilities(initialCaps);
+ mService.applyUnderlyingCapabilities(new Network[]{mobile, wifi}, caps, isDeclaredMetered);
+ assertEquals(withWifiAndMobileUnderlying, caps);
+
+ withWifiUnderlying.addCapability(NET_CAPABILITY_NOT_METERED);
+ caps = new NetworkCapabilities(initialCaps);
+ mService.applyUnderlyingCapabilities(new Network[]{null, mobile, null, wifi},
+ caps, notDeclaredMetered);
+ assertEquals(withWifiAndMobileUnderlying, caps);
+
+ caps = new NetworkCapabilities(initialCaps);
+ mService.applyUnderlyingCapabilities(new Network[]{null, mobile, null, wifi},
+ caps, notDeclaredMetered);
+ assertEquals(withWifiAndMobileUnderlying, caps);
+
+ mService.applyUnderlyingCapabilities(null, caps, notDeclaredMetered);
+ assertEquals(withWifiUnderlying, caps);
+ }
+
+ @Test
public void testVpnConnectDisconnectUnderlyingNetwork() throws Exception {
final TestNetworkCallback callback = new TestNetworkCallback();
final NetworkRequest request = new NetworkRequest.Builder()
@@ -5956,17 +6049,28 @@ public class ConnectivityServiceTest {
&& caps.hasTransport(TRANSPORT_VPN)
&& caps.hasTransport(TRANSPORT_WIFI));
+ // Change the VPN's capabilities somehow (specifically, disconnect wifi).
+ mWiFiNetworkAgent.disconnect();
+ callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
+ callback.expectCapabilitiesThat(mMockVpn, (caps)
+ -> caps.getUids().size() == 2
+ && caps.getUids().contains(new UidRange(uid, uid))
+ && caps.getUids().contains(UidRange.createForUser(restrictedUserId))
+ && caps.hasTransport(TRANSPORT_VPN)
+ && !caps.hasTransport(TRANSPORT_WIFI));
+
// Send a USER_REMOVED broadcast and expect to lose the UID range for the restricted user.
final Intent removedIntent = new Intent(ACTION_USER_REMOVED);
removedIntent.putExtra(Intent.EXTRA_USER_HANDLE, restrictedUserId);
handler.post(() -> mServiceContext.sendBroadcast(removedIntent));
- // Expect that the VPN gains the UID range for the restricted user.
+ // Expect that the VPN gains the UID range for the restricted user, and that the capability
+ // 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.hasTransport(TRANSPORT_VPN)
- && caps.hasTransport(TRANSPORT_WIFI));
+ && !caps.hasTransport(TRANSPORT_WIFI));
}
@Test
@@ -6915,8 +7019,8 @@ public class ConnectivityServiceTest {
final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
mMockVpn.establish(lp, VPN_UID, vpnRange);
- // Connected VPN should have interface rules set up. There are two expected invocations,
- // one during VPN uid update, one during VPN LinkProperties update
+ // A connected VPN should have interface rules set up. There are two expected invocations,
+ // one during the VPN initial connection, one during the VPN LinkProperties update.
ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
verify(mMockNetd, times(2)).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID);
@@ -7431,20 +7535,14 @@ public class ConnectivityServiceTest {
setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION);
- // setUp() calls mockVpn() which adds a VPN with the Test Runner's uid. Configure it to be
- // active
- final VpnInfo info = new VpnInfo();
- info.ownerUid = Process.myUid();
- info.vpnIface = VPN_IFNAME;
- mMockVpn.setVpnInfo(info);
-
mMockVpn.establishForMyUid();
- waitForIdle();
+ // Wait for networks to connect and broadcasts to be sent before removing permissions.
+ waitForIdle();
mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
-
assertTrue(mService.setUnderlyingNetworksForVpn(new Network[] {network}));
+ waitForIdle();
assertTrue(
"Active VPN permission not applied",
mService.checkConnectivityDiagnosticsPermissions(
@@ -7452,6 +7550,7 @@ public class ConnectivityServiceTest {
mContext.getOpPackageName()));
assertTrue(mService.setUnderlyingNetworksForVpn(null));
+ waitForIdle();
assertFalse(
"VPN shouldn't receive callback on non-underlying network",
mService.checkConnectivityDiagnosticsPermissions(
diff --git a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
index 5a29c2c96ba7..de35f910d53a 100644
--- a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
+++ b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
@@ -123,7 +123,7 @@ public class PermissionMonitorTest {
MockitoAnnotations.initMocks(this);
when(mContext.getPackageManager()).thenReturn(mPackageManager);
when(mContext.getSystemService(eq(Context.USER_SERVICE))).thenReturn(mUserManager);
- when(mUserManager.getUsers(eq(true))).thenReturn(
+ when(mUserManager.getAliveUsers()).thenReturn(
Arrays.asList(new UserInfo[] {
new UserInfo(MOCK_USER1, "", 0),
new UserInfo(MOCK_USER2, "", 0),
diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java
index a553b584a2e3..337507ac1d46 100644
--- a/tests/net/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/net/java/com/android/server/connectivity/VpnTest.java
@@ -21,15 +21,6 @@ import static android.content.pm.UserInfo.FLAG_MANAGED_PROFILE;
import static android.content.pm.UserInfo.FLAG_PRIMARY;
import static android.content.pm.UserInfo.FLAG_RESTRICTED;
import static android.net.ConnectivityManager.NetworkCallback;
-import static android.net.NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
-import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
-import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED;
-import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
-import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
-import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
-import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
-import static android.net.NetworkCapabilities.TRANSPORT_VPN;
-import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
@@ -41,6 +32,7 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doAnswer;
@@ -86,10 +78,10 @@ import android.os.Build.VERSION_CODES;
import android.os.Bundle;
import android.os.ConditionVariable;
import android.os.INetworkManagementService;
-import android.os.Looper;
import android.os.Process;
import android.os.UserHandle;
import android.os.UserManager;
+import android.os.test.TestLooper;
import android.provider.Settings;
import android.security.Credentials;
import android.security.KeyStore;
@@ -100,6 +92,7 @@ import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.internal.R;
+import com.android.internal.net.LegacyVpnInfo;
import com.android.internal.net.VpnConfig;
import com.android.internal.net.VpnProfile;
import com.android.server.IpSecService;
@@ -223,6 +216,8 @@ public class VpnTest {
.thenReturn(mNotificationManager);
when(mContext.getSystemService(eq(Context.CONNECTIVITY_SERVICE)))
.thenReturn(mConnectivityManager);
+ when(mContext.getSystemServiceName(eq(ConnectivityManager.class)))
+ .thenReturn(Context.CONNECTIVITY_SERVICE);
when(mContext.getSystemService(eq(Context.IPSEC_SERVICE))).thenReturn(mIpSecManager);
when(mContext.getString(R.string.config_customVpnAlwaysOnDisconnectedDialogComponent))
.thenReturn(Resources.getSystem().getString(
@@ -589,7 +584,7 @@ public class VpnTest {
}
@Test
- public void testNotificationShownForAlwaysOnApp() {
+ public void testNotificationShownForAlwaysOnApp() throws Exception {
final UserHandle userHandle = UserHandle.of(primaryUser.id);
final Vpn vpn = createVpn(primaryUser.id);
setMockedUsers(primaryUser);
@@ -617,103 +612,6 @@ public class VpnTest {
order.verify(mNotificationManager).cancel(anyString(), anyInt());
}
- @Test
- public void testCapabilities() {
- final Vpn vpn = createVpn(primaryUser.id);
- setMockedUsers(primaryUser);
-
- final Network mobile = new Network(1);
- final Network wifi = new Network(2);
-
- final Map<Network, NetworkCapabilities> networks = new HashMap<>();
- networks.put(
- mobile,
- new NetworkCapabilities()
- .addTransportType(TRANSPORT_CELLULAR)
- .addCapability(NET_CAPABILITY_INTERNET)
- .addCapability(NET_CAPABILITY_NOT_CONGESTED)
- .setLinkDownstreamBandwidthKbps(10));
- networks.put(
- wifi,
- new NetworkCapabilities()
- .addTransportType(TRANSPORT_WIFI)
- .addCapability(NET_CAPABILITY_INTERNET)
- .addCapability(NET_CAPABILITY_NOT_METERED)
- .addCapability(NET_CAPABILITY_NOT_ROAMING)
- .addCapability(NET_CAPABILITY_NOT_CONGESTED)
- .addCapability(NET_CAPABILITY_NOT_SUSPENDED)
- .setLinkUpstreamBandwidthKbps(20));
- setMockedNetworks(networks);
-
- final NetworkCapabilities caps = new NetworkCapabilities();
-
- Vpn.applyUnderlyingCapabilities(
- mConnectivityManager, new Network[] {}, caps, false /* isAlwaysMetered */);
- assertTrue(caps.hasTransport(TRANSPORT_VPN));
- assertFalse(caps.hasTransport(TRANSPORT_CELLULAR));
- assertFalse(caps.hasTransport(TRANSPORT_WIFI));
- assertEquals(LINK_BANDWIDTH_UNSPECIFIED, caps.getLinkDownstreamBandwidthKbps());
- assertEquals(LINK_BANDWIDTH_UNSPECIFIED, caps.getLinkUpstreamBandwidthKbps());
- assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_METERED));
- assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING));
- assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
- assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
-
- Vpn.applyUnderlyingCapabilities(
- mConnectivityManager,
- new Network[] {mobile},
- caps,
- false /* isAlwaysMetered */);
- assertTrue(caps.hasTransport(TRANSPORT_VPN));
- assertTrue(caps.hasTransport(TRANSPORT_CELLULAR));
- assertFalse(caps.hasTransport(TRANSPORT_WIFI));
- assertEquals(10, caps.getLinkDownstreamBandwidthKbps());
- assertEquals(LINK_BANDWIDTH_UNSPECIFIED, caps.getLinkUpstreamBandwidthKbps());
- assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_METERED));
- assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING));
- assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
- assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
-
- Vpn.applyUnderlyingCapabilities(
- mConnectivityManager, new Network[] {wifi}, caps, false /* isAlwaysMetered */);
- assertTrue(caps.hasTransport(TRANSPORT_VPN));
- assertFalse(caps.hasTransport(TRANSPORT_CELLULAR));
- assertTrue(caps.hasTransport(TRANSPORT_WIFI));
- assertEquals(LINK_BANDWIDTH_UNSPECIFIED, caps.getLinkDownstreamBandwidthKbps());
- assertEquals(20, caps.getLinkUpstreamBandwidthKbps());
- assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_METERED));
- assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING));
- assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
- assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
-
- Vpn.applyUnderlyingCapabilities(
- mConnectivityManager, new Network[] {wifi}, caps, true /* isAlwaysMetered */);
- assertTrue(caps.hasTransport(TRANSPORT_VPN));
- assertFalse(caps.hasTransport(TRANSPORT_CELLULAR));
- assertTrue(caps.hasTransport(TRANSPORT_WIFI));
- assertEquals(LINK_BANDWIDTH_UNSPECIFIED, caps.getLinkDownstreamBandwidthKbps());
- assertEquals(20, caps.getLinkUpstreamBandwidthKbps());
- assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_METERED));
- assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING));
- assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
- assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
-
- Vpn.applyUnderlyingCapabilities(
- mConnectivityManager,
- new Network[] {mobile, wifi},
- caps,
- false /* isAlwaysMetered */);
- assertTrue(caps.hasTransport(TRANSPORT_VPN));
- assertTrue(caps.hasTransport(TRANSPORT_CELLULAR));
- assertTrue(caps.hasTransport(TRANSPORT_WIFI));
- assertEquals(10, caps.getLinkDownstreamBandwidthKbps());
- assertEquals(20, caps.getLinkUpstreamBandwidthKbps());
- assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_METERED));
- assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING));
- assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
- assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
- }
-
/**
* The profile name should NOT change between releases for backwards compatibility
*
@@ -1037,7 +935,7 @@ public class VpnTest {
when(exception.getErrorType())
.thenReturn(IkeProtocolException.ERROR_TYPE_AUTHENTICATION_FAILED);
- final Vpn vpn = startLegacyVpn(mVpnProfile);
+ final Vpn vpn = startLegacyVpn(createVpn(primaryUser.id), (mVpnProfile));
final NetworkCallback cb = triggerOnAvailableAndGetCallback();
// Wait for createIkeSession() to be called before proceeding in order to ensure consistent
@@ -1048,20 +946,20 @@ public class VpnTest {
ikeCb.onClosedExceptionally(exception);
verify(mConnectivityManager, timeout(TEST_TIMEOUT_MS)).unregisterNetworkCallback(eq(cb));
- assertEquals(DetailedState.FAILED, vpn.getNetworkInfo().getDetailedState());
+ assertEquals(LegacyVpnInfo.STATE_FAILED, vpn.getLegacyVpnInfo().state);
}
@Test
public void testStartPlatformVpnIllegalArgumentExceptionInSetup() throws Exception {
when(mIkev2SessionCreator.createIkeSession(any(), any(), any(), any(), any(), any()))
.thenThrow(new IllegalArgumentException());
- final Vpn vpn = startLegacyVpn(mVpnProfile);
+ final Vpn vpn = startLegacyVpn(createVpn(primaryUser.id), mVpnProfile);
final NetworkCallback cb = triggerOnAvailableAndGetCallback();
// Wait for createIkeSession() to be called before proceeding in order to ensure consistent
// state
verify(mConnectivityManager, timeout(TEST_TIMEOUT_MS)).unregisterNetworkCallback(eq(cb));
- assertEquals(DetailedState.FAILED, vpn.getNetworkInfo().getDetailedState());
+ assertEquals(LegacyVpnInfo.STATE_FAILED, vpn.getLegacyVpnInfo().state);
}
private void setAndVerifyAlwaysOnPackage(Vpn vpn, int uid, boolean lockdownEnabled) {
@@ -1100,8 +998,7 @@ public class VpnTest {
// a subsequent CL.
}
- public Vpn startLegacyVpn(final VpnProfile vpnProfile) throws Exception {
- final Vpn vpn = createVpn(primaryUser.id);
+ private Vpn startLegacyVpn(final Vpn vpn, final VpnProfile vpnProfile) throws Exception {
setMockedUsers(primaryUser);
// Dummy egress interface
@@ -1118,7 +1015,7 @@ public class VpnTest {
@Test
public void testStartPlatformVpn() throws Exception {
- startLegacyVpn(mVpnProfile);
+ startLegacyVpn(createVpn(primaryUser.id), mVpnProfile);
// TODO: Test the Ikev2VpnRunner started up properly. Relies on utility methods added in
// a subsequent patch.
}
@@ -1153,7 +1050,7 @@ public class VpnTest {
legacyRunnerReady.open();
return new Network(102);
});
- final Vpn vpn = startLegacyVpn(profile);
+ final Vpn vpn = startLegacyVpn(createVpn(primaryUser.id), profile);
final TestDeps deps = (TestDeps) vpn.mDeps;
try {
// udppsk and 1701 are the values for TYPE_L2TP_IPSEC_PSK
@@ -1287,8 +1184,13 @@ public class VpnTest {
doReturn(UserHandle.of(userId)).when(asUserContext).getUser();
when(mContext.createContextAsUser(eq(UserHandle.of(userId)), anyInt()))
.thenReturn(asUserContext);
- return new Vpn(Looper.myLooper(), mContext, new TestDeps(), mNetService,
+ final TestLooper testLooper = new TestLooper();
+ final Vpn vpn = new Vpn(testLooper.getLooper(), mContext, new TestDeps(), mNetService,
userId, mKeyStore, mSystemServices, mIkev2SessionCreator);
+ verify(mConnectivityManager, times(1)).registerNetworkProvider(argThat(
+ provider -> provider.getName().contains("VpnNetworkProvider")
+ ));
+ return vpn;
}
private static void assertBlocked(Vpn vpn, int... uids) {
@@ -1318,15 +1220,14 @@ public class VpnTest {
* @see UserManagerService#getUsers(boolean)
*/
doAnswer(invocation -> {
- final boolean excludeDying = (boolean) invocation.getArguments()[0];
final ArrayList<UserInfo> result = new ArrayList<>(users.length);
for (UserInfo ui : users) {
- if (!excludeDying || (ui.isEnabled() && !ui.partial)) {
+ if (ui.isEnabled() && !ui.partial) {
result.add(ui);
}
}
return result;
- }).when(mUserManager).getUsers(anyBoolean());
+ }).when(mUserManager).getAliveUsers();
doAnswer(invocation -> {
final int id = (int) invocation.getArguments()[0];