diff options
101 files changed, 2614 insertions, 1111 deletions
diff --git a/StubLibraries.bp b/StubLibraries.bp index d8661169526c..fd614a7e3dc3 100644 --- a/StubLibraries.bp +++ b/StubLibraries.bp @@ -422,10 +422,6 @@ droidstubs { name: "hwbinder-stubs-docs", srcs: [ "core/java/android/os/HidlSupport.java", - "core/java/android/annotation/IntDef.java", - "core/java/android/annotation/IntRange.java", - "core/java/android/annotation/NonNull.java", - "core/java/android/annotation/SystemApi.java", "core/java/android/os/HidlMemory.java", "core/java/android/os/HwBinder.java", "core/java/android/os/HwBlob.java", @@ -451,6 +447,7 @@ droidstubs { java_library_static { name: "hwbinder.stubs", sdk_version: "core_current", + libs: ["stub-annotations"], srcs: [ ":hwbinder-stubs-docs", ], diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java index 565ed959aeb4..15e5e843674d 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java +++ b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java @@ -31,6 +31,7 @@ import android.content.Intent; import android.content.ServiceConnection; import android.net.Uri; import android.os.Binder; +import android.os.Build; import android.os.Handler; import android.os.IBinder; import android.os.Looper; @@ -73,11 +74,12 @@ public final class JobServiceContext implements ServiceConnection { private static final String TAG = "JobServiceContext"; /** Amount of time a job is allowed to execute for before being considered timed-out. */ - public static final long EXECUTING_TIMESLICE_MILLIS = 10 * 60 * 1000; // 10mins. + public static final long EXECUTING_TIMESLICE_MILLIS = + 10 * 60 * 1000 * Build.HW_TIMEOUT_MULTIPLIER; // 10mins. /** Amount of time the JobScheduler waits for the initial service launch+bind. */ - private static final long OP_BIND_TIMEOUT_MILLIS = 18 * 1000; + private static final long OP_BIND_TIMEOUT_MILLIS = 18 * 1000 * Build.HW_TIMEOUT_MULTIPLIER; /** Amount of time the JobScheduler will wait for a response from an app for a message. */ - private static final long OP_TIMEOUT_MILLIS = 8 * 1000; + private static final long OP_TIMEOUT_MILLIS = 8 * 1000 * Build.HW_TIMEOUT_MULTIPLIER; private static final String[] VERB_STRINGS = { "VERB_BINDING", "VERB_STARTING", "VERB_EXECUTING", "VERB_STOPPING", "VERB_FINISHED" diff --git a/core/api/current.txt b/core/api/current.txt index 0e7ecefbdbdc..2b5075dfae95 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -7999,13 +7999,13 @@ package android.app.usage { } public class NetworkStatsManager { - method public android.app.usage.NetworkStats queryDetails(int, String, long, long) throws android.os.RemoteException, java.lang.SecurityException; - method public android.app.usage.NetworkStats queryDetailsForUid(int, String, long, long, int) throws java.lang.SecurityException; - method public android.app.usage.NetworkStats queryDetailsForUidTag(int, String, long, long, int, int) throws java.lang.SecurityException; - method public android.app.usage.NetworkStats queryDetailsForUidTagState(int, String, long, long, int, int, int) throws java.lang.SecurityException; - method public android.app.usage.NetworkStats querySummary(int, String, long, long) throws android.os.RemoteException, java.lang.SecurityException; - method public android.app.usage.NetworkStats.Bucket querySummaryForDevice(int, String, long, long) throws android.os.RemoteException, java.lang.SecurityException; - method public android.app.usage.NetworkStats.Bucket querySummaryForUser(int, String, long, long) throws android.os.RemoteException, java.lang.SecurityException; + method @WorkerThread public android.app.usage.NetworkStats queryDetails(int, String, long, long) throws android.os.RemoteException, java.lang.SecurityException; + method @WorkerThread public android.app.usage.NetworkStats queryDetailsForUid(int, String, long, long, int) throws java.lang.SecurityException; + method @WorkerThread public android.app.usage.NetworkStats queryDetailsForUidTag(int, String, long, long, int, int) throws java.lang.SecurityException; + method @WorkerThread public android.app.usage.NetworkStats queryDetailsForUidTagState(int, String, long, long, int, int, int) throws java.lang.SecurityException; + method @WorkerThread public android.app.usage.NetworkStats querySummary(int, String, long, long) throws android.os.RemoteException, java.lang.SecurityException; + method @WorkerThread public android.app.usage.NetworkStats.Bucket querySummaryForDevice(int, String, long, long) throws android.os.RemoteException, java.lang.SecurityException; + method @WorkerThread public android.app.usage.NetworkStats.Bucket querySummaryForUser(int, String, long, long) throws android.os.RemoteException, java.lang.SecurityException; method public void registerUsageCallback(int, String, long, android.app.usage.NetworkStatsManager.UsageCallback); method public void registerUsageCallback(int, String, long, android.app.usage.NetworkStatsManager.UsageCallback, @Nullable android.os.Handler); method public void unregisterUsageCallback(android.app.usage.NetworkStatsManager.UsageCallback); @@ -25690,17 +25690,14 @@ package android.net.vcn { public final class VcnGatewayConnectionConfig { method @NonNull public int[] getExposedCapabilities(); method @IntRange(from=android.net.vcn.VcnGatewayConnectionConfig.MIN_MTU_V6) public int getMaxMtu(); - method @NonNull public int[] getRequiredUnderlyingCapabilities(); method @NonNull public long[] getRetryInterval(); } public static final class VcnGatewayConnectionConfig.Builder { ctor public VcnGatewayConnectionConfig.Builder(@NonNull android.net.vcn.VcnControlPlaneConfig); method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder addExposedCapability(int); - method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder addRequiredUnderlyingCapability(int); method @NonNull public android.net.vcn.VcnGatewayConnectionConfig build(); method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder removeExposedCapability(int); - method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder removeRequiredUnderlyingCapability(int); method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder setMaxMtu(@IntRange(from=android.net.vcn.VcnGatewayConnectionConfig.MIN_MTU_V6) int); method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder setRetryInterval(@NonNull long[]); } @@ -39304,6 +39301,7 @@ package android.telephony { field public static final String KEY_RTT_SUPPORTED_FOR_VT_BOOL = "rtt_supported_for_vt_bool"; field public static final String KEY_RTT_SUPPORTED_WHILE_ROAMING_BOOL = "rtt_supported_while_roaming_bool"; field public static final String KEY_RTT_UPGRADE_SUPPORTED_BOOL = "rtt_upgrade_supported_bool"; + field public static final String KEY_RTT_UPGRADE_SUPPORTED_FOR_DOWNGRADED_VT_CALL_BOOL = "rtt_upgrade_supported_for_downgraded_vt_call"; field public static final String KEY_SHOW_4G_FOR_3G_DATA_ICON_BOOL = "show_4g_for_3g_data_icon_bool"; field public static final String KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL = "show_4g_for_lte_data_icon_bool"; field public static final String KEY_SHOW_APN_SETTING_CDMA_BOOL = "show_apn_setting_cdma_bool"; @@ -39346,6 +39344,7 @@ package android.telephony { field public static final String KEY_VOICEMAIL_NOTIFICATION_PERSISTENT_BOOL = "voicemail_notification_persistent_bool"; field public static final String KEY_VOICE_PRIVACY_DISABLE_UI_BOOL = "voice_privacy_disable_ui_bool"; field public static final String KEY_VOLTE_REPLACEMENT_RAT_INT = "volte_replacement_rat_int"; + field public static final String KEY_VT_UPGRADE_SUPPORTED_FOR_DOWNGRADED_RTT_CALL_BOOL = "vt_upgrade_supported_for_downgraded_rtt_call"; field public static final String KEY_VVM_CELLULAR_DATA_REQUIRED_BOOL = "vvm_cellular_data_required_bool"; field public static final String KEY_VVM_CLIENT_PREFIX_STRING = "vvm_client_prefix_string"; field public static final String KEY_VVM_DESTINATION_NUMBER_STRING = "vvm_destination_number_string"; @@ -40905,6 +40904,10 @@ package android.telephony { method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public void onMessageWaitingIndicatorChanged(boolean); } + public static interface TelephonyCallback.PhysicalChannelConfigListener { + method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onPhysicalChannelConfigChanged(@NonNull java.util.List<android.telephony.PhysicalChannelConfig>); + } + public static interface TelephonyCallback.PreciseDataConnectionStateListener { method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onPreciseDataConnectionStateChanged(@NonNull android.telephony.PreciseDataConnectionState); } diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt index 992b57f356c5..4df72046340b 100644 --- a/core/api/module-lib-current.txt +++ b/core/api/module-lib-current.txt @@ -85,6 +85,7 @@ package android.net { public class VpnManager { field @Deprecated public static final int TYPE_VPN_LEGACY = 3; // 0x3 field public static final int TYPE_VPN_NONE = -1; // 0xffffffff + field public static final int TYPE_VPN_OEM = 4; // 0x4 field public static final int TYPE_VPN_PLATFORM = 2; // 0x2 field public static final int TYPE_VPN_SERVICE = 1; // 0x1 } @@ -109,6 +110,10 @@ package android.os { method public default int getStability(); } + public class Process { + field public static final int VPN_UID = 1016; // 0x3f8 + } + public class StatsServiceManager { method @NonNull public android.os.StatsServiceManager.ServiceRegisterer getStatsCompanionServiceRegisterer(); method @NonNull public android.os.StatsServiceManager.ServiceRegisterer getStatsManagerServiceRegisterer(); diff --git a/core/api/system-current.txt b/core/api/system-current.txt index da56f45e9d6e..ad867880aec5 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -9507,6 +9507,19 @@ package android.telephony { field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ImsiEncryptionInfo> CREATOR; } + public final class LinkCapacityEstimate implements android.os.Parcelable { + ctor public LinkCapacityEstimate(int, int, int); + method public int describeContents(); + method public int getDownlinkCapacityKbps(); + method public int getType(); + method public int getUplinkCapacityKbps(); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.LinkCapacityEstimate> CREATOR; + field public static final int INVALID = -1; // 0xffffffff + field public static final int LCE_TYPE_COMBINED = 2; // 0x2 + field public static final int LCE_TYPE_PRIMARY = 0; // 0x0 + field public static final int LCE_TYPE_SECONDARY = 1; // 0x1 + } + public final class LteVopsSupportInfo implements android.os.Parcelable { ctor public LteVopsSupportInfo(int, int); method public int describeContents(); @@ -9983,6 +9996,8 @@ package android.telephony { field public static final int EVENT_DISPLAY_INFO_CHANGED = 21; // 0x15 field @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public static final int EVENT_EMERGENCY_NUMBER_LIST_CHANGED = 25; // 0x19 field @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int EVENT_IMS_CALL_DISCONNECT_CAUSE_CHANGED = 28; // 0x1c + field @RequiresPermission(android.Manifest.permission.READ_CALL_LOG) public static final int EVENT_LEGACY_CALL_STATE_CHANGED = 36; // 0x24 + field @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int EVENT_LINK_CAPACITY_ESTIMATE_CHANGED = 37; // 0x25 field @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public static final int EVENT_MESSAGE_WAITING_INDICATOR_CHANGED = 3; // 0x3 field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int EVENT_OEM_HOOK_RAW = 15; // 0xf field @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int EVENT_OUTGOING_EMERGENCY_CALL = 29; // 0x1d @@ -10013,6 +10028,10 @@ package android.telephony { method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onDataEnabledChanged(boolean, int); } + public static interface TelephonyCallback.LinkCapacityEstimateChangedListener { + method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onLinkCapacityEstimateChanged(@NonNull java.util.List<android.telephony.LinkCapacityEstimate>); + } + public static interface TelephonyCallback.OutgoingEmergencyCallListener { method @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public void onOutgoingEmergencyCall(@NonNull android.telephony.emergency.EmergencyNumber, int); } @@ -10025,10 +10044,6 @@ package android.telephony { method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void onPhoneCapabilityChanged(@NonNull android.telephony.PhoneCapability); } - public static interface TelephonyCallback.PhysicalChannelConfigListener { - method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onPhysicalChannelConfigChanged(@NonNull java.util.List<android.telephony.PhysicalChannelConfig>); - } - public static interface TelephonyCallback.PreciseCallStateListener { method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onPreciseCallStateChanged(@NonNull android.telephony.PreciseCallState); } @@ -10084,7 +10099,6 @@ package android.telephony { method @Nullable @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public android.content.ComponentName getAndUpdateDefaultRespondViaMessageApplication(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getCallForwarding(int, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CallForwardingInfoCallback); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getCallWaitingStatus(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); - method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.CarrierBandwidth getCarrierBandwidth(); method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int); method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent); method public java.util.List<java.lang.String> getCarrierPackageNamesForIntentAndPhone(android.content.Intent, int); diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index 098d8b6c6058..9f1132b605ef 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -24,6 +24,7 @@ import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.SystemService; import android.annotation.TestApi; +import android.annotation.WorkerThread; import android.app.usage.NetworkStats.Bucket; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; @@ -201,6 +202,7 @@ public class NetworkStatsManager { * default network {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL}, * metered {@link NetworkStats.Bucket#METERED_ALL}, * and roaming {@link NetworkStats.Bucket#ROAMING_ALL}. + * This may take a long time, and apps should avoid calling this on their main thread. * * @param networkType As defined in {@link ConnectivityManager}, e.g. * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI} @@ -219,6 +221,7 @@ public class NetworkStatsManager { * @return Bucket object or null if permissions are insufficient or error happened during * statistics collection. */ + @WorkerThread public Bucket querySummaryForDevice(int networkType, String subscriberId, long startTime, long endTime) throws SecurityException, RemoteException { NetworkTemplate template; @@ -240,6 +243,7 @@ public class NetworkStatsManager { * uid {@link NetworkStats.Bucket#UID_ALL}, tag {@link NetworkStats.Bucket#TAG_NONE}, * metered {@link NetworkStats.Bucket#METERED_ALL}, and roaming * {@link NetworkStats.Bucket#ROAMING_ALL}. + * This may take a long time, and apps should avoid calling this on their main thread. * * @param networkType As defined in {@link ConnectivityManager}, e.g. * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI} @@ -258,6 +262,7 @@ public class NetworkStatsManager { * @return Bucket object or null if permissions are insufficient or error happened during * statistics collection. */ + @WorkerThread public Bucket querySummaryForUser(int networkType, String subscriberId, long startTime, long endTime) throws SecurityException, RemoteException { NetworkTemplate template; @@ -283,6 +288,7 @@ public class NetworkStatsManager { * means buckets' start and end timestamps are going to be the same as the 'startTime' and * 'endTime' parameters. State, uid, metered, and roaming are going to vary, and tag is going to * be the same. + * This may take a long time, and apps should avoid calling this on their main thread. * * @param networkType As defined in {@link ConnectivityManager}, e.g. * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI} @@ -301,6 +307,7 @@ public class NetworkStatsManager { * @return Statistics object or null if permissions are insufficient or error happened during * statistics collection. */ + @WorkerThread public NetworkStats querySummary(int networkType, String subscriberId, long startTime, long endTime) throws SecurityException, RemoteException { NetworkTemplate template; @@ -326,9 +333,11 @@ public class NetworkStatsManager { /** * Query network usage statistics details for a given uid. + * This may take a long time, and apps should avoid calling this on their main thread. * * @see #queryDetailsForUidTagState(int, String, long, long, int, int, int) */ + @WorkerThread public NetworkStats queryDetailsForUid(int networkType, String subscriberId, long startTime, long endTime, int uid) throws SecurityException { return queryDetailsForUidTagState(networkType, subscriberId, startTime, endTime, uid, @@ -344,9 +353,11 @@ public class NetworkStatsManager { /** * Query network usage statistics details for a given uid and tag. + * This may take a long time, and apps should avoid calling this on their main thread. * * @see #queryDetailsForUidTagState(int, String, long, long, int, int, int) */ + @WorkerThread public NetworkStats queryDetailsForUidTag(int networkType, String subscriberId, long startTime, long endTime, int uid, int tag) throws SecurityException { return queryDetailsForUidTagState(networkType, subscriberId, startTime, endTime, uid, @@ -365,6 +376,7 @@ public class NetworkStatsManager { * <p>Only includes buckets that atomically occur in the inclusive time range. Doesn't * interpolate across partial buckets. Since bucket length is in the order of hours, this * method cannot be used to measure data usage on a fine grained time scale. + * This may take a long time, and apps should avoid calling this on their main thread. * * @param networkType As defined in {@link ConnectivityManager}, e.g. * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI} @@ -387,6 +399,7 @@ public class NetworkStatsManager { * @return Statistics object or null if an error happened during statistics collection. * @throws SecurityException if permissions are insufficient to read network statistics. */ + @WorkerThread public NetworkStats queryDetailsForUidTagState(int networkType, String subscriberId, long startTime, long endTime, int uid, int tag, int state) throws SecurityException { NetworkTemplate template; @@ -425,6 +438,7 @@ public class NetworkStatsManager { * <p>Only includes buckets that atomically occur in the inclusive time range. Doesn't * interpolate across partial buckets. Since bucket length is in the order of hours, this * method cannot be used to measure data usage on a fine grained time scale. + * This may take a long time, and apps should avoid calling this on their main thread. * * @param networkType As defined in {@link ConnectivityManager}, e.g. * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI} @@ -443,6 +457,7 @@ public class NetworkStatsManager { * @return Statistics object or null if permissions are insufficient or error happened during * statistics collection. */ + @WorkerThread public NetworkStats queryDetails(int networkType, String subscriberId, long startTime, long endTime) throws SecurityException, RemoteException { NetworkTemplate template; diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java index 32aa0377cd5f..d21462e02d92 100644 --- a/core/java/android/content/ContentResolver.java +++ b/core/java/android/content/ContentResolver.java @@ -744,7 +744,7 @@ public abstract class ContentResolver implements ContentInterface { // Always log queries which take 500ms+; shorter queries are // sampled accordingly. private static final boolean ENABLE_CONTENT_SAMPLE = false; - private static final int SLOW_THRESHOLD_MILLIS = 500; + private static final int SLOW_THRESHOLD_MILLIS = 500 * Build.HW_TIMEOUT_MULTIPLIER; private final Random mRandom = new Random(); // guarded by itself /** @hide */ @@ -758,7 +758,8 @@ public abstract class ContentResolver implements ContentInterface { * before we decide it must be hung. * @hide */ - public static final int CONTENT_PROVIDER_PUBLISH_TIMEOUT_MILLIS = 10 * 1000; + public static final int CONTENT_PROVIDER_PUBLISH_TIMEOUT_MILLIS = + 10 * 1000 * Build.HW_TIMEOUT_MULTIPLIER; /** * How long we wait for an provider to be published. Should be longer than @@ -766,10 +767,11 @@ public abstract class ContentResolver implements ContentInterface { * @hide */ public static final int CONTENT_PROVIDER_READY_TIMEOUT_MILLIS = - CONTENT_PROVIDER_PUBLISH_TIMEOUT_MILLIS + 10 * 1000; + CONTENT_PROVIDER_PUBLISH_TIMEOUT_MILLIS + 10 * 1000 * Build.HW_TIMEOUT_MULTIPLIER; // Timeout given a ContentProvider that has already been started and connected to. - private static final int CONTENT_PROVIDER_TIMEOUT_MILLIS = 3 * 1000; + private static final int CONTENT_PROVIDER_TIMEOUT_MILLIS = + 3 * 1000 * Build.HW_TIMEOUT_MULTIPLIER; // Should be >= {@link #CONTENT_PROVIDER_WAIT_TIMEOUT_MILLIS}, because that's how // long ActivityManagerService is giving a content provider to get published if a new process diff --git a/core/java/android/net/VpnManager.java b/core/java/android/net/VpnManager.java index 77754d1256a7..5f65d46f3b1e 100644 --- a/core/java/android/net/VpnManager.java +++ b/core/java/android/net/VpnManager.java @@ -86,13 +86,21 @@ public class VpnManager { public static final int TYPE_VPN_LEGACY = 3; /** + * An VPN created by OEM code through other means than {@link VpnService} or {@link VpnManager}. + * @hide + */ + @SystemApi(client = MODULE_LIBRARIES) + public static final int TYPE_VPN_OEM = 4; + + /** * Channel for VPN notifications. * @hide */ public static final String NOTIFICATION_CHANNEL_VPN = "VPN"; /** @hide */ - @IntDef(value = {TYPE_VPN_NONE, TYPE_VPN_SERVICE, TYPE_VPN_PLATFORM, TYPE_VPN_LEGACY}) + @IntDef(value = {TYPE_VPN_NONE, TYPE_VPN_SERVICE, TYPE_VPN_PLATFORM, TYPE_VPN_LEGACY, + TYPE_VPN_OEM}) @Retention(RetentionPolicy.SOURCE) public @interface VpnType {} diff --git a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java index 9f83b21f0d0c..d4e8e2dca296 100644 --- a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java +++ b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java @@ -52,13 +52,12 @@ import java.util.concurrent.TimeUnit; * Network}s. * * <p>A VCN connection based on this configuration will be brought up dynamically based on device - * settings, and filed NetworkRequests. Underlying networks will be selected based on the services - * required by this configuration (as represented by network capabilities), and must be part of the - * subscription group under which this configuration is registered (see {@link + * settings, and filed NetworkRequests. Underlying Networks must provide INTERNET connectivity, and + * must be part of the subscription group under which this configuration is registered (see {@link * VcnManager#setVcnConfig}). * - * <p>As an abstraction of a cellular network, services that can be provided by a VCN network, or - * required for underlying networks are limited to services provided by cellular networks: + * <p>As an abstraction of a cellular network, services that can be provided by a VCN network are + * limited to services provided by cellular networks: * * <ul> * <li>{@link NetworkCapabilities#NET_CAPABILITY_MMS} @@ -214,13 +213,6 @@ public final class VcnGatewayConnectionConfig { checkValidCapability(cap); } - Preconditions.checkArgument( - mUnderlyingCapabilities != null && !mUnderlyingCapabilities.isEmpty(), - "underlyingCapabilities was null or empty"); - for (Integer cap : getAllUnderlyingCapabilities()) { - checkValidCapability(cap); - } - Objects.requireNonNull(mRetryIntervalsMs, "retryIntervalsMs was null"); validateRetryInterval(mRetryIntervalsMs); @@ -295,7 +287,9 @@ public final class VcnGatewayConnectionConfig { * * @see Builder#addRequiredUnderlyingCapability(int) * @see Builder#removeRequiredUnderlyingCapability(int) + * @hide */ + // TODO(b/182219992): Remove, and add when per-transport capabilities are supported @NonNull public int[] getRequiredUnderlyingCapabilities() { // Sorted set guarantees ordering @@ -470,7 +464,9 @@ public final class VcnGatewayConnectionConfig { * @return this {@link Builder} instance, for chaining * @see VcnGatewayConnectionConfig for a list of capabilities may be required of underlying * networks + * @hide */ + // TODO(b/182219992): Remove, and add when per-transport capabilities are supported @NonNull public Builder addRequiredUnderlyingCapability( @VcnSupportedCapability int underlyingCapability) { @@ -492,7 +488,9 @@ public final class VcnGatewayConnectionConfig { * @return this {@link Builder} instance, for chaining * @see VcnGatewayConnectionConfig for a list of capabilities may be required of underlying * networks + * @hide */ + // TODO(b/182219992): Remove, and add when per-transport capabilities are supported @NonNull @SuppressLint("BuilderSetStyle") // For consistency with NetCaps.Builder add/removeCap public Builder removeRequiredUnderlyingCapability( diff --git a/core/java/android/net/vcn/VcnManager.java b/core/java/android/net/vcn/VcnManager.java index 062438c6e5db..b73fdbff8ef3 100644 --- a/core/java/android/net/vcn/VcnManager.java +++ b/core/java/android/net/vcn/VcnManager.java @@ -448,7 +448,7 @@ public class VcnManager { * @param networkCapabilities an array of NetworkCapabilities.NET_CAPABILITY_* capabilities * for the Gateway Connection that encountered the error, for identification purposes. * These will be a sorted list with no duplicates and will match {@link - * VcnGatewayConnectionConfig#getRequiredUnderlyingCapabilities()} for one of the {@link + * VcnGatewayConnectionConfig#getExposedCapabilities()} for one of the {@link * VcnGatewayConnectionConfig}s set in the {@link VcnConfig} for this subscription * group. * @param errorCode the code to indicate the error that occurred diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index d7d3e5881219..189a8ac55a10 100755 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -138,7 +138,7 @@ public class Build { */ @UnsupportedAppUsage @TestApi - public static final boolean IS_EMULATOR = getString("ro.kernel.qemu").equals("1"); + public static final boolean IS_EMULATOR = getString("ro.boot.qemu").equals("1"); /** * A hardware serial number, if available. Alphanumeric only, case-insensitive. @@ -1116,6 +1116,18 @@ public class Build { } /** + * A multiplier for various timeouts on the system. + * + * The intent is that products targeting software emulators that are orders of magnitude slower + * than real hardware may set this to a large number. On real devices and hardware-accelerated + * virtualized devices this should not be set. + * + * @hide + */ + public static final int HW_TIMEOUT_MULTIPLIER = + SystemProperties.getInt("ro.hw_timeout_multiplier", 1); + + /** * True if Treble is enabled and required for this device. * * @hide diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index 8c2ca6d3e509..9d16f18ab848 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -16,8 +16,11 @@ package android.os; +import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; + import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SystemApi; import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; import android.system.ErrnoException; @@ -104,6 +107,7 @@ public class Process { * @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @SystemApi(client = MODULE_LIBRARIES) public static final int VPN_UID = 1016; /** diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java index 0ae5ed7bf726..fcb92889e69f 100644 --- a/core/java/android/telephony/PhoneStateListener.java +++ b/core/java/android/telephony/PhoneStateListener.java @@ -21,7 +21,6 @@ import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.TestApi; -import android.compat.annotation.ChangeId; import android.compat.annotation.UnsupportedAppUsage; import android.os.Binder; import android.os.Build; @@ -1265,6 +1264,8 @@ public class PhoneStateListener { // default implementation empty } + + /** * The callback methods need to be called on the handler thread where * this object was created. If the binder did that for us it'd be nice. @@ -1579,6 +1580,11 @@ public class PhoneStateListener { public void onAllowedNetworkTypesChanged(Map allowedNetworkTypesList) { // default implementation empty } + + public void onLinkCapacityEstimateChanged( + List<LinkCapacityEstimate> linkCapacityEstimateList) { + // default implementation empty + } } private void log(String s) { diff --git a/core/java/android/telephony/TelephonyCallback.java b/core/java/android/telephony/TelephonyCallback.java index a2584cae1b9c..0402ed07b7be 100644 --- a/core/java/android/telephony/TelephonyCallback.java +++ b/core/java/android/telephony/TelephonyCallback.java @@ -24,7 +24,6 @@ import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.compat.annotation.ChangeId; -import android.compat.annotation.UnsupportedAppUsage; import android.os.Binder; import android.os.Build; import android.telephony.emergency.EmergencyNumber; @@ -556,6 +555,33 @@ public class TelephonyCallback { public static final int EVENT_ALLOWED_NETWORK_TYPE_LIST_CHANGED = 35; /** + * Event for changes to the legacy call state changed listener implemented by + * {@link PhoneStateListener#onCallStateChanged(int, String)}. This listener variant is similar + * to the new {@link CallStateListener#onCallStateChanged(int)} with the important distinction + * that it CAN provide the phone number associated with a call. + * + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.READ_CALL_LOG) + public static final int EVENT_LEGACY_CALL_STATE_CHANGED = 36; + + + /** + * Event for changes to the link capacity estimate (LCE) + * + * <p>Requires permission {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE} + * + * @see LinkCapacityEstimateChangedListener#onLinkCapacityEstimateChanged + * + * @hide + */ + @SystemApi + @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE) + public static final int EVENT_LINK_CAPACITY_ESTIMATE_CHANGED = 37; + + + /** * @hide */ @IntDef(prefix = {"EVENT_"}, value = { @@ -593,7 +619,9 @@ public class TelephonyCallback { EVENT_BARRING_INFO_CHANGED, EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED, EVENT_DATA_ENABLED_CHANGED, - EVENT_ALLOWED_NETWORK_TYPE_LIST_CHANGED + EVENT_ALLOWED_NETWORK_TYPE_LIST_CHANGED, + EVENT_LEGACY_CALL_STATE_CHANGED, + EVENT_LINK_CAPACITY_ESTIMATE_CHANGED }) @Retention(RetentionPolicy.SOURCE) public @interface TelephonyEvent { @@ -1330,10 +1358,7 @@ public class TelephonyCallback { /** * Interface for current physical channel configuration listener. - * - * @hide */ - @SystemApi public interface PhysicalChannelConfigListener { /** * Callback invoked when the current physical channel configuration has changed @@ -1363,6 +1388,25 @@ public class TelephonyCallback { @TelephonyManager.DataEnabledReason int reason); } + /** + * Interface for link capacity estimate changed listener. + * + * @hide + */ + @SystemApi + public interface LinkCapacityEstimateChangedListener { + /** + * Callback invoked when the link capacity estimate (LCE) changes + * + * @param linkCapacityEstimateList a list of {@link LinkCapacityEstimate} + * The list size is at least 1. + * In case of a dual connected network, the list size could be 2. + * Use {@link LinkCapacityEstimate#getType()} to get the type of each element. + */ + @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE) + void onLinkCapacityEstimateChanged( + @NonNull List<LinkCapacityEstimate> linkCapacityEstimateList); + } /** * The callback methods need to be called on the handler thread where @@ -1706,5 +1750,16 @@ public class TelephonyCallback { () -> mExecutor.execute( () -> listener.onAllowedNetworkTypesChanged(allowedNetworkTypesList))); } + + public void onLinkCapacityEstimateChanged( + List<LinkCapacityEstimate> linkCapacityEstimateList) { + LinkCapacityEstimateChangedListener listener = + (LinkCapacityEstimateChangedListener) mTelephonyCallbackWeakRef.get(); + if (listener == null) return; + + Binder.withCleanCallingIdentity( + () -> mExecutor.execute(() -> listener.onLinkCapacityEstimateChanged( + linkCapacityEstimateList))); + } } } diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java index 15d1a595ff0e..5a8318f2aa5e 100644 --- a/core/java/android/telephony/TelephonyRegistryManager.java +++ b/core/java/android/telephony/TelephonyRegistryManager.java @@ -840,9 +840,23 @@ public class TelephonyRegistryManager { } } + /** + * Notify that the link capacity estimate has changed. + * @param slotIndex for the phone object that gets the updated link capacity estimate + * @param subId for subscription that gets the updated link capacity estimate + * @param linkCapacityEstimateList a list of {@link LinkCapacityEstimate} + */ + public void notifyLinkCapacityEstimateChanged(int slotIndex, int subId, + List<LinkCapacityEstimate> linkCapacityEstimateList) { + try { + sRegistry.notifyLinkCapacityEstimateChanged(slotIndex, subId, linkCapacityEstimateList); + } catch (RemoteException ex) { + // system server crash + } + } + public @NonNull Set<Integer> getEventsFromCallback( @NonNull TelephonyCallback telephonyCallback) { - Set<Integer> eventList = new ArraySet<>(); if (telephonyCallback instanceof TelephonyCallback.ServiceStateListener) { @@ -973,6 +987,10 @@ public class TelephonyRegistryManager { eventList.add(TelephonyCallback.EVENT_ALLOWED_NETWORK_TYPE_LIST_CHANGED); } + if (telephonyCallback instanceof TelephonyCallback.LinkCapacityEstimateChangedListener) { + eventList.add(TelephonyCallback.EVENT_LINK_CAPACITY_ESTIMATE_CHANGED); + } + return eventList; } diff --git a/core/java/android/widget/OWNERS b/core/java/android/widget/OWNERS index 718076b49f77..64570a8ad155 100644 --- a/core/java/android/widget/OWNERS +++ b/core/java/android/widget/OWNERS @@ -5,6 +5,8 @@ alanv@google.com adamp@google.com aurimas@google.com siyamed@google.com +mount@google.com +njawad@google.com per-file TextView.java, EditText.java, Editor.java = siyamed@google.com, nona@google.com, clarabayarri@google.com diff --git a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl index ee94ef8ddda3..3e7e5a52605b 100644 --- a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl +++ b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl @@ -21,6 +21,7 @@ import android.telephony.CallAttributes; import android.telephony.CellIdentity; import android.telephony.CellInfo; import android.telephony.DataConnectionRealTimeInfo; +import android.telephony.LinkCapacityEstimate; import android.telephony.TelephonyDisplayInfo; import android.telephony.PhoneCapability; import android.telephony.PhysicalChannelConfig; @@ -72,4 +73,5 @@ oneway interface IPhoneStateListener { void onPhysicalChannelConfigChanged(in List<PhysicalChannelConfig> configs); void onDataEnabledChanged(boolean enabled, int reason); void onAllowedNetworkTypesChanged(in Map allowedNetworkTypeList); + void onLinkCapacityEstimateChanged(in List<LinkCapacityEstimate> linkCapacityEstimateList); } diff --git a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl index 8d691586dfb1..23dbf9a88eb7 100644 --- a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl +++ b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl @@ -23,6 +23,7 @@ import android.telephony.BarringInfo; import android.telephony.CallQuality; import android.telephony.CellIdentity; import android.telephony.CellInfo; +import android.telephony.LinkCapacityEstimate; import android.telephony.TelephonyDisplayInfo; import android.telephony.ims.ImsReasonInfo; import android.telephony.PhoneCapability; @@ -94,5 +95,8 @@ interface ITelephonyRegistry { void notifyPhysicalChannelConfigForSubscriber(in int subId, in List<PhysicalChannelConfig> configs); void notifyDataEnabled(in int phoneId, int subId, boolean enabled, int reason); - void notifyAllowedNetworkTypesChanged(in int phoneId, in int subId, in Map allowedNetworkTypeList); + void notifyAllowedNetworkTypesChanged(in int phoneId, in int subId, + in Map allowedNetworkTypeList); + void notifyLinkCapacityEstimateChanged(in int phoneId, in int subId, + in List<LinkCapacityEstimate> linkCapacityEstimateList); } diff --git a/core/java/com/android/internal/util/LocationPermissionChecker.java b/core/java/com/android/internal/util/LocationPermissionChecker.java deleted file mode 100644 index d67bd7a853c8..000000000000 --- a/core/java/com/android/internal/util/LocationPermissionChecker.java +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.internal.util; - -import android.Manifest; -import android.annotation.IntDef; -import android.annotation.Nullable; -import android.app.ActivityManager; -import android.app.AppOpsManager; -import android.content.Context; -import android.content.pm.PackageManager; -import android.location.LocationManager; -import android.net.NetworkStack; -import android.os.Binder; -import android.os.Build; -import android.os.UserHandle; -import android.util.Log; - -import com.android.internal.annotations.VisibleForTesting; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - - -/** - * The methods used for location permission and location mode checking. - * - * @hide - */ -public class LocationPermissionChecker { - - private static final String TAG = "LocationPermissionChecker"; - - @Retention(RetentionPolicy.SOURCE) - @IntDef(prefix = {"LOCATION_PERMISSION_CHECK_STATUS_"}, value = { - SUCCEEDED, - ERROR_LOCATION_MODE_OFF, - ERROR_LOCATION_PERMISSION_MISSING, - }) - public @interface LocationPermissionCheckStatus{} - - // The location permission check succeeded. - public static final int SUCCEEDED = 0; - // The location mode turns off for the caller. - public static final int ERROR_LOCATION_MODE_OFF = 1; - // The location permission isn't granted for the caller. - public static final int ERROR_LOCATION_PERMISSION_MISSING = 2; - - private final Context mContext; - private final AppOpsManager mAppOpsManager; - - public LocationPermissionChecker(Context context) { - mContext = context; - mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); - } - - /** - * Check location permission granted by the caller. - * - * This API check if the location mode enabled for the caller and the caller has - * ACCESS_COARSE_LOCATION permission is targetSDK<29, otherwise, has ACCESS_FINE_LOCATION. - * - * @param pkgName package name of the application requesting access - * @param featureId The feature in the package - * @param uid The uid of the package - * @param message A message describing why the permission was checked. Only needed if this is - * not inside of a two-way binder call from the data receiver - * - * @return {@code true} returns if the caller has location permission and the location mode is - * enabled. - */ - public boolean checkLocationPermission(String pkgName, @Nullable String featureId, - int uid, @Nullable String message) { - return checkLocationPermissionInternal(pkgName, featureId, uid, message) == SUCCEEDED; - } - - /** - * Check location permission granted by the caller. - * - * This API check if the location mode enabled for the caller and the caller has - * ACCESS_COARSE_LOCATION permission is targetSDK<29, otherwise, has ACCESS_FINE_LOCATION. - * Compared with {@link #checkLocationPermission(String, String, int, String)}, this API returns - * the detail information about the checking result, including the reason why it's failed and - * logs the error for the caller. - * - * @param pkgName package name of the application requesting access - * @param featureId The feature in the package - * @param uid The uid of the package - * @param message A message describing why the permission was checked. Only needed if this is - * not inside of a two-way binder call from the data receiver - * - * @return {@link LocationPermissionCheckStatus} the result of the location permission check. - */ - public @LocationPermissionCheckStatus int checkLocationPermissionWithDetailInfo( - String pkgName, @Nullable String featureId, int uid, @Nullable String message) { - final int result = checkLocationPermissionInternal(pkgName, featureId, uid, message); - switch (result) { - case ERROR_LOCATION_MODE_OFF: - Log.e(TAG, "Location mode is disabled for the device"); - break; - case ERROR_LOCATION_PERMISSION_MISSING: - Log.e(TAG, "UID " + uid + " has no location permission"); - break; - } - return result; - } - - /** - * Enforce the caller has location permission. - * - * This API determines if the location mode enabled for the caller and the caller has - * ACCESS_COARSE_LOCATION permission is targetSDK<29, otherwise, has ACCESS_FINE_LOCATION. - * SecurityException is thrown if the caller has no permission or the location mode is disabled. - * - * @param pkgName package name of the application requesting access - * @param featureId The feature in the package - * @param uid The uid of the package - * @param message A message describing why the permission was checked. Only needed if this is - * not inside of a two-way binder call from the data receiver - */ - public void enforceLocationPermission(String pkgName, @Nullable String featureId, int uid, - @Nullable String message) throws SecurityException { - final int result = checkLocationPermissionInternal(pkgName, featureId, uid, message); - - switch (result) { - case ERROR_LOCATION_MODE_OFF: - throw new SecurityException("Location mode is disabled for the device"); - case ERROR_LOCATION_PERMISSION_MISSING: - throw new SecurityException("UID " + uid + " has no location permission"); - } - } - - private int checkLocationPermissionInternal(String pkgName, @Nullable String featureId, - int uid, @Nullable String message) { - checkPackage(uid, pkgName); - - // Apps with NETWORK_SETTINGS, NETWORK_SETUP_WIZARD, NETWORK_STACK & MAINLINE_NETWORK_STACK - // are granted a bypass. - if (checkNetworkSettingsPermission(uid) || checkNetworkSetupWizardPermission(uid) - || checkNetworkStackPermission(uid) || checkMainlineNetworkStackPermission(uid)) { - return SUCCEEDED; - } - - // Location mode must be enabled - if (!isLocationModeEnabled()) { - return ERROR_LOCATION_MODE_OFF; - } - - // LocationAccess by App: caller must have Coarse/Fine Location permission to have access to - // location information. - if (!checkCallersLocationPermission(pkgName, featureId, uid, - true /* coarseForTargetSdkLessThanQ */, message)) { - return ERROR_LOCATION_PERMISSION_MISSING; - } - return SUCCEEDED; - } - - /** - * Checks that calling process has android.Manifest.permission.ACCESS_FINE_LOCATION or - * android.Manifest.permission.ACCESS_COARSE_LOCATION (depending on config/targetSDK level) - * and a corresponding app op is allowed for this package and uid. - * - * @param pkgName PackageName of the application requesting access - * @param featureId The feature in the package - * @param uid The uid of the package - * @param coarseForTargetSdkLessThanQ If true and the targetSDK < Q then will check for COARSE - * else (false or targetSDK >= Q) then will check for FINE - * @param message A message describing why the permission was checked. Only needed if this is - * not inside of a two-way binder call from the data receiver - */ - public boolean checkCallersLocationPermission(String pkgName, @Nullable String featureId, - int uid, boolean coarseForTargetSdkLessThanQ, @Nullable String message) { - - boolean isTargetSdkLessThanQ = isTargetSdkLessThan(pkgName, Build.VERSION_CODES.Q, uid); - - String permissionType = Manifest.permission.ACCESS_FINE_LOCATION; - if (coarseForTargetSdkLessThanQ && isTargetSdkLessThanQ) { - // Having FINE permission implies having COARSE permission (but not the reverse) - permissionType = Manifest.permission.ACCESS_COARSE_LOCATION; - } - if (getUidPermission(permissionType, uid) == PackageManager.PERMISSION_DENIED) { - return false; - } - - // Always checking FINE - even if will not enforce. This will record the request for FINE - // so that a location request by the app is surfaced to the user. - boolean isFineLocationAllowed = noteAppOpAllowed( - AppOpsManager.OPSTR_FINE_LOCATION, pkgName, featureId, uid, message); - if (isFineLocationAllowed) { - return true; - } - if (coarseForTargetSdkLessThanQ && isTargetSdkLessThanQ) { - return noteAppOpAllowed(AppOpsManager.OPSTR_COARSE_LOCATION, pkgName, featureId, uid, - message); - } - return false; - } - - /** - * Retrieves a handle to LocationManager (if not already done) and check if location is enabled. - */ - public boolean isLocationModeEnabled() { - final LocationManager LocationManager = - (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE); - try { - return LocationManager.isLocationEnabledForUser(UserHandle.of( - getCurrentUser())); - } catch (Exception e) { - Log.e(TAG, "Failure to get location mode via API, falling back to settings", e); - return false; - } - } - - private boolean isTargetSdkLessThan(String packageName, int versionCode, int callingUid) { - final long ident = Binder.clearCallingIdentity(); - try { - if (mContext.getPackageManager().getApplicationInfoAsUser( - packageName, 0, - UserHandle.getUserHandleForUid(callingUid)).targetSdkVersion - < versionCode) { - return true; - } - } catch (PackageManager.NameNotFoundException e) { - // In case of exception, assume unknown app (more strict checking) - // Note: This case will never happen since checkPackage is - // called to verify validity before checking App's version. - } finally { - Binder.restoreCallingIdentity(ident); - } - return false; - } - - private boolean noteAppOpAllowed(String op, String pkgName, @Nullable String featureId, - int uid, @Nullable String message) { - return mAppOpsManager.noteOp(op, uid, pkgName, featureId, message) - == AppOpsManager.MODE_ALLOWED; - } - - private void checkPackage(int uid, String pkgName) - throws SecurityException { - if (pkgName == null) { - throw new SecurityException("Checking UID " + uid + " but Package Name is Null"); - } - mAppOpsManager.checkPackage(uid, pkgName); - } - - @VisibleForTesting - protected int getCurrentUser() { - return ActivityManager.getCurrentUser(); - } - - private int getUidPermission(String permissionType, int uid) { - // We don't care about pid, pass in -1 - return mContext.checkPermission(permissionType, -1, uid); - } - - /** - * Returns true if the |uid| holds NETWORK_SETTINGS permission. - */ - public boolean checkNetworkSettingsPermission(int uid) { - return getUidPermission(android.Manifest.permission.NETWORK_SETTINGS, uid) - == PackageManager.PERMISSION_GRANTED; - } - - /** - * Returns true if the |uid| holds NETWORK_SETUP_WIZARD permission. - */ - public boolean checkNetworkSetupWizardPermission(int uid) { - return getUidPermission(android.Manifest.permission.NETWORK_SETUP_WIZARD, uid) - == PackageManager.PERMISSION_GRANTED; - } - - /** - * Returns true if the |uid| holds NETWORK_STACK permission. - */ - public boolean checkNetworkStackPermission(int uid) { - return getUidPermission(android.Manifest.permission.NETWORK_STACK, uid) - == PackageManager.PERMISSION_GRANTED; - } - - /** - * Returns true if the |uid| holds MAINLINE_NETWORK_STACK permission. - */ - public boolean checkMainlineNetworkStackPermission(int uid) { - return getUidPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, uid) - == PackageManager.PERMISSION_GRANTED; - } - -} diff --git a/core/java/com/android/internal/util/Protocol.java b/core/java/com/android/internal/util/Protocol.java index 276cad9f6d6d..bbd738bc9eb6 100644 --- a/core/java/com/android/internal/util/Protocol.java +++ b/core/java/com/android/internal/util/Protocol.java @@ -59,8 +59,6 @@ public class Protocol { public static final int BASE_TETHERING = 0x00050000; public static final int BASE_NSD_MANAGER = 0x00060000; public static final int BASE_NETWORK_STATE_TRACKER = 0x00070000; - public static final int BASE_CONNECTIVITY_MANAGER = 0x00080000; - public static final int BASE_NETWORK_AGENT = 0x00081000; public static final int BASE_NETWORK_FACTORY = 0x00083000; public static final int BASE_ETHERNET = 0x00084000; public static final int BASE_LOWPAN = 0x00085000; diff --git a/core/tests/utiltests/src/com/android/internal/util/LocationPermissionCheckerTest.java b/core/tests/utiltests/src/com/android/internal/util/LocationPermissionCheckerTest.java deleted file mode 100644 index 7175f562d7ef..000000000000 --- a/core/tests/utiltests/src/com/android/internal/util/LocationPermissionCheckerTest.java +++ /dev/null @@ -1,296 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.internal.util; - -import static android.Manifest.permission.NETWORK_SETTINGS; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.ArgumentMatchers.nullable; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.Manifest; -import android.app.ActivityManager; -import android.app.AppOpsManager; -import android.content.Context; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; -import android.location.LocationManager; -import android.os.Binder; -import android.os.Build; -import android.os.UserHandle; -import android.os.UserManager; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; - -import java.util.HashMap; - -/** Unit tests for {@link LocationPermissionChecker}. */ -public class LocationPermissionCheckerTest { - - public static final String TAG = "ConnectivityUtilTest"; - - // Mock objects for testing - @Mock private Context mMockContext; - @Mock private PackageManager mMockPkgMgr; - @Mock private ApplicationInfo mMockApplInfo; - @Mock private AppOpsManager mMockAppOps; - @Mock private UserManager mMockUserManager; - @Mock private LocationManager mLocationManager; - - private static final String TEST_PKG_NAME = "com.google.somePackage"; - private static final String TEST_FEATURE_ID = "com.google.someFeature"; - private static final int MANAGED_PROFILE_UID = 1100000; - private static final int OTHER_USER_UID = 1200000; - - private final String mInteractAcrossUsersFullPermission = - "android.permission.INTERACT_ACROSS_USERS_FULL"; - private final String mManifestStringCoarse = - Manifest.permission.ACCESS_COARSE_LOCATION; - private final String mManifestStringFine = - Manifest.permission.ACCESS_FINE_LOCATION; - - // Test variables - private int mWifiScanAllowApps; - private int mUid; - private int mCoarseLocationPermission; - private int mAllowCoarseLocationApps; - private int mFineLocationPermission; - private int mAllowFineLocationApps; - private int mNetworkSettingsPermission; - private int mCurrentUser; - private boolean mIsLocationEnabled; - private boolean mThrowSecurityException; - private Answer<Integer> mReturnPermission; - private HashMap<String, Integer> mPermissionsList = new HashMap<String, Integer>(); - private LocationPermissionChecker mChecker; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - initTestVars(); - } - - private void setupMocks() throws Exception { - when(mMockPkgMgr.getApplicationInfoAsUser(eq(TEST_PKG_NAME), eq(0), any())) - .thenReturn(mMockApplInfo); - when(mMockContext.getPackageManager()).thenReturn(mMockPkgMgr); - when(mMockAppOps.noteOp(AppOpsManager.OPSTR_WIFI_SCAN, mUid, TEST_PKG_NAME, - TEST_FEATURE_ID, null)).thenReturn(mWifiScanAllowApps); - when(mMockAppOps.noteOp(eq(AppOpsManager.OPSTR_COARSE_LOCATION), eq(mUid), - eq(TEST_PKG_NAME), eq(TEST_FEATURE_ID), nullable(String.class))) - .thenReturn(mAllowCoarseLocationApps); - when(mMockAppOps.noteOp(eq(AppOpsManager.OPSTR_FINE_LOCATION), eq(mUid), - eq(TEST_PKG_NAME), eq(TEST_FEATURE_ID), nullable(String.class))) - .thenReturn(mAllowFineLocationApps); - if (mThrowSecurityException) { - doThrow(new SecurityException("Package " + TEST_PKG_NAME + " doesn't belong" - + " to application bound to user " + mUid)) - .when(mMockAppOps).checkPackage(mUid, TEST_PKG_NAME); - } - when(mMockContext.getSystemService(Context.APP_OPS_SERVICE)) - .thenReturn(mMockAppOps); - when(mMockContext.getSystemService(Context.USER_SERVICE)) - .thenReturn(mMockUserManager); - when(mMockContext.getSystemService(Context.LOCATION_SERVICE)).thenReturn(mLocationManager); - } - - private void setupTestCase() throws Exception { - setupMocks(); - setupMockInterface(); - mChecker = new LocationPermissionChecker(mMockContext); - } - - private void initTestVars() { - mPermissionsList.clear(); - mReturnPermission = createPermissionAnswer(); - mWifiScanAllowApps = AppOpsManager.MODE_ERRORED; - mUid = OTHER_USER_UID; - mThrowSecurityException = true; - mMockApplInfo.targetSdkVersion = Build.VERSION_CODES.M; - mIsLocationEnabled = false; - mCurrentUser = ActivityManager.getCurrentUser(); - mCoarseLocationPermission = PackageManager.PERMISSION_DENIED; - mFineLocationPermission = PackageManager.PERMISSION_DENIED; - mAllowCoarseLocationApps = AppOpsManager.MODE_ERRORED; - mAllowFineLocationApps = AppOpsManager.MODE_ERRORED; - mNetworkSettingsPermission = PackageManager.PERMISSION_DENIED; - } - - private void setupMockInterface() { - Binder.restoreCallingIdentity((((long) mUid) << 32) | Binder.getCallingPid()); - doAnswer(mReturnPermission).when(mMockContext).checkPermission( - anyString(), anyInt(), anyInt()); - when(mMockUserManager.isSameProfileGroup(UserHandle.SYSTEM, - UserHandle.getUserHandleForUid(MANAGED_PROFILE_UID))) - .thenReturn(true); - when(mMockContext.checkPermission(mManifestStringCoarse, -1, mUid)) - .thenReturn(mCoarseLocationPermission); - when(mMockContext.checkPermission(mManifestStringFine, -1, mUid)) - .thenReturn(mFineLocationPermission); - when(mMockContext.checkPermission(NETWORK_SETTINGS, -1, mUid)) - .thenReturn(mNetworkSettingsPermission); - when(mLocationManager.isLocationEnabledForUser(any())).thenReturn(mIsLocationEnabled); - } - - private Answer<Integer> createPermissionAnswer() { - return new Answer<Integer>() { - @Override - public Integer answer(InvocationOnMock invocation) { - int myUid = (int) invocation.getArguments()[1]; - String myPermission = (String) invocation.getArguments()[0]; - mPermissionsList.get(myPermission); - if (mPermissionsList.containsKey(myPermission)) { - int uid = mPermissionsList.get(myPermission); - if (myUid == uid) { - return PackageManager.PERMISSION_GRANTED; - } - } - return PackageManager.PERMISSION_DENIED; - } - }; - } - - @Test - public void testEnforceLocationPermission_HasAllPermissions_BeforeQ() throws Exception { - mIsLocationEnabled = true; - mThrowSecurityException = false; - mCoarseLocationPermission = PackageManager.PERMISSION_GRANTED; - mAllowCoarseLocationApps = AppOpsManager.MODE_ALLOWED; - mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; - mUid = mCurrentUser; - setupTestCase(); - - final int result = - mChecker.checkLocationPermissionWithDetailInfo( - TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null); - assertEquals(LocationPermissionChecker.SUCCEEDED, result); - } - - @Test - public void testEnforceLocationPermission_HasAllPermissions_AfterQ() throws Exception { - mMockApplInfo.targetSdkVersion = Build.VERSION_CODES.Q; - mIsLocationEnabled = true; - mThrowSecurityException = false; - mUid = mCurrentUser; - mFineLocationPermission = PackageManager.PERMISSION_GRANTED; - mAllowFineLocationApps = AppOpsManager.MODE_ALLOWED; - mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; - setupTestCase(); - - final int result = - mChecker.checkLocationPermissionWithDetailInfo( - TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null); - assertEquals(LocationPermissionChecker.SUCCEEDED, result); - } - - @Test - public void testEnforceLocationPermission_PkgNameAndUidMismatch() throws Exception { - mThrowSecurityException = true; - mIsLocationEnabled = true; - mFineLocationPermission = PackageManager.PERMISSION_GRANTED; - mAllowFineLocationApps = AppOpsManager.MODE_ALLOWED; - mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; - setupTestCase(); - - assertThrows(SecurityException.class, - () -> mChecker.checkLocationPermissionWithDetailInfo( - TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null)); - } - - @Test - public void testenforceCanAccessScanResults_NoCoarseLocationPermission() throws Exception { - mThrowSecurityException = false; - mIsLocationEnabled = true; - setupTestCase(); - - final int result = - mChecker.checkLocationPermissionWithDetailInfo( - TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null); - assertEquals(LocationPermissionChecker.ERROR_LOCATION_PERMISSION_MISSING, result); - } - - @Test - public void testenforceCanAccessScanResults_NoFineLocationPermission() throws Exception { - mThrowSecurityException = false; - mMockApplInfo.targetSdkVersion = Build.VERSION_CODES.Q; - mIsLocationEnabled = true; - mCoarseLocationPermission = PackageManager.PERMISSION_GRANTED; - mAllowFineLocationApps = AppOpsManager.MODE_ERRORED; - mUid = MANAGED_PROFILE_UID; - setupTestCase(); - - final int result = - mChecker.checkLocationPermissionWithDetailInfo( - TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null); - assertEquals(LocationPermissionChecker.ERROR_LOCATION_PERMISSION_MISSING, result); - verify(mMockAppOps, never()).noteOp(anyInt(), anyInt(), anyString()); - } - - @Test - public void testenforceCanAccessScanResults_LocationModeDisabled() throws Exception { - mThrowSecurityException = false; - mUid = MANAGED_PROFILE_UID; - mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; - mPermissionsList.put(mInteractAcrossUsersFullPermission, mUid); - mIsLocationEnabled = false; - - setupTestCase(); - - final int result = - mChecker.checkLocationPermissionWithDetailInfo( - TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null); - assertEquals(LocationPermissionChecker.ERROR_LOCATION_MODE_OFF, result); - } - - @Test - public void testenforceCanAccessScanResults_LocationModeDisabledHasNetworkSettings() - throws Exception { - mThrowSecurityException = false; - mIsLocationEnabled = false; - mNetworkSettingsPermission = PackageManager.PERMISSION_GRANTED; - setupTestCase(); - - final int result = - mChecker.checkLocationPermissionWithDetailInfo( - TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null); - assertEquals(LocationPermissionChecker.SUCCEEDED, result); - } - - - private static void assertThrows(Class<? extends Exception> exceptionClass, Runnable r) { - try { - r.run(); - Assert.fail("Expected " + exceptionClass + " to be thrown."); - } catch (Exception exception) { - assertTrue(exceptionClass.isInstance(exception)); - } - } -} diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java index 937f01ce3767..a08f390c9fd3 100644 --- a/keystore/java/android/security/KeyStore.java +++ b/keystore/java/android/security/KeyStore.java @@ -207,7 +207,7 @@ public class KeyStore { case UserState.LSKF_LOCKED: return KeyStore.State.LOCKED; default: - throw new AssertionError(KeyStore.VALUE_CORRUPTED); + throw new AssertionError(userState); } } ret = mBinder.getState(userId); diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java b/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java index 2ee952cbc5fb..d9d5300e43f9 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java @@ -123,8 +123,9 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor throws InvalidKeyException { resetAll(); - if (!(key instanceof AndroidKeyStorePrivateKey - || key instanceof AndroidKeyStoreSecretKey)) { + // Public key operations get diverted to the default provider. + if (opmode == Cipher.ENCRYPT_MODE + && (key instanceof PrivateKey || key instanceof PublicKey)) { try { mCipher = Cipher.getInstance(getTransform()); String transform = getTransform(); @@ -184,8 +185,9 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException { resetAll(); - if (!(key instanceof AndroidKeyStorePrivateKey - || key instanceof AndroidKeyStoreSecretKey)) { + // Public key operations get diverted to the default provider. + if (opmode == Cipher.ENCRYPT_MODE + && (key instanceof PrivateKey || key instanceof PublicKey)) { try { mCipher = Cipher.getInstance(getTransform()); mCipher.init(opmode, key, params, random); @@ -213,8 +215,9 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException { resetAll(); - if (!(key instanceof AndroidKeyStorePrivateKey - || key instanceof AndroidKeyStoreSecretKey)) { + // Public key operations get diverted to the default provider. + if (opmode == Cipher.ENCRYPT_MODE + && (key instanceof PrivateKey || key instanceof PublicKey)) { try { mCipher = Cipher.getInstance(getTransform()); mCipher.init(opmode, key, params, random); diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java b/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java index fa852e33a1d8..ba6d22f681ce 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java @@ -145,23 +145,15 @@ public class AndroidKeyStoreProvider extends Provider { sInstalled = true; Security.addProvider(new AndroidKeyStoreProvider()); - Security.addProvider( - new android.security.keystore.AndroidKeyStoreProvider( - "AndroidKeyStoreLegacy")); Provider workaroundProvider = new AndroidKeyStoreBCWorkaroundProvider(); - Provider legacyWorkaroundProvider = - new android.security.keystore.AndroidKeyStoreBCWorkaroundProvider( - "AndroidKeyStoreBCWorkaroundLegacy"); if (bcProviderIndex != -1) { // Bouncy Castle provider found -- install the workaround provider above it. // insertProviderAt uses 1-based positions. - Security.insertProviderAt(legacyWorkaroundProvider, bcProviderIndex + 1); Security.insertProviderAt(workaroundProvider, bcProviderIndex + 1); } else { // Bouncy Castle provider not found -- install the workaround provider at lowest // priority. Security.addProvider(workaroundProvider); - Security.addProvider(legacyWorkaroundProvider); } } diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp index 446e81e65bb8..c6ab1194cf66 100644 --- a/libs/hwui/Properties.cpp +++ b/libs/hwui/Properties.cpp @@ -124,7 +124,7 @@ bool Properties::load() { SkAndroidFrameworkTraceUtil::setEnableTracing( base::GetBoolProperty(PROPERTY_SKIA_ATRACE_ENABLED, false)); - runningInEmulator = base::GetBoolProperty(PROPERTY_QEMU_KERNEL, false); + runningInEmulator = base::GetBoolProperty(PROPERTY_IS_EMULATOR, false); defaultRenderAhead = std::max(-1, std::min(2, base::GetIntProperty(PROPERTY_RENDERAHEAD, render_ahead().value_or(0)))); diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h index d3ecb54d94f6..6ea208e933f2 100644 --- a/libs/hwui/Properties.h +++ b/libs/hwui/Properties.h @@ -160,7 +160,7 @@ enum DebugLevel { /** * Property for whether this is running in the emulator. */ -#define PROPERTY_QEMU_KERNEL "ro.kernel.qemu" +#define PROPERTY_IS_EMULATOR "ro.boot.qemu" #define PROPERTY_RENDERAHEAD "debug.hwui.render_ahead" diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp index 694b93919cde..3976086ea495 100644 --- a/media/jni/android_media_tv_Tuner.cpp +++ b/media/jni/android_media_tv_Tuner.cpp @@ -287,7 +287,10 @@ Dvr::~Dvr() { jint Dvr::close() { Result r = mDvrSp->close(); if (r == Result::SUCCESS) { - EventFlag::deleteEventFlag(&mDvrMQEventFlag); + if (mDvrMQEventFlag != nullptr) { + EventFlag::deleteEventFlag(&mDvrMQEventFlag); + } + mDvrMQ = nullptr; } return (jint) r; } @@ -723,13 +726,15 @@ Filter::~Filter() { env->DeleteWeakGlobalRef(mFilterObj); mFilterObj = NULL; - EventFlag::deleteEventFlag(&mFilterMQEventFlag); } int Filter::close() { Result r = mFilterSp->close(); if (r == Result::SUCCESS) { - EventFlag::deleteEventFlag(&mFilterMQEventFlag); + if (mFilterMQEventFlag != nullptr) { + EventFlag::deleteEventFlag(&mFilterMQEventFlag); + } + mFilterMQ = nullptr; } return (int)r; } @@ -3050,6 +3055,9 @@ static jint android_media_tv_Tuner_configure_filter( filterSp->mFilterMQ = std::make_unique<MQ>(filterMQDesc, true); EventFlag::createEventFlag( filterSp->mFilterMQ->getEventFlagWord(), &(filterSp->mFilterMQEventFlag)); + } else { + filterSp->mFilterMQ = nullptr; + filterSp->mFilterMQEventFlag = nullptr; } } return (jint) getQueueDescResult; @@ -3137,13 +3145,12 @@ static jint android_media_tv_Tuner_read_filter_fmq( } static jint android_media_tv_Tuner_close_filter(JNIEnv *env, jobject filter) { - sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter(); - if (iFilterSp == NULL) { + sp<Filter> filterSp = getFilter(env, filter); + if (filterSp == NULL) { ALOGD("Failed to close filter: filter not found"); return (jint) Result::NOT_INITIALIZED; } - Result r = iFilterSp->close(); - return (jint) r; + return filterSp->close(); } static sp<TimeFilter> getTimeFilter(JNIEnv *env, jobject filter) { diff --git a/media/jni/soundpool/StreamManager.cpp b/media/jni/soundpool/StreamManager.cpp index 8b84bf3eb8d8..309d71cfd062 100644 --- a/media/jni/soundpool/StreamManager.cpp +++ b/media/jni/soundpool/StreamManager.cpp @@ -43,6 +43,14 @@ static constexpr bool kPlayOnCallingThread = true; // Amount of time for a StreamManager thread to wait before closing. static constexpr int64_t kWaitTimeBeforeCloseNs = 9 * NANOS_PER_SECOND; +// Debug flag: +// kForceLockStreamManagerStop is set to true to force lock the StreamManager +// worker thread during stop. This limits concurrency of Stream processing. +// Normally we lock the StreamManager worker thread during stop ONLY +// for SoundPools configured with a single Stream. +// +static constexpr bool kForceLockStreamManagerStop = false; + //////////// StreamMap::StreamMap(int32_t streams) { @@ -103,6 +111,7 @@ StreamManager::StreamManager( : StreamMap(streams) , mAttributes(*attributes) , mOpPackageName(std::move(opPackageName)) + , mLockStreamManagerStop(streams == 1 || kForceLockStreamManagerStop) { ALOGV("%s(%d, %zu, ...)", __func__, streams, threads); forEach([this](Stream *stream) { @@ -113,7 +122,8 @@ StreamManager::StreamManager( }); mThreadPool = std::make_unique<ThreadPool>( - std::min(threads, (size_t)std::thread::hardware_concurrency()), + std::min((size_t)streams, // do not make more threads than streams to play + std::min(threads, (size_t)std::thread::hardware_concurrency())), "SoundPool_"); } @@ -348,14 +358,14 @@ void StreamManager::addToActiveQueue_l(Stream *stream) { void StreamManager::run(int32_t id) { ALOGV("%s(%d) entering", __func__, id); - int64_t waitTimeNs = kWaitTimeBeforeCloseNs; + int64_t waitTimeNs = 0; // on thread start, mRestartStreams can be non-empty. std::unique_lock lock(mStreamManagerLock); while (!mQuit) { - if (mRestartStreams.empty()) { // on thread start, mRestartStreams can be non-empty. + if (waitTimeNs > 0) { mStreamManagerCondition.wait_for( lock, std::chrono::duration<int64_t, std::nano>(waitTimeNs)); } - ALOGV("%s(%d) awake", __func__, id); + ALOGV("%s(%d) awake lock waitTimeNs:%lld", __func__, id, (long long)waitTimeNs); sanityCheckQueue_l(); @@ -375,12 +385,12 @@ void StreamManager::run(int32_t id) } mRestartStreams.erase(it); mProcessingStreams.emplace(stream); - lock.unlock(); + if (!mLockStreamManagerStop) lock.unlock(); stream->stop(); ALOGV("%s(%d) stopping streamID:%d", __func__, id, stream->getStreamID()); if (Stream* nextStream = stream->playPairStream()) { ALOGV("%s(%d) starting streamID:%d", __func__, id, nextStream->getStreamID()); - lock.lock(); + if (!mLockStreamManagerStop) lock.lock(); if (nextStream->getStopTimeNs() > 0) { // the next stream was stopped before we can move it to the active queue. ALOGV("%s(%d) stopping started streamID:%d", @@ -390,7 +400,7 @@ void StreamManager::run(int32_t id) addToActiveQueue_l(nextStream); } } else { - lock.lock(); + if (!mLockStreamManagerStop) lock.lock(); mAvailableStreams.insert(stream); } mProcessingStreams.erase(stream); diff --git a/media/jni/soundpool/StreamManager.h b/media/jni/soundpool/StreamManager.h index 81ac69eb4358..85b468cd2cbc 100644 --- a/media/jni/soundpool/StreamManager.h +++ b/media/jni/soundpool/StreamManager.h @@ -437,6 +437,14 @@ private: void sanityCheckQueue_l() const REQUIRES(mStreamManagerLock); const audio_attributes_t mAttributes; + const std::string mOpPackageName; + + // For legacy compatibility, we lock the stream manager on stop when + // there is only one stream. This allows a play to be called immediately + // after stopping, otherwise it is possible that the play might be discarded + // (returns 0) because that stream may be in the worker thread call to stop. + const bool mLockStreamManagerStop; + std::unique_ptr<ThreadPool> mThreadPool; // locked internally // mStreamManagerLock is used to lock access for transitions between the @@ -477,8 +485,6 @@ private: // The paired stream may be active or restarting. // No particular order. std::unordered_set<Stream*> mProcessingStreams GUARDED_BY(mStreamManagerLock); - - const std::string mOpPackageName; }; } // namespace android::soundpool diff --git a/packages/Connectivity/framework/Android.bp b/packages/Connectivity/framework/Android.bp index 9da27d271169..86433e1c38f8 100644 --- a/packages/Connectivity/framework/Android.bp +++ b/packages/Connectivity/framework/Android.bp @@ -23,7 +23,6 @@ package { default_applicable_licenses: ["frameworks_base_license"], } -// TODO: use a java_library in the bootclasspath instead filegroup { name: "framework-connectivity-internal-sources", srcs: [ @@ -84,3 +83,38 @@ java_sdk_library { ], permitted_packages: ["android.net", "com.android.connectivity.aidl"], } + +java_library { + name: "framework-connectivity.impl", + // Instead of building against private API (framework.jar), + // build against core_platform + framework-minus-apex + module + // stub libs. This allows framework.jar to depend on this library, + // so it can be part of the private API until all clients have been migrated. + // TODO: just build against module_api, and remove this jar from + // the private API. + sdk_version: "core_platform", + srcs: [ + ":framework-connectivity-sources", + ], + aidl: { + include_dirs: [ + "frameworks/base/core/java", // For framework parcelables + "frameworks/native/aidl/binder", // For PersistableBundle.aidl + ], + }, + libs: [ + "framework-minus-apex", + // TODO: just framework-tethering, framework-wifi when building against module_api + "framework-tethering.stubs.module_lib", + "framework-wifi.stubs.module_lib", + "unsupportedappusage", + "ServiceConnectivityResources", + ], + static_libs: [ + "net-utils-device-common", + ], + jarjar_rules: "jarjar-rules.txt", + apex_available: ["com.android.tethering"], + installable: true, + permitted_packages: ["android.net", "com.android.connectivity.aidl"], +} diff --git a/core/java/android/net/NetworkScore.aidl b/packages/Connectivity/framework/aidl-export/android/net/NetworkScore.aidl index af12dcf7f17a..af12dcf7f17a 100644 --- a/core/java/android/net/NetworkScore.aidl +++ b/packages/Connectivity/framework/aidl-export/android/net/NetworkScore.aidl diff --git a/packages/Connectivity/framework/api/current.txt b/packages/Connectivity/framework/api/current.txt index 243e4ca4295a..f22d4b7b779a 100644 --- a/packages/Connectivity/framework/api/current.txt +++ b/packages/Connectivity/framework/api/current.txt @@ -87,6 +87,7 @@ package android.net { method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public boolean isActiveNetworkMetered(); method public boolean isDefaultNetworkActive(); method @Deprecated public static boolean isNetworkTypeValid(int); + method public void registerBestMatchingNetworkCallback(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler); method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback); method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler); method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerNetworkCallback(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback); diff --git a/packages/Connectivity/framework/api/module-lib-current.txt b/packages/Connectivity/framework/api/module-lib-current.txt index c3b1800af2aa..7a91f6454b90 100644 --- a/packages/Connectivity/framework/api/module-lib-current.txt +++ b/packages/Connectivity/framework/api/module-lib-current.txt @@ -6,15 +6,25 @@ package android.net { } public class ConnectivityManager { + method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void factoryReset(); method @NonNull @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public java.util.List<android.net.NetworkStateSnapshot> getAllNetworkStateSnapshot(); + method @Nullable public android.net.ProxyInfo getGlobalProxy(); method @NonNull public static android.util.Range<java.lang.Integer> getIpSecNetIdRange(); - method @NonNull public static String getPrivateDnsMode(@NonNull android.content.ContentResolver); + method @NonNull public static String getPrivateDnsMode(@NonNull android.content.Context); method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void registerSystemDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler); method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void requestBackgroundNetwork(@NonNull android.net.NetworkRequest, @NonNull android.os.Handler, @NonNull android.net.ConnectivityManager.NetworkCallback); + method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void setAcceptPartialConnectivity(@NonNull android.net.Network, boolean, boolean); + method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void setAcceptUnvalidated(@NonNull android.net.Network, boolean, boolean); + method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void setAvoidUnvalidated(@NonNull android.net.Network); + method @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public void setGlobalProxy(@Nullable android.net.ProxyInfo); + method @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public void setProfileNetworkPreference(@NonNull android.os.UserHandle, int, @Nullable java.util.concurrent.Executor, @Nullable Runnable); method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_TEST_NETWORKS, android.Manifest.permission.NETWORK_STACK}) public void simulateDataStall(int, long, @NonNull android.net.Network, @NonNull android.os.PersistableBundle); + method public void systemReady(); field public static final String PRIVATE_DNS_MODE_OFF = "off"; field public static final String PRIVATE_DNS_MODE_OPPORTUNISTIC = "opportunistic"; field public static final String PRIVATE_DNS_MODE_PROVIDER_HOSTNAME = "hostname"; + field public static final int PROFILE_NETWORK_PREFERENCE_DEFAULT = 0; // 0x0 + field public static final int PROFILE_NETWORK_PREFERENCE_ENTERPRISE = 1; // 0x1 } public final class NetworkAgentConfig implements android.os.Parcelable { diff --git a/packages/Connectivity/framework/api/system-current.txt b/packages/Connectivity/framework/api/system-current.txt index a98f14ea9408..031bb916c4f2 100644 --- a/packages/Connectivity/framework/api/system-current.txt +++ b/packages/Connectivity/framework/api/system-current.txt @@ -56,7 +56,7 @@ package android.net { method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void registerTetheringEventCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityManager.OnTetheringEventCallback); method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void requestNetwork(@NonNull android.net.NetworkRequest, int, int, @NonNull android.os.Handler, @NonNull android.net.ConnectivityManager.NetworkCallback); method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_AIRPLANE_MODE, android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK}) public void setAirplaneMode(boolean); - method @RequiresPermission(android.Manifest.permission.CONTROL_OEM_PAID_NETWORK_PREFERENCE) public void setOemNetworkPreference(@NonNull android.net.OemNetworkPreferences, @Nullable java.util.concurrent.Executor, @Nullable android.net.ConnectivityManager.OnSetOemNetworkPreferenceListener); + method @RequiresPermission(android.Manifest.permission.CONTROL_OEM_PAID_NETWORK_PREFERENCE) public void setOemNetworkPreference(@NonNull android.net.OemNetworkPreferences, @Nullable java.util.concurrent.Executor, @Nullable Runnable); method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public boolean shouldAvoidBadWifi(); method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void startCaptivePortalApp(@NonNull android.net.Network, @NonNull android.os.Bundle); method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback); @@ -78,10 +78,6 @@ package android.net { field @Deprecated public static final int TYPE_WIFI_P2P = 13; // 0xd } - public static interface ConnectivityManager.OnSetOemNetworkPreferenceListener { - method public void onComplete(); - } - @Deprecated public abstract static class ConnectivityManager.OnStartTetheringCallback { ctor @Deprecated public ConnectivityManager.OnStartTetheringCallback(); method @Deprecated public void onTetheringFailed(); diff --git a/packages/Connectivity/framework/jarjar-rules.txt b/packages/Connectivity/framework/jarjar-rules.txt new file mode 100644 index 000000000000..381a4ac87505 --- /dev/null +++ b/packages/Connectivity/framework/jarjar-rules.txt @@ -0,0 +1,7 @@ +rule com.android.net.module.util.** android.net.connectivity.framework.util.@1 + +# TODO (b/149403767): remove the annotations from net-utils-device-common instead of here +zap android.annotation.** +zap com.android.net.module.annotation.** +zap com.android.internal.annotations.** + diff --git a/packages/Connectivity/framework/src/android/net/ConnectivityManager.java b/packages/Connectivity/framework/src/android/net/ConnectivityManager.java index 8b669284adc1..f748159e893c 100644 --- a/packages/Connectivity/framework/src/android/net/ConnectivityManager.java +++ b/packages/Connectivity/framework/src/android/net/ConnectivityManager.java @@ -16,15 +16,15 @@ package android.net; import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; +import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_DEFAULT_MODE; +import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE; import static android.net.NetworkRequest.Type.BACKGROUND_REQUEST; import static android.net.NetworkRequest.Type.LISTEN; +import static android.net.NetworkRequest.Type.LISTEN_FOR_BEST; import static android.net.NetworkRequest.Type.REQUEST; -import static android.net.NetworkRequest.Type.TRACK_BEST; import static android.net.NetworkRequest.Type.TRACK_DEFAULT; import static android.net.NetworkRequest.Type.TRACK_SYSTEM_DEFAULT; import static android.net.QosCallback.QosCallbackRegistrationException; -import static android.provider.Settings.Global.PRIVATE_DNS_DEFAULT_MODE; -import static android.provider.Settings.Global.PRIVATE_DNS_MODE; import android.annotation.CallbackExecutor; import android.annotation.IntDef; @@ -64,6 +64,7 @@ import android.os.RemoteException; import android.os.ResultReceiver; import android.os.ServiceManager; import android.os.ServiceSpecificException; +import android.os.UserHandle; import android.provider.Settings; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; @@ -76,7 +77,6 @@ import android.util.SparseIntArray; import com.android.connectivity.aidl.INetworkAgent; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.Preconditions; -import com.android.internal.util.Protocol; import libcore.net.event.NetworkEventDispatcher; @@ -915,8 +915,8 @@ public class ConnectivityManager { /** * @hide - * TODO: Expose for SystemServer when becomes a module. */ + @SystemApi(client = MODULE_LIBRARIES) public void systemReady() { try { mService.systemReady(); @@ -971,6 +971,33 @@ public class ConnectivityManager { } /** + * Preference for {@link #setNetworkPreferenceForUser(UserHandle, int, Executor, Runnable)}. + * Specify that the traffic for this user should by follow the default rules. + * @hide + */ + @SystemApi(client = MODULE_LIBRARIES) + public static final int PROFILE_NETWORK_PREFERENCE_DEFAULT = 0; + + /** + * Preference for {@link #setNetworkPreferenceForUser(UserHandle, int, Executor, Runnable)}. + * Specify that the traffic for this user should by default go on a network with + * {@link NetworkCapabilities#NET_CAPABILITY_ENTERPRISE}, and on the system default network + * if no such network is available. + * @hide + */ + @SystemApi(client = MODULE_LIBRARIES) + public static final int PROFILE_NETWORK_PREFERENCE_ENTERPRISE = 1; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = { + PROFILE_NETWORK_PREFERENCE_DEFAULT, + PROFILE_NETWORK_PREFERENCE_ENTERPRISE + }) + public @interface ProfileNetworkPreference { + } + + /** * Specifies the preferred network type. When the device has more * than one type available the preferred network type will be used. * @@ -3011,8 +3038,9 @@ public class ConnectivityManager { * HTTP proxy. A {@code null} value will clear the global HTTP proxy. * @hide */ + @SystemApi(client = MODULE_LIBRARIES) @RequiresPermission(android.Manifest.permission.NETWORK_STACK) - public void setGlobalProxy(ProxyInfo p) { + public void setGlobalProxy(@Nullable ProxyInfo p) { try { mService.setGlobalProxy(p); } catch (RemoteException e) { @@ -3027,6 +3055,8 @@ public class ConnectivityManager { * if no global HTTP proxy is set. * @hide */ + @SystemApi(client = MODULE_LIBRARIES) + @Nullable public ProxyInfo getGlobalProxy() { try { return mService.getGlobalProxy(); @@ -3523,29 +3553,28 @@ public class ConnectivityManager { } } - private static final int BASE = Protocol.BASE_CONNECTIVITY_MANAGER; /** @hide */ - public static final int CALLBACK_PRECHECK = BASE + 1; + public static final int CALLBACK_PRECHECK = 1; /** @hide */ - public static final int CALLBACK_AVAILABLE = BASE + 2; + public static final int CALLBACK_AVAILABLE = 2; /** @hide arg1 = TTL */ - public static final int CALLBACK_LOSING = BASE + 3; + public static final int CALLBACK_LOSING = 3; /** @hide */ - public static final int CALLBACK_LOST = BASE + 4; + public static final int CALLBACK_LOST = 4; /** @hide */ - public static final int CALLBACK_UNAVAIL = BASE + 5; + public static final int CALLBACK_UNAVAIL = 5; /** @hide */ - public static final int CALLBACK_CAP_CHANGED = BASE + 6; + public static final int CALLBACK_CAP_CHANGED = 6; /** @hide */ - public static final int CALLBACK_IP_CHANGED = BASE + 7; + public static final int CALLBACK_IP_CHANGED = 7; /** @hide obj = NetworkCapabilities, arg1 = seq number */ - private static final int EXPIRE_LEGACY_REQUEST = BASE + 8; + private static final int EXPIRE_LEGACY_REQUEST = 8; /** @hide */ - public static final int CALLBACK_SUSPENDED = BASE + 9; + public static final int CALLBACK_SUSPENDED = 9; /** @hide */ - public static final int CALLBACK_RESUMED = BASE + 10; + public static final int CALLBACK_RESUMED = 10; /** @hide */ - public static final int CALLBACK_BLK_CHANGED = BASE + 11; + public static final int CALLBACK_BLK_CHANGED = 11; /** @hide */ public static String getCallbackName(int whichCallback) { @@ -4241,15 +4270,33 @@ public class ConnectivityManager { } /** - * @hide + * Registers to receive notifications about the best matching network which satisfy the given + * {@link NetworkRequest}. The callbacks will continue to be called until + * either the application exits or {@link #unregisterNetworkCallback(NetworkCallback)} is + * called. + * + * <p>To avoid performance issues due to apps leaking callbacks, the system will limit the + * number of outstanding requests to 100 per app (identified by their UID), shared with + * {@link #registerNetworkCallback} and its variants and {@link #requestNetwork} as well as + * {@link ConnectivityDiagnosticsManager#registerConnectivityDiagnosticsCallback}. + * Requesting a network with this method will count toward this limit. If this limit is + * exceeded, an exception will be thrown. To avoid hitting this issue and to conserve resources, + * make sure to unregister the callbacks with + * {@link #unregisterNetworkCallback(NetworkCallback)}. + * + * + * @param request {@link NetworkRequest} describing this request. + * @param networkCallback The {@link NetworkCallback} that the system will call as suitable + * networks change state. + * @param handler {@link Handler} to specify the thread upon which the callback will be invoked. + * @throws RuntimeException if the app already has too many callbacks registered. */ - // TODO: Make it public api. @SuppressLint("ExecutorRegistration") public void registerBestMatchingNetworkCallback(@NonNull NetworkRequest request, @NonNull NetworkCallback networkCallback, @NonNull Handler handler) { final NetworkCapabilities nc = request.networkCapabilities; final CallbackHandler cbHandler = new CallbackHandler(handler); - sendRequestForNetwork(nc, networkCallback, 0, TRACK_BEST, TYPE_NONE, cbHandler); + sendRequestForNetwork(nc, networkCallback, 0, LISTEN_FOR_BEST, TYPE_NONE, cbHandler); } /** @@ -4344,8 +4391,13 @@ public class ConnectivityManager { * * @hide */ - @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) - public void setAcceptUnvalidated(Network network, boolean accept, boolean always) { + @SystemApi(client = MODULE_LIBRARIES) + @RequiresPermission(anyOf = { + android.Manifest.permission.NETWORK_SETTINGS, + android.Manifest.permission.NETWORK_SETUP_WIZARD, + android.Manifest.permission.NETWORK_STACK, + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) + public void setAcceptUnvalidated(@NonNull Network network, boolean accept, boolean always) { try { mService.setAcceptUnvalidated(network, accept, always); } catch (RemoteException e) { @@ -4367,8 +4419,14 @@ public class ConnectivityManager { * * @hide */ - @RequiresPermission(android.Manifest.permission.NETWORK_STACK) - public void setAcceptPartialConnectivity(Network network, boolean accept, boolean always) { + @SystemApi(client = MODULE_LIBRARIES) + @RequiresPermission(anyOf = { + android.Manifest.permission.NETWORK_SETTINGS, + android.Manifest.permission.NETWORK_SETUP_WIZARD, + android.Manifest.permission.NETWORK_STACK, + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) + public void setAcceptPartialConnectivity(@NonNull Network network, boolean accept, + boolean always) { try { mService.setAcceptPartialConnectivity(network, accept, always); } catch (RemoteException e) { @@ -4386,8 +4444,13 @@ public class ConnectivityManager { * * @hide */ - @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) - public void setAvoidUnvalidated(Network network) { + @SystemApi(client = MODULE_LIBRARIES) + @RequiresPermission(anyOf = { + android.Manifest.permission.NETWORK_SETTINGS, + android.Manifest.permission.NETWORK_SETUP_WIZARD, + android.Manifest.permission.NETWORK_STACK, + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) + public void setAvoidUnvalidated(@NonNull Network network) { try { mService.setAvoidUnvalidated(network); } catch (RemoteException e) { @@ -4517,7 +4580,10 @@ public class ConnectivityManager { * Resets all connectivity manager settings back to factory defaults. * @hide */ - @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) + @SystemApi(client = MODULE_LIBRARIES) + @RequiresPermission(anyOf = { + android.Manifest.permission.NETWORK_SETTINGS, + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void factoryReset() { try { mService.factoryReset(); @@ -4595,7 +4661,7 @@ public class ConnectivityManager { Log.e(TAG, "Can't set proxy properties", e); } // Must flush DNS cache as new network may have different DNS resolutions. - InetAddress.clearDnsCache(); + InetAddressCompat.clearDnsCache(); // Must flush socket pool as idle sockets will be bound to previous network and may // cause subsequent fetches to be performed on old network. NetworkEventDispatcher.getInstance().onNetworkConfigurationChanged(); @@ -5049,19 +5115,6 @@ public class ConnectivityManager { } /** - * Listener for {@link #setOemNetworkPreference(OemNetworkPreferences, Executor, - * OnSetOemNetworkPreferenceListener)}. - * @hide - */ - @SystemApi - public interface OnSetOemNetworkPreferenceListener { - /** - * Called when setOemNetworkPreference() successfully completes. - */ - void onComplete(); - } - - /** * Used by automotive devices to set the network preferences used to direct traffic at an * application level as per the given OemNetworkPreferences. An example use-case would be an * automotive OEM wanting to provide connectivity for applications critical to the usage of a @@ -5083,16 +5136,16 @@ public class ConnectivityManager { @RequiresPermission(android.Manifest.permission.CONTROL_OEM_PAID_NETWORK_PREFERENCE) public void setOemNetworkPreference(@NonNull final OemNetworkPreferences preference, @Nullable @CallbackExecutor final Executor executor, - @Nullable final OnSetOemNetworkPreferenceListener listener) { + @Nullable final Runnable listener) { Objects.requireNonNull(preference, "OemNetworkPreferences must be non-null"); if (null != listener) { Objects.requireNonNull(executor, "Executor must be non-null"); } - final IOnSetOemNetworkPreferenceListener listenerInternal = listener == null ? null : - new IOnSetOemNetworkPreferenceListener.Stub() { + final IOnCompleteListener listenerInternal = listener == null ? null : + new IOnCompleteListener.Stub() { @Override public void onComplete() { - executor.execute(listener::onComplete); + executor.execute(listener::run); } }; @@ -5104,6 +5157,52 @@ public class ConnectivityManager { } } + /** + * Request that a user profile is put by default on a network matching a given preference. + * + * See the documentation for the individual preferences for a description of the supported + * behaviors. + * + * @param profile the profile concerned. + * @param preference the preference for this profile. + * @param executor an executor to execute the listener on. Optional if listener is null. + * @param listener an optional listener to listen for completion of the operation. + * @throws IllegalArgumentException if {@code profile} is not a valid user profile. + * @throws SecurityException if missing the appropriate permissions. + * @hide + */ + // This function is for establishing per-profile default networking and can only be called by + // the device policy manager, running as the system server. It would make no sense to call it + // on a context for a user because it does not establish a setting on behalf of a user, rather + // it establishes a setting for a user on behalf of the DPM. + @SuppressLint({"UserHandle"}) + @SystemApi(client = MODULE_LIBRARIES) + @RequiresPermission(android.Manifest.permission.NETWORK_STACK) + public void setProfileNetworkPreference(@NonNull final UserHandle profile, + @ProfileNetworkPreference final int preference, + @Nullable @CallbackExecutor final Executor executor, + @Nullable final Runnable listener) { + if (null != listener) { + Objects.requireNonNull(executor, "Pass a non-null executor, or a null listener"); + } + final IOnCompleteListener proxy; + if (null == listener) { + proxy = null; + } else { + proxy = new IOnCompleteListener.Stub() { + @Override + public void onComplete() { + executor.execute(listener::run); + } + }; + } + try { + mService.setProfileNetworkPreference(profile, preference, proxy); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + // The first network ID of IPSec tunnel interface. private static final int TUN_INTF_NETID_START = 0xFC00; // 0xFC00 = 64512 // The network ID range of IPSec tunnel interface. @@ -5124,7 +5223,7 @@ public class ConnectivityManager { /** * Get private DNS mode from settings. * - * @param cr The ContentResolver to query private DNS mode from settings. + * @param context The Context to query the private DNS mode from settings. * @return A string of private DNS mode as one of the PRIVATE_DNS_MODE_* constants. * * @hide @@ -5132,7 +5231,8 @@ public class ConnectivityManager { @SystemApi(client = MODULE_LIBRARIES) @NonNull @PrivateDnsMode - public static String getPrivateDnsMode(@NonNull ContentResolver cr) { + public static String getPrivateDnsMode(@NonNull Context context) { + final ContentResolver cr = context.getContentResolver(); String mode = Settings.Global.getString(cr, PRIVATE_DNS_MODE); if (TextUtils.isEmpty(mode)) mode = Settings.Global.getString(cr, PRIVATE_DNS_DEFAULT_MODE); // If both PRIVATE_DNS_MODE and PRIVATE_DNS_DEFAULT_MODE are not set, choose diff --git a/packages/Connectivity/framework/src/android/net/ConnectivitySettingsManager.java b/packages/Connectivity/framework/src/android/net/ConnectivitySettingsManager.java new file mode 100644 index 000000000000..bbd83931ee0d --- /dev/null +++ b/packages/Connectivity/framework/src/android/net/ConnectivitySettingsManager.java @@ -0,0 +1,241 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.annotation.IntDef; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * A manager class for connectivity module settings. + * + * @hide + */ +public class ConnectivitySettingsManager { + + private ConnectivitySettingsManager() {} + + /** Data activity timeout settings */ + + /** + * Inactivity timeout to track mobile data activity. + * + * If set to a positive integer, it indicates the inactivity timeout value in seconds to + * infer the data activity of mobile network. After a period of no activity on mobile + * networks with length specified by the timeout, an {@code ACTION_DATA_ACTIVITY_CHANGE} + * intent is fired to indicate a transition of network status from "active" to "idle". Any + * subsequent activity on mobile networks triggers the firing of {@code + * ACTION_DATA_ACTIVITY_CHANGE} intent indicating transition from "idle" to "active". + * + * Network activity refers to transmitting or receiving data on the network interfaces. + * + * Tracking is disabled if set to zero or negative value. + */ + public static final String DATA_ACTIVITY_TIMEOUT_MOBILE = "data_activity_timeout_mobile"; + + /** + * Timeout to tracking Wifi data activity. Same as {@code DATA_ACTIVITY_TIMEOUT_MOBILE} + * but for Wifi network. + */ + public static final String DATA_ACTIVITY_TIMEOUT_WIFI = "data_activity_timeout_wifi"; + + /** Dns resolver settings */ + + /** + * Sample validity in seconds to configure for the system DNS resolver. + */ + public static final String DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS = + "dns_resolver_sample_validity_seconds"; + + /** + * Success threshold in percent for use with the system DNS resolver. + */ + public static final String DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT = + "dns_resolver_success_threshold_percent"; + + /** + * Minimum number of samples needed for statistics to be considered meaningful in the + * system DNS resolver. + */ + public static final String DNS_RESOLVER_MIN_SAMPLES = "dns_resolver_min_samples"; + + /** + * Maximum number taken into account for statistics purposes in the system DNS resolver. + */ + public static final String DNS_RESOLVER_MAX_SAMPLES = "dns_resolver_max_samples"; + + /** Network switch notification settings */ + + /** + * The maximum number of notifications shown in 24 hours when switching networks. + */ + public static final String NETWORK_SWITCH_NOTIFICATION_DAILY_LIMIT = + "network_switch_notification_daily_limit"; + + /** + * The minimum time in milliseconds between notifications when switching networks. + */ + public static final String NETWORK_SWITCH_NOTIFICATION_RATE_LIMIT_MILLIS = + "network_switch_notification_rate_limit_millis"; + + /** Captive portal settings */ + + /** + * The URL used for HTTP captive portal detection upon a new connection. + * A 204 response code from the server is used for validation. + */ + public static final String CAPTIVE_PORTAL_HTTP_URL = "captive_portal_http_url"; + + /** + * What to do when connecting a network that presents a captive portal. + * Must be one of the CAPTIVE_PORTAL_MODE_* constants above. + * + * The default for this setting is CAPTIVE_PORTAL_MODE_PROMPT. + */ + public static final String CAPTIVE_PORTAL_MODE = "captive_portal_mode"; + + /** + * Don't attempt to detect captive portals. + */ + public static final int CAPTIVE_PORTAL_MODE_IGNORE = 0; + + /** + * When detecting a captive portal, display a notification that + * prompts the user to sign in. + */ + public static final int CAPTIVE_PORTAL_MODE_PROMPT = 1; + + /** + * When detecting a captive portal, immediately disconnect from the + * network and do not reconnect to that network in the future. + */ + public static final int CAPTIVE_PORTAL_MODE_AVOID = 2; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = { + CAPTIVE_PORTAL_MODE_IGNORE, + CAPTIVE_PORTAL_MODE_PROMPT, + CAPTIVE_PORTAL_MODE_AVOID, + }) + public @interface CaptivePortalMode {} + + /** Global http proxy settings */ + + /** + * Host name for global http proxy. Set via ConnectivityManager. + */ + public static final String GLOBAL_HTTP_PROXY_HOST = "global_http_proxy_host"; + + /** + * Integer host port for global http proxy. Set via ConnectivityManager. + */ + public static final String GLOBAL_HTTP_PROXY_PORT = "global_http_proxy_port"; + + /** + * Exclusion list for global proxy. This string contains a list of + * comma-separated domains where the global proxy does not apply. + * Domains should be listed in a comma- separated list. Example of + * acceptable formats: ".domain1.com,my.domain2.com" Use + * ConnectivityManager to set/get. + */ + public static final String GLOBAL_HTTP_PROXY_EXCLUSION_LIST = + "global_http_proxy_exclusion_list"; + + /** + * The location PAC File for the proxy. + */ + public static final String GLOBAL_HTTP_PROXY_PAC = "global_proxy_pac_url"; + + /** Private dns settings */ + + /** + * The requested Private DNS mode (string), and an accompanying specifier (string). + * + * Currently, the specifier holds the chosen provider name when the mode requests + * a specific provider. It may be used to store the provider name even when the + * mode changes so that temporarily disabling and re-enabling the specific + * provider mode does not necessitate retyping the provider hostname. + */ + public static final String PRIVATE_DNS_MODE = "private_dns_mode"; + + /** + * The specific Private DNS provider name. + */ + public static final String PRIVATE_DNS_SPECIFIER = "private_dns_specifier"; + + /** + * Forced override of the default mode (hardcoded as "automatic", nee "opportunistic"). + * This allows changing the default mode without effectively disabling other modes, + * all of which require explicit user action to enable/configure. See also b/79719289. + * + * Value is a string, suitable for assignment to PRIVATE_DNS_MODE above. + */ + public static final String PRIVATE_DNS_DEFAULT_MODE = "private_dns_default_mode"; + + /** Other settings */ + + /** + * The number of milliseconds to hold on to a PendingIntent based request. This delay gives + * the receivers of the PendingIntent an opportunity to make a new network request before + * the Network satisfying the request is potentially removed. + */ + public static final String CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS = + "connectivity_release_pending_intent_delay_ms"; + + /** + * Whether the mobile data connection should remain active even when higher + * priority networks like WiFi are active, to help make network switching faster. + * + * See ConnectivityService for more info. + * + * (0 = disabled, 1 = enabled) + */ + public static final String MOBILE_DATA_ALWAYS_ON = "mobile_data_always_on"; + + /** + * Whether the wifi data connection should remain active even when higher + * priority networks like Ethernet are active, to keep both networks. + * In the case where higher priority networks are connected, wifi will be + * unused unless an application explicitly requests to use it. + * + * See ConnectivityService for more info. + * + * (0 = disabled, 1 = enabled) + */ + public static final String WIFI_ALWAYS_REQUESTED = "wifi_always_requested"; + + /** + * Whether to automatically switch away from wifi networks that lose Internet access. + * Only meaningful if config_networkAvoidBadWifi is set to 0, otherwise the system always + * avoids such networks. Valid values are: + * + * 0: Don't avoid bad wifi, don't prompt the user. Get stuck on bad wifi like it's 2013. + * null: Ask the user whether to switch away from bad wifi. + * 1: Avoid bad wifi. + */ + public static final String NETWORK_AVOID_BAD_WIFI = "network_avoid_bad_wifi"; + + /** + * User setting for ConnectivityManager.getMeteredMultipathPreference(). This value may be + * overridden by the system based on device or application state. If null, the value + * specified by config_networkMeteredMultipathPreference is used. + */ + public static final String NETWORK_METERED_MULTIPATH_PREFERENCE = + "network_metered_multipath_preference"; +} diff --git a/packages/Connectivity/framework/src/android/net/IConnectivityManager.aidl b/packages/Connectivity/framework/src/android/net/IConnectivityManager.aidl index 1bbf1a95fcca..d83cc163b53f 100644 --- a/packages/Connectivity/framework/src/android/net/IConnectivityManager.aidl +++ b/packages/Connectivity/framework/src/android/net/IConnectivityManager.aidl @@ -20,7 +20,7 @@ import android.app.PendingIntent; import android.net.ConnectionInfo; import android.net.ConnectivityDiagnosticsManager; import android.net.IConnectivityDiagnosticsCallback; -import android.net.IOnSetOemNetworkPreferenceListener; +import android.net.IOnCompleteListener; import android.net.INetworkActivityListener; import android.net.IQosCallback; import android.net.ISocketKeepaliveCallback; @@ -43,6 +43,7 @@ import android.os.Messenger; import android.os.ParcelFileDescriptor; import android.os.PersistableBundle; import android.os.ResultReceiver; +import android.os.UserHandle; import com.android.connectivity.aidl.INetworkAgent; @@ -215,5 +216,8 @@ interface IConnectivityManager void unregisterQosCallback(in IQosCallback callback); void setOemNetworkPreference(in OemNetworkPreferences preference, - in IOnSetOemNetworkPreferenceListener listener); + in IOnCompleteListener listener); + + void setProfileNetworkPreference(in UserHandle profile, int preference, + in IOnCompleteListener listener); } diff --git a/packages/Connectivity/framework/src/android/net/IOnSetOemNetworkPreferenceListener.aidl b/packages/Connectivity/framework/src/android/net/IOnCompleteListener.aidl index 7979afc54f90..4bb89f6c89e4 100644 --- a/packages/Connectivity/framework/src/android/net/IOnSetOemNetworkPreferenceListener.aidl +++ b/packages/Connectivity/framework/src/android/net/IOnCompleteListener.aidl @@ -18,6 +18,6 @@ package android.net; /** @hide */ -oneway interface IOnSetOemNetworkPreferenceListener { +oneway interface IOnCompleteListener { void onComplete(); } diff --git a/packages/Connectivity/framework/src/android/net/InetAddressCompat.java b/packages/Connectivity/framework/src/android/net/InetAddressCompat.java new file mode 100644 index 000000000000..8404441de669 --- /dev/null +++ b/packages/Connectivity/framework/src/android/net/InetAddressCompat.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.util.Log; + +import java.lang.reflect.InvocationTargetException; +import java.net.InetAddress; +import java.net.UnknownHostException; + +/** + * Compatibility utility for InetAddress core platform APIs. + * + * Connectivity has access to such APIs, but they are not part of the module_current stubs yet + * (only core_current). Most stable core platform APIs are included manually in the connectivity + * build rules, but because InetAddress is also part of the base java SDK that is earlier on the + * classpath, the extra core platform APIs are not seen. + * + * TODO (b/183097033): remove this utility as soon as core_current is part of module_current + * @hide + */ +public class InetAddressCompat { + + /** + * @see InetAddress#clearDnsCache() + */ + public static void clearDnsCache() { + try { + InetAddress.class.getMethod("clearDnsCache").invoke(null); + } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { + Log.wtf(InetAddressCompat.class.getSimpleName(), "Error clearing DNS cache", e); + } + } + + /** + * @see InetAddress#getAllByNameOnNet(String, int) + */ + public static InetAddress[] getAllByNameOnNet(String host, int netId) throws + UnknownHostException { + try { + return (InetAddress[]) InetAddress.class.getMethod("getAllByNameOnNet", + String.class, int.class).invoke(null, host, netId); + } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { + Log.wtf(InetAddressCompat.class.getSimpleName(), "Error calling getAllByNameOnNet", e); + throw new IllegalStateException("Error querying via getAllNameOnNet", e); + } + } + + /** + * @see InetAddress#getByNameOnNet(String, int) + */ + public static InetAddress getByNameOnNet(String host, int netId) throws + UnknownHostException { + try { + return (InetAddress) InetAddress.class.getMethod("getByNameOnNet", + String.class, int.class).invoke(null, host, netId); + } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { + Log.wtf(InetAddressCompat.class.getSimpleName(), "Error calling getAllByNameOnNet", e); + throw new IllegalStateException("Error querying via getByNameOnNet", e); + } + } +} diff --git a/packages/Connectivity/framework/src/android/net/Network.java b/packages/Connectivity/framework/src/android/net/Network.java index 7245db3b17db..0741414ab3aa 100644 --- a/packages/Connectivity/framework/src/android/net/Network.java +++ b/packages/Connectivity/framework/src/android/net/Network.java @@ -142,7 +142,7 @@ public class Network implements Parcelable { * @throws UnknownHostException if the address lookup fails. */ public InetAddress[] getAllByName(String host) throws UnknownHostException { - return InetAddress.getAllByNameOnNet(host, getNetIdForResolv()); + return InetAddressCompat.getAllByNameOnNet(host, getNetIdForResolv()); } /** @@ -155,7 +155,7 @@ public class Network implements Parcelable { * if the address lookup fails. */ public InetAddress getByName(String host) throws UnknownHostException { - return InetAddress.getByNameOnNet(host, getNetIdForResolv()); + return InetAddressCompat.getByNameOnNet(host, getNetIdForResolv()); } /** diff --git a/packages/Connectivity/framework/src/android/net/NetworkAgent.java b/packages/Connectivity/framework/src/android/net/NetworkAgent.java index b3ab0ee8bd3c..a127c6f6de26 100644 --- a/packages/Connectivity/framework/src/android/net/NetworkAgent.java +++ b/packages/Connectivity/framework/src/android/net/NetworkAgent.java @@ -37,7 +37,6 @@ import android.util.Log; import com.android.connectivity.aidl.INetworkAgent; import com.android.connectivity.aidl.INetworkAgentRegistry; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.Protocol; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -125,7 +124,10 @@ public abstract class NetworkAgent { */ public final int providerId; - private static final int BASE = Protocol.BASE_NETWORK_AGENT; + // ConnectivityService parses message constants from itself and NetworkAgent with MessageUtils + // for debugging purposes, and crashes if some messages have the same values. + // TODO: have ConnectivityService store message names in different maps and remove this base + private static final int BASE = 200; /** * Sent by ConnectivityService to the NetworkAgent to inform it of diff --git a/packages/Connectivity/framework/src/android/net/NetworkRequest.java b/packages/Connectivity/framework/src/android/net/NetworkRequest.java index 3fd95ee58df2..dbe3ecc4d775 100644 --- a/packages/Connectivity/framework/src/android/net/NetworkRequest.java +++ b/packages/Connectivity/framework/src/android/net/NetworkRequest.java @@ -140,7 +140,7 @@ public class NetworkRequest implements Parcelable { REQUEST, BACKGROUND_REQUEST, TRACK_SYSTEM_DEFAULT, - TRACK_BEST, + LISTEN_FOR_BEST, }; /** @@ -514,6 +514,15 @@ public class NetworkRequest implements Parcelable { } /** + * Returns true iff. this NetworkRequest is of type LISTEN_FOR_BEST. + * + * @hide + */ + public boolean isListenForBest() { + return type == Type.LISTEN_FOR_BEST; + } + + /** * Returns true iff. the contained NetworkRequest is one that: * * - should be associated with at most one satisfying network diff --git a/core/java/android/net/NetworkScore.java b/packages/Connectivity/framework/src/android/net/NetworkScore.java index f47801002296..f47801002296 100644 --- a/core/java/android/net/NetworkScore.java +++ b/packages/Connectivity/framework/src/android/net/NetworkScore.java diff --git a/packages/Connectivity/framework/src/android/net/OemNetworkPreferences.java b/packages/Connectivity/framework/src/android/net/OemNetworkPreferences.java index 48bd29769f83..5a76cd6d6b0f 100644 --- a/packages/Connectivity/framework/src/android/net/OemNetworkPreferences.java +++ b/packages/Connectivity/framework/src/android/net/OemNetworkPreferences.java @@ -73,6 +73,14 @@ public final class OemNetworkPreferences implements Parcelable { private final Bundle mNetworkMappings; /** + * Return whether this object is empty. + * @hide + */ + public boolean isEmpty() { + return mNetworkMappings.keySet().size() == 0; + } + + /** * Return the currently built application package name to {@link OemNetworkPreference} mappings. * @return the current network preferences map. */ diff --git a/packages/Connectivity/framework/src/android/net/VpnTransportInfo.java b/packages/Connectivity/framework/src/android/net/VpnTransportInfo.java index c5100794899a..cd8f4c06de65 100644 --- a/packages/Connectivity/framework/src/android/net/VpnTransportInfo.java +++ b/packages/Connectivity/framework/src/android/net/VpnTransportInfo.java @@ -22,9 +22,6 @@ import android.annotation.NonNull; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; -import android.util.SparseArray; - -import com.android.internal.util.MessageUtils; import java.util.Objects; @@ -38,9 +35,6 @@ import java.util.Objects; */ @SystemApi(client = MODULE_LIBRARIES) public final class VpnTransportInfo implements TransportInfo, Parcelable { - private static final SparseArray<String> sTypeToString = - MessageUtils.findMessageNames(new Class[]{VpnManager.class}, new String[]{"TYPE_VPN_"}); - /** Type of this VPN. */ public final int type; @@ -63,8 +57,7 @@ public final class VpnTransportInfo implements TransportInfo, Parcelable { @Override public String toString() { - final String typeString = sTypeToString.get(type, "VPN_TYPE_???"); - return String.format("VpnTransportInfo{%s}", typeString); + return String.format("VpnTransportInfo{type=%d}", type); } @Override diff --git a/packages/Connectivity/framework/src/android/net/util/MultinetworkPolicyTracker.java b/packages/Connectivity/framework/src/android/net/util/MultinetworkPolicyTracker.java index 739ddada50b4..6a49aa2576c3 100644 --- a/packages/Connectivity/framework/src/android/net/util/MultinetworkPolicyTracker.java +++ b/packages/Connectivity/framework/src/android/net/util/MultinetworkPolicyTracker.java @@ -16,8 +16,8 @@ package android.net.util; -import static android.provider.Settings.Global.NETWORK_AVOID_BAD_WIFI; -import static android.provider.Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE; +import static android.net.ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI; +import static android.net.ConnectivitySettingsManager.NETWORK_METERED_MULTIPATH_PREFERENCE; import android.annotation.NonNull; import android.content.BroadcastReceiver; @@ -110,8 +110,8 @@ public class MultinetworkPolicyTracker { mHandler = handler; mAvoidBadWifiCallback = avoidBadWifiCallback; mSettingsUris = Arrays.asList( - Settings.Global.getUriFor(NETWORK_AVOID_BAD_WIFI), - Settings.Global.getUriFor(NETWORK_METERED_MULTIPATH_PREFERENCE)); + Settings.Global.getUriFor(NETWORK_AVOID_BAD_WIFI), + Settings.Global.getUriFor(NETWORK_METERED_MULTIPATH_PREFERENCE)); mResolver = mContext.getContentResolver(); mSettingObserver = new SettingObserver(); mBroadcastReceiver = new BroadcastReceiver() { diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values/config.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values/config.xml index 7d98c76a40ba..06c81921fd3f 100644 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values/config.xml +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values/config.xml @@ -42,4 +42,14 @@ --> </string-array> + <string-array translatable="false" name="config_legacy_networktype_restore_timers"> + <item>2,60000</item><!-- mobile_mms --> + <item>3,60000</item><!-- mobile_supl --> + <item>4,60000</item><!-- mobile_dun --> + <item>5,60000</item><!-- mobile_hipri --> + <item>10,60000</item><!-- mobile_fota --> + <item>11,60000</item><!-- mobile_ims --> + <item>12,60000</item><!-- mobile_cbs --> + </string-array> + </resources>
\ No newline at end of file diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values/overlayable.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values/overlayable.xml index 00ec2df0e6f1..da8aee56276c 100644 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values/overlayable.xml +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values/overlayable.xml @@ -17,11 +17,11 @@ <overlayable name="ServiceConnectivityResourcesConfig"> <policy type="product|system|vendor"> <!-- Configuration values for ConnectivityService --> + <item type="array" name="config_legacy_networktype_restore_timers"/> <item type="string" name="config_networkCaptivePortalServerUrl"/> <item type="integer" name="config_networkTransitionTimeout"/> <item type="array" name="config_wakeonlan_supported_interfaces"/> - </policy> </overlayable> </resources> diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java index ad459a4c3b93..40a457f3f626 100644 --- a/packages/SettingsLib/src/com/android/settingslib/Utils.java +++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java @@ -22,7 +22,6 @@ import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.location.LocationManager; import android.media.AudioManager; -import android.net.ConnectivityManager; import android.net.TetheringManager; import android.os.BatteryManager; import android.os.SystemProperties; @@ -33,6 +32,7 @@ import android.provider.Settings; import android.telephony.AccessNetworkConstants; import android.telephony.NetworkRegistrationInfo; import android.telephony.ServiceState; +import android.telephony.TelephonyManager; import androidx.annotation.NonNull; import androidx.core.graphics.drawable.RoundedBitmapDrawable; @@ -435,8 +435,7 @@ public class Utils { } public static boolean isWifiOnly(Context context) { - return !context.getSystemService(ConnectivityManager.class) - .isNetworkSupported(ConnectivityManager.TYPE_MOBILE); + return !context.getSystemService(TelephonyManager.class).isDataCapable(); } /** Returns if the automatic storage management feature is turned on or not. **/ diff --git a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java index 092cbf3c7c12..60bcf37304a5 100644 --- a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java +++ b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java @@ -16,7 +16,6 @@ package com.android.settingslib.net; -import static android.net.ConnectivityManager.TYPE_MOBILE; import static android.net.NetworkStatsHistory.FIELD_RX_BYTES; import static android.net.NetworkStatsHistory.FIELD_TX_BYTES; import static android.net.TrafficStats.MB_IN_BYTES; @@ -59,7 +58,6 @@ public class DataUsageController { PERIOD_BUILDER, Locale.getDefault()); private final Context mContext; - private final ConnectivityManager mConnectivityManager; private final INetworkStatsService mStatsService; private final NetworkPolicyManager mPolicyManager; private final NetworkStatsManager mNetworkStatsManager; @@ -71,7 +69,6 @@ public class DataUsageController { public DataUsageController(Context context) { mContext = context; - mConnectivityManager = ConnectivityManager.from(context); mStatsService = INetworkStatsService.Stub.asInterface( ServiceManager.getService(Context.NETWORK_STATS_SERVICE)); mPolicyManager = NetworkPolicyManager.from(mContext); @@ -236,7 +233,7 @@ public class DataUsageController { public boolean isMobileDataSupported() { // require both supported network and ready SIM - return mConnectivityManager.isNetworkSupported(TYPE_MOBILE) + return getTelephonyManager().isDataCapable() && getTelephonyManager().getSimState() == SIM_STATE_READY; } diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java index 6568bffddecc..268603fa8b0d 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java @@ -2445,8 +2445,8 @@ class DatabaseHelper extends SQLiteOpenHelper { R.bool.def_auto_time_zone); // Sync timezone to NITZ loadSetting(stmt, Settings.Global.STAY_ON_WHILE_PLUGGED_IN, - ("1".equals(SystemProperties.get("ro.kernel.qemu")) || - res.getBoolean(R.bool.def_stay_on_while_plugged_in)) + ("1".equals(SystemProperties.get("ro.boot.qemu")) + || res.getBoolean(R.bool.def_stay_on_while_plugged_in)) ? 1 : 0); loadIntegerSetting(stmt, Settings.Global.WIFI_SLEEP_POLICY, diff --git a/services/core/java/com/android/server/BluetoothDeviceConfigListener.java b/services/core/java/com/android/server/BluetoothDeviceConfigListener.java index 2dcf82ff9410..611a37de70f4 100644 --- a/services/core/java/com/android/server/BluetoothDeviceConfigListener.java +++ b/services/core/java/com/android/server/BluetoothDeviceConfigListener.java @@ -17,6 +17,9 @@ package com.android.server; import android.provider.DeviceConfig; +import android.util.Slog; + +import java.util.ArrayList; /** * The BluetoothDeviceConfigListener handles system device config change callback and checks @@ -30,10 +33,12 @@ import android.provider.DeviceConfig; class BluetoothDeviceConfigListener { private static final String TAG = "BluetoothDeviceConfigListener"; - BluetoothManagerService mService; + private final BluetoothManagerService mService; + private final boolean mLogDebug; - BluetoothDeviceConfigListener(BluetoothManagerService service) { + BluetoothDeviceConfigListener(BluetoothManagerService service, boolean logDebug) { mService = service; + mLogDebug = logDebug; DeviceConfig.addOnPropertiesChangedListener( DeviceConfig.NAMESPACE_BLUETOOTH, (Runnable r) -> r.run(), @@ -47,6 +52,13 @@ class BluetoothDeviceConfigListener { if (!properties.getNamespace().equals(DeviceConfig.NAMESPACE_BLUETOOTH)) { return; } + if (mLogDebug) { + ArrayList<String> flags = new ArrayList<>(); + for (String name : properties.getKeyset()) { + flags.add(name + "='" + properties.getString(name, "") + "'"); + } + Slog.d(TAG, "onPropertiesChanged: " + String.join(",", flags)); + } boolean foundInit = false; for (String name : properties.getKeyset()) { if (name.startsWith("INIT_")) { diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java index aab05532e2b7..992ef2657a65 100644 --- a/services/core/java/com/android/server/BluetoothManagerService.java +++ b/services/core/java/com/android/server/BluetoothManagerService.java @@ -453,6 +453,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (mHandler.hasMessages(MESSAGE_INIT_FLAGS_CHANGED) && state == BluetoothProfile.STATE_DISCONNECTED && !mBluetoothModeChangeHelper.isA2dpOrHearingAidConnected()) { + Slog.i(TAG, "Device disconnected, reactivating pending flag changes"); onInitFlagsChanged(); } } @@ -810,6 +811,35 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return enabledProfiles; } + private boolean isDeviceProvisioned() { + return Settings.Global.getInt(mContentResolver, Settings.Global.DEVICE_PROVISIONED, + 0) != 0; + } + + // Monitor change of BLE scan only mode settings. + private void registerForProvisioningStateChange() { + ContentObserver contentObserver = new ContentObserver(null) { + @Override + public void onChange(boolean selfChange) { + if (!isDeviceProvisioned()) { + if (DBG) { + Slog.d(TAG, "DEVICE_PROVISIONED setting changed, but device is not " + + "provisioned"); + } + return; + } + if (mHandler.hasMessages(MESSAGE_INIT_FLAGS_CHANGED)) { + Slog.i(TAG, "Device provisioned, reactivating pending flag changes"); + onInitFlagsChanged(); + } + } + }; + + mContentResolver.registerContentObserver( + Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED), false, + contentObserver); + } + // Monitor change of BLE scan only mode settings. private void registerForBleScanModeChange() { ContentObserver contentObserver = new ContentObserver(null) { @@ -1375,7 +1405,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (mBluetoothAirplaneModeListener != null) { mBluetoothAirplaneModeListener.start(mBluetoothModeChangeHelper); } - mBluetoothDeviceConfigListener = new BluetoothDeviceConfigListener(this); + registerForProvisioningStateChange(); + mBluetoothDeviceConfigListener = new BluetoothDeviceConfigListener(this, DBG); } /** @@ -2219,12 +2250,25 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } mHandler.removeMessages(MESSAGE_INIT_FLAGS_CHANGED); if (mBluetoothModeChangeHelper.isA2dpOrHearingAidConnected()) { + Slog.i(TAG, "Delaying MESSAGE_INIT_FLAGS_CHANGED by " + + DELAY_FOR_RETRY_INIT_FLAG_CHECK_MS + + " ms due to existing connections"); + mHandler.sendEmptyMessageDelayed( + MESSAGE_INIT_FLAGS_CHANGED, + DELAY_FOR_RETRY_INIT_FLAG_CHECK_MS); + break; + } + if (!isDeviceProvisioned()) { + Slog.i(TAG, "Delaying MESSAGE_INIT_FLAGS_CHANGED by " + + DELAY_FOR_RETRY_INIT_FLAG_CHECK_MS + + "ms because device is not provisioned"); mHandler.sendEmptyMessageDelayed( MESSAGE_INIT_FLAGS_CHANGED, DELAY_FOR_RETRY_INIT_FLAG_CHECK_MS); break; } if (mBluetooth != null && isEnabled()) { + Slog.i(TAG, "Restarting Bluetooth due to init flag change"); restartForReason( BluetoothProtoEnums.ENABLE_DISABLE_REASON_INIT_FLAGS_CHANGED); } diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 92d9b08ed29d..58a921f0e3be 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -17,6 +17,10 @@ package com.android.server; import static android.Manifest.permission.RECEIVE_DATA_ACTIVITY_CHANGE; +import static android.content.pm.PackageManager.FEATURE_BLUETOOTH; +import static android.content.pm.PackageManager.FEATURE_WATCH; +import static android.content.pm.PackageManager.FEATURE_WIFI; +import static android.content.pm.PackageManager.FEATURE_WIFI_DIRECT; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport.KEY_NETWORK_PROBES_ATTEMPTED_BITMASK; import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport.KEY_NETWORK_PROBES_SUCCEEDED_BITMASK; @@ -28,15 +32,30 @@ import static android.net.ConnectivityDiagnosticsManager.DataStallReport.KEY_TCP import static android.net.ConnectivityDiagnosticsManager.DataStallReport.KEY_TCP_PACKET_FAIL_RATE; import static android.net.ConnectivityManager.CONNECTIVITY_ACTION; import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC; +import static android.net.ConnectivityManager.TYPE_BLUETOOTH; import static android.net.ConnectivityManager.TYPE_ETHERNET; +import static android.net.ConnectivityManager.TYPE_MOBILE; +import static android.net.ConnectivityManager.TYPE_MOBILE_CBS; +import static android.net.ConnectivityManager.TYPE_MOBILE_DUN; +import static android.net.ConnectivityManager.TYPE_MOBILE_EMERGENCY; +import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA; +import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI; +import static android.net.ConnectivityManager.TYPE_MOBILE_IA; +import static android.net.ConnectivityManager.TYPE_MOBILE_IMS; +import static android.net.ConnectivityManager.TYPE_MOBILE_MMS; +import static android.net.ConnectivityManager.TYPE_MOBILE_SUPL; import static android.net.ConnectivityManager.TYPE_NONE; +import static android.net.ConnectivityManager.TYPE_PROXY; import static android.net.ConnectivityManager.TYPE_VPN; +import static android.net.ConnectivityManager.TYPE_WIFI; +import static android.net.ConnectivityManager.TYPE_WIFI_P2P; import static android.net.ConnectivityManager.getNetworkTypeName; import static android.net.ConnectivityManager.isNetworkTypeValid; import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_PRIVDNS; import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_PARTIAL; import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_VALID; import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL; +import static android.net.NetworkCapabilities.NET_CAPABILITY_ENTERPRISE; import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND; import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED; @@ -55,6 +74,7 @@ import static android.net.NetworkCapabilities.TRANSPORT_TEST; import static android.net.NetworkCapabilities.TRANSPORT_VPN; import static android.net.NetworkPolicyManager.RULE_NONE; import static android.net.NetworkPolicyManager.uidRulesToString; +import static android.net.NetworkRequest.Type.LISTEN_FOR_BEST; import static android.net.shared.NetworkMonitorUtils.isPrivateDnsValidationRequired; import static android.os.Process.INVALID_UID; import static android.os.Process.VPN_UID; @@ -86,6 +106,7 @@ import android.net.ConnectivityDiagnosticsManager.ConnectivityReport; import android.net.ConnectivityDiagnosticsManager.DataStallReport; import android.net.ConnectivityManager; import android.net.ConnectivityManager.NetworkCallback; +import android.net.ConnectivitySettingsManager; import android.net.DataStallReportParcelable; import android.net.DnsResolverServiceManager; import android.net.ICaptivePortal; @@ -97,7 +118,7 @@ import android.net.INetworkActivityListener; import android.net.INetworkMonitor; import android.net.INetworkMonitorCallbacks; import android.net.INetworkPolicyListener; -import android.net.IOnSetOemNetworkPreferenceListener; +import android.net.IOnCompleteListener; import android.net.IQosCallback; import android.net.ISocketKeepaliveCallback; import android.net.InetAddresses; @@ -110,7 +131,6 @@ import android.net.Network; import android.net.NetworkAgent; import android.net.NetworkAgentConfig; import android.net.NetworkCapabilities; -import android.net.NetworkConfig; import android.net.NetworkInfo; import android.net.NetworkInfo.DetailedState; import android.net.NetworkMonitorManager; @@ -192,13 +212,13 @@ import com.android.connectivity.aidl.INetworkAgent; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.IndentingPrintWriter; -import com.android.internal.util.LocationPermissionChecker; import com.android.internal.util.MessageUtils; import com.android.modules.utils.BasicShellCommandHandler; import com.android.net.module.util.BaseNetdUnsolicitedEventListener; import com.android.net.module.util.CollectionUtils; import com.android.net.module.util.LinkPropertiesUtils.CompareOrUpdateResult; import com.android.net.module.util.LinkPropertiesUtils.CompareResult; +import com.android.net.module.util.LocationPermissionChecker; import com.android.net.module.util.NetworkCapabilitiesUtils; import com.android.net.module.util.PermissionUtils; import com.android.server.connectivity.AutodestructReference; @@ -214,6 +234,7 @@ import com.android.server.connectivity.NetworkNotificationManager; import com.android.server.connectivity.NetworkNotificationManager.NotificationType; import com.android.server.connectivity.NetworkRanker; import com.android.server.connectivity.PermissionMonitor; +import com.android.server.connectivity.ProfileNetworkPreferences; import com.android.server.connectivity.ProxyTracker; import com.android.server.connectivity.QosCallbackTracker; import com.android.server.net.NetworkPolicyManagerInternal; @@ -264,7 +285,7 @@ public class ConnectivityService extends IConnectivityManager.Stub /** * Default URL to use for {@link #getCaptivePortalServerUrl()}. This should not be changed * by OEMs for configuration purposes, as this value is overridden by - * Settings.Global.CAPTIVE_PORTAL_HTTP_URL. + * ConnectivitySettingsManager.CAPTIVE_PORTAL_HTTP_URL. * R.string.config_networkCaptivePortalServerUrl should be overridden instead for this purpose * (preferably via runtime resource overlays). */ @@ -297,7 +318,7 @@ public class ConnectivityService extends IConnectivityManager.Stub protected int mNascentDelayMs; // How long to delay to removal of a pending intent based request. - // See Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS + // See ConnectivitySettingsManager.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS private final int mReleasePendingIntentDelayMs; private MockableSystemProperties mSystemProperties; @@ -558,8 +579,8 @@ public class ConnectivityService extends IConnectivityManager.Stub private static final int EVENT_SET_REQUIRE_VPN_FOR_UIDS = 47; /** - * used internally when setting the default networks for OemNetworkPreferences. - * obj = OemNetworkPreferences + * Used internally when setting the default networks for OemNetworkPreferences. + * obj = Pair<OemNetworkPreferences, listener> */ private static final int EVENT_SET_OEM_NETWORK_PREFERENCE = 48; @@ -569,6 +590,12 @@ public class ConnectivityService extends IConnectivityManager.Stub private static final int EVENT_REPORT_NETWORK_ACTIVITY = 49; /** + * Used internally when setting a network preference for a user profile. + * obj = Pair<ProfileNetworkPreference, Listener> + */ + private static final int EVENT_SET_PROFILE_NETWORK_PREFERENCE = 50; + + /** * Argument for {@link #EVENT_PROVISIONING_NOTIFICATION} to indicate that the notification * should be shown. */ @@ -617,11 +644,8 @@ public class ConnectivityService extends IConnectivityManager.Stub private UserManager mUserManager; - private NetworkConfig[] mNetConfigs; - private int mNetworksDefined; - // the set of network types that can only be enabled by system/sig apps - private List mProtectedNetworks; + private List<Integer> mProtectedNetworks; private Set<String> mWolSupportedInterfaces; @@ -711,18 +735,63 @@ public class ConnectivityService extends IConnectivityManager.Stub * They are therefore not thread-safe with respect to each other. * - getNetworkForType() can be called at any time on binder threads. It is synchronized * on mTypeLists to be thread-safe with respect to a concurrent remove call. + * - getRestoreTimerForType(type) is also synchronized on mTypeLists. * - dump is thread-safe with respect to concurrent add and remove calls. */ private final ArrayList<NetworkAgentInfo> mTypeLists[]; @NonNull private final ConnectivityService mService; + // Restore timers for requestNetworkForFeature (network type -> timer in ms). Types without + // an entry have no timer (equivalent to -1). Lazily loaded. + @NonNull + private ArrayMap<Integer, Integer> mRestoreTimers = new ArrayMap<>(); + LegacyTypeTracker(@NonNull ConnectivityService service) { mService = service; mTypeLists = new ArrayList[ConnectivityManager.MAX_NETWORK_TYPE + 1]; } - public void addSupportedType(int type) { + public void loadSupportedTypes(@NonNull Context ctx, @NonNull TelephonyManager tm) { + final PackageManager pm = ctx.getPackageManager(); + if (pm.hasSystemFeature(FEATURE_WIFI)) { + addSupportedType(TYPE_WIFI); + } + if (pm.hasSystemFeature(FEATURE_WIFI_DIRECT)) { + addSupportedType(TYPE_WIFI_P2P); + } + if (tm.isDataCapable()) { + // Telephony does not have granular support for these types: they are either all + // supported, or none is supported + addSupportedType(TYPE_MOBILE); + addSupportedType(TYPE_MOBILE_MMS); + addSupportedType(TYPE_MOBILE_SUPL); + addSupportedType(TYPE_MOBILE_DUN); + addSupportedType(TYPE_MOBILE_HIPRI); + addSupportedType(TYPE_MOBILE_FOTA); + addSupportedType(TYPE_MOBILE_IMS); + addSupportedType(TYPE_MOBILE_CBS); + addSupportedType(TYPE_MOBILE_IA); + addSupportedType(TYPE_MOBILE_EMERGENCY); + } + if (pm.hasSystemFeature(FEATURE_BLUETOOTH)) { + addSupportedType(TYPE_BLUETOOTH); + } + if (pm.hasSystemFeature(FEATURE_WATCH)) { + // TYPE_PROXY is only used on Wear + addSupportedType(TYPE_PROXY); + } + // Ethernet is often not specified in the configs, although many devices can use it via + // USB host adapters. Add it as long as the ethernet service is here. + if (ctx.getSystemService(Context.ETHERNET_SERVICE) != null) { + addSupportedType(TYPE_ETHERNET); + } + + // Always add TYPE_VPN as a supported type + addSupportedType(TYPE_VPN); + } + + private void addSupportedType(int type) { if (mTypeLists[type] != null) { throw new IllegalStateException( "legacy list for type " + type + "already initialized"); @@ -743,6 +812,35 @@ public class ConnectivityService extends IConnectivityManager.Stub return null; } + public int getRestoreTimerForType(int type) { + synchronized (mTypeLists) { + if (mRestoreTimers == null) { + mRestoreTimers = loadRestoreTimers(); + } + return mRestoreTimers.getOrDefault(type, -1); + } + } + + private ArrayMap<Integer, Integer> loadRestoreTimers() { + final String[] configs = mService.mResources.get().getStringArray( + com.android.connectivity.resources.R.array + .config_legacy_networktype_restore_timers); + final ArrayMap<Integer, Integer> ret = new ArrayMap<>(configs.length); + for (final String config : configs) { + final String[] splits = TextUtils.split(config, ","); + if (splits.length != 2) { + logwtf("Invalid restore timer token count: " + config); + continue; + } + try { + ret.put(Integer.parseInt(splits[0]), Integer.parseInt(splits[1])); + } catch (NumberFormatException e) { + logwtf("Invalid restore timer number format: " + config, e); + } + } + return ret; + } + private void maybeLogBroadcast(NetworkAgentInfo nai, DetailedState state, int type, boolean isDefaultNetwork) { if (DBG) { @@ -1136,7 +1234,7 @@ public class ConnectivityService extends IConnectivityManager.Stub new ConnectivityDiagnosticsHandler(mHandlerThread.getLooper()); mReleasePendingIntentDelayMs = Settings.Secure.getInt(context.getContentResolver(), - Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS, 5_000); + ConnectivitySettingsManager.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS, 5_000); mLingerDelayMs = mSystemProperties.getInt(LINGER_DELAY_PROPERTY, DEFAULT_LINGER_DELAY_MS); // TODO: Consider making the timer customizable. @@ -1165,64 +1263,12 @@ public class ConnectivityService extends IConnectivityManager.Stub mNetTransitionWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); mPendingIntentWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); - mNetConfigs = new NetworkConfig[ConnectivityManager.MAX_NETWORK_TYPE+1]; - - // TODO: What is the "correct" way to do determine if this is a wifi only device? - boolean wifiOnly = mSystemProperties.getBoolean("ro.radio.noril", false); - log("wifiOnly=" + wifiOnly); - String[] naStrings = context.getResources().getStringArray( - com.android.internal.R.array.networkAttributes); - for (String naString : naStrings) { - try { - NetworkConfig n = new NetworkConfig(naString); - if (VDBG) log("naString=" + naString + " config=" + n); - if (n.type > ConnectivityManager.MAX_NETWORK_TYPE) { - loge("Error in networkAttributes - ignoring attempt to define type " + - n.type); - continue; - } - if (wifiOnly && ConnectivityManager.isNetworkTypeMobile(n.type)) { - log("networkAttributes - ignoring mobile as this dev is wifiOnly " + - n.type); - continue; - } - if (mNetConfigs[n.type] != null) { - loge("Error in networkAttributes - ignoring attempt to redefine type " + - n.type); - continue; - } - mLegacyTypeTracker.addSupportedType(n.type); - - mNetConfigs[n.type] = n; - mNetworksDefined++; - } catch(Exception e) { - // ignore it - leave the entry null - } - } - - // Forcibly add TYPE_VPN as a supported type, if it has not already been added via config. - if (mNetConfigs[TYPE_VPN] == null) { - // mNetConfigs is used only for "restore time", which isn't applicable to VPNs, so we - // don't need to add TYPE_VPN to mNetConfigs. - mLegacyTypeTracker.addSupportedType(TYPE_VPN); - mNetworksDefined++; // used only in the log() statement below. - } - - // Do the same for Ethernet, since it's often not specified in the configs, although many - // devices can use it via USB host adapters. - if (mNetConfigs[TYPE_ETHERNET] == null - && mContext.getSystemService(Context.ETHERNET_SERVICE) != null) { - mLegacyTypeTracker.addSupportedType(TYPE_ETHERNET); - mNetworksDefined++; - } - - if (VDBG) log("mNetworksDefined=" + mNetworksDefined); - - mProtectedNetworks = new ArrayList<Integer>(); + mLegacyTypeTracker.loadSupportedTypes(mContext, mTelephonyManager); + mProtectedNetworks = new ArrayList<>(); int[] protectedNetworks = context.getResources().getIntArray( com.android.internal.R.array.config_protectedNetworks); for (int p : protectedNetworks) { - if ((mNetConfigs[p] != null) && (mProtectedNetworks.contains(p) == false)) { + if (mLegacyTypeTracker.isTypeSupported(p) && !mProtectedNetworks.contains(p)) { mProtectedNetworks.add(p); } else { if (DBG) loge("Ignoring protectedNetwork " + p); @@ -1260,10 +1306,10 @@ public class ConnectivityService extends IConnectivityManager.Stub mQosCallbackTracker = new QosCallbackTracker(mHandler, mNetworkRequestCounter); final int dailyLimit = Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.NETWORK_SWITCH_NOTIFICATION_DAILY_LIMIT, + ConnectivitySettingsManager.NETWORK_SWITCH_NOTIFICATION_DAILY_LIMIT, LingerMonitor.DEFAULT_NOTIFICATION_DAILY_LIMIT); final long rateLimit = Settings.Global.getLong(mContext.getContentResolver(), - Settings.Global.NETWORK_SWITCH_NOTIFICATION_RATE_LIMIT_MILLIS, + ConnectivitySettingsManager.NETWORK_SWITCH_NOTIFICATION_RATE_LIMIT_MILLIS, LingerMonitor.DEFAULT_NOTIFICATION_RATE_LIMIT_MILLIS); mLingerMonitor = new LingerMonitor(mContext, mNotifier, dailyLimit, rateLimit); @@ -1289,11 +1335,16 @@ public class ConnectivityService extends IConnectivityManager.Stub } private static NetworkCapabilities createDefaultNetworkCapabilitiesForUid(int uid) { + return createDefaultNetworkCapabilitiesForUidRange(new UidRange(uid, uid)); + } + + private static NetworkCapabilities createDefaultNetworkCapabilitiesForUidRange( + @NonNull final UidRange uids) { final NetworkCapabilities netCap = new NetworkCapabilities(); netCap.addCapability(NET_CAPABILITY_INTERNET); netCap.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED); netCap.removeCapability(NET_CAPABILITY_NOT_VPN); - netCap.setSingleUid(uid); + netCap.setUids(Collections.singleton(uids)); return netCap; } @@ -1376,10 +1427,10 @@ public class ConnectivityService extends IConnectivityManager.Stub } private void handleConfigureAlwaysOnNetworks() { - handleAlwaysOnNetworkRequest( - mDefaultMobileDataRequest, Settings.Global.MOBILE_DATA_ALWAYS_ON, true); - handleAlwaysOnNetworkRequest(mDefaultWifiRequest, Settings.Global.WIFI_ALWAYS_REQUESTED, - false); + handleAlwaysOnNetworkRequest(mDefaultMobileDataRequest, + ConnectivitySettingsManager.MOBILE_DATA_ALWAYS_ON, true /* defaultValue */); + handleAlwaysOnNetworkRequest(mDefaultWifiRequest, + ConnectivitySettingsManager.WIFI_ALWAYS_REQUESTED, false /* defaultValue */); handleAlwaysOnNetworkRequest(mDefaultVehicleRequest, com.android.internal.R.bool.config_vehicleInternalNetworkAlwaysRequested); } @@ -1392,12 +1443,12 @@ public class ConnectivityService extends IConnectivityManager.Stub // Watch for whether or not to keep mobile data always on. mSettingsObserver.observe( - Settings.Global.getUriFor(Settings.Global.MOBILE_DATA_ALWAYS_ON), + Settings.Global.getUriFor(ConnectivitySettingsManager.MOBILE_DATA_ALWAYS_ON), EVENT_CONFIGURE_ALWAYS_ON_NETWORKS); // Watch for whether or not to keep wifi always on. mSettingsObserver.observe( - Settings.Global.getUriFor(Settings.Global.WIFI_ALWAYS_REQUESTED), + Settings.Global.getUriFor(ConnectivitySettingsManager.WIFI_ALWAYS_REQUESTED), EVENT_CONFIGURE_ALWAYS_ON_NETWORKS); } @@ -2603,13 +2654,6 @@ public class ConnectivityService extends IConnectivityManager.Stub } catch (RemoteException | ServiceSpecificException e) { loge("Can't set TCP buffer sizes:" + e); } - - final Integer rwndValue = Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.TCP_DEFAULT_INIT_RWND, - mSystemProperties.getInt("net.tcp.default_init_rwnd", 0)); - if (rwndValue != 0) { - mSystemProperties.setTcpInitRwnd(rwndValue); - } } @Override @@ -2626,9 +2670,8 @@ public class ConnectivityService extends IConnectivityManager.Stub // if the system property isn't set, use the value for the apn type int ret = RESTORE_DEFAULT_NETWORK_DELAY; - if ((networkType <= ConnectivityManager.MAX_NETWORK_TYPE) && - (mNetConfigs[networkType] != null)) { - ret = mNetConfigs[networkType].restoreTime; + if (mLegacyTypeTracker.isTypeSupported(networkType)) { + ret = mLegacyTypeTracker.getRestoreTimerForType(networkType); } return ret; } @@ -3067,7 +3110,8 @@ public class ConnectivityService extends IConnectivityManager.Stub nai.lastCaptivePortalDetected = visible; nai.everCaptivePortalDetected |= visible; if (nai.lastCaptivePortalDetected && - Settings.Global.CAPTIVE_PORTAL_MODE_AVOID == getCaptivePortalMode()) { + ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE_AVOID + == getCaptivePortalMode()) { if (DBG) log("Avoiding captive portal network: " + nai.toShortString()); nai.onPreventAutomaticReconnect(); teardownUnneededNetwork(nai); @@ -3178,8 +3222,8 @@ public class ConnectivityService extends IConnectivityManager.Stub private int getCaptivePortalMode() { return Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.CAPTIVE_PORTAL_MODE, - Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT); + ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE, + ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE_PROMPT); } private boolean maybeHandleNetworkAgentInfoMessage(Message msg) { @@ -3663,6 +3707,7 @@ public class ConnectivityService extends IConnectivityManager.Stub mNetworkRequestInfoLogs.log("REGISTER " + nri); for (final NetworkRequest req : nri.mRequests) { mNetworkRequests.put(req, nri); + // TODO: Consider update signal strength for other types. if (req.isListen()) { for (final NetworkAgentInfo network : mNetworkAgentInfos) { if (req.networkCapabilities.hasSignalStrength() @@ -3755,18 +3800,19 @@ public class ConnectivityService extends IConnectivityManager.Stub // listen requests won't keep up a network satisfying it. If this is not a multilayer // request, return immediately. For multilayer requests, check to see if any of the // multilayer requests may have a potential satisfier. - if (!nri.isMultilayerRequest() && nri.mRequests.get(0).isListen()) { + if (!nri.isMultilayerRequest() && (nri.mRequests.get(0).isListen() + || nri.mRequests.get(0).isListenForBest())) { return false; } for (final NetworkRequest req : nri.mRequests) { // This multilayer listen request is satisfied therefore no further requests need to be // evaluated deeming this network not a potential satisfier. - if (req.isListen() && nri.getActiveRequest() == req) { + if ((req.isListen() || req.isListenForBest()) && nri.getActiveRequest() == req) { return false; } // As non-multilayer listen requests have already returned, the below would only happen // for a multilayer request therefore continue to the next request if available. - if (req.isListen()) { + if (req.isListen() || req.isListenForBest()) { continue; } // If this Network is already the highest scoring Network for a request, or if @@ -4530,12 +4576,17 @@ public class ConnectivityService extends IConnectivityManager.Stub handleSetRequireVpnForUids(toBool(msg.arg1), (UidRange[]) msg.obj); break; case EVENT_SET_OEM_NETWORK_PREFERENCE: { - final Pair<OemNetworkPreferences, IOnSetOemNetworkPreferenceListener> arg = - (Pair<OemNetworkPreferences, - IOnSetOemNetworkPreferenceListener>) msg.obj; + final Pair<OemNetworkPreferences, IOnCompleteListener> arg = + (Pair<OemNetworkPreferences, IOnCompleteListener>) msg.obj; handleSetOemNetworkPreference(arg.first, arg.second); break; } + case EVENT_SET_PROFILE_NETWORK_PREFERENCE: { + final Pair<ProfileNetworkPreferences.Preference, IOnCompleteListener> arg = + (Pair<ProfileNetworkPreferences.Preference, IOnCompleteListener>) + msg.obj; + handleSetProfileNetworkPreference(arg.first, arg.second); + } case EVENT_REPORT_NETWORK_ACTIVITY: mNetworkActivityTracker.handleReportNetworkActivity(); break; @@ -4834,6 +4885,10 @@ public class ConnectivityService extends IConnectivityManager.Stub Log.wtf(TAG, s); } + private static void logwtf(String s, Throwable t) { + Log.wtf(TAG, s, t); + } + private static void loge(String s) { Log.e(TAG, s); } @@ -5106,6 +5161,9 @@ public class ConnectivityService extends IConnectivityManager.Stub private void onUserRemoved(UserHandle user) { mPermissionMonitor.onUserRemoved(user); + // If there was a network preference for this user, remove it. + handleSetProfileNetworkPreference(new ProfileNetworkPreferences.Preference(user, null), + null /* listener */); if (mOemNetworkPreferences.getNetworkPreferences().size() > 0) { handleSetOemNetworkPreference(mOemNetworkPreferences, null); } @@ -5549,8 +5607,10 @@ public class ConnectivityService extends IConnectivityManager.Stub // request if the app changes network state. http://b/29964605 enforceMeteredApnPolicy(networkCapabilities); break; - case TRACK_BEST: - throw new UnsupportedOperationException("Not implemented yet"); + case LISTEN_FOR_BEST: + enforceAccessPermission(); + networkCapabilities = new NetworkCapabilities(networkCapabilities); + break; default: throw new IllegalArgumentException("Unsupported request type " + reqType); } @@ -5558,11 +5618,17 @@ public class ConnectivityService extends IConnectivityManager.Stub ensureSufficientPermissionsForRequest(networkCapabilities, Binder.getCallingPid(), callingUid, callingPackageName); - // Set the UID range for this request to the single UID of the requester, or to an empty - // set of UIDs if the caller has the appropriate permission and UIDs have not been set. + // Enforce FOREGROUND if the caller does not have permission to use background network. + if (reqType == LISTEN_FOR_BEST) { + restrictBackgroundRequestForCaller(networkCapabilities); + } + + // Set the UID range for this request to the single UID of the requester, unless the + // requester has the permission to specify other UIDs. // This will overwrite any allowed UIDs in the requested capabilities. Though there // are no visible methods to set the UIDs, an app could use reflection to try and get // networks for other apps so it's essential that the UIDs are overwritten. + // Also set the requester UID and package name in the request. restrictRequestUidsForCallerAndSetRequestorInfo(networkCapabilities, callingUid, callingPackageName); @@ -5896,10 +5962,16 @@ public class ConnectivityService extends IConnectivityManager.Stub @GuardedBy("mBlockedAppUids") private final HashSet<Integer> mBlockedAppUids = new HashSet<>(); - // Current OEM network preferences. + // Current OEM network preferences. This object must only be written to on the handler thread. + // Since it is immutable and always non-null, other threads may read it if they only care + // about seeing a consistent object but not that it is current. @NonNull private OemNetworkPreferences mOemNetworkPreferences = new OemNetworkPreferences.Builder().build(); + // Current per-profile network preferences. This object follows the same threading rules as + // the OEM network preferences above. + @NonNull + private ProfileNetworkPreferences mProfileNetworkPreferences = new ProfileNetworkPreferences(); // The always-on request for an Internet-capable network that apps without a specific default // fall back to. @@ -8088,7 +8160,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } settingUrl = Settings.Global.getString(mContext.getContentResolver(), - Settings.Global.CAPTIVE_PORTAL_HTTP_URL); + ConnectivitySettingsManager.CAPTIVE_PORTAL_HTTP_URL); if (!TextUtils.isEmpty(settingUrl)) { return settingUrl; } @@ -8170,11 +8242,11 @@ public class ConnectivityService extends IConnectivityManager.Stub // restore private DNS settings to default mode (opportunistic) if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_PRIVATE_DNS)) { Settings.Global.putString(mContext.getContentResolver(), - Settings.Global.PRIVATE_DNS_MODE, PRIVATE_DNS_MODE_OPPORTUNISTIC); + ConnectivitySettingsManager.PRIVATE_DNS_MODE, PRIVATE_DNS_MODE_OPPORTUNISTIC); } Settings.Global.putString(mContext.getContentResolver(), - Settings.Global.NETWORK_AVOID_BAD_WIFI, null); + ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI, null); } @Override @@ -8879,13 +8951,13 @@ public class ConnectivityService extends IConnectivityManager.Stub private int transportTypeToLegacyType(int type) { switch (type) { case NetworkCapabilities.TRANSPORT_CELLULAR: - return ConnectivityManager.TYPE_MOBILE; + return TYPE_MOBILE; case NetworkCapabilities.TRANSPORT_WIFI: - return ConnectivityManager.TYPE_WIFI; + return TYPE_WIFI; case NetworkCapabilities.TRANSPORT_BLUETOOTH: - return ConnectivityManager.TYPE_BLUETOOTH; + return TYPE_BLUETOOTH; case NetworkCapabilities.TRANSPORT_ETHERNET: - return ConnectivityManager.TYPE_ETHERNET; + return TYPE_ETHERNET; default: loge("Unexpected transport in transportTypeToLegacyType: " + type); } @@ -8926,13 +8998,13 @@ public class ConnectivityService extends IConnectivityManager.Stub if (networkAgent.networkCapabilities.hasTransport( NetworkCapabilities.TRANSPORT_CELLULAR)) { timeout = Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.DATA_ACTIVITY_TIMEOUT_MOBILE, + ConnectivitySettingsManager.DATA_ACTIVITY_TIMEOUT_MOBILE, 10); type = NetworkCapabilities.TRANSPORT_CELLULAR; } else if (networkAgent.networkCapabilities.hasTransport( NetworkCapabilities.TRANSPORT_WIFI)) { timeout = Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.DATA_ACTIVITY_TIMEOUT_WIFI, + ConnectivitySettingsManager.DATA_ACTIVITY_TIMEOUT_WIFI, 15); type = NetworkCapabilities.TRANSPORT_WIFI; } else { @@ -9100,6 +9172,143 @@ public class ConnectivityService extends IConnectivityManager.Stub mQosCallbackTracker.unregisterCallback(callback); } + // Network preference per-profile and OEM network preferences can't be set at the same + // time, because it is unclear what should happen if both preferences are active for + // one given UID. To make it possible, the stack would have to clarify what would happen + // in case both are active at the same time. The implementation may have to be adjusted + // to implement the resulting rules. For example, a priority could be defined between them, + // where the OEM preference would be considered less or more important than the enterprise + // preference ; this would entail implementing the priorities somehow, e.g. by doing + // UID arithmetic with UID ranges or passing a priority to netd so that the routing rules + // are set at the right level. Other solutions are possible, e.g. merging of the + // preferences for the relevant UIDs. + private static void throwConcurrentPreferenceException() { + throw new IllegalStateException("Can't set NetworkPreferenceForUser and " + + "set OemNetworkPreference at the same time"); + } + + /** + * Request that a user profile is put by default on a network matching a given preference. + * + * See the documentation for the individual preferences for a description of the supported + * behaviors. + * + * @param profile the profile concerned. + * @param preference the preference for this profile, as one of the PROFILE_NETWORK_PREFERENCE_* + * constants. + * @param listener an optional listener to listen for completion of the operation. + */ + @Override + public void setProfileNetworkPreference(@NonNull final UserHandle profile, + @ConnectivityManager.ProfileNetworkPreference final int preference, + @Nullable final IOnCompleteListener listener) { + Objects.requireNonNull(profile); + PermissionUtils.enforceNetworkStackPermission(mContext); + if (DBG) { + log("setProfileNetworkPreference " + profile + " to " + preference); + } + if (profile.getIdentifier() < 0) { + throw new IllegalArgumentException("Must explicitly specify a user handle (" + + "UserHandle.CURRENT not supported)"); + } + final UserManager um; + try { + um = mContext.createContextAsUser(profile, 0 /* flags */) + .getSystemService(UserManager.class); + } catch (IllegalStateException e) { + throw new IllegalArgumentException("Profile does not exist"); + } + if (!um.isManagedProfile()) { + throw new IllegalArgumentException("Profile must be a managed profile"); + } + // Strictly speaking, mOemNetworkPreferences should only be touched on the + // handler thread. However it is an immutable object, so reading the reference is + // safe - it's just possible the value is slightly outdated. For the final check, + // see #handleSetProfileNetworkPreference. But if this can be caught here it is a + // lot easier to understand, so opportunistically check it. + if (!mOemNetworkPreferences.isEmpty()) { + throwConcurrentPreferenceException(); + } + final NetworkCapabilities nc; + switch (preference) { + case ConnectivityManager.PROFILE_NETWORK_PREFERENCE_DEFAULT: + nc = null; + break; + case ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE: + final UidRange uids = UidRange.createForUser(profile); + nc = createDefaultNetworkCapabilitiesForUidRange(uids); + nc.addCapability(NET_CAPABILITY_ENTERPRISE); + nc.removeCapability(NET_CAPABILITY_NOT_RESTRICTED); + break; + default: + throw new IllegalArgumentException( + "Invalid preference in setProfileNetworkPreference"); + } + mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_PROFILE_NETWORK_PREFERENCE, + new Pair<>(new ProfileNetworkPreferences.Preference(profile, nc), listener))); + } + + private void validateNetworkCapabilitiesOfProfileNetworkPreference( + @Nullable final NetworkCapabilities nc) { + if (null == nc) return; // Null caps are always allowed. It means to remove the setting. + ensureRequestableCapabilities(nc); + } + + private ArraySet<NetworkRequestInfo> createNrisFromProfileNetworkPreferences( + @NonNull final ProfileNetworkPreferences prefs) { + final ArraySet<NetworkRequestInfo> result = new ArraySet<>(); + for (final ProfileNetworkPreferences.Preference pref : prefs.preferences) { + // The NRI for a user should be comprised of two layers: + // - The request for the capabilities + // - The request for the default network, for fallback. Create an image of it to + // have the correct UIDs in it (also a request can only be part of one NRI, because + // of lookups in 1:1 associations like mNetworkRequests). + // Note that denying a fallback can be implemented simply by not adding the second + // request. + final ArrayList<NetworkRequest> nrs = new ArrayList<>(); + nrs.add(createNetworkRequest(NetworkRequest.Type.REQUEST, pref.capabilities)); + nrs.add(createDefaultRequest()); + setNetworkRequestUids(nrs, pref.capabilities.getUids()); + final NetworkRequestInfo nri = new NetworkRequestInfo(nrs); + result.add(nri); + } + return result; + } + + private void handleSetProfileNetworkPreference( + @NonNull final ProfileNetworkPreferences.Preference preference, + @Nullable final IOnCompleteListener listener) { + // setProfileNetworkPreference and setOemNetworkPreference are mutually exclusive, in + // particular because it's not clear what preference should win in case both apply + // to the same app. + // The binder call has already checked this, but as mOemNetworkPreferences is only + // touched on the handler thread, it's theoretically not impossible that it has changed + // since. + if (!mOemNetworkPreferences.isEmpty()) { + // This may happen on a device with an OEM preference set when a user is removed. + // In this case, it's safe to ignore. In particular this happens in the tests. + loge("handleSetProfileNetworkPreference, but OEM network preferences not empty"); + return; + } + + validateNetworkCapabilitiesOfProfileNetworkPreference(preference.capabilities); + + mProfileNetworkPreferences = mProfileNetworkPreferences.plus(preference); + final ArraySet<NetworkRequestInfo> nris = + createNrisFromProfileNetworkPreferences(mProfileNetworkPreferences); + replaceDefaultNetworkRequestsForPreference(nris); + // Finally, rematch. + rematchAllNetworksAndRequests(); + + if (null != listener) { + try { + listener.onComplete(); + } catch (RemoteException e) { + loge("Listener for setProfileNetworkPreference has died"); + } + } + } + private void enforceAutomotiveDevice() { final boolean isAutomotiveDevice = mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE); @@ -9118,17 +9327,26 @@ public class ConnectivityService extends IConnectivityManager.Stub * Calling this will overwrite the existing preference. * * @param preference {@link OemNetworkPreferences} The application network preference to be set. - * @param listener {@link ConnectivityManager.OnSetOemNetworkPreferenceListener} Listener used + * @param listener {@link ConnectivityManager.OnCompleteListener} Listener used * to communicate completion of setOemNetworkPreference(); */ @Override public void setOemNetworkPreference( @NonNull final OemNetworkPreferences preference, - @Nullable final IOnSetOemNetworkPreferenceListener listener) { + @Nullable final IOnCompleteListener listener) { enforceAutomotiveDevice(); enforceOemNetworkPreferencesPermission(); + if (!mProfileNetworkPreferences.isEmpty()) { + // Strictly speaking, mProfileNetworkPreferences should only be touched on the + // handler thread. However it is an immutable object, so reading the reference is + // safe - it's just possible the value is slightly outdated. For the final check, + // see #handleSetOemPreference. But if this can be caught here it is a + // lot easier to understand, so opportunistically check it. + throwConcurrentPreferenceException(); + } + Objects.requireNonNull(preference, "OemNetworkPreferences must be non-null"); validateOemNetworkPreferences(preference); mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_OEM_NETWORK_PREFERENCE, @@ -9147,11 +9365,22 @@ public class ConnectivityService extends IConnectivityManager.Stub private void handleSetOemNetworkPreference( @NonNull final OemNetworkPreferences preference, - @Nullable final IOnSetOemNetworkPreferenceListener listener) { + @Nullable final IOnCompleteListener listener) { Objects.requireNonNull(preference, "OemNetworkPreferences must be non-null"); if (DBG) { log("set OEM network preferences :" + preference.toString()); } + // setProfileNetworkPreference and setOemNetworkPreference are mutually exclusive, in + // particular because it's not clear what preference should win in case both apply + // to the same app. + // The binder call has already checked this, but as mOemNetworkPreferences is only + // touched on the handler thread, it's theoretically not impossible that it has changed + // since. + if (!mProfileNetworkPreferences.isEmpty()) { + logwtf("handleSetOemPreference, but per-profile network preferences not empty"); + return; + } + final ArraySet<NetworkRequestInfo> nris = new OemNetworkRequestFactory().createNrisFromOemNetworkPreferences(preference); replaceDefaultNetworkRequestsForPreference(nris); diff --git a/services/core/java/com/android/server/PersistentDataBlockService.java b/services/core/java/com/android/server/PersistentDataBlockService.java index 00d8b0f1bed4..351e616b433b 100644 --- a/services/core/java/com/android/server/PersistentDataBlockService.java +++ b/services/core/java/com/android/server/PersistentDataBlockService.java @@ -23,6 +23,7 @@ import android.app.ActivityManager; import android.content.Context; import android.content.pm.PackageManager; import android.os.Binder; +import android.os.FileUtils; import android.os.IBinder; import android.os.RemoteException; import android.os.SystemProperties; @@ -103,6 +104,9 @@ import java.util.concurrent.TimeUnit; public class PersistentDataBlockService extends SystemService { private static final String TAG = PersistentDataBlockService.class.getSimpleName(); + private static final String GSI_SANDBOX = "/data/gsi_persistent_data"; + private static final String GSI_RUNNING_PROP = "ro.gsid.image_running"; + private static final String PERSISTENT_DATA_BLOCK_PROP = "ro.frp.pst"; private static final int HEADER_SIZE = 8; // Magic number to mark block device as adhering to the format consumed by this service @@ -127,12 +131,13 @@ public class PersistentDataBlockService extends SystemService { private static final String FLASH_LOCK_UNLOCKED = "0"; private final Context mContext; - private final String mDataBlockFile; + private final boolean mIsRunningDSU; private final Object mLock = new Object(); private final CountDownLatch mInitDoneSignal = new CountDownLatch(1); private int mAllowedUid = -1; private long mBlockDeviceSize; + private String mDataBlockFile; @GuardedBy("mLock") private boolean mIsWritable = true; @@ -141,6 +146,7 @@ public class PersistentDataBlockService extends SystemService { super(context); mContext = context; mDataBlockFile = SystemProperties.get(PERSISTENT_DATA_BLOCK_PROP); + mIsRunningDSU = SystemProperties.getBoolean(GSI_RUNNING_PROP, false); mBlockDeviceSize = -1; // Load lazily } @@ -284,14 +290,28 @@ public class PersistentDataBlockService extends SystemService { return true; } + private FileOutputStream getBlockOutputStream() throws IOException { + if (!mIsRunningDSU) { + return new FileOutputStream(new File(mDataBlockFile)); + } else { + File sandbox = new File(GSI_SANDBOX); + File realpdb = new File(SystemProperties.get(PERSISTENT_DATA_BLOCK_PROP)); + if (!sandbox.exists()) { + FileUtils.copy(realpdb, sandbox); + mDataBlockFile = GSI_SANDBOX; + } + Slog.i(TAG, "PersistentDataBlock copy-on-write"); + return new FileOutputStream(sandbox); + } + } + private boolean computeAndWriteDigestLocked() { byte[] digest = computeDigestLocked(null); if (digest != null) { DataOutputStream outputStream; try { - outputStream = new DataOutputStream( - new FileOutputStream(new File(mDataBlockFile))); - } catch (FileNotFoundException e) { + outputStream = new DataOutputStream(getBlockOutputStream()); + } catch (IOException e) { Slog.e(TAG, "partition not available?", e); return false; } @@ -356,8 +376,8 @@ public class PersistentDataBlockService extends SystemService { private void formatPartitionLocked(boolean setOemUnlockEnabled) { DataOutputStream outputStream; try { - outputStream = new DataOutputStream(new FileOutputStream(new File(mDataBlockFile))); - } catch (FileNotFoundException e) { + outputStream = new DataOutputStream(getBlockOutputStream()); + } catch (IOException e) { Slog.e(TAG, "partition not available?", e); return; } @@ -382,8 +402,8 @@ public class PersistentDataBlockService extends SystemService { private void doSetOemUnlockEnabledLocked(boolean enabled) { FileOutputStream outputStream; try { - outputStream = new FileOutputStream(new File(mDataBlockFile)); - } catch (FileNotFoundException e) { + outputStream = getBlockOutputStream(); + } catch (IOException e) { Slog.e(TAG, "partition not available", e); return; } @@ -459,8 +479,8 @@ public class PersistentDataBlockService extends SystemService { DataOutputStream outputStream; try { - outputStream = new DataOutputStream(new FileOutputStream(new File(mDataBlockFile))); - } catch (FileNotFoundException e) { + outputStream = new DataOutputStream(getBlockOutputStream()); + } catch (IOException e) { Slog.e(TAG, "partition not available?", e); return -1; } @@ -545,6 +565,17 @@ public class PersistentDataBlockService extends SystemService { public void wipe() { enforceOemUnlockWritePermission(); + if (mIsRunningDSU) { + File sandbox = new File(GSI_SANDBOX); + if (sandbox.exists()) { + if (sandbox.delete()) { + mDataBlockFile = SystemProperties.get(PERSISTENT_DATA_BLOCK_PROP); + } else { + Slog.e(TAG, "Failed to wipe sandbox persistent data block"); + } + } + return; + } synchronized (mLock) { int ret = nativeWipe(mDataBlockFile); @@ -704,8 +735,8 @@ public class PersistentDataBlockService extends SystemService { private void writeDataBuffer(long offset, ByteBuffer dataBuffer) { FileOutputStream outputStream; try { - outputStream = new FileOutputStream(new File(mDataBlockFile)); - } catch (FileNotFoundException e) { + outputStream = getBlockOutputStream(); + } catch (IOException e) { Slog.e(TAG, "partition not available", e); return; } diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java index dce919db1b07..e8ef7e2c5a2c 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -60,6 +60,7 @@ import android.telephony.CellSignalStrengthNr; import android.telephony.CellSignalStrengthTdscdma; import android.telephony.CellSignalStrengthWcdma; import android.telephony.DisconnectCause; +import android.telephony.LinkCapacityEstimate; import android.telephony.LocationAccessPolicy; import android.telephony.PhoneCapability; import android.telephony.PhoneStateListener; @@ -320,6 +321,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { private Map<Integer, Long> mAllowedNetworkTypesList; + private List<List<LinkCapacityEstimate>> mLinkCapacityEstimateLists; + /** * Per-phone map of precise data connection state. The key of the map is the pair of transport * type and APN setting. This is the cache to prevent redundant callbacks to the listeners. @@ -350,6 +353,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { TelephonyCallback.EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED); REQUIRE_PRECISE_PHONE_STATE_PERMISSION.add( TelephonyCallback.EVENT_DATA_ENABLED_CHANGED); + REQUIRE_PRECISE_PHONE_STATE_PERMISSION.add( + TelephonyCallback.EVENT_LINK_CAPACITY_ESTIMATE_CHANGED); } private boolean isLocationPermissionRequired(Set<Integer> events) { @@ -535,6 +540,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { cutListToSize(mPreciseDataConnectionStates, mNumPhones); cutListToSize(mBarringInfo, mNumPhones); cutListToSize(mPhysicalChannelConfigs, mNumPhones); + cutListToSize(mLinkCapacityEstimateLists, mNumPhones); return; } @@ -571,6 +577,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mPhysicalChannelConfigs.add(i, new PhysicalChannelConfig.Builder().build()); mIsDataEnabled[i] = false; mDataEnabledReason[i] = TelephonyManager.DATA_ENABLED_REASON_USER; + mLinkCapacityEstimateLists.add(i, new ArrayList<>()); } } @@ -633,6 +640,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mIsDataEnabled = new boolean[numPhones]; mDataEnabledReason = new int[numPhones]; mAllowedNetworkTypesList = new HashMap<>(); + mLinkCapacityEstimateLists = new ArrayList<>(); for (int i = 0; i < numPhones; i++) { mCallState[i] = TelephonyManager.CALL_STATE_IDLE; mDataActivity[i] = TelephonyManager.DATA_ACTIVITY_NONE; @@ -665,6 +673,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mPhysicalChannelConfigs.add(i, new PhysicalChannelConfig.Builder().build()); mIsDataEnabled[i] = false; mDataEnabledReason[i] = TelephonyManager.DATA_ENABLED_REASON_USER; + mLinkCapacityEstimateLists.add(i, new ArrayList<>()); } mAppOps = mContext.getSystemService(AppOpsManager.class); @@ -1173,6 +1182,17 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { remove(r.binder); } } + if (events.contains( + TelephonyCallback.EVENT_LINK_CAPACITY_ESTIMATE_CHANGED)) { + try { + if (mLinkCapacityEstimateLists.get(phoneId) != null) { + r.callback.onLinkCapacityEstimateChanged(mLinkCapacityEstimateLists + .get(phoneId)); + } + } catch (RemoteException ex) { + remove(r.binder); + } + } } } } @@ -2456,6 +2476,42 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } } + /** + * Notify that the link capacity estimate has changed. + * @param phoneId the phone id. + * @param subId the subscription id. + * @param linkCapacityEstimateList a list of {@link LinkCapacityEstimate} + */ + public void notifyLinkCapacityEstimateChanged(int phoneId, int subId, + List<LinkCapacityEstimate> linkCapacityEstimateList) { + if (!checkNotifyPermission("notifyLinkCapacityEstimateChanged()")) { + return; + } + + if (VDBG) { + log("notifyLinkCapacityEstimateChanged: linkCapacityEstimateList =" + + linkCapacityEstimateList); + } + + synchronized (mRecords) { + if (validatePhoneId(phoneId)) { + mLinkCapacityEstimateLists.set(phoneId, linkCapacityEstimateList); + for (Record r : mRecords) { + if (r.matchTelephonyCallbackEvent( + TelephonyCallback.EVENT_LINK_CAPACITY_ESTIMATE_CHANGED) + && idMatch(r.subId, subId, phoneId)) { + try { + r.callback.onLinkCapacityEstimateChanged(linkCapacityEstimateList); + } catch (RemoteException ex) { + mRemoveList.add(r.binder); + } + } + } + } + handleRemoveListLocked(); + } + } + @Override public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); @@ -2500,6 +2556,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { pw.println("mTelephonyDisplayInfo=" + mTelephonyDisplayInfos[i]); pw.println("mIsDataEnabled=" + mIsDataEnabled); pw.println("mDataEnabledReason=" + mDataEnabledReason); + pw.println("mLinkCapacityEstimateList=" + mLinkCapacityEstimateLists.get(i)); pw.decreaseIndent(); } pw.println("mCarrierNetworkChangeState=" + mCarrierNetworkChangeState); @@ -2764,6 +2821,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { LocationAccessPolicy.LocationPermissionQuery.Builder locationQueryBuilder = new LocationAccessPolicy.LocationPermissionQuery.Builder() .setCallingPackage(callingPackage) + .setCallingFeatureId(callingFeatureId) .setMethod(message + " events: " + events) .setCallingPid(Binder.getCallingPid()) .setCallingUid(Binder.getCallingUid()); @@ -2913,6 +2971,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { LocationAccessPolicy.LocationPermissionQuery query = new LocationAccessPolicy.LocationPermissionQuery.Builder() .setCallingPackage(r.callingPackage) + .setCallingFeatureId(r.callingFeatureId) .setCallingPid(r.callerPid) .setCallingUid(r.callerUid) .setMethod("TelephonyRegistry push") @@ -2936,6 +2995,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { LocationAccessPolicy.LocationPermissionQuery query = new LocationAccessPolicy.LocationPermissionQuery.Builder() .setCallingPackage(r.callingPackage) + .setCallingFeatureId(r.callingFeatureId) .setCallingPid(r.callerPid) .setCallingUid(r.callerUid) .setMethod("TelephonyRegistry push") diff --git a/services/core/java/com/android/server/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java index 1ef93f4da255..6c18cdea51fa 100644 --- a/services/core/java/com/android/server/VcnManagementService.java +++ b/services/core/java/com/android/server/VcnManagementService.java @@ -64,7 +64,7 @@ import android.util.Slog; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting.Visibility; -import com.android.internal.util.LocationPermissionChecker; +import com.android.net.module.util.LocationPermissionChecker; import com.android.server.vcn.TelephonySubscriptionTracker; import com.android.server.vcn.Vcn; import com.android.server.vcn.VcnContext; diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java index a8478476b7e6..a37115d1f5c7 100644 --- a/services/core/java/com/android/server/Watchdog.java +++ b/services/core/java/com/android/server/Watchdog.java @@ -75,7 +75,8 @@ public class Watchdog extends Thread { // can trigger the watchdog. // Note 2: The debug value is already below the wait time in ZygoteConnection. Wrapped // applications may not work with a debug build. CTS will fail. - private static final long DEFAULT_TIMEOUT = DB ? 10 * 1000 : 60 * 1000; + private static final long DEFAULT_TIMEOUT = + (DB ? 10 * 1000 : 60 * 1000) * Build.HW_TIMEOUT_MULTIPLIER; private static final long CHECK_INTERVAL = DEFAULT_TIMEOUT / 2; // These are temporally ordered: larger values as lateness increases diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index dd0e1f6458f9..ca4b9c38b593 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -140,14 +140,14 @@ public final class ActiveServices { private static final int DEBUG_FGS_ENFORCE_TYPE = 1; // How long we wait for a service to finish executing. - static final int SERVICE_TIMEOUT = 20*1000; + static final int SERVICE_TIMEOUT = 20 * 1000 * Build.HW_TIMEOUT_MULTIPLIER; // How long we wait for a service to finish executing. static final int SERVICE_BACKGROUND_TIMEOUT = SERVICE_TIMEOUT * 10; // How long the startForegroundService() grace period is to get around to // calling startForeground() before we ANR + stop it. - static final int SERVICE_START_FOREGROUND_TIMEOUT = 10*1000; + static final int SERVICE_START_FOREGROUND_TIMEOUT = 10 * 1000 * Build.HW_TIMEOUT_MULTIPLIER; final ActivityManagerService mAm; diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index bd08b628483e..cc5a25a57e38 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -478,7 +478,7 @@ public class ActivityManagerService extends IActivityManager.Stub // How long we wait for a launched process to attach to the activity manager // before we decide it's never going to come up for real. - static final int PROC_START_TIMEOUT = 10*1000; + static final int PROC_START_TIMEOUT = 10 * 1000 * Build.HW_TIMEOUT_MULTIPLIER; // How long we wait to kill an application zygote, after the last process using // it has gone away. static final int KILL_APP_ZYGOTE_DELAY_MS = 5 * 1000; @@ -490,8 +490,8 @@ public class ActivityManagerService extends IActivityManager.Stub static final int PROC_START_TIMEOUT_WITH_WRAPPER = 1200*1000; // How long we allow a receiver to run before giving up on it. - static final int BROADCAST_FG_TIMEOUT = 10*1000; - static final int BROADCAST_BG_TIMEOUT = 60*1000; + static final int BROADCAST_FG_TIMEOUT = 10 * 1000 * Build.HW_TIMEOUT_MULTIPLIER; + static final int BROADCAST_BG_TIMEOUT = 60 * 1000 * Build.HW_TIMEOUT_MULTIPLIER; public static final int MY_PID = myPid(); @@ -573,7 +573,8 @@ public class ActivityManagerService extends IActivityManager.Stub private static final int MAX_BUGREPORT_TITLE_SIZE = 50; private static final int MAX_BUGREPORT_DESCRIPTION_SIZE = 150; - private static final int NATIVE_DUMP_TIMEOUT_MS = 2000; // 2 seconds; + private static final int NATIVE_DUMP_TIMEOUT_MS = + 2000 * Build.HW_TIMEOUT_MULTIPLIER; // 2 seconds; private static final int JAVA_DUMP_MINIMUM_SIZE = 100; // 100 bytes. OomAdjuster mOomAdjuster; diff --git a/services/core/java/com/android/server/am/BroadcastConstants.java b/services/core/java/com/android/server/am/BroadcastConstants.java index be17b1bc600c..54b3e648c9bc 100644 --- a/services/core/java/com/android/server/am/BroadcastConstants.java +++ b/services/core/java/com/android/server/am/BroadcastConstants.java @@ -18,6 +18,7 @@ package com.android.server.am; import android.content.ContentResolver; import android.database.ContentObserver; +import android.os.Build; import android.os.Handler; import android.provider.Settings; import android.util.KeyValueListParser; @@ -42,12 +43,13 @@ public class BroadcastConstants { "bcast_allow_bg_activity_start_timeout"; // All time intervals are in milliseconds - private static final long DEFAULT_TIMEOUT = 10_000; - private static final long DEFAULT_SLOW_TIME = 5_000; - private static final long DEFAULT_DEFERRAL = 5_000; + private static final long DEFAULT_TIMEOUT = 10_000 * Build.HW_TIMEOUT_MULTIPLIER; + private static final long DEFAULT_SLOW_TIME = 5_000 * Build.HW_TIMEOUT_MULTIPLIER; + private static final long DEFAULT_DEFERRAL = 5_000 * Build.HW_TIMEOUT_MULTIPLIER; private static final float DEFAULT_DEFERRAL_DECAY_FACTOR = 0.75f; private static final long DEFAULT_DEFERRAL_FLOOR = 0; - private static final long DEFAULT_ALLOW_BG_ACTIVITY_START_TIMEOUT = 10_000; + private static final long DEFAULT_ALLOW_BG_ACTIVITY_START_TIMEOUT = + 10_000 * Build.HW_TIMEOUT_MULTIPLIER; // All time constants are in milliseconds diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java index d2b642c21713..b355730c6450 100644 --- a/services/core/java/com/android/server/clipboard/ClipboardService.java +++ b/services/core/java/com/android/server/clipboard/ClipboardService.java @@ -158,7 +158,7 @@ public class ClipboardService extends SystemService { private static final String TAG = "ClipboardService"; private static final boolean IS_EMULATOR = - SystemProperties.getBoolean("ro.kernel.qemu", false); + SystemProperties.getBoolean("ro.boot.qemu", false); private final ActivityManagerInternal mAmInternal; private final IUriGrantsManager mUgm; diff --git a/services/core/java/com/android/server/connectivity/DnsManager.java b/services/core/java/com/android/server/connectivity/DnsManager.java index 7a5abf807fbb..ffeb77d1d109 100644 --- a/services/core/java/com/android/server/connectivity/DnsManager.java +++ b/services/core/java/com/android/server/connectivity/DnsManager.java @@ -18,15 +18,15 @@ package com.android.server.connectivity; import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF; import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME; +import static android.net.ConnectivitySettingsManager.DNS_RESOLVER_MAX_SAMPLES; +import static android.net.ConnectivitySettingsManager.DNS_RESOLVER_MIN_SAMPLES; +import static android.net.ConnectivitySettingsManager.DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS; +import static android.net.ConnectivitySettingsManager.DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT; +import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_DEFAULT_MODE; +import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE; +import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_SPECIFIER; import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.VALIDATION_RESULT_FAILURE; import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.VALIDATION_RESULT_SUCCESS; -import static android.provider.Settings.Global.DNS_RESOLVER_MAX_SAMPLES; -import static android.provider.Settings.Global.DNS_RESOLVER_MIN_SAMPLES; -import static android.provider.Settings.Global.DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS; -import static android.provider.Settings.Global.DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT; -import static android.provider.Settings.Global.PRIVATE_DNS_DEFAULT_MODE; -import static android.provider.Settings.Global.PRIVATE_DNS_MODE; -import static android.provider.Settings.Global.PRIVATE_DNS_SPECIFIER; import android.annotation.NonNull; import android.content.ContentResolver; @@ -127,13 +127,17 @@ public class DnsManager { private static final int DNS_RESOLVER_DEFAULT_MIN_SAMPLES = 8; private static final int DNS_RESOLVER_DEFAULT_MAX_SAMPLES = 64; - public static PrivateDnsConfig getPrivateDnsConfig(ContentResolver cr) { - final String mode = ConnectivityManager.getPrivateDnsMode(cr); + /** + * Get PrivateDnsConfig. + */ + public static PrivateDnsConfig getPrivateDnsConfig(Context context) { + final String mode = ConnectivityManager.getPrivateDnsMode(context); final boolean useTls = !TextUtils.isEmpty(mode) && !PRIVATE_DNS_MODE_OFF.equals(mode); if (PRIVATE_DNS_MODE_PROVIDER_HOSTNAME.equals(mode)) { - final String specifier = getStringSetting(cr, PRIVATE_DNS_SPECIFIER); + final String specifier = getStringSetting(context.getContentResolver(), + PRIVATE_DNS_SPECIFIER); return new PrivateDnsConfig(specifier, null); } @@ -268,7 +272,7 @@ public class DnsManager { } public PrivateDnsConfig getPrivateDnsConfig() { - return getPrivateDnsConfig(mContentResolver); + return getPrivateDnsConfig(mContext); } public void removeNetwork(Network network) { diff --git a/services/core/java/com/android/server/connectivity/MockableSystemProperties.java b/services/core/java/com/android/server/connectivity/MockableSystemProperties.java index ef767341d609..a25b89ac039a 100644 --- a/services/core/java/com/android/server/connectivity/MockableSystemProperties.java +++ b/services/core/java/com/android/server/connectivity/MockableSystemProperties.java @@ -17,7 +17,6 @@ package com.android.server.connectivity; import android.os.SystemProperties; -import android.sysprop.NetworkProperties; public class MockableSystemProperties { @@ -32,10 +31,4 @@ public class MockableSystemProperties { public boolean getBoolean(String key, boolean def) { return SystemProperties.getBoolean(key, def); } - /** - * Set net.tcp_def_init_rwnd to the tcp initial receive window size. - */ - public void setTcpInitRwnd(int value) { - NetworkProperties.tcp_init_rwnd(value); - } } diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java index 9dcc55b81a58..e44dcf5975f1 100644 --- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java +++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java @@ -719,6 +719,7 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { break; case LISTEN: + case LISTEN_FOR_BEST: case TRACK_DEFAULT: case TRACK_SYSTEM_DEFAULT: break; diff --git a/services/core/java/com/android/server/connectivity/ProfileNetworkPreferences.java b/services/core/java/com/android/server/connectivity/ProfileNetworkPreferences.java new file mode 100644 index 000000000000..dd2815d9e2e3 --- /dev/null +++ b/services/core/java/com/android/server/connectivity/ProfileNetworkPreferences.java @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.connectivity; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.net.NetworkCapabilities; +import android.os.UserHandle; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * A data class containing all the per-profile network preferences. + * + * A given profile can only have one preference. + */ +public class ProfileNetworkPreferences { + /** + * A single preference, as it applies to a given user profile. + */ + public static class Preference { + @NonNull public final UserHandle user; + // Capabilities are only null when sending an object to remove the setting for a user + @Nullable public final NetworkCapabilities capabilities; + + public Preference(@NonNull final UserHandle user, + @Nullable final NetworkCapabilities capabilities) { + this.user = user; + this.capabilities = null == capabilities ? null : new NetworkCapabilities(capabilities); + } + + /** toString */ + public String toString() { + return "[ProfileNetworkPreference user=" + user + " caps=" + capabilities + "]"; + } + } + + @NonNull public final List<Preference> preferences; + + public ProfileNetworkPreferences() { + preferences = Collections.EMPTY_LIST; + } + + private ProfileNetworkPreferences(@NonNull final List<Preference> list) { + preferences = Collections.unmodifiableList(list); + } + + /** + * Returns a new object consisting of this object plus the passed preference. + * + * If a preference already exists for the same user, it will be replaced by the passed + * preference. Passing a Preference object containing a null capabilities object is equivalent + * to (and indeed, implemented as) removing the preference for this user. + */ + public ProfileNetworkPreferences plus(@NonNull final Preference pref) { + final ArrayList<Preference> newPrefs = new ArrayList<>(); + for (final Preference existingPref : preferences) { + if (!existingPref.user.equals(pref.user)) { + newPrefs.add(existingPref); + } + } + if (null != pref.capabilities) { + newPrefs.add(pref); + } + return new ProfileNetworkPreferences(newPrefs); + } + + public boolean isEmpty() { + return preferences.isEmpty(); + } +} diff --git a/services/core/java/com/android/server/connectivity/ProxyTracker.java b/services/core/java/com/android/server/connectivity/ProxyTracker.java index 8b9c83678777..f8833071d1bf 100644 --- a/services/core/java/com/android/server/connectivity/ProxyTracker.java +++ b/services/core/java/com/android/server/connectivity/ProxyTracker.java @@ -16,10 +16,10 @@ package com.android.server.connectivity; -import static android.provider.Settings.Global.GLOBAL_HTTP_PROXY_EXCLUSION_LIST; -import static android.provider.Settings.Global.GLOBAL_HTTP_PROXY_HOST; -import static android.provider.Settings.Global.GLOBAL_HTTP_PROXY_PAC; -import static android.provider.Settings.Global.GLOBAL_HTTP_PROXY_PORT; +import static android.net.ConnectivitySettingsManager.GLOBAL_HTTP_PROXY_EXCLUSION_LIST; +import static android.net.ConnectivitySettingsManager.GLOBAL_HTTP_PROXY_HOST; +import static android.net.ConnectivitySettingsManager.GLOBAL_HTTP_PROXY_PAC; +import static android.net.ConnectivitySettingsManager.GLOBAL_HTTP_PROXY_PORT; import static android.provider.Settings.Global.HTTP_PROXY; import android.annotation.NonNull; diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java index 06b54b5c21fc..4038bf290161 100644 --- a/services/core/java/com/android/server/pm/StagingManager.java +++ b/services/core/java/com/android/server/pm/StagingManager.java @@ -203,7 +203,7 @@ public class StagingManager { newSigningDetails = ApkSignatureVerifier.verify(apexPath, minSignatureScheme); } catch (PackageParserException e) { throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED, - "Failed to parse APEX package " + apexPath, e); + "Failed to parse APEX package " + apexPath + " : " + e, e); } // Get signing details of the existing package @@ -221,7 +221,8 @@ public class StagingManager { existingApexPkg.applicationInfo.sourceDir, SignatureSchemeVersion.JAR); } catch (PackageParserException e) { throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED, - "Failed to parse APEX package " + existingApexPkg.applicationInfo.sourceDir, e); + "Failed to parse APEX package " + existingApexPkg.applicationInfo.sourceDir + + " : " + e, e); } // Verify signing details for upgrade @@ -283,7 +284,7 @@ public class StagingManager { } } catch (PackageParserException e) { throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED, - "Failed to parse APEX package " + apexInfo.modulePath, e); + "Failed to parse APEX package " + apexInfo.modulePath + " : " + e, e); } final PackageInfo activePackage = mApexManager.getPackageInfo(packageInfo.packageName, ApexManager.MATCH_ACTIVE_PACKAGE); diff --git a/services/core/java/com/android/server/pm/dex/ArtStatsLogUtils.java b/services/core/java/com/android/server/pm/dex/ArtStatsLogUtils.java index 3b77c39cc31b..0c8e36b75425 100644 --- a/services/core/java/com/android/server/pm/dex/ArtStatsLogUtils.java +++ b/services/core/java/com/android/server/pm/dex/ArtStatsLogUtils.java @@ -189,7 +189,7 @@ public class ArtStatsLogUtils { private static int getDexMetadataType(String dexMetadataPath) { if (dexMetadataPath == null) { - return ArtStatsLog.ART_DATUM_REPORTED__DEX_METADATA_TYPE__NONE_DEX_METADATA; + return ArtStatsLog.ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_NONE; } StrictJarFile jarFile = null; try { @@ -199,17 +199,21 @@ public class ArtStatsLogUtils { boolean hasProfile = findFileName(jarFile, PROFILE_DEX_METADATA); boolean hasVdex = findFileName(jarFile, VDEX_DEX_METADATA); if (hasProfile && hasVdex) { - return ArtStatsLog.ART_DATUM_REPORTED__DEX_METADATA_TYPE__PROFILE_AND_VDEX; + return ArtStatsLog. + ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_PROFILE_AND_VDEX; } else if (hasProfile) { - return ArtStatsLog.ART_DATUM_REPORTED__DEX_METADATA_TYPE__PROFILE; + return ArtStatsLog. + ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_PROFILE; } else if (hasVdex) { - return ArtStatsLog.ART_DATUM_REPORTED__DEX_METADATA_TYPE__VDEX; + return ArtStatsLog. + ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_VDEX; } else { - return ArtStatsLog.ART_DATUM_REPORTED__DEX_METADATA_TYPE__UNKNOWN_DEX_METADATA; + return ArtStatsLog. + ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_UNKNOWN; } } catch (IOException ignore) { Slog.e(TAG, "Error when parsing dex metadata " + dexMetadataPath); - return ArtStatsLog.ART_DATUM_REPORTED__DEX_METADATA_TYPE__ERROR_DEX_METADATA; + return ArtStatsLog.ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_ERROR; } finally { try { if (jarFile != null) { diff --git a/services/core/java/com/android/server/pm/dex/DexManager.java b/services/core/java/com/android/server/pm/dex/DexManager.java index 349561d3f1d1..37f317557aeb 100644 --- a/services/core/java/com/android/server/pm/dex/DexManager.java +++ b/services/core/java/com/android/server/pm/dex/DexManager.java @@ -986,7 +986,7 @@ public class DexManager { * Fetches the battery manager object and caches it if it hasn't been fetched already. */ private BatteryManager getBatteryManager() { - if (mBatteryManager == null) { + if (mBatteryManager == null && mContext != null) { mBatteryManager = mContext.getSystemService(BatteryManager.class); } @@ -1008,10 +1008,6 @@ public class DexManager { && mPowerManager.getCurrentThermalStatus() >= PowerManager.THERMAL_STATUS_SEVERE); - if (DEBUG) { - Log.d(TAG, "Battery, thermal, or memory are critical: " + isBtmCritical); - } - return isBtmCritical; } diff --git a/services/core/java/com/android/server/policy/LegacyGlobalActions.java b/services/core/java/com/android/server/policy/LegacyGlobalActions.java index 9c3a39440054..5b48abb3e1f2 100644 --- a/services/core/java/com/android/server/policy/LegacyGlobalActions.java +++ b/services/core/java/com/android/server/policy/LegacyGlobalActions.java @@ -24,11 +24,11 @@ import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; +import android.content.pm.PackageManager; import android.content.pm.UserInfo; import android.database.ContentObserver; import android.graphics.drawable.Drawable; import android.media.AudioManager; -import android.net.ConnectivityManager; import android.os.Build; import android.os.Handler; import android.os.Message; @@ -113,7 +113,7 @@ class LegacyGlobalActions implements DialogInterface.OnDismissListener, DialogIn private boolean mDeviceProvisioned = false; private ToggleAction.State mAirplaneState = ToggleAction.State.Off; private boolean mIsWaitingForEcmExit = false; - private boolean mHasTelephony; + private final boolean mHasTelephony; private boolean mHasVibrator; private final boolean mShowSilentToggle; private final EmergencyAffordanceManager mEmergencyAffordanceManager; @@ -137,9 +137,8 @@ class LegacyGlobalActions implements DialogInterface.OnDismissListener, DialogIn filter.addAction(TelephonyManager.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED); context.registerReceiver(mBroadcastReceiver, filter); - ConnectivityManager cm = (ConnectivityManager) - context.getSystemService(Context.CONNECTIVITY_SERVICE); - mHasTelephony = cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE); + mHasTelephony = + context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY); // get notified of phone state changes TelephonyManager telephonyManager = diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java index 7e6b7cd05762..e060171bde47 100644 --- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java @@ -110,6 +110,7 @@ import android.content.pm.UserInfo; import android.content.res.Configuration; import android.graphics.Rect; import android.os.Binder; +import android.os.Build; import android.os.Bundle; import android.os.Debug; import android.os.Handler; @@ -165,13 +166,13 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { static final String TAG_TASKS = TAG + POSTFIX_TASKS; /** How long we wait until giving up on the last activity telling us it is idle. */ - private static final int IDLE_TIMEOUT = 10 * 1000; + private static final int IDLE_TIMEOUT = 10 * 1000 * Build.HW_TIMEOUT_MULTIPLIER; /** How long we can hold the sleep wake lock before giving up. */ - private static final int SLEEP_TIMEOUT = 5 * 1000; + private static final int SLEEP_TIMEOUT = 5 * 1000 * Build.HW_TIMEOUT_MULTIPLIER; // How long we can hold the launch wake lock before giving up. - private static final int LAUNCH_TIMEOUT = 10 * 1000; + private static final int LAUNCH_TIMEOUT = 10 * 1000 * Build.HW_TIMEOUT_MULTIPLIER; /** How long we wait until giving up on the activity telling us it released the top state. */ private static final int TOP_RESUMED_STATE_LOSS_TIMEOUT = 500; diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index 816a6a065e69..f55a983a8b0d 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -312,9 +312,10 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION; // How long we wait until we timeout on key dispatching. - public static final int KEY_DISPATCHING_TIMEOUT_MS = 5 * 1000; + public static final int KEY_DISPATCHING_TIMEOUT_MS = 5 * 1000 * Build.HW_TIMEOUT_MULTIPLIER; // How long we wait until we timeout on key dispatching during instrumentation. - static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT_MS = 60 * 1000; + static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT_MS = + 60 * 1000 * Build.HW_TIMEOUT_MULTIPLIER; // How long we permit background activity starts after an activity in the process // started or finished. static final long ACTIVITY_BG_START_GRACE_PERIOD_MS = 10 * 1000; diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 374abd6a6f85..736a6f68725e 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -15621,8 +15621,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { Objects.requireNonNull(who, "ComponentName is null"); enforceDeviceOwner(who); - final String currentMode = - ConnectivityManager.getPrivateDnsMode(mContext.getContentResolver()); + final String currentMode = ConnectivityManager.getPrivateDnsMode(mContext); switch (currentMode) { case ConnectivityManager.PRIVATE_DNS_MODE_OFF: return PRIVATE_DNS_MODE_OFF; diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 7bde760191b5..46ec65d7567c 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -332,8 +332,6 @@ public final class SystemServer { private static final String UNCRYPT_PACKAGE_FILE = "/cache/recovery/uncrypt_file"; private static final String BLOCK_MAP_FILE = "/cache/recovery/block.map"; - private static final String GSI_RUNNING_PROP = "ro.gsid.image_running"; - // maximum number of binder threads used for system_server // will be higher than the system default private static final int sMaxBinderThreads = 31; @@ -1127,7 +1125,7 @@ public final class SystemServer { false); boolean enableLeftyService = SystemProperties.getBoolean("config.enable_lefty", false); - boolean isEmulator = SystemProperties.get("ro.kernel.qemu").equals("1"); + boolean isEmulator = SystemProperties.get("ro.boot.qemu").equals("1"); boolean isWatch = context.getPackageManager().hasSystemFeature( PackageManager.FEATURE_WATCH); @@ -1443,8 +1441,7 @@ public final class SystemServer { t.traceEnd(); final boolean hasPdb = !SystemProperties.get(PERSISTENT_DATA_BLOCK_PROP).equals(""); - final boolean hasGsi = SystemProperties.getInt(GSI_RUNNING_PROP, 0) > 0; - if (hasPdb && !hasGsi) { + if (hasPdb) { t.traceBegin("StartPersistentDataBlock"); mSystemServiceManager.startService(PersistentDataBlockService.class); t.traceEnd(); diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java b/services/tests/mockingservicestests/src/com/android/server/pm/dex/DexManagerTests.java index ee0a16a70265..2e0cadf264cf 100644 --- a/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java +++ b/services/tests/mockingservicestests/src/com/android/server/pm/dex/DexManagerTests.java @@ -11,7 +11,7 @@ * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and - * limitations under the License + * limitations under the License. */ package com.android.server.pm.dex; @@ -28,28 +28,34 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.res.Resources; +import android.os.BatteryManager; import android.os.Build; +import android.os.PowerManager; import android.os.UserHandle; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; +import com.android.dx.mockito.inline.extended.ExtendedMockito; +import com.android.dx.mockito.inline.extended.StaticMockitoSession; import com.android.server.pm.Installer; +import com.android.server.pm.PackageManagerService; import dalvik.system.DelegateLastClassLoader; import dalvik.system.PathClassLoader; import dalvik.system.VMRuntime; +import org.junit.After; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; import org.mockito.quality.Strictness; import java.io.File; @@ -69,9 +75,15 @@ public class DexManagerTests { DelegateLastClassLoader.class.getName(); private static final String UNSUPPORTED_CLASS_LOADER_NAME = "unsupported.class_loader"; - @Rule public MockitoRule mockito = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS); + private static final int TEST_BATTERY_LEVEL_CRITICAL = 10; + private static final int TEST_BATTERY_LEVEL_DEFAULT = 80; + + public StaticMockitoSession mMockitoSession; @Mock Installer mInstaller; @Mock IPackageManager mPM; + @Mock BatteryManager mMockBatteryManager; + @Mock PowerManager mMockPowerManager; + private final Object mInstallLock = new Object(); private DexManager mDexManager; @@ -117,7 +129,37 @@ public class DexManagerTests { mSystemServerJarUpdatedContext = new TestData("android", isa, mUser0, DELEGATE_LAST_CLASS_LOADER_NAME); - mDexManager = new DexManager(/*Context*/ null, mPM, /*PackageDexOptimizer*/ null, + // Initialize Static Mocking + + mMockitoSession = ExtendedMockito.mockitoSession() + .initMocks(this) + .strictness(Strictness.LENIENT) + .startMocking(); + + // Mock.... + + mMockBatteryManager = ExtendedMockito.mock(BatteryManager.class); + mMockPowerManager = ExtendedMockito.mock(PowerManager.class); + + setDefaultMockValues(); + + Resources mockResources = ExtendedMockito.mock(Resources.class); + ExtendedMockito.when(mockResources + .getInteger(com.android.internal.R.integer.config_criticalBatteryWarningLevel)) + .thenReturn(15); + + Context mockContext = ExtendedMockito.mock(Context.class); + ExtendedMockito.doReturn(mockResources) + .when(mockContext) + .getResources(); + ExtendedMockito.doReturn(mMockBatteryManager) + .when(mockContext) + .getSystemService(BatteryManager.class); + ExtendedMockito.doReturn(mMockPowerManager) + .when(mockContext) + .getSystemService(PowerManager.class); + + mDexManager = new DexManager(mockContext, mPM, /*PackageDexOptimizer*/ null, mInstaller, mInstallLock); // Foo and Bar are available to user0. @@ -128,6 +170,25 @@ public class DexManagerTests { mDexManager.load(existingPackages); } + @After + public void teardown() throws Exception { + mMockitoSession.finishMocking(); + } + + private void setDefaultMockValues() { + ExtendedMockito.doReturn(BatteryManager.BATTERY_STATUS_DISCHARGING) + .when(mMockBatteryManager) + .getIntProperty(BatteryManager.BATTERY_PROPERTY_STATUS); + + ExtendedMockito.doReturn(TEST_BATTERY_LEVEL_DEFAULT) + .when(mMockBatteryManager) + .getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY); + + ExtendedMockito.doReturn(PowerManager.THERMAL_STATUS_NONE) + .when(mMockPowerManager) + .getCurrentThermalStatus(); + } + @Test public void testNotifyPrimaryUse() { // The main dex file and splits are re-loaded by the app. @@ -633,6 +694,114 @@ public class DexManagerTests { assertNoDclInfo(mSystemServerJarInvalid); } + @Test + public void testInstallScenarioToReasonDefault() { + assertEquals( + PackageManagerService.REASON_INSTALL, + mDexManager.getCompilationReasonForInstallScenario( + PackageManager.INSTALL_SCENARIO_DEFAULT)); + + assertEquals( + PackageManagerService.REASON_INSTALL_FAST, + mDexManager.getCompilationReasonForInstallScenario( + PackageManager.INSTALL_SCENARIO_FAST)); + + assertEquals( + PackageManagerService.REASON_INSTALL_BULK, + mDexManager.getCompilationReasonForInstallScenario( + PackageManager.INSTALL_SCENARIO_BULK)); + + assertEquals( + PackageManagerService.REASON_INSTALL_BULK_SECONDARY, + mDexManager.getCompilationReasonForInstallScenario( + PackageManager.INSTALL_SCENARIO_BULK_SECONDARY)); + } + + @Test + public void testInstallScenarioToReasonThermal() { + ExtendedMockito.doReturn(PowerManager.THERMAL_STATUS_SEVERE) + .when(mMockPowerManager) + .getCurrentThermalStatus(); + + assertEquals( + PackageManagerService.REASON_INSTALL, + mDexManager.getCompilationReasonForInstallScenario( + PackageManager.INSTALL_SCENARIO_DEFAULT)); + + assertEquals( + PackageManagerService.REASON_INSTALL_FAST, + mDexManager.getCompilationReasonForInstallScenario( + PackageManager.INSTALL_SCENARIO_FAST)); + + assertEquals( + PackageManagerService.REASON_INSTALL_BULK_DOWNGRADED, + mDexManager.getCompilationReasonForInstallScenario( + PackageManager.INSTALL_SCENARIO_BULK)); + + assertEquals( + PackageManagerService.REASON_INSTALL_BULK_SECONDARY_DOWNGRADED, + mDexManager.getCompilationReasonForInstallScenario( + PackageManager.INSTALL_SCENARIO_BULK_SECONDARY)); + } + + @Test + public void testInstallScenarioToReasonBatteryDischarging() { + ExtendedMockito.doReturn(TEST_BATTERY_LEVEL_CRITICAL) + .when(mMockBatteryManager) + .getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY); + + assertEquals( + PackageManagerService.REASON_INSTALL, + mDexManager.getCompilationReasonForInstallScenario( + PackageManager.INSTALL_SCENARIO_DEFAULT)); + + assertEquals( + PackageManagerService.REASON_INSTALL_FAST, + mDexManager.getCompilationReasonForInstallScenario( + PackageManager.INSTALL_SCENARIO_FAST)); + + assertEquals( + PackageManagerService.REASON_INSTALL_BULK_DOWNGRADED, + mDexManager.getCompilationReasonForInstallScenario( + PackageManager.INSTALL_SCENARIO_BULK)); + + assertEquals( + PackageManagerService.REASON_INSTALL_BULK_SECONDARY_DOWNGRADED, + mDexManager.getCompilationReasonForInstallScenario( + PackageManager.INSTALL_SCENARIO_BULK_SECONDARY)); + } + + @Test + public void testInstallScenarioToReasonBatteryCharging() { + ExtendedMockito.doReturn(TEST_BATTERY_LEVEL_CRITICAL) + .when(mMockBatteryManager) + .getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY); + + ExtendedMockito.doReturn(BatteryManager.BATTERY_STATUS_CHARGING) + .when(mMockBatteryManager) + .getIntProperty(BatteryManager.BATTERY_PROPERTY_STATUS); + + assertEquals( + PackageManagerService.REASON_INSTALL, + mDexManager.getCompilationReasonForInstallScenario( + PackageManager.INSTALL_SCENARIO_DEFAULT)); + + assertEquals( + PackageManagerService.REASON_INSTALL_FAST, + mDexManager.getCompilationReasonForInstallScenario( + PackageManager.INSTALL_SCENARIO_FAST)); + + assertEquals( + PackageManagerService.REASON_INSTALL_BULK, + mDexManager.getCompilationReasonForInstallScenario( + PackageManager.INSTALL_SCENARIO_BULK)); + + assertEquals( + PackageManagerService.REASON_INSTALL_BULK_SECONDARY, + mDexManager.getCompilationReasonForInstallScenario( + PackageManager.INSTALL_SCENARIO_BULK_SECONDARY)); + } + private void assertSecondaryUse(TestData testData, PackageUseInfo pui, List<String> secondaries, boolean isUsedByOtherApps, int ownerUserId, String[] expectedContexts) { diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/dex/OWNERS b/services/tests/mockingservicestests/src/com/android/server/pm/dex/OWNERS new file mode 100644 index 000000000000..5a4431ee8c89 --- /dev/null +++ b/services/tests/mockingservicestests/src/com/android/server/pm/dex/OWNERS @@ -0,0 +1,2 @@ +calin@google.com +ngeoffray@google.com diff --git a/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest/OWNERS b/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest/OWNERS new file mode 100644 index 000000000000..e95633abe79a --- /dev/null +++ b/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest/OWNERS @@ -0,0 +1 @@ +include /core/java/android/app/admin/OWNERS diff --git a/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest2/OWNERS b/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest2/OWNERS new file mode 100644 index 000000000000..e95633abe79a --- /dev/null +++ b/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest2/OWNERS @@ -0,0 +1 @@ +include /core/java/android/app/admin/OWNERS diff --git a/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest3/OWNERS b/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest3/OWNERS new file mode 100644 index 000000000000..e95633abe79a --- /dev/null +++ b/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest3/OWNERS @@ -0,0 +1 @@ +include /core/java/android/app/admin/OWNERS diff --git a/services/tests/servicestests/assets/OwnersTest/OWNERS b/services/tests/servicestests/assets/OwnersTest/OWNERS new file mode 100644 index 000000000000..e95633abe79a --- /dev/null +++ b/services/tests/servicestests/assets/OwnersTest/OWNERS @@ -0,0 +1 @@ +include /core/java/android/app/admin/OWNERS diff --git a/services/tests/servicestests/assets/PolicyVersionUpgraderTest/OWNERS b/services/tests/servicestests/assets/PolicyVersionUpgraderTest/OWNERS new file mode 100644 index 000000000000..e95633abe79a --- /dev/null +++ b/services/tests/servicestests/assets/PolicyVersionUpgraderTest/OWNERS @@ -0,0 +1 @@ +include /core/java/android/app/admin/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java index a38745f2a66e..d9af51f819c3 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java @@ -42,7 +42,6 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.os.FileUtils; -import android.security.keystore.AndroidKeyStoreSecretKey; import android.security.keystore.KeyGenParameterSpec; import android.security.keystore.KeyProperties; import android.security.keystore.recovery.KeyChainSnapshot; @@ -109,7 +108,7 @@ public class KeySyncTaskTest { private RecoverySnapshotStorage mRecoverySnapshotStorage; private RecoverableKeyStoreDb mRecoverableKeyStoreDb; private File mDatabaseFile; - private AndroidKeyStoreSecretKey mWrappingKey; + private SecretKey mWrappingKey; private PlatformEncryptionKey mEncryptKey; private KeySyncTask mKeySyncTask; @@ -848,7 +847,7 @@ public class KeySyncTaskTest { return keyGenerator.generateKey(); } - private AndroidKeyStoreSecretKey generateAndroidKeyStoreKey() throws Exception { + private SecretKey generateAndroidKeyStoreKey() throws Exception { KeyGenerator keyGenerator = KeyGenerator.getInstance( KEY_ALGORITHM, ANDROID_KEY_STORE_PROVIDER); @@ -857,7 +856,7 @@ public class KeySyncTaskTest { .setBlockModes(KeyProperties.BLOCK_MODE_GCM) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) .build()); - return (AndroidKeyStoreSecretKey) keyGenerator.generateKey(); + return keyGenerator.generateKey(); } private static byte[] utf8Bytes(String s) { diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyGeneratorTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyGeneratorTest.java index c295177814b0..64130266b2c4 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyGeneratorTest.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyGeneratorTest.java @@ -23,7 +23,6 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import android.content.Context; -import android.security.keystore.AndroidKeyStoreSecretKey; import android.security.keystore.KeyGenParameterSpec; import android.security.keystore.KeyProperties; @@ -45,6 +44,7 @@ import java.util.Random; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; +import javax.crypto.SecretKey; import javax.crypto.spec.GCMParameterSpec; @SmallTest @@ -77,7 +77,7 @@ public class RecoverableKeyGeneratorTest { mDatabaseFile = context.getDatabasePath(DATABASE_FILE_NAME); mRecoverableKeyStoreDb = RecoverableKeyStoreDb.newInstance(context); - AndroidKeyStoreSecretKey platformKey = generatePlatformKey(); + SecretKey platformKey = generatePlatformKey(); mPlatformKey = new PlatformEncryptionKey(TEST_GENERATION_ID, platformKey); mDecryptKey = new PlatformDecryptionKey(TEST_GENERATION_ID, platformKey); mRecoverableKeyGenerator = RecoverableKeyGenerator.newInstance(mRecoverableKeyStoreDb); @@ -168,7 +168,7 @@ public class RecoverableKeyGeneratorTest { assertArrayEquals(rawMaterial, unwrappedMaterial); } - private AndroidKeyStoreSecretKey generatePlatformKey() throws Exception { + private SecretKey generatePlatformKey() throws Exception { KeyGenerator keyGenerator = KeyGenerator.getInstance( KEY_ALGORITHM, ANDROID_KEY_STORE_PROVIDER); @@ -177,7 +177,7 @@ public class RecoverableKeyGeneratorTest { .setBlockModes(KeyProperties.BLOCK_MODE_GCM) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) .build()); - return (AndroidKeyStoreSecretKey) keyGenerator.generateKey(); + return keyGenerator.generateKey(); } private static byte[] randomBytes(int n) { diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java index ac7447006444..f4e74bab2bd4 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java @@ -45,7 +45,6 @@ import android.content.Intent; import android.os.Binder; import android.os.ServiceSpecificException; import android.os.UserHandle; -import android.security.keystore.AndroidKeyStoreSecretKey; import android.security.keystore.KeyGenParameterSpec; import android.security.keystore.KeyProperties; import android.security.keystore.recovery.KeyChainProtectionParams; @@ -1311,7 +1310,7 @@ public class RecoverableKeyStoreManagerTest { mRecoverableKeyStoreDb.setShouldCreateSnapshot(userId, uid, false); } - private AndroidKeyStoreSecretKey generateAndroidKeyStoreKey() throws Exception { + private SecretKey generateAndroidKeyStoreKey() throws Exception { KeyGenerator keyGenerator = KeyGenerator.getInstance( KEY_ALGORITHM, ANDROID_KEY_STORE_PROVIDER); @@ -1320,6 +1319,6 @@ public class RecoverableKeyStoreManagerTest { .setBlockModes(KeyProperties.BLOCK_MODE_GCM) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) .build()); - return (AndroidKeyStoreSecretKey) keyGenerator.generateKey(); + return keyGenerator.generateKey(); } } diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/WrappedKeyTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/WrappedKeyTest.java index 9813ab74721e..60052f7114b3 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/WrappedKeyTest.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/WrappedKeyTest.java @@ -21,7 +21,6 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import android.security.keystore.AndroidKeyStoreSecretKey; import android.security.keystore.KeyGenParameterSpec; import android.security.keystore.KeyProperties; import android.util.Pair; @@ -117,7 +116,7 @@ public class WrappedKeyTest { @Test public void decryptWrappedKeys_decryptsWrappedKeys_nullMetadata() throws Exception { String alias = "karlin"; - AndroidKeyStoreSecretKey platformKey = generateAndroidKeyStoreKey(); + SecretKey platformKey = generateAndroidKeyStoreKey(); SecretKey appKey = generateKey(); WrappedKey wrappedKey = WrappedKey.fromSecretKey( new PlatformEncryptionKey(GENERATION_ID, platformKey), appKey, NULL_METADATA); @@ -136,7 +135,7 @@ public class WrappedKeyTest { @Test public void decryptWrappedKeys_decryptsWrappedKeys_nonNullMetadata() throws Exception { String alias = "karlin"; - AndroidKeyStoreSecretKey platformKey = generateAndroidKeyStoreKey(); + SecretKey platformKey = generateAndroidKeyStoreKey(); SecretKey appKey = generateKey(); WrappedKey wrappedKey = WrappedKey.fromSecretKey( new PlatformEncryptionKey(GENERATION_ID, platformKey), appKey, NON_NULL_METADATA); @@ -155,7 +154,7 @@ public class WrappedKeyTest { @Test public void decryptWrappedKeys_doesNotDieIfSomeKeysAreUnwrappable() throws Exception { String alias = "karlin"; - AndroidKeyStoreSecretKey platformKey = generateAndroidKeyStoreKey(); + SecretKey platformKey = generateAndroidKeyStoreKey(); SecretKey appKey = generateKey(); WrappedKey wrappedKey = WrappedKey.fromSecretKey( new PlatformEncryptionKey(GENERATION_ID, platformKey), appKey, NULL_METADATA); @@ -171,7 +170,7 @@ public class WrappedKeyTest { @Test public void decryptWrappedKeys_throwsIfPlatformKeyGenerationIdDoesNotMatch() throws Exception { - AndroidKeyStoreSecretKey platformKey = generateAndroidKeyStoreKey(); + SecretKey platformKey = generateAndroidKeyStoreKey(); WrappedKey wrappedKey = WrappedKey.fromSecretKey( new PlatformEncryptionKey(GENERATION_ID, platformKey), generateKey(), /*metadata=*/ null); @@ -197,7 +196,7 @@ public class WrappedKeyTest { return keyGenerator.generateKey(); } - private AndroidKeyStoreSecretKey generateAndroidKeyStoreKey() throws Exception { + private SecretKey generateAndroidKeyStoreKey() throws Exception { KeyGenerator keyGenerator = KeyGenerator.getInstance( KEY_ALGORITHM, ANDROID_KEY_STORE_PROVIDER); @@ -207,6 +206,6 @@ public class WrappedKeyTest { .setBlockModes(KeyProperties.BLOCK_MODE_GCM) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) .build()); - return (AndroidKeyStoreSecretKey) keyGenerator.generateKey(); + return keyGenerator.generateKey(); } } diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/ArtStatsLogUtilsTest.java b/services/tests/servicestests/src/com/android/server/pm/dex/ArtStatsLogUtilsTest.java index 3ab34484ce25..e605d755183f 100644 --- a/services/tests/servicestests/src/com/android/server/pm/dex/ArtStatsLogUtilsTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/dex/ArtStatsLogUtilsTest.java @@ -106,7 +106,8 @@ public final class ArtStatsLogUtilsTest { RESULT_CODE); // Assert - verifyWrites(ArtStatsLog.ART_DATUM_REPORTED__DEX_METADATA_TYPE__PROFILE_AND_VDEX); + verifyWrites(ArtStatsLog. + ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_PROFILE_AND_VDEX); } finally { deleteSliently(dexMetadataPath); deleteSliently(apk); @@ -135,7 +136,8 @@ public final class ArtStatsLogUtilsTest { RESULT_CODE); // Assert - verifyWrites(ArtStatsLog.ART_DATUM_REPORTED__DEX_METADATA_TYPE__PROFILE); + verifyWrites(ArtStatsLog. + ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_PROFILE); } finally { deleteSliently(dexMetadataPath); deleteSliently(apk); @@ -164,7 +166,8 @@ public final class ArtStatsLogUtilsTest { RESULT_CODE); // Assert - verifyWrites(ArtStatsLog.ART_DATUM_REPORTED__DEX_METADATA_TYPE__VDEX); + verifyWrites(ArtStatsLog. + ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_VDEX); } finally { deleteSliently(dexMetadataPath); deleteSliently(apk); @@ -191,7 +194,8 @@ public final class ArtStatsLogUtilsTest { RESULT_CODE); // Assert - verifyWrites(ArtStatsLog.ART_DATUM_REPORTED__DEX_METADATA_TYPE__NONE_DEX_METADATA); + verifyWrites(ArtStatsLog. + ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_NONE); } finally { deleteSliently(apk); } @@ -219,7 +223,8 @@ public final class ArtStatsLogUtilsTest { RESULT_CODE); // Assert - verifyWrites(ArtStatsLog.ART_DATUM_REPORTED__DEX_METADATA_TYPE__UNKNOWN_DEX_METADATA); + verifyWrites(ArtStatsLog. + ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_UNKNOWN); } finally { deleteSliently(dexMetadataPath); deleteSliently(apk); diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index dc05488618cf..217570e1401c 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -2898,6 +2898,18 @@ public class CarrierConfigManager { public static final String KEY_RTT_SUPPORTED_FOR_VT_BOOL = "rtt_supported_for_vt_bool"; /** + * Indicates if the carrier supports upgrading a call that was previously an RTT call to VT. + */ + public static final String KEY_VT_UPGRADE_SUPPORTED_FOR_DOWNGRADED_RTT_CALL_BOOL = + "vt_upgrade_supported_for_downgraded_rtt_call"; + + /** + * Indicates if the carrier supports upgrading a call that was previously a VT call to RTT. + */ + public static final String KEY_RTT_UPGRADE_SUPPORTED_FOR_DOWNGRADED_VT_CALL_BOOL = + "rtt_upgrade_supported_for_downgraded_vt_call"; + + /** * Indicates if the carrier supports upgrading a voice call to an RTT call during the call. */ public static final String KEY_RTT_UPGRADE_SUPPORTED_BOOL = "rtt_upgrade_supported_bool"; @@ -4618,6 +4630,8 @@ public class CarrierConfigManager { sDefaults.putBoolean(KEY_TTY_SUPPORTED_BOOL, true); sDefaults.putBoolean(KEY_HIDE_TTY_HCO_VCO_WITH_RTT_BOOL, false); sDefaults.putBoolean(KEY_RTT_SUPPORTED_WHILE_ROAMING_BOOL, false); + sDefaults.putBoolean(KEY_RTT_UPGRADE_SUPPORTED_FOR_DOWNGRADED_VT_CALL_BOOL, true); + sDefaults.putBoolean(KEY_VT_UPGRADE_SUPPORTED_FOR_DOWNGRADED_RTT_CALL_BOOL, true); sDefaults.putBoolean(KEY_DISABLE_CHARGE_INDICATION_BOOL, false); sDefaults.putBoolean(KEY_SUPPORT_NO_REPLY_TIMER_FOR_CFNRY_BOOL, true); sDefaults.putStringArray(KEY_FEATURE_ACCESS_CODES_STRING_ARRAY, null); diff --git a/telephony/java/android/telephony/LinkCapacityEstimate.aidl b/telephony/java/android/telephony/LinkCapacityEstimate.aidl new file mode 100644 index 000000000000..286f33fc9810 --- /dev/null +++ b/telephony/java/android/telephony/LinkCapacityEstimate.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony; + +parcelable LinkCapacityEstimate;
\ No newline at end of file diff --git a/telephony/java/android/telephony/LinkCapacityEstimate.java b/telephony/java/android/telephony/LinkCapacityEstimate.java new file mode 100644 index 000000000000..deeb80961c3c --- /dev/null +++ b/telephony/java/android/telephony/LinkCapacityEstimate.java @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.Objects; + +/** + * Link Capacity Estimate from the modem + * @hide + */ +@SystemApi +public final class LinkCapacityEstimate implements Parcelable { + /** A value indicates that the capacity estimate is not available */ + public static final int INVALID = -1; + + /** + * LCE for the primary network + */ + public static final int LCE_TYPE_PRIMARY = 0; + + /** + * LCE for the secondary network + */ + public static final int LCE_TYPE_SECONDARY = 1; + + /** + * Combined LCE for primary network and secondary network reported by the legacy modem + */ + public static final int LCE_TYPE_COMBINED = 2; + + /** @hide */ + @IntDef(prefix = { "LCE_TYPE_" }, value = { + LCE_TYPE_PRIMARY, + LCE_TYPE_SECONDARY, + LCE_TYPE_COMBINED, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface LceType {} + + private final @LceType int mType; + + /** Downlink capacity estimate in kbps */ + private final int mDownlinkCapacityKbps; + + /** Uplink capacity estimate in kbps */ + private final int mUplinkCapacityKbps; + + /** + * Constructor for link capacity estimate + */ + public LinkCapacityEstimate(@LceType int type, + int downlinkCapacityKbps, int uplinkCapacityKbps) { + mDownlinkCapacityKbps = downlinkCapacityKbps; + mUplinkCapacityKbps = uplinkCapacityKbps; + mType = type; + } + + /** + * @hide + */ + public LinkCapacityEstimate(Parcel in) { + mDownlinkCapacityKbps = in.readInt(); + mUplinkCapacityKbps = in.readInt(); + mType = in.readInt(); + } + + /** + * Retrieves the type of LCE + * @return The type of link capacity estimate + */ + public @LceType int getType() { + return mType; + } + + /** + * Retrieves the downlink bandwidth in Kbps. + * This will be {@link #INVALID} if the network is not connected + * @return The estimated first hop downstream (network to device) bandwidth. + */ + public int getDownlinkCapacityKbps() { + return mDownlinkCapacityKbps; + } + + /** + * Retrieves the uplink bandwidth in Kbps. + * This will be {@link #INVALID} if the network is not connected + * + * @return The estimated first hop upstream (device to network) bandwidth. + */ + public int getUplinkCapacityKbps() { + return mUplinkCapacityKbps; + } + + @Override + public String toString() { + return new StringBuilder() + .append("{mType=") + .append(mType) + .append(", mDownlinkCapacityKbps=") + .append(mDownlinkCapacityKbps) + .append(", mUplinkCapacityKbps=") + .append(mUplinkCapacityKbps) + .append("}") + .toString(); + } + + /** + * {@link Parcelable#describeContents} + */ + public int describeContents() { + return 0; + } + + /** + * {@link Parcelable#writeToParcel} + * @hide + */ + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeInt(mDownlinkCapacityKbps); + dest.writeInt(mUplinkCapacityKbps); + dest.writeInt(mType); + } + + @Override + public boolean equals(@Nullable Object o) { + if (o == null || !(o instanceof LinkCapacityEstimate) || hashCode() != o.hashCode()) { + return false; + } + + if (this == o) { + return true; + } + + LinkCapacityEstimate that = (LinkCapacityEstimate) o; + return mDownlinkCapacityKbps == that.mDownlinkCapacityKbps + && mUplinkCapacityKbps == that.mUplinkCapacityKbps + && mType == that.mType; + } + + @Override + public int hashCode() { + return Objects.hash(mDownlinkCapacityKbps, mUplinkCapacityKbps, mType); + } + + public static final + @android.annotation.NonNull Parcelable.Creator<LinkCapacityEstimate> CREATOR = + new Parcelable.Creator() { + public LinkCapacityEstimate createFromParcel(Parcel in) { + return new LinkCapacityEstimate(in); + } + + public LinkCapacityEstimate[] newArray(int size) { + return new LinkCapacityEstimate[size]; + } + }; +} diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 364c9be9614a..99b5687ba20d 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -13981,33 +13981,6 @@ public class TelephonyManager { } /** - * Get carrier bandwidth. In case of Dual connected network this will report - * bandwidth per primary and secondary network. - * @return CarrierBandwidth with bandwidth of both primary and secondary carrier. - * @throws IllegalStateException if the Telephony process is not currently available. - * @hide - */ - @SystemApi - @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) - @NonNull - public CarrierBandwidth getCarrierBandwidth() { - try { - ITelephony service = getITelephony(); - if (service != null) { - return service.getCarrierBandwidth(getSubId()); - } else { - throw new IllegalStateException("telephony service is null."); - } - } catch (RemoteException ex) { - Log.e(TAG, "getCarrierBandwidth RemoteException", ex); - ex.rethrowFromSystemServer(); - } - - //Should not reach. Adding return statement to make compiler happy - return null; - } - - /** * Called when userActivity is signalled in the power manager. * This should only be called from system Uid. * @hide @@ -14927,7 +14900,9 @@ public class TelephonyManager { public static final int PREPARE_UNATTENDED_REBOOT_PIN_REQUIRED = 1; /** - * The unattended reboot was not prepared due to generic error. + * The unattended reboot was not prepared due to a non-recoverable error. After this error, + * the client that manages the unattended reboot should not try to invoke the API again + * until the next power cycle. * @hide */ @SystemApi diff --git a/telephony/java/android/telephony/data/SliceInfo.java b/telephony/java/android/telephony/data/SliceInfo.java index 51857a7b4908..609d1112d5b4 100644 --- a/telephony/java/android/telephony/data/SliceInfo.java +++ b/telephony/java/android/telephony/data/SliceInfo.java @@ -29,7 +29,12 @@ import java.lang.annotation.RetentionPolicy; import java.util.Objects; /** - * Represents a S-NSSAI as defined in 3GPP TS 24.501. + * Represents a S-NSSAI as defined in 3GPP TS 24.501, which represents a network slice. + * + * There are 2 main fields that define a slice, SliceServiceType and SliceDifferentiator. + * SliceServiceType defines the type of service provided by the slice, and SliceDifferentiator is + * used to differentiate between multiple slices of the same type. If the devices is not on HPLMN, + * the mappedHplmn versions of these 2 fields indicate the corresponding values in HPLMN. * * @hide */ diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index f74484bd4fd8..45702c311ff3 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -31,7 +31,6 @@ import android.service.carrier.CarrierIdentifier; import android.telecom.PhoneAccount; import android.telecom.PhoneAccountHandle; import android.telephony.CallForwardingInfo; -import android.telephony.CarrierBandwidth; import android.telephony.CarrierRestrictionRules; import android.telephony.CellIdentity; import android.telephony.CellInfo; @@ -54,6 +53,7 @@ import android.telephony.TelephonyHistogram; import android.telephony.VisualVoicemailSmsFilterSettings; import android.telephony.emergency.EmergencyNumber; import android.telephony.ims.RcsClientConfiguration; +import android.telephony.ims.RcsContactUceCapability; import android.telephony.ims.aidl.IImsCapabilityCallback; import android.telephony.ims.aidl.IImsConfig; import android.telephony.ims.aidl.IImsConfigCallback; @@ -2219,12 +2219,6 @@ interface ITelephony { boolean isNrDualConnectivityEnabled(int subId); /** - * Get carrier bandwidth per primary and secondary carrier - * @return CarrierBandwidth with bandwidth of both primary and secondary carrier. - */ - CarrierBandwidth getCarrierBandwidth(int subId); - - /** * Checks whether the device supports the given capability on the radio interface. * * @param capability the name of the capability @@ -2357,6 +2351,41 @@ interface ITelephony { void setDeviceUceEnabled(boolean isEnabled); /** + * Add feature tags to the IMS registration being tracked by UCE and potentially + * generate a new PUBLISH to the network. + * Note: This is designed for a SHELL command only. + */ + RcsContactUceCapability addUceRegistrationOverrideShell(int subId, in List<String> featureTags); + + /** + * Remove feature tags from the IMS registration being tracked by UCE and potentially + * generate a new PUBLISH to the network. + * Note: This is designed for a SHELL command only. + */ + RcsContactUceCapability removeUceRegistrationOverrideShell(int subId, + in List<String> featureTags); + + /** + * Clear overridden feature tags in the IMS registration being tracked by UCE and potentially + * generate a new PUBLISH to the network. + * Note: This is designed for a SHELL command only. + */ + RcsContactUceCapability clearUceRegistrationOverrideShell(int subId); + + /** + * Get the latest RcsContactUceCapability structure that is used in SIP PUBLISH procedures. + * Note: This is designed for a SHELL command only. + */ + RcsContactUceCapability getLatestRcsContactUceCapabilityShell(int subId); + + /** + * Returns the last PIDF XML sent to the network during the last PUBLISH or "none" if the + * device does not have an active PUBLISH. + * Note: This is designed for a SHELL command only. + */ + String getLastUcePidfXmlShell(int subId); + + /** * Set a SignalStrengthUpdateRequest to receive notification when Signal Strength breach the * specified thresholds. */ diff --git a/tests/net/java/android/net/VpnTransportInfoTest.java b/tests/net/java/android/net/VpnTransportInfoTest.java index d04c87b29c25..b7a42ec29356 100644 --- a/tests/net/java/android/net/VpnTransportInfoTest.java +++ b/tests/net/java/android/net/VpnTransportInfoTest.java @@ -42,7 +42,13 @@ public class VpnTransportInfoTest { VpnTransportInfo v1 = new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM); VpnTransportInfo v2 = new VpnTransportInfo(VpnManager.TYPE_VPN_SERVICE); VpnTransportInfo v3 = new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM); + VpnTransportInfo v4 = new VpnTransportInfo(VpnManager.TYPE_VPN_LEGACY); + VpnTransportInfo v5 = new VpnTransportInfo(VpnManager.TYPE_VPN_OEM); + assertNotEquals(v1, v2); + assertNotEquals(v3, v4); + assertNotEquals(v4, v5); + assertEquals(v1, v3); assertEquals(v1.hashCode(), v3.hashCode()); } diff --git a/tests/net/java/android/net/util/MultinetworkPolicyTrackerTest.kt b/tests/net/java/android/net/util/MultinetworkPolicyTrackerTest.kt index c1315f64c56b..1945ce7ba90d 100644 --- a/tests/net/java/android/net/util/MultinetworkPolicyTrackerTest.kt +++ b/tests/net/java/android/net/util/MultinetworkPolicyTrackerTest.kt @@ -21,10 +21,10 @@ import android.content.res.Resources import android.net.ConnectivityManager.MULTIPATH_PREFERENCE_HANDOVER import android.net.ConnectivityManager.MULTIPATH_PREFERENCE_PERFORMANCE import android.net.ConnectivityManager.MULTIPATH_PREFERENCE_RELIABILITY +import android.net.ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI +import android.net.ConnectivitySettingsManager.NETWORK_METERED_MULTIPATH_PREFERENCE import android.net.util.MultinetworkPolicyTracker.ActiveDataSubscriptionIdListener import android.provider.Settings -import android.provider.Settings.Global.NETWORK_AVOID_BAD_WIFI -import android.provider.Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE import android.telephony.SubscriptionInfo import android.telephony.SubscriptionManager import android.telephony.TelephonyManager diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index cc58edf80e88..7ac488d7de21 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -23,6 +23,8 @@ import static android.content.Intent.ACTION_USER_ADDED; import static android.content.Intent.ACTION_USER_REMOVED; import static android.content.Intent.ACTION_USER_UNLOCKED; import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED; +import static android.content.pm.PackageManager.FEATURE_WIFI; +import static android.content.pm.PackageManager.FEATURE_WIFI_DIRECT; import static android.content.pm.PackageManager.GET_PERMISSIONS; import static android.content.pm.PackageManager.MATCH_ANY_USER; import static android.content.pm.PackageManager.PERMISSION_DENIED; @@ -35,11 +37,14 @@ import static android.net.ConnectivityManager.NETID_UNSET; import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF; import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC; import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME; +import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_DEFAULT; +import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE; import static android.net.ConnectivityManager.TYPE_ETHERNET; import static android.net.ConnectivityManager.TYPE_MOBILE; import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA; import static android.net.ConnectivityManager.TYPE_MOBILE_MMS; import static android.net.ConnectivityManager.TYPE_MOBILE_SUPL; +import static android.net.ConnectivityManager.TYPE_PROXY; import static android.net.ConnectivityManager.TYPE_VPN; import static android.net.ConnectivityManager.TYPE_WIFI; import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_DNS; @@ -174,6 +179,7 @@ import android.net.ConnectivityManager.NetworkCallback; import android.net.ConnectivityManager.PacketKeepalive; import android.net.ConnectivityManager.PacketKeepaliveCallback; import android.net.ConnectivityManager.TooManyRequestsException; +import android.net.ConnectivitySettingsManager; import android.net.ConnectivityThread; import android.net.DataStallReportParcelable; import android.net.EthernetManager; @@ -183,7 +189,7 @@ import android.net.INetd; import android.net.INetworkMonitor; import android.net.INetworkMonitorCallbacks; import android.net.INetworkPolicyListener; -import android.net.IOnSetOemNetworkPreferenceListener; +import android.net.IOnCompleteListener; import android.net.IQosCallback; import android.net.InetAddresses; import android.net.InterfaceConfigurationParcel; @@ -378,6 +384,11 @@ public class ConnectivityServiceTest { // Set a non-zero value to verify the flow to set tcp init rwnd value. private static final int TEST_TCP_INIT_RWND = 60; + // Used for testing the per-work-profile default network. + private static final int TEST_APP_ID = 103; + private static final int TEST_WORK_PROFILE_USER_ID = 2; + private static final int TEST_WORK_PROFILE_APP_UID = + UserHandle.getUid(TEST_WORK_PROFILE_USER_ID, TEST_APP_ID); private static final String CLAT_PREFIX = "v4-"; private static final String MOBILE_IFNAME = "test_rmnet_data0"; private static final String WIFI_IFNAME = "test_wlan0"; @@ -421,6 +432,7 @@ public class ConnectivityServiceTest { private VpnManagerService mVpnManagerService; private TestNetworkCallback mDefaultNetworkCallback; private TestNetworkCallback mSystemDefaultNetworkCallback; + private TestNetworkCallback mProfileDefaultNetworkCallback; // State variables required to emulate NetworkPolicyManagerService behaviour. private int mUidRules = RULE_NONE; @@ -542,13 +554,26 @@ public class ConnectivityServiceTest { return super.getSystemService(name); } + final HashMap<UserHandle, UserManager> mUserManagers = new HashMap<>(); @Override public Context createContextAsUser(UserHandle user, int flags) { final Context asUser = mock(Context.class, AdditionalAnswers.delegatesTo(this)); doReturn(user).when(asUser).getUser(); + doAnswer((inv) -> { + final UserManager um = mUserManagers.computeIfAbsent(user, + u -> mock(UserManager.class, AdditionalAnswers.delegatesTo(mUserManager))); + return um; + }).when(asUser).getSystemService(Context.USER_SERVICE); return asUser; } + public void setWorkProfile(@NonNull final UserHandle userHandle, boolean value) { + // This relies on all contexts for a given user returning the same UM mock + final UserManager umMock = createContextAsUser(userHandle, 0 /* flags */) + .getSystemService(UserManager.class); + doReturn(value).when(umMock).isManagedProfile(); + } + @Override public ContentResolver getContentResolver() { return mContentResolver; @@ -1079,6 +1104,10 @@ public class ConnectivityServiceTest { public void triggerUnfulfillable(NetworkRequest r) { super.releaseRequestAsUnfulfillableByAnyFactory(r); } + + public void assertNoRequestChanged() { + assertNull(mRequestHistory.poll(0, r -> true)); + } } private Set<UidRange> uidRangesForUids(int... uids) { @@ -1404,17 +1433,36 @@ public class ConnectivityServiceTest { fail("ConditionVariable was blocked for more than " + TIMEOUT_MS + "ms"); } - private void registerNetworkCallbackAsUid(NetworkRequest request, NetworkCallback callback, - int uid) { + private <T> T doAsUid(final int uid, @NonNull final Supplier<T> what) { when(mDeps.getCallingUid()).thenReturn(uid); try { - mCm.registerNetworkCallback(request, callback); - waitForIdle(); + return what.get(); } finally { returnRealCallingUid(); } } + private void doAsUid(final int uid, @NonNull final Runnable what) { + doAsUid(uid, () -> { + what.run(); return Void.TYPE; + }); + } + + private void registerNetworkCallbackAsUid(NetworkRequest request, NetworkCallback callback, + int uid) { + doAsUid(uid, () -> { + mCm.registerNetworkCallback(request, callback); + }); + } + + private void registerDefaultNetworkCallbackAsUid(@NonNull final NetworkCallback callback, + final int uid) { + doAsUid(uid, () -> { + mCm.registerDefaultNetworkCallback(callback); + waitForIdle(); + }); + } + private static final int PRIMARY_USER = 0; private static final int APP1_UID = UserHandle.getUid(PRIMARY_USER, 10100); private static final int APP2_UID = UserHandle.getUid(PRIMARY_USER, 10101); @@ -1461,6 +1509,9 @@ public class ConnectivityServiceTest { Looper.prepare(); } mockDefaultPackages(); + mockHasSystemFeature(FEATURE_WIFI, true); + mockHasSystemFeature(FEATURE_WIFI_DIRECT, true); + doReturn(true).when(mTelephonyManager).isDataCapable(); FakeSettingsProvider.clearSettingsProvider(); mServiceContext = new MockContext(InstrumentationRegistry.getContext(), @@ -1503,7 +1554,7 @@ public class ConnectivityServiceTest { mQosCallbackTracker = mock(QosCallbackTracker.class); // Ensure that the default setting for Captive Portals is used for most tests - setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT); + setCaptivePortalMode(ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE_PROMPT); setAlwaysOnNetworks(false); setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com"); } @@ -1513,10 +1564,7 @@ public class ConnectivityServiceTest { } private ConnectivityService.Dependencies makeDependencies() { - doReturn(TEST_TCP_INIT_RWND).when(mSystemProperties) - .getInt("net.tcp.default_init_rwnd", 0); doReturn(false).when(mSystemProperties).getBoolean("ro.radio.noril", false); - doNothing().when(mSystemProperties).setTcpInitRwnd(anyInt()); final ConnectivityService.Dependencies deps = mock(ConnectivityService.Dependencies.class); doReturn(mCsHandlerThread).when(deps).makeHandlerThread(); doReturn(mNetIdManager).when(deps).makeNetIdManager(); @@ -1574,6 +1622,7 @@ public class ConnectivityServiceTest { @After public void tearDown() throws Exception { unregisterDefaultNetworkCallbacks(); + maybeTearDownEnterpriseNetwork(); setAlwaysOnNetworks(false); if (mCellNetworkAgent != null) { mCellNetworkAgent.disconnect(); @@ -1784,7 +1833,8 @@ public class ConnectivityServiceTest { assertTrue(mCm.isNetworkSupported(TYPE_WIFI)); assertTrue(mCm.isNetworkSupported(TYPE_MOBILE)); assertTrue(mCm.isNetworkSupported(TYPE_MOBILE_MMS)); - assertFalse(mCm.isNetworkSupported(TYPE_MOBILE_FOTA)); + assertTrue(mCm.isNetworkSupported(TYPE_MOBILE_FOTA)); + assertFalse(mCm.isNetworkSupported(TYPE_PROXY)); // Check that TYPE_ETHERNET is supported. Unlike the asserts above, which only validate our // mocks, this assert exercises the ConnectivityService code path that ensures that @@ -3357,7 +3407,7 @@ public class ConnectivityServiceTest { .addCapability(NET_CAPABILITY_VALIDATED).build(); mCm.registerNetworkCallback(validatedRequest, validatedCallback); - setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_AVOID); + setCaptivePortalMode(ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE_AVOID); // Bring up a network with a captive portal. // Expect it to fail to connect and not result in any callbacks. mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); @@ -4007,20 +4057,21 @@ public class ConnectivityServiceTest { private void setCaptivePortalMode(int mode) { ContentResolver cr = mServiceContext.getContentResolver(); - Settings.Global.putInt(cr, Settings.Global.CAPTIVE_PORTAL_MODE, mode); + Settings.Global.putInt(cr, ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE, mode); } private void setAlwaysOnNetworks(boolean enable) { ContentResolver cr = mServiceContext.getContentResolver(); - Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, enable ? 1 : 0); + Settings.Global.putInt(cr, ConnectivitySettingsManager.MOBILE_DATA_ALWAYS_ON, + enable ? 1 : 0); mService.updateAlwaysOnNetworks(); waitForIdle(); } private void setPrivateDnsSettings(String mode, String specifier) { final ContentResolver cr = mServiceContext.getContentResolver(); - Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_MODE, mode); - Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_SPECIFIER, specifier); + Settings.Global.putString(cr, ConnectivitySettingsManager.PRIVATE_DNS_MODE, mode); + Settings.Global.putString(cr, ConnectivitySettingsManager.PRIVATE_DNS_SPECIFIER, specifier); mService.updatePrivateDnsSettings(); waitForIdle(); } @@ -4258,7 +4309,7 @@ public class ConnectivityServiceTest { @Test public void testAvoidBadWifiSetting() throws Exception { final ContentResolver cr = mServiceContext.getContentResolver(); - final String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI; + final String settingName = ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI; mPolicyTracker.mConfigRestrictsAvoidBadWifi = false; String[] values = new String[] {null, "0", "1"}; @@ -4315,7 +4366,7 @@ public class ConnectivityServiceTest { TestNetworkCallback validatedWifiCallback = new TestNetworkCallback(); mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback); - Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 0); + Settings.Global.putInt(cr, ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI, 0); mPolicyTracker.reevaluate(); // Bring up validated cell. @@ -4383,7 +4434,7 @@ public class ConnectivityServiceTest { validatedWifiCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); // Simulate the user selecting "switch" and checking the don't ask again checkbox. - Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1); + Settings.Global.putInt(cr, ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI, 1); mPolicyTracker.reevaluate(); // We now switch to cell. @@ -4396,11 +4447,11 @@ public class ConnectivityServiceTest { // Simulate the user turning the cellular fallback setting off and then on. // We switch to wifi and then to cell. - Settings.Global.putString(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, null); + Settings.Global.putString(cr, ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI, null); mPolicyTracker.reevaluate(); defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); assertEquals(mCm.getActiveNetwork(), wifiNetwork); - Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1); + Settings.Global.putInt(cr, ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI, 1); mPolicyTracker.reevaluate(); defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); assertEquals(mCm.getActiveNetwork(), cellNetwork); @@ -4419,7 +4470,7 @@ public class ConnectivityServiceTest { @Test public void testMeteredMultipathPreferenceSetting() throws Exception { final ContentResolver cr = mServiceContext.getContentResolver(); - final String settingName = Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE; + final String settingName = ConnectivitySettingsManager.NETWORK_METERED_MULTIPATH_PREFERENCE; for (int config : Arrays.asList(0, 3, 2)) { for (String setting: Arrays.asList(null, "0", "2", "1")) { @@ -7993,7 +8044,6 @@ public class ConnectivityServiceTest { // Switching default network updates TCP buffer sizes. verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES); - verify(mSystemProperties, times(1)).setTcpInitRwnd(eq(TEST_TCP_INIT_RWND)); // Add an IPv4 address. Expect prefix discovery to be stopped. Netd doesn't tell us that // the NAT64 prefix was removed because one was never discovered. cellLp.addLinkAddress(myIpv4); @@ -8479,14 +8529,12 @@ public class ConnectivityServiceTest { mCellNetworkAgent.connect(false); networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES); - verify(mSystemProperties, times(1)).setTcpInitRwnd(eq(TEST_TCP_INIT_RWND)); // Change link Properties should have updated tcp buffer size. LinkProperties lp = new LinkProperties(); lp.setTcpBufferSizes(testTcpBufferSizes); mCellNetworkAgent.sendLinkProperties(lp); networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent); verifyTcpBufferSizeChange(testTcpBufferSizes); - verify(mSystemProperties, times(2)).setTcpInitRwnd(eq(TEST_TCP_INIT_RWND)); // Clean up. mCellNetworkAgent.disconnect(); networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); @@ -10114,9 +10162,12 @@ public class ConnectivityServiceTest { Manifest.permission.NETWORK_SETTINGS, PERMISSION_GRANTED); mSystemDefaultNetworkCallback = new TestNetworkCallback(); mDefaultNetworkCallback = new TestNetworkCallback(); + mProfileDefaultNetworkCallback = new TestNetworkCallback(); mCm.registerSystemDefaultNetworkCallback(mSystemDefaultNetworkCallback, new Handler(ConnectivityThread.getInstanceLooper())); mCm.registerDefaultNetworkCallback(mDefaultNetworkCallback); + registerDefaultNetworkCallbackAsUid(mProfileDefaultNetworkCallback, + TEST_WORK_PROFILE_APP_UID); mServiceContext.setPermission( Manifest.permission.NETWORK_SETTINGS, PERMISSION_DENIED); } @@ -10128,6 +10179,9 @@ public class ConnectivityServiceTest { if (null != mSystemDefaultNetworkCallback) { mCm.unregisterNetworkCallback(mSystemDefaultNetworkCallback); } + if (null != mProfileDefaultNetworkCallback) { + mCm.unregisterNetworkCallback(mProfileDefaultNetworkCallback); + } } private void setupMultipleDefaultNetworksForOemNetworkPreferenceNotCurrentUidTest( @@ -10183,7 +10237,7 @@ public class ConnectivityServiceTest { oemPrefListener.expectOnComplete(); } - private static class TestOemListenerCallback implements IOnSetOemNetworkPreferenceListener { + private static class TestOemListenerCallback implements IOnCompleteListener { final CompletableFuture<Object> mDone = new CompletableFuture<>(); @Override @@ -11121,11 +11175,494 @@ public class ConnectivityServiceTest { mCm.unregisterNetworkCallback(cellCb); } + // Cannot be part of MockNetworkFactory since it requires method of the test. + private void expectNoRequestChanged(@NonNull MockNetworkFactory factory) { + waitForIdle(); + factory.assertNoRequestChanged(); + } + @Test - public void testRegisterBestMatchingNetworkCallback() throws Exception { - final NetworkRequest request = new NetworkRequest.Builder().build(); - assertThrows(UnsupportedOperationException.class, - () -> mCm.registerBestMatchingNetworkCallback(request, new NetworkCallback(), - mCsHandlerThread.getThreadHandler())); + public void testRegisterBestMatchingNetworkCallback_noIssueToFactory() throws Exception { + // Prepare mock mms factory. + final HandlerThread handlerThread = new HandlerThread("MockCellularFactory"); + handlerThread.start(); + NetworkCapabilities filter = new NetworkCapabilities() + .addTransportType(TRANSPORT_CELLULAR) + .addCapability(NET_CAPABILITY_MMS); + final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(), + mServiceContext, "testFactory", filter, mCsHandlerThread); + testFactory.setScoreFilter(40); + + try { + // Register the factory and expect it will see default request, because all requests + // are sent to all factories. + testFactory.register(); + testFactory.expectRequestAdd(); + testFactory.assertRequestCountEquals(1); + // The factory won't try to start the network since the default request doesn't + // match the filter (no INTERNET capability). + assertFalse(testFactory.getMyStartRequested()); + + // Register callback for listening best matching network. Verify that the request won't + // be sent to factory. + final TestNetworkCallback bestMatchingCb = new TestNetworkCallback(); + mCm.registerBestMatchingNetworkCallback( + new NetworkRequest.Builder().addCapability(NET_CAPABILITY_MMS).build(), + bestMatchingCb, mCsHandlerThread.getThreadHandler()); + bestMatchingCb.assertNoCallback(); + expectNoRequestChanged(testFactory); + testFactory.assertRequestCountEquals(1); + assertFalse(testFactory.getMyStartRequested()); + + // Fire a normal mms request, verify the factory will only see the request. + final TestNetworkCallback mmsNetworkCallback = new TestNetworkCallback(); + final NetworkRequest mmsRequest = new NetworkRequest.Builder() + .addCapability(NET_CAPABILITY_MMS).build(); + mCm.requestNetwork(mmsRequest, mmsNetworkCallback); + testFactory.expectRequestAdd(); + testFactory.assertRequestCountEquals(2); + assertTrue(testFactory.getMyStartRequested()); + + // Unregister best matching callback, verify factory see no change. + mCm.unregisterNetworkCallback(bestMatchingCb); + expectNoRequestChanged(testFactory); + testFactory.assertRequestCountEquals(2); + assertTrue(testFactory.getMyStartRequested()); + } finally { + testFactory.terminate(); + } + } + + @Test + public void testRegisterBestMatchingNetworkCallback_trackBestNetwork() throws Exception { + final TestNetworkCallback bestMatchingCb = new TestNetworkCallback(); + mCm.registerBestMatchingNetworkCallback( + new NetworkRequest.Builder().addCapability(NET_CAPABILITY_TRUSTED).build(), + bestMatchingCb, mCsHandlerThread.getThreadHandler()); + + mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); + mCellNetworkAgent.connect(true); + bestMatchingCb.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); + + mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); + mWiFiNetworkAgent.connect(true); + bestMatchingCb.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); + + // Change something on cellular to trigger capabilities changed, since the callback + // only cares about the best network, verify it received nothing from cellular. + mCellNetworkAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED); + bestMatchingCb.assertNoCallback(); + + // Make cellular the best network again, verify the callback now tracks cellular. + mWiFiNetworkAgent.adjustScore(-50); + bestMatchingCb.expectAvailableCallbacksValidated(mCellNetworkAgent); + + // Make cellular temporary non-trusted, which will not satisfying the request. + // Verify the callback switch from/to the other network accordingly. + mCellNetworkAgent.removeCapability(NET_CAPABILITY_TRUSTED); + bestMatchingCb.expectAvailableCallbacksValidated(mWiFiNetworkAgent); + mCellNetworkAgent.addCapability(NET_CAPABILITY_TRUSTED); + bestMatchingCb.expectAvailableDoubleValidatedCallbacks(mCellNetworkAgent); + + // Verify the callback doesn't care about wifi disconnect. + mWiFiNetworkAgent.disconnect(); + bestMatchingCb.assertNoCallback(); + mCellNetworkAgent.disconnect(); + bestMatchingCb.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); + } + + private UidRangeParcel[] uidRangeFor(final UserHandle handle) { + UidRange range = UidRange.createForUser(handle); + return new UidRangeParcel[] { new UidRangeParcel(range.start, range.stop) }; + } + + private static class TestOnCompleteListener implements Runnable { + final class OnComplete {} + final ArrayTrackRecord<OnComplete>.ReadHead mHistory = + new ArrayTrackRecord<OnComplete>().newReadHead(); + + @Override + public void run() { + mHistory.add(new OnComplete()); + } + + public void expectOnComplete() { + assertNotNull(mHistory.poll(TIMEOUT_MS, it -> true)); + } + } + + private TestNetworkAgentWrapper makeEnterpriseNetworkAgent() throws Exception { + final NetworkCapabilities workNc = new NetworkCapabilities(); + workNc.addCapability(NET_CAPABILITY_ENTERPRISE); + workNc.removeCapability(NET_CAPABILITY_NOT_RESTRICTED); + return new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, new LinkProperties(), workNc); + } + + private TestNetworkCallback mEnterpriseCallback; + private UserHandle setupEnterpriseNetwork() { + final UserHandle userHandle = UserHandle.of(TEST_WORK_PROFILE_USER_ID); + mServiceContext.setWorkProfile(userHandle, true); + + // File a request to avoid the enterprise network being disconnected as soon as the default + // request goes away – it would make impossible to test that networkRemoveUidRanges + // is called, as the network would disconnect first for lack of a request. + mEnterpriseCallback = new TestNetworkCallback(); + final NetworkRequest keepUpRequest = new NetworkRequest.Builder() + .addCapability(NET_CAPABILITY_ENTERPRISE) + .build(); + mCm.requestNetwork(keepUpRequest, mEnterpriseCallback); + return userHandle; + } + + private void maybeTearDownEnterpriseNetwork() { + if (null != mEnterpriseCallback) { + mCm.unregisterNetworkCallback(mEnterpriseCallback); + } + } + + /** + * Make sure per-profile networking preference behaves as expected when the enterprise network + * goes up and down while the preference is active. Make sure they behave as expected whether + * there is a general default network or not. + */ + @Test + public void testPreferenceForUserNetworkUpDown() throws Exception { + final InOrder inOrder = inOrder(mMockNetd); + final UserHandle testHandle = setupEnterpriseNetwork(); + registerDefaultNetworkCallbacks(); + + mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); + mCellNetworkAgent.connect(true); + + mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); + mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); + mProfileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); + inOrder.verify(mMockNetd).networkCreatePhysical(mCellNetworkAgent.getNetwork().netId, + INetd.PERMISSION_NONE); + + final TestOnCompleteListener listener = new TestOnCompleteListener(); + mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE, + r -> r.run(), listener); + listener.expectOnComplete(); + + // Setting a network preference for this user will create a new set of routing rules for + // the UID range that corresponds to this user, so as to define the default network + // for these apps separately. This is true because the multi-layer request relevant to + // this UID range contains a TRACK_DEFAULT, so the range will be moved through UID-specific + // rules to the correct network – in this case the system default network. The case where + // the default network for the profile happens to be the same as the system default + // is not handled specially, the rules are always active as long as a preference is set. + inOrder.verify(mMockNetd).networkAddUidRanges(mCellNetworkAgent.getNetwork().netId, + uidRangeFor(testHandle)); + + // The enterprise network is not ready yet. + assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback, + mProfileDefaultNetworkCallback); + + final TestNetworkAgentWrapper workAgent = makeEnterpriseNetworkAgent(); + workAgent.connect(false); + + mProfileDefaultNetworkCallback.expectAvailableCallbacksUnvalidated(workAgent); + mSystemDefaultNetworkCallback.assertNoCallback(); + mDefaultNetworkCallback.assertNoCallback(); + inOrder.verify(mMockNetd).networkCreatePhysical(workAgent.getNetwork().netId, + INetd.PERMISSION_SYSTEM); + inOrder.verify(mMockNetd).networkAddUidRanges(workAgent.getNetwork().netId, + uidRangeFor(testHandle)); + inOrder.verify(mMockNetd).networkRemoveUidRanges(mCellNetworkAgent.getNetwork().netId, + uidRangeFor(testHandle)); + + // Make sure changes to the work agent send callbacks to the app in the work profile, but + // not to the other apps. + workAgent.setNetworkValid(true /* isStrictMode */); + workAgent.mNetworkMonitor.forceReevaluation(Process.myUid()); + mProfileDefaultNetworkCallback.expectCapabilitiesThat(workAgent, + nc -> nc.hasCapability(NET_CAPABILITY_VALIDATED) + && nc.hasCapability(NET_CAPABILITY_ENTERPRISE)); + assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback); + + workAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED); + mProfileDefaultNetworkCallback.expectCapabilitiesThat(workAgent, nc -> + nc.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)); + assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback); + + // Conversely, change a capability on the system-wide default network and make sure + // that only the apps outside of the work profile receive the callbacks. + mCellNetworkAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED); + mSystemDefaultNetworkCallback.expectCapabilitiesThat(mCellNetworkAgent, nc -> + nc.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)); + mDefaultNetworkCallback.expectCapabilitiesThat(mCellNetworkAgent, nc -> + nc.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)); + mProfileDefaultNetworkCallback.assertNoCallback(); + + // Disconnect and reconnect the system-wide default network and make sure that the + // apps on this network see the appropriate callbacks, and the app on the work profile + // doesn't because it continues to use the enterprise network. + mCellNetworkAgent.disconnect(); + mSystemDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); + mDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); + mProfileDefaultNetworkCallback.assertNoCallback(); + inOrder.verify(mMockNetd).networkDestroy(mCellNetworkAgent.getNetwork().netId); + + mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); + mCellNetworkAgent.connect(true); + mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); + mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); + mProfileDefaultNetworkCallback.assertNoCallback(); + inOrder.verify(mMockNetd).networkCreatePhysical(mCellNetworkAgent.getNetwork().netId, + INetd.PERMISSION_NONE); + + // When the agent disconnects, test that the app on the work profile falls back to the + // default network. + workAgent.disconnect(); + mProfileDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, workAgent); + mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); + assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback); + inOrder.verify(mMockNetd).networkAddUidRanges(mCellNetworkAgent.getNetwork().netId, + uidRangeFor(testHandle)); + inOrder.verify(mMockNetd).networkDestroy(workAgent.getNetwork().netId); + + mCellNetworkAgent.disconnect(); + mSystemDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); + mDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); + mProfileDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); + + // Waiting for the handler to be idle before checking for networkDestroy is necessary + // here because ConnectivityService calls onLost before the network is fully torn down. + waitForIdle(); + inOrder.verify(mMockNetd).networkDestroy(mCellNetworkAgent.getNetwork().netId); + + // If the control comes here, callbacks seem to behave correctly in the presence of + // a default network when the enterprise network goes up and down. Now, make sure they + // also behave correctly in the absence of a system-wide default network. + final TestNetworkAgentWrapper workAgent2 = makeEnterpriseNetworkAgent(); + workAgent2.connect(false); + + mProfileDefaultNetworkCallback.expectAvailableCallbacksUnvalidated(workAgent2); + assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback); + inOrder.verify(mMockNetd).networkCreatePhysical(workAgent2.getNetwork().netId, + INetd.PERMISSION_SYSTEM); + inOrder.verify(mMockNetd).networkAddUidRanges(workAgent2.getNetwork().netId, + uidRangeFor(testHandle)); + + workAgent2.setNetworkValid(true /* isStrictMode */); + workAgent2.mNetworkMonitor.forceReevaluation(Process.myUid()); + mProfileDefaultNetworkCallback.expectCapabilitiesThat(workAgent2, + nc -> nc.hasCapability(NET_CAPABILITY_ENTERPRISE) + && !nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); + assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback); + inOrder.verify(mMockNetd, never()).networkAddUidRanges(anyInt(), any()); + + // When the agent disconnects, test that the app on the work profile falls back to the + // default network. + workAgent2.disconnect(); + mProfileDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, workAgent2); + assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback); + inOrder.verify(mMockNetd).networkDestroy(workAgent2.getNetwork().netId); + + assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback, + mProfileDefaultNetworkCallback); + + // Callbacks will be unregistered by tearDown() + } + + /** + * Test that, in a given networking context, calling setPreferenceForUser to set per-profile + * defaults on then off works as expected. + */ + @Test + public void testSetPreferenceForUserOnOff() throws Exception { + final InOrder inOrder = inOrder(mMockNetd); + final UserHandle testHandle = setupEnterpriseNetwork(); + + // Connect both a regular cell agent and an enterprise network first. + mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); + mCellNetworkAgent.connect(true); + + final TestNetworkAgentWrapper workAgent = makeEnterpriseNetworkAgent(); + workAgent.connect(true); + + final TestOnCompleteListener listener = new TestOnCompleteListener(); + mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE, + r -> r.run(), listener); + listener.expectOnComplete(); + inOrder.verify(mMockNetd).networkCreatePhysical(mCellNetworkAgent.getNetwork().netId, + INetd.PERMISSION_NONE); + inOrder.verify(mMockNetd).networkAddUidRanges(workAgent.getNetwork().netId, + uidRangeFor(testHandle)); + + registerDefaultNetworkCallbacks(); + + mSystemDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); + mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); + mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(workAgent); + + mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_DEFAULT, + r -> r.run(), listener); + listener.expectOnComplete(); + + mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); + assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback); + inOrder.verify(mMockNetd).networkRemoveUidRanges(workAgent.getNetwork().netId, + uidRangeFor(testHandle)); + + workAgent.disconnect(); + mCellNetworkAgent.disconnect(); + + // Callbacks will be unregistered by tearDown() + } + + /** + * Test per-profile default networks for two different profiles concurrently. + */ + @Test + public void testSetPreferenceForTwoProfiles() throws Exception { + final InOrder inOrder = inOrder(mMockNetd); + final UserHandle testHandle2 = setupEnterpriseNetwork(); + final UserHandle testHandle4 = UserHandle.of(TEST_WORK_PROFILE_USER_ID + 2); + mServiceContext.setWorkProfile(testHandle4, true); + registerDefaultNetworkCallbacks(); + + final TestNetworkCallback app4Cb = new TestNetworkCallback(); + final int testWorkProfileAppUid4 = + UserHandle.getUid(testHandle4.getIdentifier(), TEST_APP_ID); + registerDefaultNetworkCallbackAsUid(app4Cb, testWorkProfileAppUid4); + + // Connect both a regular cell agent and an enterprise network first. + mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); + mCellNetworkAgent.connect(true); + + final TestNetworkAgentWrapper workAgent = makeEnterpriseNetworkAgent(); + workAgent.connect(true); + + mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); + mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); + mProfileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); + app4Cb.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); + inOrder.verify(mMockNetd).networkCreatePhysical(mCellNetworkAgent.getNetwork().netId, + INetd.PERMISSION_NONE); + inOrder.verify(mMockNetd).networkCreatePhysical(workAgent.getNetwork().netId, + INetd.PERMISSION_SYSTEM); + + final TestOnCompleteListener listener = new TestOnCompleteListener(); + mCm.setProfileNetworkPreference(testHandle2, PROFILE_NETWORK_PREFERENCE_ENTERPRISE, + r -> r.run(), listener); + listener.expectOnComplete(); + inOrder.verify(mMockNetd).networkAddUidRanges(workAgent.getNetwork().netId, + uidRangeFor(testHandle2)); + + mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(workAgent); + assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback, + app4Cb); + + mCm.setProfileNetworkPreference(testHandle4, PROFILE_NETWORK_PREFERENCE_ENTERPRISE, + r -> r.run(), listener); + listener.expectOnComplete(); + inOrder.verify(mMockNetd).networkAddUidRanges(workAgent.getNetwork().netId, + uidRangeFor(testHandle4)); + + app4Cb.expectAvailableCallbacksValidated(workAgent); + assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback, + mProfileDefaultNetworkCallback); + + mCm.setProfileNetworkPreference(testHandle2, PROFILE_NETWORK_PREFERENCE_DEFAULT, + r -> r.run(), listener); + listener.expectOnComplete(); + inOrder.verify(mMockNetd).networkRemoveUidRanges(workAgent.getNetwork().netId, + uidRangeFor(testHandle2)); + + mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); + assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback, + app4Cb); + + workAgent.disconnect(); + mCellNetworkAgent.disconnect(); + + mCm.unregisterNetworkCallback(app4Cb); + // Other callbacks will be unregistered by tearDown() + } + + @Test + public void testProfilePreferenceRemovedUponUserRemoved() throws Exception { + final InOrder inOrder = inOrder(mMockNetd); + final UserHandle testHandle = setupEnterpriseNetwork(); + + mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); + mCellNetworkAgent.connect(true); + + final TestOnCompleteListener listener = new TestOnCompleteListener(); + mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE, + r -> r.run(), listener); + listener.expectOnComplete(); + inOrder.verify(mMockNetd).networkCreatePhysical(mCellNetworkAgent.getNetwork().netId, + INetd.PERMISSION_NONE); + inOrder.verify(mMockNetd).networkAddUidRanges(mCellNetworkAgent.getNetwork().netId, + uidRangeFor(testHandle)); + + final Intent removedIntent = new Intent(ACTION_USER_REMOVED); + removedIntent.putExtra(Intent.EXTRA_USER, testHandle); + processBroadcast(removedIntent); + + inOrder.verify(mMockNetd).networkRemoveUidRanges(mCellNetworkAgent.getNetwork().netId, + uidRangeFor(testHandle)); + } + + /** + * Make sure that OEM preference and per-profile preference can't be used at the same + * time and throw ISE if tried + */ + @Test + public void testOemPreferenceAndProfilePreferenceExclusive() throws Exception { + final UserHandle testHandle = UserHandle.of(TEST_WORK_PROFILE_USER_ID); + mServiceContext.setWorkProfile(testHandle, true); + final TestOnCompleteListener listener = new TestOnCompleteListener(); + + setupMultipleDefaultNetworksForOemNetworkPreferenceNotCurrentUidTest( + OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY); + assertThrows("Should not be able to set per-profile pref while OEM prefs present", + IllegalStateException.class, () -> + mCm.setProfileNetworkPreference(testHandle, + PROFILE_NETWORK_PREFERENCE_ENTERPRISE, + r -> r.run(), listener)); + + // Empty the OEM prefs + final TestOemListenerCallback oemPrefListener = new TestOemListenerCallback(); + final OemNetworkPreferences emptyOemPref = new OemNetworkPreferences.Builder().build(); + mService.setOemNetworkPreference(emptyOemPref, oemPrefListener); + oemPrefListener.expectOnComplete(); + + mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE, + r -> r.run(), listener); + listener.expectOnComplete(); + assertThrows("Should not be able to set OEM prefs while per-profile pref is on", + IllegalStateException.class , () -> + mService.setOemNetworkPreference(emptyOemPref, oemPrefListener)); + } + + /** + * Make sure wrong preferences for per-profile default networking are rejected. + */ + @Test + public void testProfileNetworkPrefWrongPreference() throws Exception { + final UserHandle testHandle = UserHandle.of(TEST_WORK_PROFILE_USER_ID); + mServiceContext.setWorkProfile(testHandle, true); + assertThrows("Should not be able to set an illegal preference", + IllegalArgumentException.class, + () -> mCm.setProfileNetworkPreference(testHandle, + PROFILE_NETWORK_PREFERENCE_ENTERPRISE + 1, null, null)); + } + + /** + * Make sure requests for per-profile default networking for a non-work profile are + * rejected + */ + @Test + public void testProfileNetworkPrefWrongProfile() throws Exception { + final UserHandle testHandle = UserHandle.of(TEST_WORK_PROFILE_USER_ID); + mServiceContext.setWorkProfile(testHandle, false); + assertThrows("Should not be able to set a user pref for a non-work profile", + IllegalArgumentException.class , () -> + mCm.setProfileNetworkPreference(testHandle, + PROFILE_NETWORK_PREFERENCE_ENTERPRISE, null, null)); } } diff --git a/tests/net/java/com/android/server/LegacyTypeTrackerTest.kt b/tests/net/java/com/android/server/LegacyTypeTrackerTest.kt index a10a3c81bc86..5ec111954fcc 100644 --- a/tests/net/java/com/android/server/LegacyTypeTrackerTest.kt +++ b/tests/net/java/com/android/server/LegacyTypeTrackerTest.kt @@ -21,13 +21,29 @@ package com.android.server +import android.content.Context +import android.content.pm.PackageManager +import android.content.pm.PackageManager.FEATURE_WIFI +import android.content.pm.PackageManager.FEATURE_WIFI_DIRECT import android.net.ConnectivityManager.TYPE_ETHERNET import android.net.ConnectivityManager.TYPE_MOBILE +import android.net.ConnectivityManager.TYPE_MOBILE_CBS +import android.net.ConnectivityManager.TYPE_MOBILE_DUN +import android.net.ConnectivityManager.TYPE_MOBILE_EMERGENCY +import android.net.ConnectivityManager.TYPE_MOBILE_FOTA +import android.net.ConnectivityManager.TYPE_MOBILE_HIPRI +import android.net.ConnectivityManager.TYPE_MOBILE_IA +import android.net.ConnectivityManager.TYPE_MOBILE_IMS +import android.net.ConnectivityManager.TYPE_MOBILE_MMS import android.net.ConnectivityManager.TYPE_MOBILE_SUPL +import android.net.ConnectivityManager.TYPE_VPN import android.net.ConnectivityManager.TYPE_WIFI +import android.net.ConnectivityManager.TYPE_WIFI_P2P import android.net.ConnectivityManager.TYPE_WIMAX +import android.net.EthernetManager import android.net.NetworkInfo.DetailedState.CONNECTED import android.net.NetworkInfo.DetailedState.DISCONNECTED +import android.telephony.TelephonyManager import androidx.test.filters.SmallTest import androidx.test.runner.AndroidJUnit4 import com.android.server.ConnectivityService.LegacyTypeTracker @@ -36,7 +52,6 @@ import org.junit.Assert.assertFalse import org.junit.Assert.assertNull import org.junit.Assert.assertSame import org.junit.Assert.assertTrue -import org.junit.Assert.fail import org.junit.Test import org.junit.runner.RunWith import org.mockito.ArgumentMatchers.any @@ -52,88 +67,130 @@ const val UNSUPPORTED_TYPE = TYPE_WIMAX @RunWith(AndroidJUnit4::class) @SmallTest class LegacyTypeTrackerTest { - private val supportedTypes = arrayOf(TYPE_MOBILE, TYPE_WIFI, TYPE_ETHERNET, TYPE_MOBILE_SUPL) + private val supportedTypes = arrayOf(TYPE_WIFI, TYPE_WIFI_P2P, TYPE_ETHERNET, TYPE_MOBILE, + TYPE_MOBILE_SUPL, TYPE_MOBILE_MMS, TYPE_MOBILE_SUPL, TYPE_MOBILE_DUN, TYPE_MOBILE_HIPRI, + TYPE_MOBILE_FOTA, TYPE_MOBILE_IMS, TYPE_MOBILE_CBS, TYPE_MOBILE_IA, + TYPE_MOBILE_EMERGENCY, TYPE_VPN) private val mMockService = mock(ConnectivityService::class.java).apply { doReturn(false).`when`(this).isDefaultNetwork(any()) } - private val mTracker = LegacyTypeTracker(mMockService).apply { - supportedTypes.forEach { - addSupportedType(it) - } + private val mPm = mock(PackageManager::class.java) + private val mContext = mock(Context::class.java).apply { + doReturn(true).`when`(mPm).hasSystemFeature(FEATURE_WIFI) + doReturn(true).`when`(mPm).hasSystemFeature(FEATURE_WIFI_DIRECT) + doReturn(mPm).`when`(this).packageManager + doReturn(mock(EthernetManager::class.java)).`when`(this).getSystemService( + Context.ETHERNET_SERVICE) + } + private val mTm = mock(TelephonyManager::class.java).apply { + doReturn(true).`when`(this).isDataCapable + } + + private fun makeTracker() = LegacyTypeTracker(mMockService).apply { + loadSupportedTypes(mContext, mTm) } @Test fun testSupportedTypes() { - try { - mTracker.addSupportedType(supportedTypes[0]) - fail("Expected IllegalStateException") - } catch (expected: IllegalStateException) {} + val tracker = makeTracker() supportedTypes.forEach { - assertTrue(mTracker.isTypeSupported(it)) + assertTrue(tracker.isTypeSupported(it)) + } + assertFalse(tracker.isTypeSupported(UNSUPPORTED_TYPE)) + } + + @Test + fun testSupportedTypes_NoEthernet() { + doReturn(null).`when`(mContext).getSystemService(Context.ETHERNET_SERVICE) + assertFalse(makeTracker().isTypeSupported(TYPE_ETHERNET)) + } + + @Test + fun testSupportedTypes_NoTelephony() { + doReturn(false).`when`(mTm).isDataCapable + val tracker = makeTracker() + val nonMobileTypes = arrayOf(TYPE_WIFI, TYPE_WIFI_P2P, TYPE_ETHERNET, TYPE_VPN) + nonMobileTypes.forEach { + assertTrue(tracker.isTypeSupported(it)) + } + supportedTypes.toSet().minus(nonMobileTypes).forEach { + assertFalse(tracker.isTypeSupported(it)) + } + } + + @Test + fun testSupportedTypes_NoWifiDirect() { + doReturn(false).`when`(mPm).hasSystemFeature(FEATURE_WIFI_DIRECT) + val tracker = makeTracker() + assertFalse(tracker.isTypeSupported(TYPE_WIFI_P2P)) + supportedTypes.toSet().minus(TYPE_WIFI_P2P).forEach { + assertTrue(tracker.isTypeSupported(it)) } - assertFalse(mTracker.isTypeSupported(UNSUPPORTED_TYPE)) } @Test fun testSupl() { + val tracker = makeTracker() val mobileNai = mock(NetworkAgentInfo::class.java) - mTracker.add(TYPE_MOBILE, mobileNai) + tracker.add(TYPE_MOBILE, mobileNai) verify(mMockService).sendLegacyNetworkBroadcast(mobileNai, CONNECTED, TYPE_MOBILE) reset(mMockService) - mTracker.add(TYPE_MOBILE_SUPL, mobileNai) + tracker.add(TYPE_MOBILE_SUPL, mobileNai) verify(mMockService).sendLegacyNetworkBroadcast(mobileNai, CONNECTED, TYPE_MOBILE_SUPL) reset(mMockService) - mTracker.remove(TYPE_MOBILE_SUPL, mobileNai, false /* wasDefault */) + tracker.remove(TYPE_MOBILE_SUPL, mobileNai, false /* wasDefault */) verify(mMockService).sendLegacyNetworkBroadcast(mobileNai, DISCONNECTED, TYPE_MOBILE_SUPL) reset(mMockService) - mTracker.add(TYPE_MOBILE_SUPL, mobileNai) + tracker.add(TYPE_MOBILE_SUPL, mobileNai) verify(mMockService).sendLegacyNetworkBroadcast(mobileNai, CONNECTED, TYPE_MOBILE_SUPL) reset(mMockService) - mTracker.remove(mobileNai, false) + tracker.remove(mobileNai, false) verify(mMockService).sendLegacyNetworkBroadcast(mobileNai, DISCONNECTED, TYPE_MOBILE_SUPL) verify(mMockService).sendLegacyNetworkBroadcast(mobileNai, DISCONNECTED, TYPE_MOBILE) } @Test fun testAddNetwork() { + val tracker = makeTracker() val mobileNai = mock(NetworkAgentInfo::class.java) val wifiNai = mock(NetworkAgentInfo::class.java) - mTracker.add(TYPE_MOBILE, mobileNai) - mTracker.add(TYPE_WIFI, wifiNai) - assertSame(mTracker.getNetworkForType(TYPE_MOBILE), mobileNai) - assertSame(mTracker.getNetworkForType(TYPE_WIFI), wifiNai) + tracker.add(TYPE_MOBILE, mobileNai) + tracker.add(TYPE_WIFI, wifiNai) + assertSame(tracker.getNetworkForType(TYPE_MOBILE), mobileNai) + assertSame(tracker.getNetworkForType(TYPE_WIFI), wifiNai) // Make sure adding a second NAI does not change the results. val secondMobileNai = mock(NetworkAgentInfo::class.java) - mTracker.add(TYPE_MOBILE, secondMobileNai) - assertSame(mTracker.getNetworkForType(TYPE_MOBILE), mobileNai) - assertSame(mTracker.getNetworkForType(TYPE_WIFI), wifiNai) + tracker.add(TYPE_MOBILE, secondMobileNai) + assertSame(tracker.getNetworkForType(TYPE_MOBILE), mobileNai) + assertSame(tracker.getNetworkForType(TYPE_WIFI), wifiNai) // Make sure removing a network that wasn't added for this type is a no-op. - mTracker.remove(TYPE_MOBILE, wifiNai, false /* wasDefault */) - assertSame(mTracker.getNetworkForType(TYPE_MOBILE), mobileNai) - assertSame(mTracker.getNetworkForType(TYPE_WIFI), wifiNai) + tracker.remove(TYPE_MOBILE, wifiNai, false /* wasDefault */) + assertSame(tracker.getNetworkForType(TYPE_MOBILE), mobileNai) + assertSame(tracker.getNetworkForType(TYPE_WIFI), wifiNai) // Remove the top network for mobile and make sure the second one becomes the network // of record for this type. - mTracker.remove(TYPE_MOBILE, mobileNai, false /* wasDefault */) - assertSame(mTracker.getNetworkForType(TYPE_MOBILE), secondMobileNai) - assertSame(mTracker.getNetworkForType(TYPE_WIFI), wifiNai) + tracker.remove(TYPE_MOBILE, mobileNai, false /* wasDefault */) + assertSame(tracker.getNetworkForType(TYPE_MOBILE), secondMobileNai) + assertSame(tracker.getNetworkForType(TYPE_WIFI), wifiNai) // Make sure adding a network for an unsupported type does not register it. - mTracker.add(UNSUPPORTED_TYPE, mobileNai) - assertNull(mTracker.getNetworkForType(UNSUPPORTED_TYPE)) + tracker.add(UNSUPPORTED_TYPE, mobileNai) + assertNull(tracker.getNetworkForType(UNSUPPORTED_TYPE)) } @Test fun testBroadcastOnDisconnect() { + val tracker = makeTracker() val mobileNai1 = mock(NetworkAgentInfo::class.java) val mobileNai2 = mock(NetworkAgentInfo::class.java) doReturn(false).`when`(mMockService).isDefaultNetwork(mobileNai1) - mTracker.add(TYPE_MOBILE, mobileNai1) + tracker.add(TYPE_MOBILE, mobileNai1) verify(mMockService).sendLegacyNetworkBroadcast(mobileNai1, CONNECTED, TYPE_MOBILE) reset(mMockService) doReturn(false).`when`(mMockService).isDefaultNetwork(mobileNai2) - mTracker.add(TYPE_MOBILE, mobileNai2) + tracker.add(TYPE_MOBILE, mobileNai2) verify(mMockService, never()).sendLegacyNetworkBroadcast(any(), any(), anyInt()) - mTracker.remove(TYPE_MOBILE, mobileNai1, false /* wasDefault */) + tracker.remove(TYPE_MOBILE, mobileNai1, false /* wasDefault */) verify(mMockService).sendLegacyNetworkBroadcast(mobileNai1, DISCONNECTED, TYPE_MOBILE) verify(mMockService).sendLegacyNetworkBroadcast(mobileNai2, CONNECTED, TYPE_MOBILE) } diff --git a/tests/net/java/com/android/server/connectivity/DnsManagerTest.java b/tests/net/java/com/android/server/connectivity/DnsManagerTest.java index 5760211d9a27..692c50fbef86 100644 --- a/tests/net/java/com/android/server/connectivity/DnsManagerTest.java +++ b/tests/net/java/com/android/server/connectivity/DnsManagerTest.java @@ -18,15 +18,15 @@ package com.android.server.connectivity; import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF; import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME; +import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_DEFAULT_MODE; +import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE; +import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_SPECIFIER; import static android.net.NetworkCapabilities.MAX_TRANSPORT; import static android.net.NetworkCapabilities.MIN_TRANSPORT; import static android.net.NetworkCapabilities.TRANSPORT_VPN; import static android.net.NetworkCapabilities.TRANSPORT_WIFI; import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.VALIDATION_RESULT_FAILURE; import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.VALIDATION_RESULT_SUCCESS; -import static android.provider.Settings.Global.PRIVATE_DNS_DEFAULT_MODE; -import static android.provider.Settings.Global.PRIVATE_DNS_MODE; -import static android.provider.Settings.Global.PRIVATE_DNS_SPECIFIER; import static com.android.testutils.MiscAsserts.assertContainsExactly; import static com.android.testutils.MiscAsserts.assertContainsStringsExactly; @@ -312,14 +312,14 @@ public class DnsManagerTest { @Test public void testOverrideDefaultMode() throws Exception { // Hard-coded default is opportunistic mode. - final PrivateDnsConfig cfgAuto = DnsManager.getPrivateDnsConfig(mContentResolver); + final PrivateDnsConfig cfgAuto = DnsManager.getPrivateDnsConfig(mCtx); assertTrue(cfgAuto.useTls); assertEquals("", cfgAuto.hostname); assertEquals(new InetAddress[0], cfgAuto.ips); // Pretend a gservices push sets the default to "off". Settings.Global.putString(mContentResolver, PRIVATE_DNS_DEFAULT_MODE, "off"); - final PrivateDnsConfig cfgOff = DnsManager.getPrivateDnsConfig(mContentResolver); + final PrivateDnsConfig cfgOff = DnsManager.getPrivateDnsConfig(mCtx); assertFalse(cfgOff.useTls); assertEquals("", cfgOff.hostname); assertEquals(new InetAddress[0], cfgOff.ips); @@ -328,7 +328,7 @@ public class DnsManagerTest { Settings.Global.putString( mContentResolver, PRIVATE_DNS_MODE, PRIVATE_DNS_MODE_PROVIDER_HOSTNAME); Settings.Global.putString(mContentResolver, PRIVATE_DNS_SPECIFIER, "strictmode.com"); - final PrivateDnsConfig cfgStrict = DnsManager.getPrivateDnsConfig(mContentResolver); + final PrivateDnsConfig cfgStrict = DnsManager.getPrivateDnsConfig(mCtx); assertTrue(cfgStrict.useTls); assertEquals("strictmode.com", cfgStrict.hostname); assertEquals(new InetAddress[0], cfgStrict.ips); diff --git a/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java b/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java index 5b17aadc50a6..8a0c923d5fb0 100644 --- a/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java +++ b/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java @@ -109,16 +109,6 @@ public class VcnGatewayConnectionConfigTest { } @Test - public void testBuilderRequiresNonEmptyUnderlyingCaps() { - try { - newBuilder().addExposedCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET).build(); - - fail("Expected exception due to invalid required underlying capabilities"); - } catch (IllegalArgumentException e) { - } - } - - @Test public void testBuilderRequiresNonNullRetryInterval() { try { newBuilder().setRetryInterval(null); diff --git a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java index a02002752c38..814cad4ab448 100644 --- a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java +++ b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java @@ -74,7 +74,7 @@ import android.telephony.TelephonyManager; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; -import com.android.internal.util.LocationPermissionChecker; +import com.android.net.module.util.LocationPermissionChecker; import com.android.server.VcnManagementService.VcnCallback; import com.android.server.VcnManagementService.VcnStatusCallbackInfo; import com.android.server.vcn.TelephonySubscriptionTracker; |