diff options
32 files changed, 1040 insertions, 330 deletions
diff --git a/api/StubLibraries.bp b/api/StubLibraries.bp index ef1fa6097056..ec4fc46a76fb 100644 --- a/api/StubLibraries.bp +++ b/api/StubLibraries.bp @@ -239,6 +239,10 @@ java_defaults { name: "android-non-updatable_from_source_defaults", libs: ["stub-annotations"], static_libs: ["framework-res-package-jar"], // Export package of framework-res +} + +java_defaults { + name: "android-non-updatable_exportable_from_source_defaults", dist: { targets: ["sdk"], tag: ".jar", @@ -265,6 +269,14 @@ java_library { } java_library { + name: "android-non-updatable.stubs.exportable", + defaults: ["android-non-updatable_defaults"], + static_libs: [ + "android-non-updatable.stubs.exportable.from-source", + ], +} + +java_library { name: "android-non-updatable.stubs.system", defaults: ["android-non-updatable_defaults"], static_libs: [ @@ -283,6 +295,14 @@ java_library { } java_library { + name: "android-non-updatable.stubs.exportable.system", + defaults: ["android-non-updatable_defaults"], + static_libs: [ + "android-non-updatable.stubs.exportable.system.from-source", + ], +} + +java_library { name: "android-non-updatable.stubs.module_lib", defaults: ["android-non-updatable_defaults"], static_libs: [ @@ -301,6 +321,14 @@ java_library { } java_library { + name: "android-non-updatable.stubs.exportable.module_lib", + defaults: ["android-non-updatable_defaults"], + static_libs: [ + "android-non-updatable.stubs.exportable.module_lib.from-source", + ], +} + +java_library { name: "android-non-updatable.stubs.test", defaults: ["android-non-updatable_defaults"], static_libs: [ @@ -319,6 +347,14 @@ java_library { } java_library { + name: "android-non-updatable.stubs.exportable.test", + defaults: ["android-non-updatable_defaults"], + static_libs: [ + "android-non-updatable.stubs.exportable.test.from-source", + ], +} + +java_library { name: "android-non-updatable.stubs.from-source", defaults: [ "android-non-updatable_defaults", @@ -326,6 +362,17 @@ java_library { ], srcs: [":api-stubs-docs-non-updatable"], libs: ["all-modules-public-stubs"], +} + +java_library { + name: "android-non-updatable.stubs.exportable.from-source", + defaults: [ + "android-non-updatable_defaults", + "android-non-updatable_from_source_defaults", + "android-non-updatable_exportable_from_source_defaults", + ], + srcs: [":api-stubs-docs-non-updatable{.exportable}"], + libs: ["all-modules-public-stubs"], dist: { dir: "apistubs/android/public", }, @@ -339,6 +386,17 @@ java_library { ], srcs: [":system-api-stubs-docs-non-updatable"], libs: ["all-modules-system-stubs"], +} + +java_library { + name: "android-non-updatable.stubs.exportable.system.from-source", + defaults: [ + "android-non-updatable_defaults", + "android-non-updatable_from_source_defaults", + "android-non-updatable_exportable_from_source_defaults", + ], + srcs: [":system-api-stubs-docs-non-updatable{.exportable}"], + libs: ["all-modules-system-stubs"], dist: { dir: "apistubs/android/system", }, @@ -352,6 +410,17 @@ java_library { ], srcs: [":module-lib-api-stubs-docs-non-updatable"], libs: non_updatable_api_deps_on_modules, +} + +java_library { + name: "android-non-updatable.stubs.exportable.module_lib.from-source", + defaults: [ + "android-non-updatable_defaults", + "android-non-updatable_from_source_defaults", + "android-non-updatable_exportable_from_source_defaults", + ], + srcs: [":module-lib-api-stubs-docs-non-updatable{.exportable}"], + libs: non_updatable_api_deps_on_modules, dist: { dir: "apistubs/android/module-lib", }, @@ -365,6 +434,17 @@ java_library { ], srcs: [":test-api-stubs-docs-non-updatable"], libs: ["all-modules-system-stubs"], +} + +java_library { + name: "android-non-updatable.stubs.exportable.test.from-source", + defaults: [ + "android-non-updatable_defaults", + "android-non-updatable_from_source_defaults", + "android-non-updatable_exportable_from_source_defaults", + ], + srcs: [":test-api-stubs-docs-non-updatable{.exportable}"], + libs: ["all-modules-system-stubs"], dist: { dir: "apistubs/android/test", }, @@ -462,6 +542,16 @@ java_library { } java_library { + name: "android_stubs_current_exportable.from-source", + static_libs: [ + "all-modules-public-stubs-exportable", + "android-non-updatable.stubs.exportable", + "private-stub-annotations-jar", + ], + defaults: ["android.jar_defaults"], +} + +java_library { name: "android_system_stubs_current.from-source", static_libs: [ "all-modules-system-stubs", @@ -470,6 +560,19 @@ java_library { ], defaults: [ "android.jar_defaults", + ], + visibility: ["//frameworks/base/services"], +} + +java_library { + name: "android_system_stubs_current_exportable.from-source", + static_libs: [ + "all-modules-system-stubs-exportable", + "android-non-updatable.stubs.exportable.system", + "private-stub-annotations-jar", + ], + defaults: [ + "android.jar_defaults", "android_stubs_dists_default", ], dist: { @@ -498,6 +601,23 @@ java_library { ], defaults: [ "android.jar_defaults", + ], + visibility: ["//frameworks/base/services"], +} + +java_library { + name: "android_test_stubs_current_exportable.from-source", + static_libs: [ + // Updatable modules do not have test APIs, but we want to include their SystemApis, like we + // include the SystemApi of framework-non-updatable-sources. + "all-updatable-modules-system-stubs-exportable", + // Non-updatable modules on the other hand can have test APIs, so include their test-stubs. + "all-non-updatable-modules-test-stubs-exportable", + "android-non-updatable.stubs.exportable.test", + "private-stub-annotations-jar", + ], + defaults: [ + "android.jar_defaults", "android_stubs_dists_default", ], dist: { @@ -505,6 +625,7 @@ java_library { }, } +// This module does not need to be copied to dist java_library { name: "android_test_frameworks_core_stubs_current.from-source", static_libs: [ @@ -513,24 +634,34 @@ java_library { ], defaults: [ "android.jar_defaults", - "android_stubs_dists_default", ], - dist: { - dir: "apistubs/android/test-core", - }, + visibility: ["//frameworks/base/services"], } java_library { name: "android_module_lib_stubs_current.from-source", defaults: [ "android.jar_defaults", - "android_stubs_dists_default", ], static_libs: [ "android-non-updatable.stubs.module_lib", "art.module.public.api.stubs.module_lib", "i18n.module.public.api.stubs", ], + visibility: ["//frameworks/base/services"], +} + +java_library { + name: "android_module_lib_stubs_current_exportable.from-source", + defaults: [ + "android.jar_defaults", + "android_stubs_dists_default", + ], + static_libs: [ + "android-non-updatable.stubs.exportable.module_lib", + "art.module.public.api.stubs.exportable.module_lib", + "i18n.module.public.api.stubs.exportable", + ], dist: { dir: "apistubs/android/module-lib", }, @@ -540,13 +671,26 @@ java_library { name: "android_system_server_stubs_current.from-source", defaults: [ "android.jar_defaults", - "android_stubs_dists_default", ], srcs: [":services-non-updatable-stubs"], installable: false, static_libs: [ "android_module_lib_stubs_current.from-source", ], + visibility: ["//frameworks/base/services"], +} + +java_library { + name: "android_system_server_stubs_current_exportable.from-source", + defaults: [ + "android.jar_defaults", + "android_stubs_dists_default", + ], + srcs: [":services-non-updatable-stubs{.exportable}"], + installable: false, + static_libs: [ + "android_module_lib_stubs_current_exportable.from-source", + ], dist: { dir: "apistubs/android/system-server", }, diff --git a/api/api.go b/api/api.go index 43713aad0e1e..a632582ce76d 100644 --- a/api/api.go +++ b/api/api.go @@ -205,6 +205,15 @@ func createMergedPublicStubs(ctx android.LoadHookContext, modules []string) { ctx.CreateModule(java.LibraryFactory, &props) } +func createMergedPublicExportableStubs(ctx android.LoadHookContext, modules []string) { + props := libraryProps{} + props.Name = proptools.StringPtr("all-modules-public-stubs-exportable") + props.Static_libs = transformArray(modules, "", ".stubs.exportable") + props.Sdk_version = proptools.StringPtr("module_current") + props.Visibility = []string{"//frameworks/base"} + ctx.CreateModule(java.LibraryFactory, &props) +} + func createMergedSystemStubs(ctx android.LoadHookContext, modules []string) { // First create the all-updatable-modules-system-stubs { @@ -229,6 +238,30 @@ func createMergedSystemStubs(ctx android.LoadHookContext, modules []string) { } } +func createMergedSystemExportableStubs(ctx android.LoadHookContext, modules []string) { + // First create the all-updatable-modules-system-stubs + { + updatable_modules := removeAll(modules, non_updatable_modules) + props := libraryProps{} + props.Name = proptools.StringPtr("all-updatable-modules-system-stubs-exportable") + props.Static_libs = transformArray(updatable_modules, "", ".stubs.exportable.system") + props.Sdk_version = proptools.StringPtr("module_current") + props.Visibility = []string{"//frameworks/base"} + ctx.CreateModule(java.LibraryFactory, &props) + } + // Now merge all-updatable-modules-system-stubs and stubs from non-updatable modules + // into all-modules-system-stubs. + { + props := libraryProps{} + props.Name = proptools.StringPtr("all-modules-system-stubs-exportable") + props.Static_libs = transformArray(non_updatable_modules, "", ".stubs.exportable.system") + props.Static_libs = append(props.Static_libs, "all-updatable-modules-system-stubs-exportable") + props.Sdk_version = proptools.StringPtr("module_current") + props.Visibility = []string{"//frameworks/base"} + ctx.CreateModule(java.LibraryFactory, &props) + } +} + func createMergedTestStubsForNonUpdatableModules(ctx android.LoadHookContext) { props := libraryProps{} props.Name = proptools.StringPtr("all-non-updatable-modules-test-stubs") @@ -238,6 +271,15 @@ func createMergedTestStubsForNonUpdatableModules(ctx android.LoadHookContext) { ctx.CreateModule(java.LibraryFactory, &props) } +func createMergedTestExportableStubsForNonUpdatableModules(ctx android.LoadHookContext) { + props := libraryProps{} + props.Name = proptools.StringPtr("all-non-updatable-modules-test-stubs-exportable") + props.Static_libs = transformArray(non_updatable_modules, "", ".stubs.exportable.test") + props.Sdk_version = proptools.StringPtr("module_current") + props.Visibility = []string{"//frameworks/base"} + ctx.CreateModule(java.LibraryFactory, &props) +} + func createMergedFrameworkImpl(ctx android.LoadHookContext, modules []string) { // This module is for the "framework-all" module, which should not include the core libraries. modules = removeAll(modules, core_libraries_modules) @@ -268,6 +310,19 @@ func createMergedFrameworkImpl(ctx android.LoadHookContext, modules []string) { } } +func createMergedFrameworkModuleLibExportableStubs(ctx android.LoadHookContext, modules []string) { + // The user of this module compiles against the "core" SDK and against non-updatable modules, + // so remove to avoid dupes. + modules = removeAll(modules, core_libraries_modules) + modules = removeAll(modules, non_updatable_modules) + props := libraryProps{} + props.Name = proptools.StringPtr("framework-updatable-stubs-module_libs_api-exportable") + props.Static_libs = transformArray(modules, "", ".stubs.exportable.module_lib") + props.Sdk_version = proptools.StringPtr("module_current") + props.Visibility = []string{"//frameworks/base"} + ctx.CreateModule(java.LibraryFactory, &props) +} + func createMergedFrameworkModuleLibStubs(ctx android.LoadHookContext, modules []string) { // The user of this module compiles against the "core" SDK and against non-updatable modules, // so remove to avoid dupes. @@ -383,6 +438,27 @@ func createFullApiLibraries(ctx android.LoadHookContext) { } } +func createFullExportableApiLibraries(ctx android.LoadHookContext) { + javaLibraryNames := []string{ + "android_stubs_current_exportable", + "android_system_stubs_current_exportable", + "android_test_stubs_current_exportable", + "android_module_lib_stubs_current_exportable", + "android_system_server_stubs_current_exportable", + } + + for _, libraryName := range javaLibraryNames { + props := libraryProps{} + props.Name = proptools.StringPtr(libraryName) + staticLib := libraryName + ".from-source" + props.Static_libs = []string{staticLib} + props.Defaults = []string{"android.jar_defaults"} + props.Visibility = []string{"//visibility:public"} + + ctx.CreateModule(java.LibraryFactory, &props) + } +} + func (a *CombinedApis) createInternalModules(ctx android.LoadHookContext) { bootclasspath := a.properties.Bootclasspath system_server_classpath := a.properties.System_server_classpath @@ -398,6 +474,11 @@ func (a *CombinedApis) createInternalModules(ctx android.LoadHookContext) { createMergedFrameworkModuleLibStubs(ctx, bootclasspath) createMergedFrameworkImpl(ctx, bootclasspath) + createMergedPublicExportableStubs(ctx, bootclasspath) + createMergedSystemExportableStubs(ctx, bootclasspath) + createMergedTestExportableStubsForNonUpdatableModules(ctx) + createMergedFrameworkModuleLibExportableStubs(ctx, bootclasspath) + createMergedAnnotationsFilegroups(ctx, bootclasspath, system_server_classpath) createPublicStubsSourceFilegroup(ctx, bootclasspath) @@ -405,6 +486,8 @@ func (a *CombinedApis) createInternalModules(ctx android.LoadHookContext) { createApiContributionDefaults(ctx, bootclasspath) createFullApiLibraries(ctx) + + createFullExportableApiLibraries(ctx) } func combinedApisModuleFactory() android.Module { diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 66d04a3132eb..f9e7aeb9ec6b 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -3541,7 +3541,7 @@ public class ActivityManager { * foreground. This may be running a window that is behind the current * foreground (so paused and with its state saved, not interacting with * the user, but visible to them to some degree); it may also be running - * other services under the system's control that it inconsiders important. + * other services under the system's control that it considers important. */ public static final int IMPORTANCE_VISIBLE = 200; @@ -3613,9 +3613,9 @@ public class ActivityManager { public static final int IMPORTANCE_CANT_SAVE_STATE = 350; /** - * Constant for {@link #importance}: This process process contains - * cached code that is expendable, not actively running any app components - * we care about. + * Constant for {@link #importance}: This process contains cached code + * that is expendable, not actively running any app components we care + * about. */ public static final int IMPORTANCE_CACHED = 400; diff --git a/core/java/android/net/vcn/VcnManager.java b/core/java/android/net/vcn/VcnManager.java index 561db9c8a8ce..83b7edaec72d 100644 --- a/core/java/android/net/vcn/VcnManager.java +++ b/core/java/android/net/vcn/VcnManager.java @@ -80,8 +80,6 @@ public class VcnManager { * <p>The VCN will only migrate to a Carrier WiFi network that has a signal strength greater * than, or equal to this threshold. * - * <p>WARNING: The VCN does not listen for changes to this key made after VCN startup. - * * @hide */ @NonNull @@ -94,8 +92,6 @@ public class VcnManager { * <p>If the VCN's selected Carrier WiFi network has a signal strength less than this threshold, * the VCN will attempt to migrate away from the Carrier WiFi network. * - * <p>WARNING: The VCN does not listen for changes to this key made after VCN startup. - * * @hide */ @NonNull @@ -120,6 +116,15 @@ public class VcnManager { public static final String VCN_NETWORK_SELECTION_IPSEC_PACKET_LOSS_PERCENT_THRESHOLD_KEY = "vcn_network_selection_ipsec_packet_loss_percent_threshold"; + /** + * Key for the list of timeouts in minute to stop penalizing an underlying network candidate + * + * @hide + */ + @NonNull + public static final String VCN_NETWORK_SELECTION_PENALTY_TIMEOUT_MINUTES_LIST_KEY = + "vcn_network_selection_penalty_timeout_minutes_list"; + // TODO: Add separate signal strength thresholds for 2.4 GHz and 5GHz /** @@ -168,6 +173,7 @@ public class VcnManager { VCN_NETWORK_SELECTION_WIFI_EXIT_RSSI_THRESHOLD_KEY, VCN_NETWORK_SELECTION_POLL_IPSEC_STATE_INTERVAL_SECONDS_KEY, VCN_NETWORK_SELECTION_IPSEC_PACKET_LOSS_PERCENT_THRESHOLD_KEY, + VCN_NETWORK_SELECTION_PENALTY_TIMEOUT_MINUTES_LIST_KEY, VCN_RESTRICTED_TRANSPORTS_INT_ARRAY_KEY, VCN_SAFE_MODE_TIMEOUT_SECONDS_KEY, VCN_TUNNEL_AGGREGATION_SA_COUNT_MAX_KEY, diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 2cc850d5c11e..7bad9c561f8a 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -12961,6 +12961,16 @@ public final class Settings { @Readable public static final String OTA_DISABLE_AUTOMATIC_UPDATE = "ota_disable_automatic_update"; + + /** + * Whether to boot with 16K page size compatible kernel + * 1 = Boot with 16K kernel + * 0 = Boot with 4K kernel (default) + * @hide + */ + @Readable + public static final String ENABLE_16K_PAGES = "enable_16k_pages"; + /** Timeout for package verification. * @hide */ @Readable diff --git a/core/java/android/window/SplashScreenView.java b/core/java/android/window/SplashScreenView.java index bdaad2b68fc2..473b814fc4a7 100644 --- a/core/java/android/window/SplashScreenView.java +++ b/core/java/android/window/SplashScreenView.java @@ -47,6 +47,7 @@ import android.view.SurfaceView; import android.view.View; import android.view.ViewGroup; import android.view.Window; +import android.view.WindowManager; import android.widget.FrameLayout; import android.widget.ImageView; @@ -337,7 +338,14 @@ public final class SplashScreenView extends FrameLayout { "SplashScreenView"); ImageView imageView = new ImageView(viewContext); imageView.setBackground(mIconDrawable); - viewHost.setView(imageView, mIconSize, mIconSize); + final int windowFlag = WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE + | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE + | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; + final WindowManager.LayoutParams lp = + new WindowManager.LayoutParams(mIconSize, mIconSize, + WindowManager.LayoutParams.TYPE_APPLICATION, windowFlag, + PixelFormat.TRANSPARENT); + viewHost.setView(imageView, lp); SurfaceControlViewHost.SurfacePackage surfacePackage = viewHost.getSurfacePackage(); surfaceView.setChildSurfacePackage(surfacePackage); view.mSurfacePackage = surfacePackage; diff --git a/data/etc/com.android.settings.xml b/data/etc/com.android.settings.xml index dcc96861bc31..fbe1b8e65171 100644 --- a/data/etc/com.android.settings.xml +++ b/data/etc/com.android.settings.xml @@ -48,6 +48,7 @@ <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/> <permission name="android.permission.READ_SEARCH_INDEXABLES"/> <permission name="android.permission.REBOOT"/> + <permission name="android.permission.RECOVERY"/> <permission name="android.permission.STATUS_BAR"/> <permission name="android.permission.SUGGEST_MANUAL_TIME_AND_ZONE"/> <permission name="android.permission.TETHER_PRIVILEGED"/> diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractWifiMacAddressPreferenceController.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractWifiMacAddressPreferenceController.java index 1d433e767e5b..943e3fc27ebb 100644 --- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractWifiMacAddressPreferenceController.java +++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractWifiMacAddressPreferenceController.java @@ -59,7 +59,7 @@ public abstract class AbstractWifiMacAddressPreferenceController @Override public boolean isAvailable() { - return true; + return mWifiManager != null; } @Override @@ -70,10 +70,8 @@ public abstract class AbstractWifiMacAddressPreferenceController @Override public void displayPreference(PreferenceScreen screen) { super.displayPreference(screen); - if (isAvailable()) { - mWifiMacAddress = screen.findPreference(KEY_WIFI_MAC_ADDRESS); - updateConnectivity(); - } + mWifiMacAddress = screen.findPreference(KEY_WIFI_MAC_ADDRESS); + updateConnectivity(); } @Override @@ -84,16 +82,16 @@ public abstract class AbstractWifiMacAddressPreferenceController @SuppressLint("HardwareIds") @Override protected void updateConnectivity() { + if (mWifiManager == null || mWifiMacAddress == null) { + return; + } + final String[] macAddresses = mWifiManager.getFactoryMacAddresses(); String macAddress = null; if (macAddresses != null && macAddresses.length > 0) { macAddress = macAddresses[0]; } - if (mWifiMacAddress == null) { - return; - } - if (TextUtils.isEmpty(macAddress) || macAddress.equals(WifiInfo.DEFAULT_MAC_ADDRESS)) { mWifiMacAddress.setSummary(R.string.status_unavailable); } else { diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java index 91c72b543cc4..bc93c5b70374 100644 --- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java +++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java @@ -280,6 +280,7 @@ public class SettingsBackupTest { Settings.Global.ENABLE_ADB_INCREMENTAL_INSTALL_DEFAULT, Settings.Global.ENABLE_MULTI_SLOT_TIMEOUT_MILLIS, Settings.Global.ENHANCED_4G_MODE_ENABLED, + Settings.Global.ENABLE_16K_PAGES, // Added for 16K developer option Settings.Global.EPHEMERAL_COOKIE_MAX_SIZE_BYTES, Settings.Global.ERROR_LOGCAT_PREFIX, Settings.Global.EUICC_PROVISIONED, diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java index 9c82a8d8e45a..b8d2284275ea 100644 --- a/services/core/java/com/android/server/am/ProcessList.java +++ b/services/core/java/com/android/server/am/ProcessList.java @@ -2861,7 +2861,11 @@ public final class ProcessList { return true; } - private static void freezeBinderAndPackageCgroup(ArrayList<Pair<ProcessRecord, Boolean>> procs, + private static boolean unfreezePackageCgroup(int packageUID) { + return freezePackageCgroup(packageUID, false); + } + + private static void freezeBinderAndPackageCgroup(List<Pair<ProcessRecord, Boolean>> procs, int packageUID) { // Freeze all binder processes under the target UID (whose cgroup is about to be frozen). // Since we're going to kill these, we don't need to unfreze them later. @@ -2869,12 +2873,9 @@ public final class ProcessList { // processes (forks) should not be Binder users. int N = procs.size(); for (int i = 0; i < N; i++) { - final int uid = procs.get(i).first.uid; final int pid = procs.get(i).first.getPid(); int nRetries = 0; - // We only freeze the cgroup of the target package, so we do not need to freeze the - // Binder interfaces of dependant processes in other UIDs. - if (pid > 0 && uid == packageUID) { + if (pid > 0) { try { int rc; do { @@ -2888,12 +2889,19 @@ public final class ProcessList { } // We freeze the entire UID (parent) cgroup so that newly-specialized processes also freeze - // despite being added to a new child cgroup. The cgroups of package dependant processes are - // not frozen, since it's possible this would freeze processes with no dependency on the - // package being killed here. + // despite being added to a child cgroup created after this call that would otherwise be + // unfrozen. freezePackageCgroup(packageUID, true); } + private static List<Pair<ProcessRecord, Boolean>> getUIDSublist( + List<Pair<ProcessRecord, Boolean>> procs, int startIdx) { + final int uid = procs.get(startIdx).first.uid; + int endIdx = startIdx + 1; + while (endIdx < procs.size() && procs.get(endIdx).first.uid == uid) ++endIdx; + return procs.subList(startIdx, endIdx); + } + @GuardedBy({"mService", "mProcLock"}) boolean killPackageProcessesLSP(String packageName, int appId, int userId, int minOomAdj, boolean callerWillRestart, boolean allowRestart, @@ -2989,25 +2997,36 @@ public final class ProcessList { } } - final int packageUID = UserHandle.getUid(userId, appId); - final boolean doFreeze = appId >= Process.FIRST_APPLICATION_UID - && appId <= Process.LAST_APPLICATION_UID; - if (doFreeze) { - freezeBinderAndPackageCgroup(procs, packageUID); + final boolean killingUserApp = appId >= Process.FIRST_APPLICATION_UID + && appId <= Process.LAST_APPLICATION_UID; + + if (killingUserApp) { + procs.sort((o1, o2) -> Integer.compare(o1.first.uid, o2.first.uid)); } - int N = procs.size(); - for (int i=0; i<N; i++) { - final Pair<ProcessRecord, Boolean> proc = procs.get(i); - removeProcessLocked(proc.first, callerWillRestart, allowRestart || proc.second, - reasonCode, subReason, reason, !doFreeze /* async */); + int idx = 0; + while (idx < procs.size()) { + final List<Pair<ProcessRecord, Boolean>> uidProcs = getUIDSublist(procs, idx); + final int packageUID = uidProcs.get(0).first.uid; + + // Do not freeze for system apps or for dependencies of the targeted package, but + // make sure to freeze the targeted package for all users if called with USER_ALL. + final boolean doFreeze = killingUserApp && UserHandle.getAppId(packageUID) == appId; + + if (doFreeze) freezeBinderAndPackageCgroup(uidProcs, packageUID); + + for (Pair<ProcessRecord, Boolean> proc : uidProcs) { + removeProcessLocked(proc.first, callerWillRestart, allowRestart || proc.second, + reasonCode, subReason, reason, !doFreeze /* async */); + } + killAppZygotesLocked(packageName, appId, userId, false /* force */); + + if (doFreeze) unfreezePackageCgroup(packageUID); + + idx += uidProcs.size(); } - killAppZygotesLocked(packageName, appId, userId, false /* force */); mService.updateOomAdjLocked(OOM_ADJ_REASON_PROCESS_END); - if (doFreeze) { - freezePackageCgroup(packageUID, false); - } - return N > 0; + return procs.size() > 0; } @GuardedBy("mService") diff --git a/services/core/java/com/android/server/pm/UserDataPreparer.java b/services/core/java/com/android/server/pm/UserDataPreparer.java index 4c42c2dd0850..1d414011cff3 100644 --- a/services/core/java/com/android/server/pm/UserDataPreparer.java +++ b/services/core/java/com/android/server/pm/UserDataPreparer.java @@ -141,7 +141,7 @@ class UserDataPreparer { // If internal storage of the system user fails to prepare on first boot, then // things are *really* broken, so we might as well reboot to recovery right away. try { - Log.wtf(TAG, "prepareUserData failed for user " + userId, e); + Log.e(TAG, "prepareUserData failed for user " + userId, e); if (isNewUser && userId == UserHandle.USER_SYSTEM && volumeUuid == null) { RecoverySystem.rebootPromptAndWipeUserData(mContext, "failed to prepare internal storage for system user"); diff --git a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java index fcc0de1c2258..3094b182093b 100644 --- a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java +++ b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java @@ -1910,6 +1910,12 @@ public class VcnGatewayConnection extends StateMachine { // Transforms do not need to be persisted; the IkeSession will keep them alive mIpSecManager.applyTunnelModeTransform(tunnelIface, direction, transform); + if (direction == IpSecManager.DIRECTION_IN + && mVcnContext.isFlagNetworkMetricMonitorEnabled() + && mVcnContext.isFlagIpSecTransformStateEnabled()) { + mUnderlyingNetworkController.updateInboundTransform(mUnderlying, transform); + } + // For inbound transforms, additionally allow forwarded traffic to bridge to DUN (as // needed) final Set<Integer> exposedCaps = mConnectionConfig.getAllExposedCapabilities(); diff --git a/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkController.java b/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkController.java index 48df44b7c4ac..3f8d39e72e89 100644 --- a/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkController.java +++ b/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkController.java @@ -30,6 +30,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.net.ConnectivityManager; import android.net.ConnectivityManager.NetworkCallback; +import android.net.IpSecTransform; import android.net.LinkProperties; import android.net.Network; import android.net.NetworkCapabilities; @@ -52,6 +53,7 @@ import com.android.internal.annotations.VisibleForTesting.Visibility; import com.android.internal.util.IndentingPrintWriter; import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot; import com.android.server.vcn.VcnContext; +import com.android.server.vcn.routeselection.UnderlyingNetworkEvaluator.NetworkEvaluatorCallback; import com.android.server.vcn.util.LogUtils; import java.util.ArrayList; @@ -201,6 +203,14 @@ public class UnderlyingNetworkController { NetworkCallback oldWifiExitRssiThresholdCallback = mWifiExitRssiThresholdCallback; List<NetworkCallback> oldCellCallbacks = new ArrayList<>(mCellBringupCallbacks); mCellBringupCallbacks.clear(); + + if (mVcnContext.isFlagNetworkMetricMonitorEnabled() + && mVcnContext.isFlagIpSecTransformStateEnabled()) { + for (UnderlyingNetworkEvaluator evaluator : mUnderlyingNetworkRecords.values()) { + evaluator.close(); + } + } + mUnderlyingNetworkRecords.clear(); // Register new callbacks. Make-before-break; always register new callbacks before removal @@ -417,11 +427,42 @@ public class UnderlyingNetworkController { if (oldSnapshot .getAllSubIdsInGroup(mSubscriptionGroup) .equals(newSnapshot.getAllSubIdsInGroup(mSubscriptionGroup))) { + + if (mVcnContext.isFlagNetworkMetricMonitorEnabled() + && mVcnContext.isFlagIpSecTransformStateEnabled()) { + reevaluateNetworks(); + } return; } registerOrUpdateNetworkRequests(); } + /** + * Pass the IpSecTransform of the VCN to UnderlyingNetworkController for metric monitoring + * + * <p>Caller MUST call it when IpSecTransforms have been created for VCN creation or migration + */ + public void updateInboundTransform( + @NonNull UnderlyingNetworkRecord currentNetwork, @NonNull IpSecTransform transform) { + if (!mVcnContext.isFlagNetworkMetricMonitorEnabled() + || !mVcnContext.isFlagIpSecTransformStateEnabled()) { + logWtf("#updateInboundTransform: unexpected call; flags missing"); + return; + } + + Objects.requireNonNull(currentNetwork, "currentNetwork is null"); + Objects.requireNonNull(transform, "transform is null"); + + if (mCurrentRecord == null + || mRouteSelectionCallback == null + || !Objects.equals(currentNetwork.network, mCurrentRecord.network)) { + // The caller (VcnGatewayConnection) is out-of-dated. Ignore this call. + return; + } + + mUnderlyingNetworkRecords.get(mCurrentRecord.network).setInboundTransform(transform); + } + /** Tears down this Tracker, and releases all underlying network requests. */ public void teardown() { mVcnContext.ensureRunningOnLooperThread(); @@ -438,7 +479,7 @@ public class UnderlyingNetworkController { private TreeSet<UnderlyingNetworkEvaluator> getSortedUnderlyingNetworks() { TreeSet<UnderlyingNetworkEvaluator> sorted = - new TreeSet<>(UnderlyingNetworkEvaluator.getComparator()); + new TreeSet<>(UnderlyingNetworkEvaluator.getComparator(mVcnContext)); for (UnderlyingNetworkEvaluator evaluator : mUnderlyingNetworkRecords.values()) { if (evaluator.getPriorityClass() != NetworkPriorityClassifier.PRIORITY_INVALID) { @@ -525,11 +566,17 @@ public class UnderlyingNetworkController { mConnectionConfig.getVcnUnderlyingNetworkPriorities(), mSubscriptionGroup, mLastSnapshot, - mCarrierConfig)); + mCarrierConfig, + new NetworkEvaluatorCallbackImpl())); } @Override public void onLost(@NonNull Network network) { + if (mVcnContext.isFlagNetworkMetricMonitorEnabled() + && mVcnContext.isFlagIpSecTransformStateEnabled()) { + mUnderlyingNetworkRecords.get(network).close(); + } + mUnderlyingNetworkRecords.remove(network); reevaluateNetworks(); @@ -598,6 +645,21 @@ public class UnderlyingNetworkController { } } + @VisibleForTesting + class NetworkEvaluatorCallbackImpl implements NetworkEvaluatorCallback { + @Override + public void onEvaluationResultChanged() { + if (!mVcnContext.isFlagNetworkMetricMonitorEnabled() + || !mVcnContext.isFlagIpSecTransformStateEnabled()) { + logWtf("#onEvaluationResultChanged: unexpected call; flags missing"); + return; + } + + mVcnContext.ensureRunningOnLooperThread(); + reevaluateNetworks(); + } + } + private String getLogPrefix() { return "(" + LogUtils.getHashedSubscriptionGroup(mSubscriptionGroup) @@ -690,21 +752,22 @@ public class UnderlyingNetworkController { @VisibleForTesting(visibility = Visibility.PRIVATE) public static class Dependencies { - /** Construct a new UnderlyingNetworkEvaluator */ public UnderlyingNetworkEvaluator newUnderlyingNetworkEvaluator( @NonNull VcnContext vcnContext, @NonNull Network network, @NonNull List<VcnUnderlyingNetworkTemplate> underlyingNetworkTemplates, @NonNull ParcelUuid subscriptionGroup, @NonNull TelephonySubscriptionSnapshot lastSnapshot, - @Nullable PersistableBundleWrapper carrierConfig) { + @Nullable PersistableBundleWrapper carrierConfig, + @NonNull NetworkEvaluatorCallback evaluatorCallback) { return new UnderlyingNetworkEvaluator( vcnContext, network, underlyingNetworkTemplates, subscriptionGroup, lastSnapshot, - carrierConfig); + carrierConfig, + evaluatorCallback); } } } diff --git a/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkEvaluator.java b/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkEvaluator.java index c124a1976ac6..2f4cf5e5d8c7 100644 --- a/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkEvaluator.java +++ b/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkEvaluator.java @@ -16,23 +16,32 @@ package com.android.server.vcn.routeselection; +import static com.android.server.VcnManagementService.LOCAL_LOG; import static com.android.server.vcn.util.PersistableBundleUtils.PersistableBundleWrapper; import android.annotation.NonNull; import android.annotation.Nullable; +import android.net.IpSecTransform; import android.net.LinkProperties; import android.net.Network; import android.net.NetworkCapabilities; +import android.net.vcn.VcnManager; import android.net.vcn.VcnUnderlyingNetworkTemplate; +import android.os.Handler; import android.os.ParcelUuid; +import android.util.Slog; +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.annotations.VisibleForTesting.Visibility; import com.android.internal.util.IndentingPrintWriter; import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot; import com.android.server.vcn.VcnContext; +import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.Objects; +import java.util.concurrent.TimeUnit; /** * UnderlyingNetworkEvaluator evaluates the quality and priority class of a network candidate for @@ -43,20 +52,41 @@ import java.util.Objects; public class UnderlyingNetworkEvaluator { private static final String TAG = UnderlyingNetworkEvaluator.class.getSimpleName(); + private static final int[] PENALTY_TIMEOUT_MINUTES_DEFAULT = new int[] {5}; + @NonNull private final VcnContext mVcnContext; + @NonNull private final Handler mHandler; + @NonNull private final Object mCancellationToken = new Object(); + @NonNull private final UnderlyingNetworkRecord.Builder mNetworkRecordBuilder; + @NonNull private final NetworkEvaluatorCallback mEvaluatorCallback; + @NonNull private final List<NetworkMetricMonitor> mMetricMonitors = new ArrayList<>(); + + @NonNull private final Dependencies mDependencies; + + // TODO: Support back-off timeouts + private long mPenalizedTimeoutMs; + private boolean mIsSelected; + private boolean mIsPenalized; private int mPriorityClass = NetworkPriorityClassifier.PRIORITY_INVALID; + @VisibleForTesting(visibility = Visibility.PRIVATE) public UnderlyingNetworkEvaluator( @NonNull VcnContext vcnContext, @NonNull Network network, @NonNull List<VcnUnderlyingNetworkTemplate> underlyingNetworkTemplates, @NonNull ParcelUuid subscriptionGroup, @NonNull TelephonySubscriptionSnapshot lastSnapshot, - @Nullable PersistableBundleWrapper carrierConfig) { + @Nullable PersistableBundleWrapper carrierConfig, + @NonNull NetworkEvaluatorCallback evaluatorCallback, + @NonNull Dependencies dependencies) { mVcnContext = Objects.requireNonNull(vcnContext, "Missing vcnContext"); + mHandler = new Handler(mVcnContext.getLooper()); + + mDependencies = Objects.requireNonNull(dependencies, "Missing dependencies"); + mEvaluatorCallback = Objects.requireNonNull(evaluatorCallback, "Missing deps"); Objects.requireNonNull(underlyingNetworkTemplates, "Missing underlyingNetworkTemplates"); Objects.requireNonNull(subscriptionGroup, "Missing subscriptionGroup"); @@ -66,9 +96,76 @@ public class UnderlyingNetworkEvaluator { new UnderlyingNetworkRecord.Builder( Objects.requireNonNull(network, "Missing network")); mIsSelected = false; + mIsPenalized = false; + mPenalizedTimeoutMs = getPenaltyTimeoutMs(carrierConfig); updatePriorityClass( underlyingNetworkTemplates, subscriptionGroup, lastSnapshot, carrierConfig); + + if (isIpSecPacketLossDetectorEnabled()) { + try { + mMetricMonitors.add( + mDependencies.newIpSecPacketLossDetector( + mVcnContext, + mNetworkRecordBuilder.getNetwork(), + carrierConfig, + new MetricMonitorCallbackImpl())); + } catch (IllegalAccessException e) { + // No action. Do not add anything to mMetricMonitors + } + } + } + + public UnderlyingNetworkEvaluator( + @NonNull VcnContext vcnContext, + @NonNull Network network, + @NonNull List<VcnUnderlyingNetworkTemplate> underlyingNetworkTemplates, + @NonNull ParcelUuid subscriptionGroup, + @NonNull TelephonySubscriptionSnapshot lastSnapshot, + @Nullable PersistableBundleWrapper carrierConfig, + @NonNull NetworkEvaluatorCallback evaluatorCallback) { + this( + vcnContext, + network, + underlyingNetworkTemplates, + subscriptionGroup, + lastSnapshot, + carrierConfig, + evaluatorCallback, + new Dependencies()); + } + + @VisibleForTesting(visibility = Visibility.PRIVATE) + public static class Dependencies { + /** Get an IpSecPacketLossDetector instance */ + public IpSecPacketLossDetector newIpSecPacketLossDetector( + @NonNull VcnContext vcnContext, + @NonNull Network network, + @Nullable PersistableBundleWrapper carrierConfig, + @NonNull NetworkMetricMonitor.NetworkMetricMonitorCallback callback) + throws IllegalAccessException { + return new IpSecPacketLossDetector(vcnContext, network, carrierConfig, callback); + } + } + + /** Callback to notify caller to reevaluate network selection */ + public interface NetworkEvaluatorCallback { + /** + * Called when mIsPenalized changed + * + * <p>When receiving this call, UnderlyingNetworkController should reevaluate all network + * candidates for VCN underlying network selection + */ + void onEvaluationResultChanged(); + } + + private class MetricMonitorCallbackImpl + implements NetworkMetricMonitor.NetworkMetricMonitorCallback { + public void onValidationResultReceived() { + mVcnContext.ensureRunningOnLooperThread(); + + handleValidationResult(); + } } private void updatePriorityClass( @@ -91,8 +188,25 @@ public class UnderlyingNetworkEvaluator { } } - public static Comparator<UnderlyingNetworkEvaluator> getComparator() { + private boolean isIpSecPacketLossDetectorEnabled() { + return isIpSecPacketLossDetectorEnabled(mVcnContext); + } + + private static boolean isIpSecPacketLossDetectorEnabled(VcnContext vcnContext) { + return vcnContext.isFlagIpSecTransformStateEnabled() + && vcnContext.isFlagNetworkMetricMonitorEnabled(); + } + + /** Get the comparator for UnderlyingNetworkEvaluator */ + public static Comparator<UnderlyingNetworkEvaluator> getComparator(VcnContext vcnContext) { return (left, right) -> { + if (isIpSecPacketLossDetectorEnabled(vcnContext)) { + if (left.mIsPenalized != right.mIsPenalized) { + // A penalized network should have lower priority which means a larger index + return left.mIsPenalized ? 1 : -1; + } + } + final int leftIndex = left.mPriorityClass; final int rightIndex = right.mPriorityClass; @@ -112,6 +226,64 @@ public class UnderlyingNetworkEvaluator { }; } + private static long getPenaltyTimeoutMs(@Nullable PersistableBundleWrapper carrierConfig) { + final int[] timeoutMinuteList; + + if (carrierConfig != null) { + timeoutMinuteList = + carrierConfig.getIntArray( + VcnManager.VCN_NETWORK_SELECTION_PENALTY_TIMEOUT_MINUTES_LIST_KEY, + PENALTY_TIMEOUT_MINUTES_DEFAULT); + } else { + timeoutMinuteList = PENALTY_TIMEOUT_MINUTES_DEFAULT; + } + + // TODO: Add the support of back-off timeouts and return the full list + return TimeUnit.MINUTES.toMillis(timeoutMinuteList[0]); + } + + private void handleValidationResult() { + final boolean wasPenalized = mIsPenalized; + mIsPenalized = false; + for (NetworkMetricMonitor monitor : mMetricMonitors) { + mIsPenalized |= monitor.isValidationFailed(); + } + + if (wasPenalized == mIsPenalized) { + return; + } + + logInfo( + "#handleValidationResult: wasPenalized " + + wasPenalized + + " mIsPenalized " + + mIsPenalized); + + if (mIsPenalized) { + mHandler.postDelayed( + new ExitPenaltyBoxRunnable(), mCancellationToken, mPenalizedTimeoutMs); + } else { + // Exit the penalty box + mHandler.removeCallbacksAndEqualMessages(mCancellationToken); + } + mEvaluatorCallback.onEvaluationResultChanged(); + } + + public class ExitPenaltyBoxRunnable implements Runnable { + @Override + public void run() { + if (!mIsPenalized) { + logWtf("Evaluator not being penalized but ExitPenaltyBoxRunnable was scheduled"); + return; + } + + // TODO: There might be a future metric monitor (e.g. ping) that will require the + // validation to pass before exiting the penalty box. + mIsPenalized = false; + mEvaluatorCallback.onEvaluationResultChanged(); + } + } + /** Set the NetworkCapabilities */ public void setNetworkCapabilities( @NonNull NetworkCapabilities nc, @@ -162,6 +334,10 @@ public class UnderlyingNetworkEvaluator { updatePriorityClass( underlyingNetworkTemplates, subscriptionGroup, lastSnapshot, carrierConfig); + + for (NetworkMetricMonitor monitor : mMetricMonitors) { + monitor.setIsSelectedUnderlyingNetwork(isSelected); + } } /** @@ -174,6 +350,35 @@ public class UnderlyingNetworkEvaluator { @Nullable PersistableBundleWrapper carrierConfig) { updatePriorityClass( underlyingNetworkTemplates, subscriptionGroup, lastSnapshot, carrierConfig); + + // The already scheduled event will not be affected. The followup events will be scheduled + // with the new timeout + mPenalizedTimeoutMs = getPenaltyTimeoutMs(carrierConfig); + + for (NetworkMetricMonitor monitor : mMetricMonitors) { + monitor.setCarrierConfig(carrierConfig); + } + } + + /** Update the inbound IpSecTransform applied to the network */ + public void setInboundTransform(@NonNull IpSecTransform transform) { + if (!mIsSelected) { + logWtf("setInboundTransform on an unselected evaluator"); + return; + } + + for (NetworkMetricMonitor monitor : mMetricMonitors) { + monitor.setInboundTransform(transform); + } + } + + /** Close the evaluator and stop all the underlying network metric monitors */ + public void close() { + mHandler.removeCallbacksAndEqualMessages(mCancellationToken); + + for (NetworkMetricMonitor monitor : mMetricMonitors) { + monitor.close(); + } } /** Return whether this network evaluator is valid */ @@ -196,6 +401,11 @@ public class UnderlyingNetworkEvaluator { return mPriorityClass; } + /** Return whether the network is being penalized */ + public boolean isPenalized() { + return mIsPenalized; + } + /** Dump the information of this instance */ public void dump(IndentingPrintWriter pw) { pw.println("UnderlyingNetworkEvaluator:"); @@ -211,7 +421,22 @@ public class UnderlyingNetworkEvaluator { pw.println("mIsSelected: " + mIsSelected); pw.println("mPriorityClass: " + mPriorityClass); + pw.println("mIsPenalized: " + mIsPenalized); pw.decreaseIndent(); } + + private String getLogPrefix() { + return "[Network " + mNetworkRecordBuilder.getNetwork() + "] "; + } + + private void logInfo(String msg) { + Slog.i(TAG, getLogPrefix() + msg); + LOCAL_LOG.log("[INFO ] " + TAG + getLogPrefix() + msg); + } + + private void logWtf(String msg) { + Slog.wtf(TAG, getLogPrefix() + msg); + LOCAL_LOG.log("[WTF ] " + TAG + getLogPrefix() + msg); + } } diff --git a/services/profcollect/Android.bp b/services/profcollect/Android.bp index 2040bb6e544f..fe431f5c8867 100644 --- a/services/profcollect/Android.bp +++ b/services/profcollect/Android.bp @@ -22,24 +22,25 @@ package { } filegroup { - name: "services.profcollect-javasources", - srcs: ["src/**/*.java"], - path: "src", - visibility: ["//frameworks/base/services"], + name: "services.profcollect-javasources", + srcs: ["src/**/*.java"], + path: "src", + visibility: ["//frameworks/base/services"], } filegroup { - name: "services.profcollect-sources", - srcs: [ - ":services.profcollect-javasources", - ":profcollectd_aidl", - ], - visibility: ["//frameworks/base/services:__subpackages__"], + name: "services.profcollect-sources", + srcs: [ + ":services.profcollect-javasources", + ":profcollectd_aidl", + ], + visibility: ["//frameworks/base/services:__subpackages__"], } java_library_static { - name: "services.profcollect", - defaults: ["platform_service_defaults"], - srcs: [":services.profcollect-sources"], - libs: ["services.core"], + name: "services.profcollect", + defaults: ["platform_service_defaults"], + srcs: [":services.profcollect-sources"], + static_libs: ["services.core"], + libs: ["service-art.stubs.system_server"], } diff --git a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java index 4007672a0599..582b712ec3fc 100644 --- a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java +++ b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java @@ -41,12 +41,15 @@ import android.util.Log; import com.android.internal.R; import com.android.internal.os.BackgroundThread; import com.android.server.IoThread; +import com.android.server.LocalManagerRegistry; import com.android.server.LocalServices; import com.android.server.SystemService; +import com.android.server.art.ArtManagerLocal; import com.android.server.wm.ActivityMetricsLaunchObserver; import com.android.server.wm.ActivityMetricsLaunchObserverRegistry; import com.android.server.wm.ActivityTaskManagerInternal; +import java.util.concurrent.ForkJoinPool; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; @@ -261,6 +264,7 @@ public final class ProfcollectForwardingService extends SystemService { BackgroundThread.get().getThreadHandler().post( () -> { registerAppLaunchObserver(); + registerDex2oatObserver(); registerOTAObserver(); }); } @@ -304,6 +308,44 @@ public final class ProfcollectForwardingService extends SystemService { } } + private void registerDex2oatObserver() { + ArtManagerLocal aml = LocalManagerRegistry.getManager(ArtManagerLocal.class); + if (aml == null) { + Log.w(LOG_TAG, "Couldn't get ArtManagerLocal"); + return; + } + aml.setBatchDexoptStartCallback(ForkJoinPool.commonPool(), + (snapshot, reason, defaultPackages, builder, passedSignal) -> { + traceOnDex2oatStart(); + }); + } + + private void traceOnDex2oatStart() { + if (mIProfcollect == null) { + return; + } + // Sample for a fraction of dex2oat runs. + final int traceFrequency = + DeviceConfig.getInt(DeviceConfig.NAMESPACE_PROFCOLLECT_NATIVE_BOOT, + "dex2oat_trace_freq", 10); + int randomNum = ThreadLocalRandom.current().nextInt(100); + if (randomNum < traceFrequency) { + if (DEBUG) { + Log.d(LOG_TAG, "Tracing on dex2oat event"); + } + BackgroundThread.get().getThreadHandler().post(() -> { + try { + // Dex2oat could take a while before it starts. Add a short delay before start + // tracing. + Thread.sleep(1000); + mIProfcollect.trace_once("dex2oat"); + } catch (RemoteException | InterruptedException e) { + Log.e(LOG_TAG, "Failed to initiate trace: " + e.getMessage()); + } + }); + } + } + private void registerOTAObserver() { UpdateEngine updateEngine = new UpdateEngine(); updateEngine.bind(new UpdateEngineCallback() { diff --git a/tools/aapt2/integration-tests/MergeOnlyTest/LeafLib/Android.mk b/tests/Camera2Tests/CameraToo/tests/Android.bp index c084849a9d28..8339a2c8ab25 100644 --- a/tools/aapt2/integration-tests/MergeOnlyTest/LeafLib/Android.mk +++ b/tests/Camera2Tests/CameraToo/tests/Android.bp @@ -1,5 +1,4 @@ -// -// Copyright (C) 2019 The Android Open Source Project +// Copyright (C) 2014 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,20 +11,24 @@ // 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. -// -LOCAL_PATH := $(call my-dir) +package { + // See: http://go/android-license-faq + default_applicable_licenses: [ + "frameworks_base_license", + ], +} -include $(CLEAR_VARS) -LOCAL_USE_AAPT2 := true -LOCAL_AAPT_NAMESPACES := true -LOCAL_MODULE := AaptTestMergeOnly_LeafLib -LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 -LOCAL_LICENSE_CONDITIONS := notice -LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../../../../NOTICE -LOCAL_SDK_VERSION := current -LOCAL_MODULE_TAGS := tests -LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res -LOCAL_MIN_SDK_VERSION := 21 -LOCAL_AAPT_FLAGS := --merge-only -include $(BUILD_STATIC_JAVA_LIBRARY) +android_test { + name: "CameraTooTests", + instrumentation_for: "CameraToo", + srcs: ["src/**/*.java"], + sdk_version: "current", + static_libs: [ + "androidx.test.rules", + "mockito-target-minus-junit4", + ], + data: [ + ":CameraToo", + ], +} diff --git a/tests/Camera2Tests/CameraToo/tests/Android.mk b/tests/Camera2Tests/CameraToo/tests/Android.mk deleted file mode 100644 index dfa64f1feade..000000000000 --- a/tests/Camera2Tests/CameraToo/tests/Android.mk +++ /dev/null @@ -1,28 +0,0 @@ -# Copyright (C) 2014 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -LOCAL_PATH := $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_MODULE_TAGS := tests -LOCAL_PACKAGE_NAME := CameraTooTests -LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 -LOCAL_LICENSE_CONDITIONS := notice -LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../../../NOTICE -LOCAL_INSTRUMENTATION_FOR := CameraToo -LOCAL_SDK_VERSION := current -LOCAL_SRC_FILES := $(call all-java-files-under,src) -LOCAL_STATIC_JAVA_LIBRARIES := androidx.test.rules mockito-target-minus-junit4 - -include $(BUILD_PACKAGE) diff --git a/tests/Camera2Tests/CameraToo/tests/AndroidTest.xml b/tests/Camera2Tests/CameraToo/tests/AndroidTest.xml new file mode 100644 index 000000000000..884c095fef49 --- /dev/null +++ b/tests/Camera2Tests/CameraToo/tests/AndroidTest.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2023 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<configuration description="Runs CameraToo tests."> + <option name="test-suite-tag" value="apct" /> + <option name="test-suite-tag" value="apct-instrumentation" /> + + <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller"> + <option name="cleanup-apks" value="true" /> + <option name="test-file-name" value="CameraTooTests.apk" /> + <option name="test-file-name" value="CameraToo.apk" /> + </target_preparer> + + <test class="com.android.tradefed.testtype.AndroidJUnitTest" > + <option name="package" value="com.example.android.camera2.cameratoo.tests" /> + <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" /> + </test> +</configuration> diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java index f84616426389..20b7f1f14691 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java +++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java @@ -269,6 +269,7 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection @Test public void testCreatedTransformsAreApplied() throws Exception { verifyVcnTransformsApplied(mGatewayConnection, false /* expectForwardTransform */); + verify(mUnderlyingNetworkController).updateInboundTransform(any(), any()); } @Test @@ -327,6 +328,8 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection eq(TEST_IPSEC_TUNNEL_RESOURCE_ID), eq(direction), anyInt(), any()); } + verify(mUnderlyingNetworkController).updateInboundTransform(any(), any()); + assertEquals(mGatewayConnection.mConnectedState, mGatewayConnection.getCurrentState()); final List<ChildSaProposal> saProposals = diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java index 4c7b25aaa7c3..e29e4621d571 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java +++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java @@ -223,6 +223,8 @@ public class VcnGatewayConnectionTestBase { doReturn(mVcnNetworkProvider).when(mVcnContext).getVcnNetworkProvider(); doReturn(mFeatureFlags).when(mVcnContext).getFeatureFlags(); doReturn(true).when(mVcnContext).isFlagSafeModeTimeoutConfigEnabled(); + doReturn(true).when(mVcnContext).isFlagIpSecTransformStateEnabled(); + doReturn(true).when(mVcnContext).isFlagNetworkMetricMonitorEnabled(); doReturn(mUnderlyingNetworkController) .when(mDeps) diff --git a/tests/vcn/java/com/android/server/vcn/routeselection/NetworkEvaluationTestBase.java b/tests/vcn/java/com/android/server/vcn/routeselection/NetworkEvaluationTestBase.java index 355c22156a78..6015e9318464 100644 --- a/tests/vcn/java/com/android/server/vcn/routeselection/NetworkEvaluationTestBase.java +++ b/tests/vcn/java/com/android/server/vcn/routeselection/NetworkEvaluationTestBase.java @@ -26,6 +26,8 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; import android.content.Context; +import android.net.IpSecConfig; +import android.net.IpSecTransform; import android.net.LinkProperties; import android.net.Network; import android.net.NetworkCapabilities; @@ -141,4 +143,8 @@ public abstract class NetworkEvaluationTestBase { mock(Handler.class)); setupSystemService(mContext, mPowerManager, Context.POWER_SERVICE, PowerManager.class); } + + protected IpSecTransform makeDummyIpSecTransform() throws Exception { + return new IpSecTransform(mContext, new IpSecConfig()); + } } diff --git a/tests/vcn/java/com/android/server/vcn/routeselection/UnderlyingNetworkControllerTest.java b/tests/vcn/java/com/android/server/vcn/routeselection/UnderlyingNetworkControllerTest.java index 992f10275739..588624b56221 100644 --- a/tests/vcn/java/com/android/server/vcn/routeselection/UnderlyingNetworkControllerTest.java +++ b/tests/vcn/java/com/android/server/vcn/routeselection/UnderlyingNetworkControllerTest.java @@ -47,6 +47,8 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.net.ConnectivityManager; +import android.net.IpSecConfig; +import android.net.IpSecTransform; import android.net.LinkProperties; import android.net.Network; import android.net.NetworkCapabilities; @@ -70,6 +72,7 @@ import com.android.server.vcn.routeselection.UnderlyingNetworkController.Depende import com.android.server.vcn.routeselection.UnderlyingNetworkController.NetworkBringupCallback; import com.android.server.vcn.routeselection.UnderlyingNetworkController.UnderlyingNetworkControllerCallback; import com.android.server.vcn.routeselection.UnderlyingNetworkController.UnderlyingNetworkListener; +import com.android.server.vcn.routeselection.UnderlyingNetworkEvaluator.NetworkEvaluatorCallback; import org.junit.Before; import org.junit.Test; @@ -153,11 +156,13 @@ public class UnderlyingNetworkControllerTest { @Mock private CarrierConfigManager mCarrierConfigManager; @Mock private TelephonySubscriptionSnapshot mSubscriptionSnapshot; @Mock private UnderlyingNetworkControllerCallback mNetworkControllerCb; + @Mock private NetworkEvaluatorCallback mEvaluatorCallback; @Mock private Network mNetwork; @Spy private Dependencies mDependencies = new Dependencies(); @Captor private ArgumentCaptor<UnderlyingNetworkListener> mUnderlyingNetworkListenerCaptor; + @Captor private ArgumentCaptor<NetworkEvaluatorCallback> mEvaluatorCallbackCaptor; private TestLooper mTestLooper; private VcnContext mVcnContext; @@ -176,7 +181,7 @@ public class UnderlyingNetworkControllerTest { mTestLooper.getLooper(), mVcnNetworkProvider, false /* isInTestMode */)); - resetVcnContext(); + resetVcnContext(mVcnContext); setupSystemService( mContext, @@ -202,10 +207,11 @@ public class UnderlyingNetworkControllerTest { .getVcnUnderlyingNetworkPriorities(), SUB_GROUP, mSubscriptionSnapshot, - null)); + null, + mEvaluatorCallback)); doReturn(mNetworkEvaluator) .when(mDependencies) - .newUnderlyingNetworkEvaluator(any(), any(), any(), any(), any(), any()); + .newUnderlyingNetworkEvaluator(any(), any(), any(), any(), any(), any(), any()); mUnderlyingNetworkController = new UnderlyingNetworkController( @@ -217,9 +223,11 @@ public class UnderlyingNetworkControllerTest { mDependencies); } - private void resetVcnContext() { - reset(mVcnContext); - doNothing().when(mVcnContext).ensureRunningOnLooperThread(); + private void resetVcnContext(VcnContext vcnContext) { + reset(vcnContext); + doNothing().when(vcnContext).ensureRunningOnLooperThread(); + doReturn(true).when(vcnContext).isFlagNetworkMetricMonitorEnabled(); + doReturn(true).when(vcnContext).isFlagIpSecTransformStateEnabled(); } // Package private for use in NetworkPriorityClassifierTest @@ -245,11 +253,13 @@ public class UnderlyingNetworkControllerTest { final ConnectivityManager cm = mock(ConnectivityManager.class); setupSystemService(mContext, cm, Context.CONNECTIVITY_SERVICE, ConnectivityManager.class); final VcnContext vcnContext = - new VcnContext( - mContext, - mTestLooper.getLooper(), - mVcnNetworkProvider, - true /* isInTestMode */); + spy( + new VcnContext( + mContext, + mTestLooper.getLooper(), + mVcnNetworkProvider, + true /* isInTestMode */)); + resetVcnContext(vcnContext); new UnderlyingNetworkController( vcnContext, @@ -554,6 +564,45 @@ public class UnderlyingNetworkControllerTest { verify(mNetworkEvaluator).reevaluate(any(), any(), any(), any()); } + @Test + public void testUpdateIpSecTransform() { + verifyRegistrationOnAvailableAndGetCallback(); + + final UnderlyingNetworkRecord expectedRecord = + getTestNetworkRecord( + mNetwork, + INITIAL_NETWORK_CAPABILITIES, + INITIAL_LINK_PROPERTIES, + false /* isBlocked */); + final IpSecTransform expectedTransform = new IpSecTransform(mContext, new IpSecConfig()); + + mUnderlyingNetworkController.updateInboundTransform(expectedRecord, expectedTransform); + verify(mNetworkEvaluator).setInboundTransform(expectedTransform); + } + + @Test + public void testOnEvaluationResultChanged() { + verifyRegistrationOnAvailableAndGetCallback(); + + // Verify #reevaluateNetworks is called by checking #getNetworkRecord + verify(mNetworkEvaluator).getNetworkRecord(); + + // Trigger the callback + verify(mDependencies) + .newUnderlyingNetworkEvaluator( + any(), + any(), + any(), + any(), + any(), + any(), + mEvaluatorCallbackCaptor.capture()); + mEvaluatorCallbackCaptor.getValue().onEvaluationResultChanged(); + + // Verify #reevaluateNetworks is called again + verify(mNetworkEvaluator, times(2)).getNetworkRecord(); + } + private UnderlyingNetworkListener verifyRegistrationOnAvailableAndGetCallback() { return verifyRegistrationOnAvailableAndGetCallback(INITIAL_NETWORK_CAPABILITIES); } @@ -682,7 +731,7 @@ public class UnderlyingNetworkControllerTest { cb.onBlockedStatusChanged(mNetwork, true /* isBlocked */); - verifyOnSelectedUnderlyingNetworkChanged(null); + verify(mNetworkControllerCb).onSelectedUnderlyingNetworkChanged(null); } @Test @@ -690,6 +739,7 @@ public class UnderlyingNetworkControllerTest { UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback(); cb.onLost(mNetwork); + verify(mNetworkEvaluator).close(); verify(mNetworkControllerCb).onSelectedUnderlyingNetworkChanged(null); } @@ -755,10 +805,11 @@ public class UnderlyingNetworkControllerTest { underlyingNetworkTemplates, SUB_GROUP, mSubscriptionSnapshot, - null)); + null, + mEvaluatorCallback)); doReturn(evaluator) .when(mDependencies) - .newUnderlyingNetworkEvaluator(any(), any(), any(), any(), any(), any()); + .newUnderlyingNetworkEvaluator(any(), any(), any(), any(), any(), any(), any()); cb.onAvailable(network); cb.onCapabilitiesChanged(network, responseNetworkCaps); diff --git a/tests/vcn/java/com/android/server/vcn/routeselection/UnderlyingNetworkEvaluatorTest.java b/tests/vcn/java/com/android/server/vcn/routeselection/UnderlyingNetworkEvaluatorTest.java index 985e70c9771e..aa81efe9a1ce 100644 --- a/tests/vcn/java/com/android/server/vcn/routeselection/UnderlyingNetworkEvaluatorTest.java +++ b/tests/vcn/java/com/android/server/vcn/routeselection/UnderlyingNetworkEvaluatorTest.java @@ -16,27 +16,65 @@ package com.android.server.vcn.routeselection; +import static android.net.vcn.VcnManager.VCN_NETWORK_SELECTION_PENALTY_TIMEOUT_MINUTES_LIST_KEY; + import static com.android.server.vcn.routeselection.NetworkPriorityClassifier.PRIORITY_INVALID; import static com.android.server.vcn.util.PersistableBundleUtils.PersistableBundleWrapper; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyObject; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import android.net.IpSecTransform; import android.net.vcn.VcnGatewayConnectionConfig; -import android.os.PersistableBundle; + +import com.android.server.vcn.routeselection.NetworkMetricMonitor.NetworkMetricMonitorCallback; +import com.android.server.vcn.routeselection.UnderlyingNetworkEvaluator.Dependencies; +import com.android.server.vcn.routeselection.UnderlyingNetworkEvaluator.NetworkEvaluatorCallback; import org.junit.Before; import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; + +import java.util.concurrent.TimeUnit; public class UnderlyingNetworkEvaluatorTest extends NetworkEvaluationTestBase { - private PersistableBundleWrapper mCarrierConfig; + private static final int PENALTY_TIMEOUT_MIN = 10; + private static final long PENALTY_TIMEOUT_MS = TimeUnit.MINUTES.toMillis(PENALTY_TIMEOUT_MIN); + + @Mock private PersistableBundleWrapper mCarrierConfig; + @Mock private IpSecPacketLossDetector mIpSecPacketLossDetector; + @Mock private Dependencies mDependencies; + @Mock private NetworkEvaluatorCallback mEvaluatorCallback; + + @Captor private ArgumentCaptor<NetworkMetricMonitorCallback> mMetricMonitorCbCaptor; + + private UnderlyingNetworkEvaluator mNetworkEvaluator; @Before public void setUp() throws Exception { super.setUp(); - mCarrierConfig = new PersistableBundleWrapper(new PersistableBundle()); + + when(mDependencies.newIpSecPacketLossDetector(any(), any(), any(), any())) + .thenReturn(mIpSecPacketLossDetector); + + when(mCarrierConfig.getIntArray( + eq(VCN_NETWORK_SELECTION_PENALTY_TIMEOUT_MINUTES_LIST_KEY), anyObject())) + .thenReturn(new int[] {PENALTY_TIMEOUT_MIN}); + + mNetworkEvaluator = newValidUnderlyingNetworkEvaluator(); } private UnderlyingNetworkEvaluator newUnderlyingNetworkEvaluator() { @@ -46,7 +84,34 @@ public class UnderlyingNetworkEvaluatorTest extends NetworkEvaluationTestBase { VcnGatewayConnectionConfig.DEFAULT_UNDERLYING_NETWORK_TEMPLATES, SUB_GROUP, mSubscriptionSnapshot, + mCarrierConfig, + mEvaluatorCallback, + mDependencies); + } + + private UnderlyingNetworkEvaluator newValidUnderlyingNetworkEvaluator() { + final UnderlyingNetworkEvaluator evaluator = newUnderlyingNetworkEvaluator(); + + evaluator.setNetworkCapabilities( + CELL_NETWORK_CAPABILITIES, + VcnGatewayConnectionConfig.DEFAULT_UNDERLYING_NETWORK_TEMPLATES, + SUB_GROUP, + mSubscriptionSnapshot, + mCarrierConfig); + evaluator.setLinkProperties( + LINK_PROPERTIES, + VcnGatewayConnectionConfig.DEFAULT_UNDERLYING_NETWORK_TEMPLATES, + SUB_GROUP, + mSubscriptionSnapshot, + mCarrierConfig); + evaluator.setIsBlocked( + false /* isBlocked */, + VcnGatewayConnectionConfig.DEFAULT_UNDERLYING_NETWORK_TEMPLATES, + SUB_GROUP, + mSubscriptionSnapshot, mCarrierConfig); + + return evaluator; } @Test @@ -98,4 +163,174 @@ public class UnderlyingNetworkEvaluatorTest extends NetworkEvaluationTestBase { assertEquals(2, evaluator.getPriorityClass()); assertEquals(expectedRecord, evaluator.getNetworkRecord()); } + + private void checkSetSelectedNetwork(boolean isSelected) { + mNetworkEvaluator.setIsSelected( + isSelected, + VcnGatewayConnectionConfig.DEFAULT_UNDERLYING_NETWORK_TEMPLATES, + SUB_GROUP, + mSubscriptionSnapshot, + mCarrierConfig); + verify(mIpSecPacketLossDetector).setIsSelectedUnderlyingNetwork(isSelected); + } + + @Test + public void testSetIsSelected_selected() throws Exception { + checkSetSelectedNetwork(true /* isSelectedExpected */); + } + + @Test + public void testSetIsSelected_unselected() throws Exception { + checkSetSelectedNetwork(false /* isSelectedExpected */); + } + + @Test + public void testSetIpSecTransform_onSelectedNetwork() throws Exception { + final IpSecTransform transform = makeDummyIpSecTransform(); + + // Make the network selected + mNetworkEvaluator.setIsSelected( + true, + VcnGatewayConnectionConfig.DEFAULT_UNDERLYING_NETWORK_TEMPLATES, + SUB_GROUP, + mSubscriptionSnapshot, + mCarrierConfig); + mNetworkEvaluator.setInboundTransform(transform); + + verify(mIpSecPacketLossDetector).setInboundTransform(transform); + } + + @Test + public void testSetIpSecTransform_onUnSelectedNetwork() throws Exception { + mNetworkEvaluator.setIsSelected( + false, + VcnGatewayConnectionConfig.DEFAULT_UNDERLYING_NETWORK_TEMPLATES, + SUB_GROUP, + mSubscriptionSnapshot, + mCarrierConfig); + mNetworkEvaluator.setInboundTransform(makeDummyIpSecTransform()); + + verify(mIpSecPacketLossDetector, never()).setInboundTransform(any()); + } + + @Test + public void close() throws Exception { + mNetworkEvaluator.close(); + + verify(mIpSecPacketLossDetector).close(); + mTestLooper.moveTimeForward(PENALTY_TIMEOUT_MS); + assertNull(mTestLooper.nextMessage()); + } + + private NetworkMetricMonitorCallback getMetricMonitorCbCaptor() throws Exception { + verify(mDependencies) + .newIpSecPacketLossDetector(any(), any(), any(), mMetricMonitorCbCaptor.capture()); + + return mMetricMonitorCbCaptor.getValue(); + } + + private void checkPenalizeNetwork() throws Exception { + assertFalse(mNetworkEvaluator.isPenalized()); + + // Validation failed + when(mIpSecPacketLossDetector.isValidationFailed()).thenReturn(true); + getMetricMonitorCbCaptor().onValidationResultReceived(); + + // Verify the evaluator is penalized + assertTrue(mNetworkEvaluator.isPenalized()); + verify(mEvaluatorCallback).onEvaluationResultChanged(); + } + + @Test + public void testRcvValidationResult_penalizeNetwork_penaltyTimeout() throws Exception { + checkPenalizeNetwork(); + + // Penalty timeout + mTestLooper.moveTimeForward(PENALTY_TIMEOUT_MS); + mTestLooper.dispatchAll(); + + // Verify the evaluator is not penalized + assertFalse(mNetworkEvaluator.isPenalized()); + verify(mEvaluatorCallback, times(2)).onEvaluationResultChanged(); + } + + @Test + public void testRcvValidationResult_penalizeNetwork_passValidation() throws Exception { + checkPenalizeNetwork(); + + // Validation passed + when(mIpSecPacketLossDetector.isValidationFailed()).thenReturn(false); + getMetricMonitorCbCaptor().onValidationResultReceived(); + + // Verify the evaluator is not penalized and penalty timeout is canceled + assertFalse(mNetworkEvaluator.isPenalized()); + verify(mEvaluatorCallback, times(2)).onEvaluationResultChanged(); + mTestLooper.moveTimeForward(PENALTY_TIMEOUT_MS); + assertNull(mTestLooper.nextMessage()); + } + + @Test + public void testRcvValidationResult_penalizeNetwork_closeEvaluator() throws Exception { + checkPenalizeNetwork(); + + mNetworkEvaluator.close(); + + // Verify penalty timeout is canceled + mTestLooper.moveTimeForward(PENALTY_TIMEOUT_MS); + assertNull(mTestLooper.nextMessage()); + } + + @Test + public void testRcvValidationResult_PenaltyStateUnchanged() throws Exception { + assertFalse(mNetworkEvaluator.isPenalized()); + + // Validation passed + when(mIpSecPacketLossDetector.isValidationFailed()).thenReturn(false); + getMetricMonitorCbCaptor().onValidationResultReceived(); + + // Verifications + assertFalse(mNetworkEvaluator.isPenalized()); + verify(mEvaluatorCallback, never()).onEvaluationResultChanged(); + } + + @Test + public void testSetCarrierConfig() throws Exception { + final int additionalTimeoutMin = 10; + when(mCarrierConfig.getIntArray( + eq(VCN_NETWORK_SELECTION_PENALTY_TIMEOUT_MINUTES_LIST_KEY), anyObject())) + .thenReturn(new int[] {PENALTY_TIMEOUT_MIN + additionalTimeoutMin}); + + // Update evaluator and penalize the network + mNetworkEvaluator.reevaluate( + VcnGatewayConnectionConfig.DEFAULT_UNDERLYING_NETWORK_TEMPLATES, + SUB_GROUP, + mSubscriptionSnapshot, + mCarrierConfig); + checkPenalizeNetwork(); + + // Verify penalty timeout is changed + mTestLooper.moveTimeForward(PENALTY_TIMEOUT_MS); + assertNull(mTestLooper.nextMessage()); + mTestLooper.moveTimeForward(TimeUnit.MINUTES.toMillis(additionalTimeoutMin)); + assertNotNull(mTestLooper.nextMessage()); + + // Verify NetworkMetricMonitor is notified + verify(mIpSecPacketLossDetector).setCarrierConfig(any()); + } + + @Test + public void testCompare() throws Exception { + when(mIpSecPacketLossDetector.isValidationFailed()).thenReturn(true); + getMetricMonitorCbCaptor().onValidationResultReceived(); + + final UnderlyingNetworkEvaluator penalized = mNetworkEvaluator; + final UnderlyingNetworkEvaluator notPenalized = newValidUnderlyingNetworkEvaluator(); + + assertEquals(penalized.getPriorityClass(), notPenalized.getPriorityClass()); + + final int result = + UnderlyingNetworkEvaluator.getComparator(mVcnContext) + .compare(penalized, notPenalized); + assertEquals(1, result); + } } diff --git a/tools/aapt2/integration-tests/MergeOnlyTest/Android.mk b/tools/aapt2/integration-tests/MergeOnlyTest/Android.mk deleted file mode 100644 index 6361f9b8ae7d..000000000000 --- a/tools/aapt2/integration-tests/MergeOnlyTest/Android.mk +++ /dev/null @@ -1,2 +0,0 @@ -LOCAL_PATH := $(call my-dir) -include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/tools/aapt2/integration-tests/MergeOnlyTest/App/Android.mk b/tools/aapt2/integration-tests/MergeOnlyTest/App/Android.mk deleted file mode 100644 index 27b6068632f3..000000000000 --- a/tools/aapt2/integration-tests/MergeOnlyTest/App/Android.mk +++ /dev/null @@ -1,32 +0,0 @@ -// -// Copyright (C) 2019 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -LOCAL_PATH := $(call my-dir) - -include $(CLEAR_VARS) -LOCAL_USE_AAPT2 := true -LOCAL_AAPT_NAMESPACES := true -LOCAL_PACKAGE_NAME := AaptTestMergeOnly_App -LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 -LOCAL_LICENSE_CONDITIONS := notice -LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../../../../NOTICE -LOCAL_SDK_VERSION := current -LOCAL_EXPORT_PACKAGE_RESOURCES := true -LOCAL_MODULE_TAGS := tests -LOCAL_STATIC_ANDROID_LIBRARIES := \ - AaptTestMergeOnly_LeafLib \ - AaptTestMergeOnly_LocalLib -include $(BUILD_PACKAGE) diff --git a/tools/aapt2/integration-tests/MergeOnlyTest/LocalLib/Android.mk b/tools/aapt2/integration-tests/MergeOnlyTest/LocalLib/Android.mk deleted file mode 100644 index 699ad79ecf1a..000000000000 --- a/tools/aapt2/integration-tests/MergeOnlyTest/LocalLib/Android.mk +++ /dev/null @@ -1,31 +0,0 @@ -// -// Copyright (C) 2019 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -LOCAL_PATH := $(call my-dir) - -include $(CLEAR_VARS) -LOCAL_USE_AAPT2 := true -LOCAL_AAPT_NAMESPACES := true -LOCAL_MODULE := AaptTestMergeOnly_LocalLib -LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 -LOCAL_LICENSE_CONDITIONS := notice -LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../../../../NOTICE -LOCAL_SDK_VERSION := current -LOCAL_MODULE_TAGS := tests -LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res -LOCAL_MIN_SDK_VERSION := 21 -LOCAL_AAPT_FLAGS := --merge-only -include $(BUILD_STATIC_JAVA_LIBRARY) diff --git a/tools/aapt2/integration-tests/NamespaceTest/Android.mk b/tools/aapt2/integration-tests/NamespaceTest/Android.mk deleted file mode 100644 index 6361f9b8ae7d..000000000000 --- a/tools/aapt2/integration-tests/NamespaceTest/Android.mk +++ /dev/null @@ -1,2 +0,0 @@ -LOCAL_PATH := $(call my-dir) -include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/tools/aapt2/integration-tests/NamespaceTest/App/Android.mk b/tools/aapt2/integration-tests/NamespaceTest/App/Android.mk deleted file mode 100644 index 98b74403a7ff..000000000000 --- a/tools/aapt2/integration-tests/NamespaceTest/App/Android.mk +++ /dev/null @@ -1,33 +0,0 @@ -# -# Copyright (C) 2017 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -LOCAL_PATH := $(call my-dir) - -include $(CLEAR_VARS) -LOCAL_USE_AAPT2 := true -LOCAL_AAPT_NAMESPACES := true -LOCAL_PACKAGE_NAME := AaptTestNamespace_App -LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 -LOCAL_LICENSE_CONDITIONS := notice -LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../../../../NOTICE -LOCAL_SDK_VERSION := current -LOCAL_EXPORT_PACKAGE_RESOURCES := true -LOCAL_MODULE_TAGS := tests -LOCAL_SRC_FILES := $(call all-java-files-under,src) -LOCAL_STATIC_ANDROID_LIBRARIES := \ - AaptTestNamespace_LibOne \ - AaptTestNamespace_LibTwo -include $(BUILD_PACKAGE) diff --git a/tools/aapt2/integration-tests/NamespaceTest/LibOne/Android.mk b/tools/aapt2/integration-tests/NamespaceTest/LibOne/Android.mk deleted file mode 100644 index dd4170234258..000000000000 --- a/tools/aapt2/integration-tests/NamespaceTest/LibOne/Android.mk +++ /dev/null @@ -1,33 +0,0 @@ -# -# Copyright (C) 2017 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -LOCAL_PATH := $(call my-dir) - -include $(CLEAR_VARS) -LOCAL_USE_AAPT2 := true -LOCAL_AAPT_NAMESPACES := true -LOCAL_MODULE := AaptTestNamespace_LibOne -LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 -LOCAL_LICENSE_CONDITIONS := notice -LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../../../../NOTICE -LOCAL_SDK_VERSION := current -LOCAL_MODULE_TAGS := tests -LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res -LOCAL_MIN_SDK_VERSION := 21 - -# We need this to retain the R.java generated for this library. -LOCAL_JAR_EXCLUDE_FILES := none -include $(BUILD_STATIC_JAVA_LIBRARY) diff --git a/tools/aapt2/integration-tests/NamespaceTest/LibTwo/Android.mk b/tools/aapt2/integration-tests/NamespaceTest/LibTwo/Android.mk deleted file mode 100644 index 0d11bcbda64d..000000000000 --- a/tools/aapt2/integration-tests/NamespaceTest/LibTwo/Android.mk +++ /dev/null @@ -1,34 +0,0 @@ -# -# Copyright (C) 2017 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -LOCAL_PATH := $(call my-dir) - -include $(CLEAR_VARS) -LOCAL_USE_AAPT2 := true -LOCAL_AAPT_NAMESPACES := true -LOCAL_MODULE := AaptTestNamespace_LibTwo -LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 -LOCAL_LICENSE_CONDITIONS := notice -LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../../../../NOTICE -LOCAL_SDK_VERSION := current -LOCAL_MODULE_TAGS := tests -LOCAL_SRC_FILES := $(call all-java-files-under,src) -LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res -LOCAL_MIN_SDK_VERSION := 21 - -# We need this to retain the R.java generated for this library. -LOCAL_JAR_EXCLUDE_FILES := none -include $(BUILD_STATIC_JAVA_LIBRARY) diff --git a/tools/aapt2/integration-tests/NamespaceTest/Split/Android.mk b/tools/aapt2/integration-tests/NamespaceTest/Split/Android.mk deleted file mode 100644 index 30375728c9e0..000000000000 --- a/tools/aapt2/integration-tests/NamespaceTest/Split/Android.mk +++ /dev/null @@ -1,32 +0,0 @@ -# -# Copyright (C) 2017 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -LOCAL_PATH := $(call my-dir) - -include $(CLEAR_VARS) -LOCAL_USE_AAPT2 := true -LOCAL_AAPT_NAMESPACES := true -LOCAL_PACKAGE_NAME := AaptTestNamespace_Split -LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 -LOCAL_LICENSE_CONDITIONS := notice -LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../../../../NOTICE -LOCAL_SDK_VERSION := current -LOCAL_MODULE_TAGS := tests -LOCAL_SRC_FILES := $(call all-java-files-under,src) -LOCAL_APK_LIBRARIES := AaptTestNamespace_App -LOCAL_RES_LIBRARIES := AaptTestNamespace_App -LOCAL_AAPT_FLAGS := --package-id 0x80 --rename-manifest-package com.android.aapt.namespace.app -include $(BUILD_PACKAGE) |