diff options
76 files changed, 1747 insertions, 956 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..4d55bf90ad40 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); @@ -39304,6 +39304,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 +39347,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 +40907,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..a21ce7998193 100644 --- a/core/api/module-lib-current.txt +++ b/core/api/module-lib-current.txt @@ -109,6 +109,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..68be0bfa1f24 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -10025,10 +10025,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); } 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/packages/Connectivity/framework/src/android/net/IOnSetOemNetworkPreferenceListener.aidl b/core/java/android/net/IOnCompleteListener.aidl index 7979afc54f90..4bb89f6c89e4 100644 --- a/packages/Connectivity/framework/src/android/net/IOnSetOemNetworkPreferenceListener.aidl +++ b/core/java/android/net/IOnCompleteListener.aidl @@ -18,6 +18,6 @@ package android.net; /** @hide */ -oneway interface IOnSetOemNetworkPreferenceListener { +oneway interface IOnCompleteListener { void onComplete(); } 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/TelephonyCallback.java b/core/java/android/telephony/TelephonyCallback.java index a2584cae1b9c..73ba003bcfe4 100644 --- a/core/java/android/telephony/TelephonyCallback.java +++ b/core/java/android/telephony/TelephonyCallback.java @@ -1330,10 +1330,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 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/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/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/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..bb296476c72f 100644 --- a/packages/Connectivity/framework/api/module-lib-current.txt +++ b/packages/Connectivity/framework/api/module-lib-current.txt @@ -8,9 +8,10 @@ package android.net { public class ConnectivityManager { 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 @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(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); field public static final String PRIVATE_DNS_MODE_OFF = "off"; field public static final String PRIVATE_DNS_MODE_OPPORTUNISTIC = "opportunistic"; diff --git a/packages/Connectivity/framework/api/system-current.txt b/packages/Connectivity/framework/api/system-current.txt index a98f14ea9408..4dca411cca24 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); @@ -67,6 +67,8 @@ package android.net { method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void unregisterTetheringEventCallback(@NonNull android.net.ConnectivityManager.OnTetheringEventCallback); field public static final String EXTRA_CAPTIVE_PORTAL_PROBE_SPEC = "android.net.extra.CAPTIVE_PORTAL_PROBE_SPEC"; field public static final String EXTRA_CAPTIVE_PORTAL_USER_AGENT = "android.net.extra.CAPTIVE_PORTAL_USER_AGENT"; + field public static final int PROFILE_NETWORK_PREFERENCE_DEFAULT = 0; // 0x0 + field public static final int PROFILE_NETWORK_PREFERENCE_ENTERPRISE = 1; // 0x1 field public static final int TETHERING_BLUETOOTH = 2; // 0x2 field public static final int TETHERING_USB = 1; // 0x1 field public static final int TETHERING_WIFI = 0; // 0x0 @@ -78,10 +80,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 b350bc2527e2..a587e6ce01d3 100644 --- a/packages/Connectivity/framework/src/android/net/ConnectivityManager.java +++ b/packages/Connectivity/framework/src/android/net/ConnectivityManager.java @@ -20,8 +20,8 @@ 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; @@ -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; @@ -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 + 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 + 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. * @@ -3523,29 +3550,28 @@ public class ConnectivityManager { } } - private static final int BASE = Protocol.BASE_CONNECTIVITY_MANAGER; /** @hide */ - public static final int CALLBACK_PRECHECK = BASE + 1; + public static final int CALLBACK_PRECHECK = 1; /** @hide */ - public static final int CALLBACK_AVAILABLE = BASE + 2; + public static final int CALLBACK_AVAILABLE = 2; /** @hide arg1 = TTL */ - public static final int CALLBACK_LOSING = BASE + 3; + public static final int CALLBACK_LOSING = 3; /** @hide */ - public static final int CALLBACK_LOST = BASE + 4; + public static final int CALLBACK_LOST = 4; /** @hide */ - public static final int CALLBACK_UNAVAIL = BASE + 5; + public static final int CALLBACK_UNAVAIL = 5; /** @hide */ - public static final int CALLBACK_CAP_CHANGED = BASE + 6; + public static final int CALLBACK_CAP_CHANGED = 6; /** @hide */ - public static final int CALLBACK_IP_CHANGED = BASE + 7; + public static final int CALLBACK_IP_CHANGED = 7; /** @hide obj = NetworkCapabilities, arg1 = seq number */ - private static final int EXPIRE_LEGACY_REQUEST = BASE + 8; + private static final int EXPIRE_LEGACY_REQUEST = 8; /** @hide */ - public static final int CALLBACK_SUSPENDED = BASE + 9; + public static final int CALLBACK_SUSPENDED = 9; /** @hide */ - public static final int CALLBACK_RESUMED = BASE + 10; + public static final int CALLBACK_RESUMED = 10; /** @hide */ - public static final int CALLBACK_BLK_CHANGED = BASE + 11; + public static final int CALLBACK_BLK_CHANGED = 11; /** @hide */ public static String getCallbackName(int whichCallback) { @@ -4241,15 +4267,33 @@ public class ConnectivityManager { } /** - * @hide + * Registers to receive notifications about the best matching network which satisfy the given + * {@link NetworkRequest}. The callbacks will continue to be called until + * either the application exits or {@link #unregisterNetworkCallback(NetworkCallback)} is + * called. + * + * <p>To avoid performance issues due to apps leaking callbacks, the system will limit the + * number of outstanding requests to 100 per app (identified by their UID), shared with + * {@link #registerNetworkCallback} and its variants and {@link #requestNetwork} as well as + * {@link ConnectivityDiagnosticsManager#registerConnectivityDiagnosticsCallback}. + * Requesting a network with this method will count toward this limit. If this limit is + * exceeded, an exception will be thrown. To avoid hitting this issue and to conserve resources, + * make sure to unregister the callbacks with + * {@link #unregisterNetworkCallback(NetworkCallback)}. + * + * + * @param request {@link NetworkRequest} describing this request. + * @param networkCallback The {@link NetworkCallback} that the system will call as suitable + * networks change state. + * @param handler {@link Handler} to specify the thread upon which the callback will be invoked. + * @throws RuntimeException if the app already has too many callbacks registered. */ - // TODO: Make it public api. @SuppressLint("ExecutorRegistration") public void registerBestMatchingNetworkCallback(@NonNull NetworkRequest request, @NonNull NetworkCallback networkCallback, @NonNull Handler handler) { final NetworkCapabilities nc = request.networkCapabilities; final CallbackHandler cbHandler = new CallbackHandler(handler); - sendRequestForNetwork(nc, networkCallback, 0, TRACK_BEST, TYPE_NONE, cbHandler); + sendRequestForNetwork(nc, networkCallback, 0, LISTEN_FOR_BEST, TYPE_NONE, cbHandler); } /** @@ -5049,19 +5093,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 +5114,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 +5135,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 +5201,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 +5209,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/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/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/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/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 29c88c74947d..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; @@ -98,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; @@ -111,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; @@ -193,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; @@ -215,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; @@ -559,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; @@ -570,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. */ @@ -618,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; @@ -712,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"); @@ -744,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) { @@ -1166,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); @@ -1290,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; } @@ -2604,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 @@ -2627,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; } @@ -3665,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() @@ -3757,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 @@ -4532,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; @@ -4836,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); } @@ -5108,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); } @@ -5551,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); } @@ -5560,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); @@ -5898,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. @@ -8881,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); } @@ -9102,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); @@ -9120,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, @@ -9149,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..f4231d29fe9b 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -2764,6 +2764,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 +2914,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 +2938,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 cb81cb650b56..ffeb77d1d109 100644 --- a/services/core/java/com/android/server/connectivity/DnsManager.java +++ b/services/core/java/com/android/server/connectivity/DnsManager.java @@ -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/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/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/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 364c9be9614a..e77ee365b4d3 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -14927,7 +14927,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/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 38d1d31833c5..76b1d10614e1 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; @@ -184,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; @@ -379,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"; @@ -422,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; @@ -543,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; @@ -1080,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) { @@ -1405,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); @@ -1462,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(), @@ -1514,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(); @@ -1575,6 +1622,7 @@ public class ConnectivityServiceTest { @After public void tearDown() throws Exception { unregisterDefaultNetworkCallbacks(); + maybeTearDownEnterpriseNetwork(); setAlwaysOnNetworks(false); if (mCellNetworkAgent != null) { mCellNetworkAgent.disconnect(); @@ -1785,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 @@ -7995,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); @@ -8481,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); @@ -10116,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); } @@ -10130,6 +10179,9 @@ public class ConnectivityServiceTest { if (null != mSystemDefaultNetworkCallback) { mCm.unregisterNetworkCallback(mSystemDefaultNetworkCallback); } + if (null != mProfileDefaultNetworkCallback) { + mCm.unregisterNetworkCallback(mProfileDefaultNetworkCallback); + } } private void setupMultipleDefaultNetworksForOemNetworkPreferenceNotCurrentUidTest( @@ -10185,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 @@ -11123,11 +11175,495 @@ 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(); + waitForIdle(); + 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)); + waitForIdle(); + inOrder.verify(mMockNetd).networkDestroy(workAgent.getNetwork().netId); + + mCellNetworkAgent.disconnect(); + mSystemDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); + mDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); + mProfileDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); + + 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); + waitForIdle(); + 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 ad118df97261..692c50fbef86 100644 --- a/tests/net/java/com/android/server/connectivity/DnsManagerTest.java +++ b/tests/net/java/com/android/server/connectivity/DnsManagerTest.java @@ -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/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; |