diff options
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]; |