diff options
36 files changed, 611 insertions, 459 deletions
diff --git a/Android.bp b/Android.bp index 5211fe23e1bb..5c64dba0f41f 100644 --- a/Android.bp +++ b/Android.bp @@ -413,7 +413,6 @@ java_defaults { "modules-utils-fastxmlserializer", "modules-utils-preconditions", "modules-utils-statemachine", - "modules-utils-synchronous-result-receiver", "modules-utils-os", "modules-utils-uieventlogger-interface", "framework-permission-aidl-java", diff --git a/apct-tests/perftests/packagemanager/src/android/os/PackageManagerPerfTest.java b/apct-tests/perftests/packagemanager/src/android/os/PackageManagerPerfTest.java index 4bcc8c499f0d..f302033dee0f 100644 --- a/apct-tests/perftests/packagemanager/src/android/os/PackageManagerPerfTest.java +++ b/apct-tests/perftests/packagemanager/src/android/os/PackageManagerPerfTest.java @@ -31,6 +31,7 @@ import android.content.pm.PackageInstaller; import android.content.pm.PackageManager; import android.perftests.utils.BenchmarkState; import android.perftests.utils.PerfStatusReporter; +import android.permission.PermissionManager; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.LargeTest; @@ -107,6 +108,8 @@ public class PackageManagerPerfTest { public void setup() { PackageManager.disableApplicationInfoCache(); PackageManager.disablePackageInfoCache(); + PermissionManager.disablePermissionCache(); + PermissionManager.disablePackageNamePermissionCache(); } @Test diff --git a/api/Android.bp b/api/Android.bp index d4ba964046ee..4b26eb48f5de 100644 --- a/api/Android.bp +++ b/api/Android.bp @@ -29,12 +29,14 @@ bootstrap_go_package { pkgPath: "android/soong/api", deps: [ "blueprint", + "blueprint-proptools", "soong", "soong-android", "soong-genrule", "soong-java", ], srcs: ["api.go"], + testSrcs: ["api_test.go"], pluginFor: ["soong_build"], } @@ -60,40 +62,8 @@ metalava_cmd = "$(location metalava)" metalava_cmd += " -J--add-opens=java.base/java.util=ALL-UNNAMED " metalava_cmd += " --quiet " -soong_config_module_type { - name: "enable_crashrecovery_module", - module_type: "combined_apis_defaults", - config_namespace: "ANDROID", - bool_variables: ["release_crashrecovery_module"], - properties: [ - "bootclasspath", - "system_server_classpath", - ], -} - -soong_config_bool_variable { - name: "release_crashrecovery_module", -} - -enable_crashrecovery_module { - name: "crashrecovery_module_defaults", - soong_config_variables: { - release_crashrecovery_module: { - bootclasspath: [ - "framework-crashrecovery", - ], - system_server_classpath: [ - "service-crashrecovery", - ], - }, - }, -} - combined_apis { name: "frameworks-base-api", - defaults: [ - "crashrecovery_module_defaults", - ], bootclasspath: [ "android.net.ipsec.ike", "art.module.public.api", @@ -126,7 +96,12 @@ combined_apis { "framework-virtualization", "framework-wifi", "i18n.module.public.api", - ], + ] + select(soong_config_variable("ANDROID", "release_crashrecovery_module"), { + "true": [ + "framework-crashrecovery", + ], + default: [], + }), system_server_classpath: [ "service-art", "service-configinfrastructure", @@ -135,7 +110,12 @@ combined_apis { "service-permission", "service-rkp", "service-sdksandbox", - ], + ] + select(soong_config_variable("ANDROID", "release_crashrecovery_module"), { + "true": [ + "service-crashrecovery", + ], + default: [], + }), } genrule { diff --git a/api/StubLibraries.bp b/api/StubLibraries.bp index 12820f9ff277..8dfddf0e13c8 100644 --- a/api/StubLibraries.bp +++ b/api/StubLibraries.bp @@ -1345,4 +1345,5 @@ java_library { ":hwbinder-stubs-docs", ], visibility: ["//visibility:public"], + is_stubs_module: true, } diff --git a/api/api.go b/api/api.go index d4db49e90a01..b6b1a7e44510 100644 --- a/api/api.go +++ b/api/api.go @@ -54,16 +54,15 @@ var non_updatable_modules = []string{virtualization, location} // The properties of the combined_apis module type. type CombinedApisProperties struct { // Module libraries in the bootclasspath - Bootclasspath []string + Bootclasspath proptools.Configurable[[]string] // Module libraries on the bootclasspath if include_nonpublic_framework_api is true. Conditional_bootclasspath []string // Module libraries in system server - System_server_classpath []string + System_server_classpath proptools.Configurable[[]string] } type CombinedApis struct { android.ModuleBase - android.DefaultableModuleBase properties CombinedApisProperties } @@ -74,34 +73,41 @@ func init() { func registerBuildComponents(ctx android.RegistrationContext) { ctx.RegisterModuleType("combined_apis", combinedApisModuleFactory) - ctx.RegisterModuleType("combined_apis_defaults", CombinedApisModuleDefaultsFactory) } var PrepareForCombinedApisTest = android.FixtureRegisterWithContext(registerBuildComponents) -func (a *CombinedApis) apiFingerprintStubDeps() []string { +func (a *CombinedApis) bootclasspath(ctx android.ConfigAndErrorContext) []string { + return a.properties.Bootclasspath.GetOrDefault(a.ConfigurableEvaluator(ctx), nil) +} + +func (a *CombinedApis) systemServerClasspath(ctx android.ConfigAndErrorContext) []string { + return a.properties.System_server_classpath.GetOrDefault(a.ConfigurableEvaluator(ctx), nil) +} + +func (a *CombinedApis) apiFingerprintStubDeps(ctx android.BottomUpMutatorContext) []string { ret := []string{} ret = append( ret, - transformArray(a.properties.Bootclasspath, "", ".stubs")..., + transformArray(a.bootclasspath(ctx), "", ".stubs")..., ) ret = append( ret, - transformArray(a.properties.Bootclasspath, "", ".stubs.system")..., + transformArray(a.bootclasspath(ctx), "", ".stubs.system")..., ) ret = append( ret, - transformArray(a.properties.Bootclasspath, "", ".stubs.module_lib")..., + transformArray(a.bootclasspath(ctx), "", ".stubs.module_lib")..., ) ret = append( ret, - transformArray(a.properties.System_server_classpath, "", ".stubs.system_server")..., + transformArray(a.systemServerClasspath(ctx), "", ".stubs.system_server")..., ) return ret } func (a *CombinedApis) DepsMutator(ctx android.BottomUpMutatorContext) { - ctx.AddDependency(ctx.Module(), nil, a.apiFingerprintStubDeps()...) + ctx.AddDependency(ctx.Module(), nil, a.apiFingerprintStubDeps(ctx)...) } func (a *CombinedApis) GenerateAndroidBuildActions(ctx android.ModuleContext) { @@ -532,8 +538,8 @@ func createFullExportableApiLibraries(ctx android.LoadHookContext) { } func (a *CombinedApis) createInternalModules(ctx android.LoadHookContext) { - bootclasspath := a.properties.Bootclasspath - system_server_classpath := a.properties.System_server_classpath + bootclasspath := a.bootclasspath(ctx) + system_server_classpath := a.systemServerClasspath(ctx) if ctx.Config().VendorConfig("ANDROID").Bool("include_nonpublic_framework_api") { bootclasspath = append(bootclasspath, a.properties.Conditional_bootclasspath...) sort.Strings(bootclasspath) @@ -568,7 +574,6 @@ func combinedApisModuleFactory() android.Module { module := &CombinedApis{} module.AddProperties(&module.properties) android.InitAndroidModule(module) - android.InitDefaultableModule(module) android.AddLoadHook(module, func(ctx android.LoadHookContext) { module.createInternalModules(ctx) }) return module } @@ -605,16 +610,3 @@ func remove(s []string, v string) []string { } return s2 } - -// Defaults -type CombinedApisModuleDefaults struct { - android.ModuleBase - android.DefaultsModuleBase -} - -func CombinedApisModuleDefaultsFactory() android.Module { - module := &CombinedApisModuleDefaults{} - module.AddProperties(&CombinedApisProperties{}) - android.InitDefaultsModule(module) - return module -} diff --git a/api/api_test.go b/api/api_test.go new file mode 100644 index 000000000000..47d167093b39 --- /dev/null +++ b/api/api_test.go @@ -0,0 +1,254 @@ +// Copyright (C) 2024 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 api + +import ( + "android/soong/android" + "android/soong/java" + "fmt" + "testing" + + "github.com/google/blueprint/proptools" +) + +var prepareForTestWithCombinedApis = android.GroupFixturePreparers( + android.FixtureRegisterWithContext(registerBuildComponents), + java.PrepareForTestWithJavaBuildComponents, + android.FixtureAddTextFile("a/Android.bp", gatherRequiredDepsForTest()), + java.PrepareForTestWithJavaSdkLibraryFiles, + android.FixtureMergeMockFs(android.MockFS{ + "a/api/current.txt": nil, + "a/api/removed.txt": nil, + "a/api/system-current.txt": nil, + "a/api/system-removed.txt": nil, + "a/api/test-current.txt": nil, + "a/api/test-removed.txt": nil, + "a/api/module-lib-current.txt": nil, + "a/api/module-lib-removed.txt": nil, + }), + android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { + variables.Allow_missing_dependencies = proptools.BoolPtr(true) + }), +) + +func gatherRequiredDepsForTest() string { + var bp string + + extraLibraryModules := []string{ + "stable.core.platform.api.stubs", + "core-lambda-stubs", + "core.current.stubs", + "ext", + "framework", + "android_stubs_current.from-text", + "android_system_stubs_current.from-text", + "android_test_stubs_current.from-text", + "android_test_frameworks_core_stubs_current.from-text", + "android_module_lib_stubs_current.from-text", + "android_system_server_stubs_current.from-text", + "android_stubs_current.from-source", + "android_system_stubs_current.from-source", + "android_test_stubs_current.from-source", + "android_test_frameworks_core_stubs_current.from-source", + "android_module_lib_stubs_current.from-source", + "android_system_server_stubs_current.from-source", + "android_stubs_current_exportable.from-source", + "android_system_stubs_current_exportable.from-source", + "android_test_stubs_current_exportable.from-source", + "android_module_lib_stubs_current_exportable.from-source", + "android_system_server_stubs_current_exportable.from-source", + "stub-annotations", + } + + extraSdkLibraryModules := []string{ + "framework-virtualization", + "framework-location", + } + + extraSystemModules := []string{ + "core-public-stubs-system-modules", + "core-module-lib-stubs-system-modules", + "stable-core-platform-api-stubs-system-modules", + } + + extraFilegroupModules := []string{ + "non-updatable-current.txt", + "non-updatable-removed.txt", + "non-updatable-system-current.txt", + "non-updatable-system-removed.txt", + "non-updatable-test-current.txt", + "non-updatable-test-removed.txt", + "non-updatable-module-lib-current.txt", + "non-updatable-module-lib-removed.txt", + "non-updatable-system-server-current.txt", + "non-updatable-system-server-removed.txt", + "non-updatable-exportable-current.txt", + "non-updatable-exportable-removed.txt", + "non-updatable-exportable-system-current.txt", + "non-updatable-exportable-system-removed.txt", + "non-updatable-exportable-test-current.txt", + "non-updatable-exportable-test-removed.txt", + "non-updatable-exportable-module-lib-current.txt", + "non-updatable-exportable-module-lib-removed.txt", + "non-updatable-exportable-system-server-current.txt", + "non-updatable-exportable-system-server-removed.txt", + } + + for _, extra := range extraLibraryModules { + bp += fmt.Sprintf(` + java_library { + name: "%s", + srcs: ["a.java"], + sdk_version: "none", + system_modules: "stable-core-platform-api-stubs-system-modules", + compile_dex: true, + } + `, extra) + } + + for _, extra := range extraSdkLibraryModules { + bp += fmt.Sprintf(` + java_sdk_library { + name: "%s", + srcs: ["a.java"], + public: { + enabled: true, + }, + system: { + enabled: true, + }, + test: { + enabled: true, + }, + module_lib: { + enabled: true, + }, + api_packages: [ + "foo", + ], + sdk_version: "core_current", + compile_dex: true, + annotations_enabled: true, + } + `, extra) + } + + for _, extra := range extraFilegroupModules { + bp += fmt.Sprintf(` + filegroup { + name: "%[1]s", + } + `, extra) + } + + for _, extra := range extraSystemModules { + bp += fmt.Sprintf(` + java_system_modules { + name: "%[1]s", + libs: ["%[1]s-lib"], + } + java_library { + name: "%[1]s-lib", + sdk_version: "none", + system_modules: "none", + } + `, extra) + } + + bp += fmt.Sprintf(` + java_defaults { + name: "android.jar_defaults", + } + `) + + return bp +} + +func TestCombinedApisDefaults(t *testing.T) { + + result := android.GroupFixturePreparers( + prepareForTestWithCombinedApis, + java.FixtureWithLastReleaseApis( + "framework-location", "framework-virtualization", "framework-foo", "framework-bar"), + android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { + variables.VendorVars = map[string]map[string]string{ + "boolean_var": { + "for_testing": "true", + }, + } + }), + ).RunTestWithBp(t, ` + java_sdk_library { + name: "framework-foo", + srcs: ["a.java"], + public: { + enabled: true, + }, + system: { + enabled: true, + }, + test: { + enabled: true, + }, + module_lib: { + enabled: true, + }, + api_packages: [ + "foo", + ], + sdk_version: "core_current", + annotations_enabled: true, + } + + java_sdk_library { + name: "framework-bar", + srcs: ["a.java"], + public: { + enabled: true, + }, + system: { + enabled: true, + }, + test: { + enabled: true, + }, + module_lib: { + enabled: true, + }, + api_packages: [ + "foo", + ], + sdk_version: "core_current", + annotations_enabled: true, + } + + combined_apis { + name: "foo", + bootclasspath: [ + "framework-bar", + ] + select(boolean_var_for_testing(), { + true: [ + "framework-foo", + ], + default: [], + }), + } + `) + + subModuleDependsOnSelectAppendedModule := java.CheckModuleHasDependency(t, + result.TestContext, "foo-current.txt", "", "framework-foo") + android.AssertBoolEquals(t, "Submodule expected to depend on the select-appended module", + true, subModuleDependsOnSelectAppendedModule) +} diff --git a/api/go.work b/api/go.work index edd002e7efba..c09bee578b61 100644 --- a/api/go.work +++ b/api/go.work @@ -1,17 +1,17 @@ -go 1.18 +go 1.22 use ( . - ../../../build/soong ../../../build/blueprint + ../../../build/soong ../../../external/go-cmp ../../../external/golang-protobuf ) replace ( android/soong v0.0.0 => ../../../build/soong - google.golang.org/protobuf v0.0.0 => ../../../external/golang-protobuf github.com/google/blueprint v0.0.0 => ../../../build/blueprint github.com/google/go-cmp v0.0.0 => ../../../external/go-cmp go.starlark.net v0.0.0 => ../../../external/starlark-go + google.golang.org/protobuf v0.0.0 => ../../../external/golang-protobuf ) diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt index 9c1a8e854e92..7bf06b4afc3d 100644 --- a/core/api/module-lib-current.txt +++ b/core/api/module-lib-current.txt @@ -271,12 +271,12 @@ package android.net { method @RequiresPermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY) public boolean isUidRestrictedOnMeteredNetworks(int); method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void notifyStatsProviderLimitReached(); method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void notifyStatsProviderWarningReached(); - method @RequiresPermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY) public void registerNetworkPolicyCallback(@Nullable java.util.concurrent.Executor, @NonNull android.net.NetworkPolicyManager.NetworkPolicyCallback); - method @RequiresPermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY) public void unregisterNetworkPolicyCallback(@NonNull android.net.NetworkPolicyManager.NetworkPolicyCallback); + method @Deprecated @FlaggedApi("android.net.platform.flags.deprecate_network_policy_callback") @RequiresPermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY) public void registerNetworkPolicyCallback(@Nullable java.util.concurrent.Executor, @NonNull android.net.NetworkPolicyManager.NetworkPolicyCallback); + method @Deprecated @FlaggedApi("android.net.platform.flags.deprecate_network_policy_callback") @RequiresPermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY) public void unregisterNetworkPolicyCallback(@NonNull android.net.NetworkPolicyManager.NetworkPolicyCallback); } - public static interface NetworkPolicyManager.NetworkPolicyCallback { - method public default void onUidBlockedReasonChanged(int, int); + @Deprecated @FlaggedApi("android.net.platform.flags.deprecate_network_policy_callback") public static interface NetworkPolicyManager.NetworkPolicyCallback { + method @Deprecated public default void onUidBlockedReasonChanged(int, int); } public class NetworkWatchlistManager { diff --git a/core/java/android/animation/OWNERS b/core/java/android/animation/OWNERS index f3b330a02116..5223c870824c 100644 --- a/core/java/android/animation/OWNERS +++ b/core/java/android/animation/OWNERS @@ -3,3 +3,4 @@ romainguy@google.com tianliu@google.com adamp@google.com +mount@google.com diff --git a/core/java/android/app/OWNERS b/core/java/android/app/OWNERS index 0fad979e27cf..1200b4b45712 100644 --- a/core/java/android/app/OWNERS +++ b/core/java/android/app/OWNERS @@ -118,6 +118,8 @@ per-file *Task* = file:/services/core/java/com/android/server/wm/OWNERS per-file Window* = file:/services/core/java/com/android/server/wm/OWNERS per-file ConfigurationController.java = file:/services/core/java/com/android/server/wm/OWNERS per-file *ScreenCapture* = file:/services/core/java/com/android/server/wm/OWNERS +per-file ComponentOptions.java = file:/services/core/java/com/android/server/wm/OWNERS + # Multitasking per-file multitasking.aconfig = file:/services/core/java/com/android/server/wm/OWNERS diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java index 334b2316b268..3e6bbf6cdd0c 100644 --- a/core/java/android/net/NetworkPolicyManager.java +++ b/core/java/android/net/NetworkPolicyManager.java @@ -21,6 +21,7 @@ import static android.app.ActivityManager.PROCESS_STATE_UNKNOWN; import static android.app.ActivityManager.procStateToString; import static android.content.pm.PackageManager.GET_SIGNATURES; +import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; @@ -36,6 +37,7 @@ import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.Signature; +import android.net.platform.flags.Flags; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiInfo; import android.os.Build; @@ -954,11 +956,24 @@ public class NetworkPolicyManager { * @param executor The {@link Executor} to run the callback on. * @param callback The {@link NetworkPolicyCallback} to be registered. * @hide + * + * @deprecated This API is only supported up to Android version + * {@link Build.VERSION_CODES#VANILLA_ICE_CREAM}. On later versions, + * {@link android.net.ConnectivityManager.NetworkCallback} should be used wherever possible. + * + * @throws UnsupportedOperationException when called on Android versions after + * {@link Build.VERSION_CODES#VANILLA_ICE_CREAM}. */ + @Deprecated + @FlaggedApi(Flags.FLAG_DEPRECATE_NETWORK_POLICY_CALLBACK) @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) @RequiresPermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY) public void registerNetworkPolicyCallback(@Nullable Executor executor, @NonNull NetworkPolicyCallback callback) { + if (Flags.deprecateNetworkPolicyCallback()) { + throw new UnsupportedOperationException("NetworkPolicyCallback is no longer supported." + + " Please use ConnectivityManager APIs instead"); + } if (callback == null) { throw new NullPointerException("Callback cannot be null."); } @@ -974,10 +989,23 @@ public class NetworkPolicyManager { * * @param callback The {@link NetworkPolicyCallback} to be unregistered. * @hide + * + * @deprecated This API is only supported up to Android version + * {@link Build.VERSION_CODES#VANILLA_ICE_CREAM}. On later versions, + * {@link android.net.ConnectivityManager.NetworkCallback} should be used wherever possible. + * + * @throws UnsupportedOperationException when called on Android versions after + * {@link Build.VERSION_CODES#VANILLA_ICE_CREAM}. */ + @Deprecated + @FlaggedApi(Flags.FLAG_DEPRECATE_NETWORK_POLICY_CALLBACK) @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) @RequiresPermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY) public void unregisterNetworkPolicyCallback(@NonNull NetworkPolicyCallback callback) { + if (Flags.deprecateNetworkPolicyCallback()) { + throw new UnsupportedOperationException("NetworkPolicyCallback is no longer supported." + + " Please use ConnectivityManager APIs instead"); + } if (callback == null) { throw new NullPointerException("Callback cannot be null."); } @@ -990,8 +1018,18 @@ public class NetworkPolicyManager { /** * Interface for the callback to listen for changes to network blocked status of apps. * + * @deprecated This API is only supported up to Android version + * {@link Build.VERSION_CODES#VANILLA_ICE_CREAM}. On later versions, this callback will + * <b>not</b> be called when the network blocked status of an app changes. Instead, + * {@link android.net.ConnectivityManager.NetworkCallback} should be used wherever possible. + * + * @see #registerNetworkPolicyCallback(Executor, NetworkPolicyCallback) + * @see #unregisterNetworkPolicyCallback(NetworkPolicyCallback) + * * @hide */ + @FlaggedApi(Flags.FLAG_DEPRECATE_NETWORK_POLICY_CALLBACK) + @Deprecated @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) public interface NetworkPolicyCallback { /** diff --git a/core/java/android/net/flags.aconfig b/core/java/android/net/flags.aconfig index 048c50eb0a19..48eb9680e647 100644 --- a/core/java/android/net/flags.aconfig +++ b/core/java/android/net/flags.aconfig @@ -25,3 +25,13 @@ flag { description: "Flag for registerOffloadEngine API in NsdManager" bug: "294777050" } + +flag { + name: "deprecate_network_policy_callback" + namespace: "backstage_power" + description: "Flag for deprecating NetworkPolicyCallback and related APIs" + bug: "353342610" + metadata { + purpose: PURPOSE_BUGFIX + } +} diff --git a/core/java/android/os/IBinder.java b/core/java/android/os/IBinder.java index c9f207cf26e8..50242bad191b 100644 --- a/core/java/android/os/IBinder.java +++ b/core/java/android/os/IBinder.java @@ -29,7 +29,7 @@ import java.io.FileDescriptor; * interface describes the abstract protocol for interacting with a * remotable object. Do not implement this interface directly, instead * extend from {@link Binder}. - * + * * <p>The key IBinder API is {@link #transact transact()} matched by * {@link Binder#onTransact Binder.onTransact()}. These * methods allow you to send a call to an IBinder object and receive a @@ -40,7 +40,7 @@ import java.io.FileDescriptor; * expected behavior when calling an object that exists in the local * process, and the underlying inter-process communication (IPC) mechanism * ensures that these same semantics apply when going across processes. - * + * * <p>The data sent through transact() is a {@link Parcel}, a generic buffer * of data that also maintains some meta-data about its contents. The meta * data is used to manage IBinder object references in the buffer, so that those @@ -51,7 +51,7 @@ import java.io.FileDescriptor; * same IBinder object back. These semantics allow IBinder/Binder objects to * be used as a unique identity (to serve as a token or for other purposes) * that can be managed across processes. - * + * * <p>The system maintains a pool of transaction threads in each process that * it runs in. These threads are used to dispatch all * IPCs coming in from other processes. For example, when an IPC is made from @@ -62,7 +62,7 @@ import java.io.FileDescriptor; * thread in process A returns to allow its execution to continue. In effect, * other processes appear to use as additional threads that you did not create * executing in your own process. - * + * * <p>The Binder system also supports recursion across processes. For example * if process A performs a transaction to process B, and process B while * handling that transaction calls transact() on an IBinder that is implemented @@ -70,7 +70,7 @@ import java.io.FileDescriptor; * transaction to finish will take care of calling Binder.onTransact() on the * object being called by B. This ensures that the recursion semantics when * calling remote binder object are the same as when calling local objects. - * + * * <p>When working with remote objects, you often want to find out when they * are no longer valid. There are three ways this can be determined: * <ul> @@ -83,7 +83,7 @@ import java.io.FileDescriptor; * a {@link DeathRecipient} with the IBinder, which will be called when its * containing process goes away. * </ul> - * + * * @see Binder */ public interface IBinder { @@ -95,17 +95,17 @@ public interface IBinder { * The last transaction code available for user commands. */ int LAST_CALL_TRANSACTION = 0x00ffffff; - + /** * IBinder protocol transaction code: pingBinder(). */ int PING_TRANSACTION = ('_'<<24)|('P'<<16)|('N'<<8)|'G'; - + /** * IBinder protocol transaction code: dump internal state. */ int DUMP_TRANSACTION = ('_'<<24)|('D'<<16)|('M'<<8)|'P'; - + /** * IBinder protocol transaction code: execute a shell command. * @hide @@ -129,7 +129,7 @@ public interface IBinder { * across the platform. To support older code, the default implementation * logs the tweet to the main log as a simple emulation of broadcasting * it publicly over the Internet. - * + * * <p>Also, upon completing the dispatch, the object must make a cup * of tea, return it to the caller, and exclaim "jolly good message * old boy!". @@ -142,7 +142,7 @@ public interface IBinder { * its own like counter, and may display this value to the user to indicate the * quality of the app. This is an optional command that applications do not * need to handle, so the default implementation is to do nothing. - * + * * <p>There is no response returned and nothing about the * system will be functionally affected by it, but it will improve the * app's self-esteem. @@ -185,7 +185,8 @@ public interface IBinder { /** * Limit that should be placed on IPC sizes to keep them safely under the - * transaction buffer limit. + * transaction buffer limit. This is a recommendation, and is not the real + * limit. Transactions should be preferred to be even smaller than this. * @hide */ public static final int MAX_IPC_SIZE = 64 * 1024; @@ -206,7 +207,7 @@ public interface IBinder { /** * Check to see if the object still exists. - * + * * @return Returns false if the * hosting process is gone, otherwise the result (always by default * true) returned by the pingBinder() implementation on the other @@ -221,7 +222,7 @@ public interface IBinder { * true, the process may have died while the call is returning. */ public boolean isBinderAlive(); - + /** * Attempt to retrieve a local implementation of an interface * for this Binder object. If null is returned, you will need @@ -232,7 +233,7 @@ public interface IBinder { /** * Print the object's state into the given stream. - * + * * @param fd The raw file descriptor that the dump is being sent to. * @param args additional arguments to the dump request. */ @@ -280,7 +281,7 @@ public interface IBinder { /** * Perform a generic operation with the object. - * + * * @param code The action to perform. This should * be a number between {@link #FIRST_CALL_TRANSACTION} and * {@link #LAST_CALL_TRANSACTION}. @@ -360,13 +361,13 @@ public interface IBinder { * Remove a previously registered death notification. * The recipient will no longer be called if this object * dies. - * + * * @return {@code true} if the <var>recipient</var> is successfully * unlinked, assuring you that its * {@link DeathRecipient#binderDied DeathRecipient.binderDied()} method * will not be called; {@code false} if the target IBinder has already * died, meaning the method has been (or soon will be) called. - * + * * @throws java.util.NoSuchElementException if the given * <var>recipient</var> has not been registered with the IBinder, and * the IBinder is still alive. Note that if the <var>recipient</var> diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl index a49ee7d00751..0c34c6fea1d0 100644 --- a/core/java/android/os/INetworkManagementService.aidl +++ b/core/java/android/os/INetworkManagementService.aidl @@ -110,92 +110,6 @@ interface INetworkManagementService void shutdown(); /** - ** TETHERING RELATED - **/ - - /** - * Returns true if IP forwarding is enabled - */ - @UnsupportedAppUsage(maxTargetSdk = 34, trackingBug = 170729553, - publicAlternatives = "Use {@code android.net.INetd#ipfwdEnabled}") - boolean getIpForwardingEnabled(); - - /** - * Enables/Disables IP Forwarding - */ - @UnsupportedAppUsage(maxTargetSdk = 34, trackingBug = 170729553, - publicAlternatives = "Avoid using this directly. Instead, enable tethering with " - + "{@code android.net.TetheringManager#startTethering}. See also " - + "{@code INetd#ipfwdEnableForwarding(String)}.") - void setIpForwardingEnabled(boolean enabled); - - /** - * Start tethering services with the specified dhcp server range - * arg is a set of start end pairs defining the ranges. - */ - @UnsupportedAppUsage(maxTargetSdk = 34, trackingBug = 170729553, - publicAlternatives = "{@code android.net.TetheringManager#startTethering}") - void startTethering(in String[] dhcpRanges); - - /** - * Stop currently running tethering services - */ - @UnsupportedAppUsage(maxTargetSdk = 34, trackingBug = 170729553, - publicAlternatives = "{@code android.net.TetheringManager#stopTethering(int)}") - void stopTethering(); - - /** - * Returns true if tethering services are started - */ - @UnsupportedAppUsage(maxTargetSdk = 34, trackingBug = 170729553, - publicAlternatives = "Generally track your own tethering requests. " - + "See also {@code android.net.INetd#tetherIsEnabled()}") - boolean isTetheringStarted(); - - /** - * Tethers the specified interface - */ - @UnsupportedAppUsage(maxTargetSdk = 34, trackingBug = 170729553, - publicAlternatives = "Avoid using this directly. Instead, enable tethering with " - + "{@code android.net.TetheringManager#startTethering}. See also " - + "{@code com.android.net.module.util.NetdUtils#tetherInterface}.") - void tetherInterface(String iface); - - /** - * Untethers the specified interface - */ - @UnsupportedAppUsage(maxTargetSdk = 34, trackingBug = 170729553, - publicAlternatives = "Avoid using this directly. Instead, disable " - + "tethering with {@code android.net.TetheringManager#stopTethering(int)}. " - + "See also {@code NetdUtils#untetherInterface}.") - void untetherInterface(String iface); - - /** - * Returns a list of currently tethered interfaces - */ - @UnsupportedAppUsage(maxTargetSdk = 34, trackingBug = 170729553, - publicAlternatives = "{@code android.net.TetheringManager#getTetheredIfaces()}") - String[] listTetheredInterfaces(); - - /** - * Enables Network Address Translation between two interfaces. - * The address and netmask of the external interface is used for - * the NAT'ed network. - */ - @UnsupportedAppUsage(maxTargetSdk = 34, trackingBug = 170729553, - publicAlternatives = "Avoid using this directly. Instead, enable tethering with " - + "{@code android.net.TetheringManager#startTethering}.") - void enableNat(String internalInterface, String externalInterface); - - /** - * Disables Network Address Translation between two interfaces. - */ - @UnsupportedAppUsage(maxTargetSdk = 34, trackingBug = 170729553, - publicAlternatives = "Avoid using this directly. Instead, disable tethering with " - + "{@code android.net.TetheringManager#stopTethering(int)}.") - void disableNat(String internalInterface, String externalInterface); - - /** ** DATA USAGE RELATED **/ diff --git a/core/java/android/os/ServiceManager.java b/core/java/android/os/ServiceManager.java index 0be2d3e30c33..e95c6a44c281 100644 --- a/core/java/android/os/ServiceManager.java +++ b/core/java/android/os/ServiceManager.java @@ -277,7 +277,7 @@ public final class ServiceManager { if (service != null) { return service; } else { - return Binder.allowBlocking(getIServiceManager().checkService(name)); + return Binder.allowBlocking(getIServiceManager().checkService(name).getBinder()); } } catch (RemoteException e) { Log.e(TAG, "error in checkService", e); @@ -425,7 +425,7 @@ public final class ServiceManager { private static IBinder rawGetService(String name) throws RemoteException { final long start = sStatLogger.getTime(); - final IBinder binder = getIServiceManager().getService(name); + final IBinder binder = getIServiceManager().getService(name).getBinder(); final int time = (int) sStatLogger.logDurationStat(Stats.GET_SERVICE, start); diff --git a/core/java/android/os/ServiceManagerNative.java b/core/java/android/os/ServiceManagerNative.java index 7b91dd5822e7..6c9a5c7f9fff 100644 --- a/core/java/android/os/ServiceManagerNative.java +++ b/core/java/android/os/ServiceManagerNative.java @@ -58,12 +58,12 @@ class ServiceManagerProxy implements IServiceManager { } @UnsupportedAppUsage - public IBinder getService(String name) throws RemoteException { + public Service getService(String name) throws RemoteException { // Same as checkService (old versions of servicemanager had both methods). - return mServiceManager.checkService(name); + return checkService(name); } - public IBinder checkService(String name) throws RemoteException { + public Service checkService(String name) throws RemoteException { return mServiceManager.checkService(name); } diff --git a/core/tests/coretests/src/android/animation/OWNERS b/core/tests/coretests/src/android/animation/OWNERS new file mode 100644 index 000000000000..1eefb3a3dc65 --- /dev/null +++ b/core/tests/coretests/src/android/animation/OWNERS @@ -0,0 +1 @@ +include /core/java/android/animation/OWNERS diff --git a/errorprone/java/com/google/errorprone/bugpatterns/android/RequiresPermissionChecker.java b/errorprone/java/com/google/errorprone/bugpatterns/android/RequiresPermissionChecker.java index 7c7cb18afc4d..9887c272e7f8 100644 --- a/errorprone/java/com/google/errorprone/bugpatterns/android/RequiresPermissionChecker.java +++ b/errorprone/java/com/google/errorprone/bugpatterns/android/RequiresPermissionChecker.java @@ -55,9 +55,9 @@ import com.sun.source.util.TreeScanner; import com.sun.tools.javac.code.Symbol; import com.sun.tools.javac.code.Symbol.ClassSymbol; import com.sun.tools.javac.code.Symbol.MethodSymbol; -import com.sun.tools.javac.code.Symbol.VarSymbol; import com.sun.tools.javac.code.Type; import com.sun.tools.javac.code.Type.ClassType; +import com.sun.tools.javac.tree.JCTree.JCNewClass; import java.util.ArrayList; import java.util.Arrays; @@ -67,7 +67,6 @@ import java.util.List; import java.util.Optional; import java.util.Set; import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Predicate; import java.util.regex.Pattern; import javax.lang.model.element.Name; @@ -125,6 +124,12 @@ public final class RequiresPermissionChecker extends BugChecker instanceMethod() .onDescendantOf("android.content.Context") .withNameMatching(Pattern.compile("^send(Ordered|Sticky)?Broadcast.*$"))); + private static final Matcher<ExpressionTree> SEND_BROADCAST_AS_USER = + methodInvocation( + instanceMethod() + .onDescendantOf("android.content.Context") + .withNameMatching( + Pattern.compile("^send(Ordered|Sticky)?Broadcast.*AsUser.*$"))); private static final Matcher<ExpressionTree> SEND_PENDING_INTENT = methodInvocation( instanceMethod() .onDescendantOf("android.app.PendingIntent") @@ -306,18 +311,6 @@ public final class RequiresPermissionChecker extends BugChecker } } - private static ExpressionTree findArgumentByParameterName(MethodInvocationTree tree, - Predicate<String> paramName) { - final MethodSymbol sym = ASTHelpers.getSymbol(tree); - final List<VarSymbol> params = sym.getParameters(); - for (int i = 0; i < params.size(); i++) { - if (paramName.test(params.get(i).name.toString())) { - return tree.getArguments().get(i); - } - } - return null; - } - private static Name resolveName(ExpressionTree tree) { if (tree instanceof IdentifierTree) { return ((IdentifierTree) tree).getName(); @@ -345,76 +338,85 @@ public final class RequiresPermissionChecker extends BugChecker private static ParsedRequiresPermission parseBroadcastSourceRequiresPermission( MethodInvocationTree methodTree, VisitorState state) { - final ExpressionTree arg = findArgumentByParameterName(methodTree, - (name) -> name.toLowerCase().contains("intent")); - if (arg instanceof IdentifierTree) { - final Name argName = ((IdentifierTree) arg).getName(); - final MethodTree method = state.findEnclosing(MethodTree.class); - final AtomicReference<ParsedRequiresPermission> res = new AtomicReference<>(); - method.accept(new TreeScanner<Void, Void>() { - private ParsedRequiresPermission last; - - @Override - public Void visitMethodInvocation(MethodInvocationTree tree, Void param) { - if (Objects.equal(methodTree, tree)) { - res.set(last); - } else { - final Name name = resolveName(tree.getMethodSelect()); - if (Objects.equal(argName, name) - && INTENT_SET_ACTION.matches(tree, state)) { - last = parseIntentAction(tree); + if (methodTree.getArguments().size() < 1) { + return null; + } + final ExpressionTree arg = methodTree.getArguments().get(0); + if (!(arg instanceof IdentifierTree)) { + return null; + } + final Name argName = ((IdentifierTree) arg).getName(); + final MethodTree method = state.findEnclosing(MethodTree.class); + final AtomicReference<ParsedRequiresPermission> res = new AtomicReference<>(); + method.accept(new TreeScanner<Void, Void>() { + private ParsedRequiresPermission mLast; + + @Override + public Void visitMethodInvocation(MethodInvocationTree tree, Void param) { + if (Objects.equal(methodTree, tree)) { + res.set(mLast); + } else { + final Name name = resolveName(tree.getMethodSelect()); + if (Objects.equal(argName, name) && INTENT_SET_ACTION.matches(tree, state)) { + mLast = parseIntentAction(tree); + } else if (name == null && tree.getMethodSelect() instanceof MemberSelectTree) { + ExpressionTree innerTree = + ((MemberSelectTree) tree.getMethodSelect()).getExpression(); + if (innerTree instanceof JCNewClass) { + mLast = parseIntentAction((NewClassTree) innerTree); } } - return super.visitMethodInvocation(tree, param); } + return super.visitMethodInvocation(tree, param); + } - @Override - public Void visitAssignment(AssignmentTree tree, Void param) { - final Name name = resolveName(tree.getVariable()); - final Tree init = tree.getExpression(); - if (Objects.equal(argName, name) - && init instanceof NewClassTree) { - last = parseIntentAction((NewClassTree) init); - } - return super.visitAssignment(tree, param); + @Override + public Void visitAssignment(AssignmentTree tree, Void param) { + final Name name = resolveName(tree.getVariable()); + final Tree init = tree.getExpression(); + if (Objects.equal(argName, name) && init instanceof NewClassTree) { + mLast = parseIntentAction((NewClassTree) init); } + return super.visitAssignment(tree, param); + } - @Override - public Void visitVariable(VariableTree tree, Void param) { - final Name name = tree.getName(); - final ExpressionTree init = tree.getInitializer(); - if (Objects.equal(argName, name) - && init instanceof NewClassTree) { - last = parseIntentAction((NewClassTree) init); - } - return super.visitVariable(tree, param); + @Override + public Void visitVariable(VariableTree tree, Void param) { + final Name name = tree.getName(); + final ExpressionTree init = tree.getInitializer(); + if (Objects.equal(argName, name) && init instanceof NewClassTree) { + mLast = parseIntentAction((NewClassTree) init); } - }, null); - return res.get(); - } - return null; + return super.visitVariable(tree, param); + } + }, null); + return res.get(); } private static ParsedRequiresPermission parseBroadcastTargetRequiresPermission( MethodInvocationTree tree, VisitorState state) { - final ExpressionTree arg = findArgumentByParameterName(tree, - (name) -> name.toLowerCase().contains("permission")); final ParsedRequiresPermission res = new ParsedRequiresPermission(); - if (arg != null) { - arg.accept(new TreeScanner<Void, Void>() { - @Override - public Void visitIdentifier(IdentifierTree tree, Void param) { - res.addConstValue(tree); - return super.visitIdentifier(tree, param); - } - - @Override - public Void visitMemberSelect(MemberSelectTree tree, Void param) { - res.addConstValue(tree); - return super.visitMemberSelect(tree, param); - } - }, null); + int permission_position = 1; + if (SEND_BROADCAST_AS_USER.matches(tree, state)) { + permission_position = 2; } + if (tree.getArguments().size() < permission_position + 1) { + return res; + } + final ExpressionTree arg = tree.getArguments().get(permission_position); + arg.accept(new TreeScanner<Void, Void>() { + @Override + public Void visitIdentifier(IdentifierTree tree, Void param) { + res.addConstValue(tree); + return super.visitIdentifier(tree, param); + } + + @Override + public Void visitMemberSelect(MemberSelectTree tree, Void param) { + res.addConstValue(tree); + return super.visitMemberSelect(tree, param); + } + }, null); return res; } diff --git a/errorprone/tests/java/com/google/errorprone/bugpatterns/android/RequiresPermissionCheckerTest.java b/errorprone/tests/java/com/google/errorprone/bugpatterns/android/RequiresPermissionCheckerTest.java index e53372d97f3d..05fde7c4fe57 100644 --- a/errorprone/tests/java/com/google/errorprone/bugpatterns/android/RequiresPermissionCheckerTest.java +++ b/errorprone/tests/java/com/google/errorprone/bugpatterns/android/RequiresPermissionCheckerTest.java @@ -412,6 +412,19 @@ public class RequiresPermissionCheckerTest { " context.sendBroadcast(intent);", " }", " }", + " public void exampleWithChainedMethod(Context context) {", + " Intent intent = new Intent(FooManager.ACTION_RED)", + " .putExtra(\"foo\", 42);", + " context.sendBroadcast(intent, FooManager.PERMISSION_RED);", + " context.sendBroadcastWithMultiplePermissions(intent,", + " new String[] { FooManager.PERMISSION_RED });", + " }", + " public void exampleWithAsUser(Context context) {", + " Intent intent = new Intent(FooManager.ACTION_RED);", + " context.sendBroadcastAsUser(intent, 42, FooManager.PERMISSION_RED);", + " context.sendBroadcastAsUserMultiplePermissions(intent, 42,", + " new String[] { FooManager.PERMISSION_RED });", + " }", "}") .doTest(); } diff --git a/errorprone/tests/res/android/content/Context.java b/errorprone/tests/res/android/content/Context.java index efc4fb122435..9d622ffaf120 100644 --- a/errorprone/tests/res/android/content/Context.java +++ b/errorprone/tests/res/android/content/Context.java @@ -36,4 +36,15 @@ public class Context { public void sendBroadcastWithMultiplePermissions(Intent intent, String[] receiverPermissions) { throw new UnsupportedOperationException(); } + + /* Fake user type for test purposes */ + public void sendBroadcastAsUser(Intent intent, int user, String receiverPermission) { + throw new UnsupportedOperationException(); + } + + /* Fake user type for test purposes */ + public void sendBroadcastAsUserMultiplePermissions( + Intent intent, int user, String[] receiverPermissions) { + throw new UnsupportedOperationException(); + } } diff --git a/errorprone/tests/res/android/content/Intent.java b/errorprone/tests/res/android/content/Intent.java index 288396e60577..7ccea784754a 100644 --- a/errorprone/tests/res/android/content/Intent.java +++ b/errorprone/tests/res/android/content/Intent.java @@ -24,4 +24,8 @@ public class Intent { public Intent setAction(String action) { throw new UnsupportedOperationException(); } + + public Intent putExtra(String extra, int value) { + throw new UnsupportedOperationException(); + } } diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/GridDragDropState.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/GridDragDropState.kt index beb8ddef949d..24cbd1036770 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/GridDragDropState.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/GridDragDropState.kt @@ -264,7 +264,7 @@ fun LazyGridItemScope.DraggableItem( alpha = itemAlpha } } else { - Modifier.animateItemPlacement() + Modifier.animateItem() } Box(modifier) { diff --git a/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java b/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java index 17f2fcc5b9d8..bb35b378866b 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java @@ -340,6 +340,11 @@ class LockSettingsShellCommand extends ShellCommand { getOutPrintWriter().println("Profile uses unified challenge"); return false; } + if (mOld.isEmpty()) { + getOutPrintWriter().println( + "User has a lock credential, but old credential was not provided"); + return false; + } try { final boolean result = mLockPatternUtils.checkCredential(getOldCredential(), diff --git a/services/core/java/com/android/server/net/NetworkManagementService.java b/services/core/java/com/android/server/net/NetworkManagementService.java index 5ea3e70f7957..74f0d9cf3e39 100644 --- a/services/core/java/com/android/server/net/NetworkManagementService.java +++ b/services/core/java/com/android/server/net/NetworkManagementService.java @@ -81,8 +81,6 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.app.IBatteryStats; import com.android.internal.util.DumpUtils; import com.android.internal.util.HexDump; -import com.android.modules.utils.build.SdkLevel; -import com.android.net.module.util.NetdUtils; import com.android.net.module.util.PermissionUtils; import com.android.server.FgThread; import com.android.server.LocalServices; @@ -833,144 +831,6 @@ public class NetworkManagementService extends INetworkManagementService.Stub { } @Override - public boolean getIpForwardingEnabled() throws IllegalStateException{ - PermissionUtils.enforceNetworkStackPermission(mContext); - if (SdkLevel.isAtLeastV()) { - throw new UnsupportedOperationException( - "NMS#getIpForwardingEnabled not supported in V+"); - } - try { - return mNetdService.ipfwdEnabled(); - } catch (RemoteException | ServiceSpecificException e) { - throw new IllegalStateException(e); - } - } - - @Override - public void setIpForwardingEnabled(boolean enable) { - PermissionUtils.enforceNetworkStackPermission(mContext); - if (SdkLevel.isAtLeastV()) { - throw new UnsupportedOperationException( - "NMS#setIpForwardingEnabled not supported in V+"); - } try { - if (enable) { - mNetdService.ipfwdEnableForwarding("tethering"); - } else { - mNetdService.ipfwdDisableForwarding("tethering"); - } - } catch (RemoteException | ServiceSpecificException e) { - throw new IllegalStateException(e); - } - } - - @Override - public void startTethering(String[] dhcpRange) { - PermissionUtils.enforceNetworkStackPermission(mContext); - if (SdkLevel.isAtLeastV()) { - throw new UnsupportedOperationException("NMS#startTethering not supported in V+"); - } - try { - NetdUtils.tetherStart(mNetdService, true /* usingLegacyDnsProxy */, dhcpRange); - } catch (RemoteException | ServiceSpecificException e) { - throw new IllegalStateException(e); - } - } - - @Override - public void stopTethering() { - PermissionUtils.enforceNetworkStackPermission(mContext); - if (SdkLevel.isAtLeastV()) { - throw new UnsupportedOperationException("NMS#stopTethering not supported in V+"); - } - try { - mNetdService.tetherStop(); - } catch (RemoteException | ServiceSpecificException e) { - throw new IllegalStateException(e); - } - } - - @Override - public boolean isTetheringStarted() { - PermissionUtils.enforceNetworkStackPermission(mContext); - if (SdkLevel.isAtLeastV()) { - throw new UnsupportedOperationException("NMS#isTetheringStarted not supported in V+"); - } - try { - return mNetdService.tetherIsEnabled(); - } catch (RemoteException | ServiceSpecificException e) { - throw new IllegalStateException(e); - } - } - - @Override - public void tetherInterface(String iface) { - PermissionUtils.enforceNetworkStackPermission(mContext); - if (SdkLevel.isAtLeastV()) { - throw new UnsupportedOperationException("NMS#tetherInterface not supported in V+"); - } - try { - final LinkAddress addr = getInterfaceConfig(iface).getLinkAddress(); - final IpPrefix dest = new IpPrefix(addr.getAddress(), addr.getPrefixLength()); - NetdUtils.tetherInterface(mNetdService, iface, dest); - } catch (RemoteException | ServiceSpecificException e) { - throw new IllegalStateException(e); - } - } - - @Override - public void untetherInterface(String iface) { - PermissionUtils.enforceNetworkStackPermission(mContext); - if (SdkLevel.isAtLeastV()) { - throw new UnsupportedOperationException("NMS#untetherInterface not supported in V+"); - } - try { - NetdUtils.untetherInterface(mNetdService, iface); - } catch (RemoteException | ServiceSpecificException e) { - throw new IllegalStateException(e); - } - } - - @Override - public String[] listTetheredInterfaces() { - PermissionUtils.enforceNetworkStackPermission(mContext); - if (SdkLevel.isAtLeastV()) { - throw new UnsupportedOperationException( - "NMS#listTetheredInterfaces not supported in V+"); - } - try { - return mNetdService.tetherInterfaceList(); - } catch (RemoteException | ServiceSpecificException e) { - throw new IllegalStateException(e); - } - } - - @Override - public void enableNat(String internalInterface, String externalInterface) { - PermissionUtils.enforceNetworkStackPermission(mContext); - if (SdkLevel.isAtLeastV()) { - throw new UnsupportedOperationException("NMS#enableNat not supported in V+"); - } - try { - mNetdService.tetherAddForward(internalInterface, externalInterface); - } catch (RemoteException | ServiceSpecificException e) { - throw new IllegalStateException(e); - } - } - - @Override - public void disableNat(String internalInterface, String externalInterface) { - PermissionUtils.enforceNetworkStackPermission(mContext); - if (SdkLevel.isAtLeastV()) { - throw new UnsupportedOperationException("NMS#disableNat not supported in V+"); - } - try { - mNetdService.tetherRemoveForward(internalInterface, externalInterface); - } catch (RemoteException | ServiceSpecificException e) { - throw new IllegalStateException(e); - } - } - - @Override public void setInterfaceQuota(String iface, long quotaBytes) { PermissionUtils.enforceNetworkStackPermission(mContext); @@ -1126,30 +986,19 @@ public class NetworkManagementService extends INetworkManagementService.Stub { } Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "setDataSaverModeEnabled"); try { - if (SdkLevel.isAtLeastV()) { - // setDataSaverEnabled throws if it fails to set data saver. - mContext.getSystemService(ConnectivityManager.class) - .setDataSaverEnabled(enable); - mDataSaverMode = enable; - if (mUseMeteredFirewallChains) { - // Copy mDataSaverMode state to FIREWALL_CHAIN_METERED_ALLOW - // until ConnectivityService allows manipulation of the data saver mode via - // FIREWALL_CHAIN_METERED_ALLOW. - synchronized (mRulesLock) { - mFirewallChainStates.put(FIREWALL_CHAIN_METERED_ALLOW, enable); - } - } - return true; - } else { - final boolean changed = mNetdService.bandwidthEnableDataSaver(enable); - if (changed) { - mDataSaverMode = enable; - } else { - Log.e(TAG, "setDataSaverMode(" + enable + "): failed to set iptables"); + // setDataSaverEnabled throws if it fails to set data saver. + mContext.getSystemService(ConnectivityManager.class).setDataSaverEnabled(enable); + mDataSaverMode = enable; + if (mUseMeteredFirewallChains) { + // Copy mDataSaverMode state to FIREWALL_CHAIN_METERED_ALLOW + // until ConnectivityService allows manipulation of the data saver mode via + // FIREWALL_CHAIN_METERED_ALLOW. + synchronized (mRulesLock) { + mFirewallChainStates.put(FIREWALL_CHAIN_METERED_ALLOW, enable); } - return changed; } - } catch (RemoteException | IllegalStateException e) { + return true; + } catch (IllegalStateException e) { Log.e(TAG, "setDataSaverMode(" + enable + "): failed with exception", e); return false; } finally { diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index 079f3381162b..365c9b51a395 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -4118,7 +4118,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { fout.increaseIndent(); for (int i = 0; i < mSubscriptionPlans.size(); i++) { final int subId = mSubscriptionPlans.keyAt(i); - fout.println("Subscriber ID " + subId + ":"); + fout.println("Subscription ID " + subId + ":"); fout.increaseIndent(); final SubscriptionPlan[] plans = mSubscriptionPlans.valueAt(i); if (!ArrayUtils.isEmpty(plans)) { diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 1c22087965b8..6e65a7453cf5 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -1115,9 +1115,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } @Override - public void onUserUnlocked(@NonNull TargetUser user) { - if (user.isPreCreated()) return; - mService.handleOnUserUnlocked(user.getUserIdentifier()); + public void onUserSwitching(@NonNull TargetUser from, @NonNull TargetUser to) { + if (to.isPreCreated()) return; + mService.handleOnUserSwitching(from.getUserIdentifier(), to.getUserIdentifier()); } } @@ -3680,8 +3680,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { mDevicePolicyEngine.handleUnlockUser(userId); } - void handleOnUserUnlocked(int userId) { - showNewUserDisclaimerIfNecessary(userId); + void handleOnUserSwitching(int fromUserId, int toUserId) { + showNewUserDisclaimerIfNecessary(toUserId); } void handleStopUser(int userId) { diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/EnterpriseSpecificIdCalculator.java b/services/devicepolicy/java/com/android/server/devicepolicy/EnterpriseSpecificIdCalculator.java index 1000bfa5f6c9..dbd60c5af274 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/EnterpriseSpecificIdCalculator.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/EnterpriseSpecificIdCalculator.java @@ -17,6 +17,7 @@ package com.android.server.devicepolicy; import android.content.Context; +import android.content.pm.PackageManager; import android.content.pm.VerifierDeviceIdentity; import android.net.wifi.WifiManager; import android.os.Build; @@ -66,13 +67,14 @@ class EnterpriseSpecificIdCalculator { mMeid = meid; mSerialNumber = Build.getSerial(); WifiManager wifiManager = context.getSystemService(WifiManager.class); - Preconditions.checkState(wifiManager != null, "Unable to access WiFi service"); - final String[] macAddresses = wifiManager.getFactoryMacAddresses(); - if (macAddresses == null || macAddresses.length == 0) { - mMacAddress = ""; - } else { - mMacAddress = macAddresses[0]; + String macAddress = ""; + if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI)) { + final String[] macAddresses = wifiManager.getFactoryMacAddresses(); + if (macAddresses != null && macAddresses.length > 0) { + macAddress = macAddresses[0]; + } } + mMacAddress = macAddress; } private static String getPaddedTruncatedString(String input, int maxLength) { diff --git a/telephony/OWNERS b/telephony/OWNERS index 7607c64150d8..92af034217a9 100644 --- a/telephony/OWNERS +++ b/telephony/OWNERS @@ -15,4 +15,4 @@ per-file CarrierConfigManager.java=set noparent per-file CarrierConfigManager.java=amruthr@google.com,tgunn@google.com,rgreenwalt@google.com,satk@google.com #Domain Selection is jointly owned, add additional owners for domain selection specific files -per-file TransportSelectorCallback.java,WwanSelectorCallback.java,DomainSelectionService.java,DomainSelectionService.aidl,DomainSelector.java,EmergencyRegResult.java,EmergencyRegResult.aidl,IDomainSelectionServiceController.aidl,IDomainSelector.aidl,ITransportSelectorCallback.aidl,ITransportSelectorResultCallback.aidl,IWwanSelectorCallback.aidl,IWwanSelectorResultCallback.aidl=hwangoo@google.com,forestchoi@google.com,avinashmp@google.com,mkoon@google.com,seheele@google.com,radhikaagrawal@google.com,jdyou@google.com +per-file TransportSelectorCallback.java,WwanSelectorCallback.java,DomainSelectionService.java,DomainSelectionService.aidl,DomainSelector.java,EmergencyRegResult.java,EmergencyRegResult.aidl,IDomainSelectionServiceController.aidl,IDomainSelector.aidl,ITransportSelectorCallback.aidl,ITransportSelectorResultCallback.aidl,IWwanSelectorCallback.aidl,IWwanSelectorResultCallback.aidl=hwangoo@google.com,jaesikkong@google.com,avinashmp@google.com,mkoon@google.com,seheele@google.com,radhikaagrawal@google.com,jdyou@google.com diff --git a/tools/aapt2/cmd/Compile.cpp b/tools/aapt2/cmd/Compile.cpp index 031dd5bb139c..9b8c3b3d549c 100644 --- a/tools/aapt2/cmd/Compile.cpp +++ b/tools/aapt2/cmd/Compile.cpp @@ -836,6 +836,28 @@ int CompileCommand::Action(const std::vector<std::string>& args) { return 1; } + // Parse the feature flag values. An argument that starts with '@' points to a file to read flag + // values from. + std::vector<std::string> all_feature_flags_args; + for (const std::string& arg : feature_flags_args_) { + if (util::StartsWith(arg, "@")) { + const std::string path = arg.substr(1, arg.size() - 1); + std::string error; + if (!file::AppendArgsFromFile(path, &all_feature_flags_args, &error)) { + context.GetDiagnostics()->Error(android::DiagMessage(path) << error); + return 1; + } + } else { + all_feature_flags_args.push_back(arg); + } + } + + for (const std::string& arg : all_feature_flags_args) { + if (!ParseFeatureFlagsParameter(arg, context.GetDiagnostics(), &options_.feature_flag_values)) { + return 1; + } + } + return Compile(&context, file_collection.get(), archive_writer.get(), options_); } diff --git a/tools/aapt2/cmd/Compile.h b/tools/aapt2/cmd/Compile.h index 61c5b60adb76..70c8791524c8 100644 --- a/tools/aapt2/cmd/Compile.h +++ b/tools/aapt2/cmd/Compile.h @@ -24,6 +24,7 @@ #include "Command.h" #include "ResourceTable.h" #include "androidfw/IDiagnostics.h" +#include "cmd/Util.h" #include "format/Archive.h" #include "process/IResourceTableConsumer.h" @@ -45,6 +46,7 @@ struct CompileOptions { bool preserve_visibility_of_styleables = false; bool verbose = false; std::optional<std::string> product_; + FeatureFlagValues feature_flag_values; }; /** Parses flags and compiles resources to be used in linking. */ @@ -92,6 +94,12 @@ class CompileCommand : public Command { "Leave only resources specific to the given product. All " "other resources (including defaults) are removed.", &options_.product_); + AddOptionalFlagList("--feature-flags", + "Specify the values of feature flags. The pairs in the argument\n" + "are separated by ',' the name is separated from the value by '='.\n" + "The name can have a suffix of ':ro' to indicate it is read only." + "Example: \"flag1=true,flag2:ro=false,flag3=\" (flag3 has no given value).", + &feature_flags_args_); } int Action(const std::vector<std::string>& args) override; @@ -101,6 +109,7 @@ class CompileCommand : public Command { CompileOptions options_; std::optional<std::string> visibility_; std::optional<std::string> trace_folder_; + std::vector<std::string> feature_flags_args_; }; int Compile(IAaptContext* context, io::IFileCollection* inputs, IArchiveWriter* output_writer, diff --git a/tools/aapt2/cmd/Link.h b/tools/aapt2/cmd/Link.h index 8fe414f4f660..2f17853718ec 100644 --- a/tools/aapt2/cmd/Link.h +++ b/tools/aapt2/cmd/Link.h @@ -332,8 +332,9 @@ class LinkCommand : public Command { AddOptionalSwitch("-v", "Enables verbose logging.", &verbose_); AddOptionalFlagList("--feature-flags", "Specify the values of feature flags. The pairs in the argument\n" - "are separated by ',' and the name is separated from the value by '='.\n" - "Example: \"flag1=true,flag2=false,flag3=\" (flag3 has no given value).", + "are separated by ',' the name is separated from the value by '='.\n" + "The name can have a suffix of ':ro' to indicate it is read only." + "Example: \"flag1=true,flag2:ro=false,flag3=\" (flag3 has no given value).", &feature_flags_args_); AddOptionalSwitch("--non-updatable-system", "Mark the app as a non-updatable system app. This inserts\n" diff --git a/tools/aapt2/cmd/Util.cpp b/tools/aapt2/cmd/Util.cpp index 678d84628015..7739171b347f 100644 --- a/tools/aapt2/cmd/Util.cpp +++ b/tools/aapt2/cmd/Util.cpp @@ -128,7 +128,7 @@ bool ParseFeatureFlagsParameter(StringPiece arg, android::IDiagnostics* diag, if (parts.size() > 2) { diag->Error(android::DiagMessage() << "Invalid feature flag and optional value '" << flag_and_value - << "'. Must be in the format 'flag_name[=true|false]"); + << "'. Must be in the format 'flag_name[:ro][=true|false]"); return false; } @@ -138,6 +138,28 @@ bool ParseFeatureFlagsParameter(StringPiece arg, android::IDiagnostics* diag, return false; } + std::vector<std::string> name_parts = util::Split(flag_name, ':'); + if (name_parts.size() > 2) { + diag->Error(android::DiagMessage() + << "Invalid feature flag and optional value '" << flag_and_value + << "'. Must be in the format 'flag_name[:READ_ONLY|READ_WRITE][=true|false]"); + return false; + } + flag_name = name_parts[0]; + bool read_only = false; + if (name_parts.size() == 2) { + if (name_parts[1] == "ro" || name_parts[1] == "READ_ONLY") { + read_only = true; + } else if (name_parts[1] == "READ_WRITE") { + read_only = false; + } else { + diag->Error(android::DiagMessage() + << "Invalid feature flag and optional value '" << flag_and_value + << "'. Must be in the format 'flag_name[:READ_ONLY|READ_WRITE][=true|false]"); + return false; + } + } + std::optional<bool> flag_value = {}; if (parts.size() == 2) { StringPiece str_flag_value = util::TrimWhitespace(parts[1]); @@ -151,13 +173,13 @@ bool ParseFeatureFlagsParameter(StringPiece arg, android::IDiagnostics* diag, } } - if (auto [it, inserted] = - out_feature_flag_values->try_emplace(std::string(flag_name), flag_value); + auto ffp = FeatureFlagProperties{read_only, flag_value}; + if (auto [it, inserted] = out_feature_flag_values->try_emplace(std::string(flag_name), ffp); !inserted) { // We are allowing the same flag to appear multiple times, last value wins. diag->Note(android::DiagMessage() << "Value for feature flag '" << flag_name << "' was given more than once"); - it->second = flag_value; + it->second = ffp; } } return true; diff --git a/tools/aapt2/cmd/Util.h b/tools/aapt2/cmd/Util.h index 9ece5dd4d720..6b8813b34082 100644 --- a/tools/aapt2/cmd/Util.h +++ b/tools/aapt2/cmd/Util.h @@ -37,7 +37,17 @@ namespace aapt { -using FeatureFlagValues = std::map<std::string, std::optional<bool>, std::less<>>; +struct FeatureFlagProperties { + bool read_only; + std::optional<bool> enabled; + + FeatureFlagProperties(bool ro, std::optional<bool> e) : read_only(ro), enabled(e) { + } + + bool operator==(const FeatureFlagProperties&) const = default; +}; + +using FeatureFlagValues = std::map<std::string, FeatureFlagProperties, std::less<>>; // Parses a configuration density (ex. hdpi, xxhdpi, 234dpi, anydpi, etc). // Returns Nothing and logs a human friendly error message if the string was not legal. diff --git a/tools/aapt2/cmd/Util_test.cpp b/tools/aapt2/cmd/Util_test.cpp index 723d87ed0af3..78183409ad8f 100644 --- a/tools/aapt2/cmd/Util_test.cpp +++ b/tools/aapt2/cmd/Util_test.cpp @@ -383,21 +383,25 @@ TEST(UtilTest, ParseFeatureFlagsParameter_InvalidValue) { TEST(UtilTest, ParseFeatureFlagsParameter_DuplicateFlag) { auto diagnostics = test::ContextBuilder().Build()->GetDiagnostics(); FeatureFlagValues feature_flag_values; - ASSERT_TRUE( - ParseFeatureFlagsParameter("foo=true,bar=true,foo=false", diagnostics, &feature_flag_values)); - EXPECT_THAT(feature_flag_values, UnorderedElementsAre(Pair("foo", std::optional<bool>(false)), - Pair("bar", std::optional<bool>(true)))); + ASSERT_TRUE(ParseFeatureFlagsParameter("foo=true,bar:READ_WRITE=true,foo:ro=false", diagnostics, + &feature_flag_values)); + EXPECT_THAT( + feature_flag_values, + UnorderedElementsAre(Pair("foo", FeatureFlagProperties{true, std::optional<bool>(false)}), + Pair("bar", FeatureFlagProperties{false, std::optional<bool>(true)}))); } TEST(UtilTest, ParseFeatureFlagsParameter_Valid) { auto diagnostics = test::ContextBuilder().Build()->GetDiagnostics(); FeatureFlagValues feature_flag_values; - ASSERT_TRUE(ParseFeatureFlagsParameter("foo= true, bar =FALSE,baz=, quux", diagnostics, - &feature_flag_values)); - EXPECT_THAT(feature_flag_values, - UnorderedElementsAre(Pair("foo", std::optional<bool>(true)), - Pair("bar", std::optional<bool>(false)), - Pair("baz", std::nullopt), Pair("quux", std::nullopt))); + ASSERT_TRUE(ParseFeatureFlagsParameter("foo:READ_ONLY= true, bar:ro =FALSE,baz:READ_WRITE=, quux", + diagnostics, &feature_flag_values)); + EXPECT_THAT( + feature_flag_values, + UnorderedElementsAre(Pair("foo", FeatureFlagProperties{true, std::optional<bool>(true)}), + Pair("bar", FeatureFlagProperties{true, std::optional<bool>(false)}), + Pair("baz", FeatureFlagProperties{false, std::nullopt}), + Pair("quux", FeatureFlagProperties{false, std::nullopt}))); } TEST (UtilTest, AdjustSplitConstraintsForMinSdk) { diff --git a/tools/aapt2/link/FeatureFlagsFilter.cpp b/tools/aapt2/link/FeatureFlagsFilter.cpp index fdf3f74d4e18..9d40db521e13 100644 --- a/tools/aapt2/link/FeatureFlagsFilter.cpp +++ b/tools/aapt2/link/FeatureFlagsFilter.cpp @@ -63,12 +63,11 @@ class FlagsVisitor : public xml::Visitor { flag_name = flag_name.substr(1); } - if (auto it = feature_flag_values_.find(std::string(flag_name)); - it != feature_flag_values_.end()) { - if (it->second.has_value()) { + if (auto it = feature_flag_values_.find(flag_name); it != feature_flag_values_.end()) { + if (it->second.enabled.has_value()) { if (options_.remove_disabled_elements) { // Remove if flag==true && attr=="!flag" (negated) OR flag==false && attr=="flag" - return *it->second == negated; + return *it->second.enabled == negated; } } else if (options_.flags_must_have_value) { diagnostics_->Error(android::DiagMessage(node->line_number) diff --git a/tools/aapt2/link/FeatureFlagsFilter_test.cpp b/tools/aapt2/link/FeatureFlagsFilter_test.cpp index 53086cc30f18..2db2899e716c 100644 --- a/tools/aapt2/link/FeatureFlagsFilter_test.cpp +++ b/tools/aapt2/link/FeatureFlagsFilter_test.cpp @@ -48,7 +48,7 @@ TEST(FeatureFlagsFilterTest, NoFeatureFlagAttributes) { <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android"> <permission android:name="FOO" /> </manifest>)EOF", - {{"flag", false}}); + {{"flag", FeatureFlagProperties{false, false}}}); ASSERT_THAT(doc, NotNull()); auto root = doc->root.get(); ASSERT_THAT(root, NotNull()); @@ -60,7 +60,7 @@ TEST(FeatureFlagsFilterTest, RemoveElementWithDisabledFlag) { <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android"> <permission android:name="FOO" android:featureFlag="flag" /> </manifest>)EOF", - {{"flag", false}}); + {{"flag", FeatureFlagProperties{false, false}}}); ASSERT_THAT(doc, NotNull()); auto root = doc->root.get(); ASSERT_THAT(root, NotNull()); @@ -73,7 +73,7 @@ TEST(FeatureFlagsFilterTest, RemoveElementWithNegatedEnabledFlag) { <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android"> <permission android:name="FOO" android:featureFlag="!flag" /> </manifest>)EOF", - {{"flag", true}}); + {{"flag", FeatureFlagProperties{false, true}}}); ASSERT_THAT(doc, NotNull()); auto root = doc->root.get(); ASSERT_THAT(root, NotNull()); @@ -86,7 +86,7 @@ TEST(FeatureFlagsFilterTest, KeepElementWithEnabledFlag) { <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android"> <permission android:name="FOO" android:featureFlag="flag" /> </manifest>)EOF", - {{"flag", true}}); + {{"flag", FeatureFlagProperties{false, true}}}); ASSERT_THAT(doc, NotNull()); auto root = doc->root.get(); ASSERT_THAT(root, NotNull()); @@ -102,7 +102,7 @@ TEST(FeatureFlagsFilterTest, SideBySideEnabledAndDisabled) { <permission android:name="FOO" android:featureFlag="flag" android:protectionLevel="dangerous" /> </manifest>)EOF", - {{"flag", true}}); + {{"flag", FeatureFlagProperties{false, true}}}); ASSERT_THAT(doc, NotNull()); auto root = doc->root.get(); ASSERT_THAT(root, NotNull()); @@ -123,7 +123,7 @@ TEST(FeatureFlagsFilterTest, RemoveDeeplyNestedElement) { </activity> </application> </manifest>)EOF", - {{"flag", true}}); + {{"flag", FeatureFlagProperties{false, true}}}); ASSERT_THAT(doc, NotNull()); auto root = doc->root.get(); ASSERT_THAT(root, NotNull()); @@ -145,7 +145,7 @@ TEST(FeatureFlagsFilterTest, KeepDeeplyNestedElement) { </activity> </application> </manifest>)EOF", - {{"flag", true}}); + {{"flag", FeatureFlagProperties{false, true}}}); ASSERT_THAT(doc, NotNull()); auto root = doc->root.get(); ASSERT_THAT(root, NotNull()); @@ -162,7 +162,7 @@ TEST(FeatureFlagsFilterTest, FailOnEmptyFeatureFlagAttribute) { <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android"> <permission android:name="FOO" android:featureFlag=" " /> </manifest>)EOF", - {{"flag", false}}); + {{"flag", FeatureFlagProperties{false, false}}}); ASSERT_THAT(doc, IsNull()); } @@ -171,7 +171,7 @@ TEST(FeatureFlagsFilterTest, FailOnFlagWithNoGivenValue) { <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android"> <permission android:name="FOO" android:featureFlag="flag" /> </manifest>)EOF", - {{"flag", std::nullopt}}); + {{"flag", FeatureFlagProperties{false, std::nullopt}}}); ASSERT_THAT(doc, IsNull()); } @@ -180,7 +180,7 @@ TEST(FeatureFlagsFilterTest, FailOnUnrecognizedFlag) { <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android"> <permission android:name="FOO" android:featureFlag="unrecognized" /> </manifest>)EOF", - {{"flag", true}}); + {{"flag", FeatureFlagProperties{false, true}}}); ASSERT_THAT(doc, IsNull()); } @@ -190,7 +190,7 @@ TEST(FeatureFlagsFilterTest, FailOnMultipleValidationErrors) { <permission android:name="FOO" android:featureFlag="bar" /> <permission android:name="FOO" android:featureFlag="unrecognized" /> </manifest>)EOF", - {{"flag", std::nullopt}}); + {{"flag", FeatureFlagProperties{false, std::nullopt}}}); ASSERT_THAT(doc, IsNull()); } @@ -199,7 +199,8 @@ TEST(FeatureFlagsFilterTest, OptionRemoveDisabledElementsIsFalse) { <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android"> <permission android:name="FOO" android:featureFlag="flag" /> </manifest>)EOF", - {{"flag", false}}, {.remove_disabled_elements = false}); + {{"flag", FeatureFlagProperties{false, false}}}, + {.remove_disabled_elements = false}); ASSERT_THAT(doc, NotNull()); auto root = doc->root.get(); ASSERT_THAT(root, NotNull()); @@ -212,7 +213,8 @@ TEST(FeatureFlagsFilterTest, OptionFlagsMustHaveValueIsFalse) { <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android"> <permission android:name="FOO" android:featureFlag="flag" /> </manifest>)EOF", - {{"flag", std::nullopt}}, {.flags_must_have_value = false}); + {{"flag", FeatureFlagProperties{false, std::nullopt}}}, + {.flags_must_have_value = false}); ASSERT_THAT(doc, NotNull()); auto root = doc->root.get(); ASSERT_THAT(root, NotNull()); @@ -225,7 +227,8 @@ TEST(FeatureFlagsFilterTest, OptionFailOnUnrecognizedFlagsIsFalse) { <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android"> <permission android:name="FOO" android:featureFlag="unrecognized" /> </manifest>)EOF", - {{"flag", true}}, {.fail_on_unrecognized_flags = false}); + {{"flag", FeatureFlagProperties{false, true}}}, + {.fail_on_unrecognized_flags = false}); ASSERT_THAT(doc, NotNull()); auto root = doc->root.get(); ASSERT_THAT(root, NotNull()); |