diff options
109 files changed, 2272 insertions, 447 deletions
diff --git a/AconfigFlags.bp b/AconfigFlags.bp index c76be6f43372..858620b41088 100644 --- a/AconfigFlags.bp +++ b/AconfigFlags.bp @@ -12,51 +12,36 @@ // See the License for the specific language governing permissions and // limitations under the License. -aconfig_srcjars = [ - // !!! KEEP THIS LIST ALPHABETICAL !!! - ":aconfig_mediacodec_flags_java_lib{.generated_srcjars}", - ":android.content.pm.flags-aconfig-java{.generated_srcjars}", - ":android.content.res.flags-aconfig-java{.generated_srcjars}", - ":android.crashrecovery.flags-aconfig-java{.generated_srcjars}", - ":android.hardware.biometrics.flags-aconfig-java{.generated_srcjars}", - ":android.media.playback.flags-aconfig-java{.generated_srcjars}", - ":android.net.vcn.flags-aconfig-java{.generated_srcjars}", - ":android.nfc.flags-aconfig-java{.generated_srcjars}", - ":android.os.flags-aconfig-java{.generated_srcjars}", - ":android.security.flags-aconfig-java{.generated_srcjars}", - ":com.android.hardware.camera2-aconfig-java{.generated_srcjars}", - ":com.android.hardware.input-aconfig-java{.generated_srcjars}", - ":com.android.net.flags-aconfig-java{.generated_srcjars}", - ":com.android.net.thread.flags-aconfig-java{.generated_srcjars}", - ":com.android.text.flags-aconfig-java{.generated_srcjars}", - ":com.android.window.flags.window-aconfig-java{.generated_srcjars}", - // !!! KEEP THIS LIST ALPHABETICAL !!! -] - -stubs_defaults { +aconfig_declarations_group { name: "framework-minus-apex-aconfig-declarations", - aconfig_declarations: [ - "android.content.pm.flags-aconfig", - "android.content.res.flags-aconfig", - "android.crashrecovery.flags-aconfig", - "android.hardware.biometrics.flags-aconfig", - "android.media.playback.flags-aconfig", - "android.net.vcn.flags-aconfig", - "android.nfc.flags-aconfig", - "android.os.flags-aconfig", - "android.security.flags-aconfig", - "com.android.hardware.camera2-aconfig", - "com.android.hardware.input.input-aconfig", - "com.android.net.thread.flags-aconfig", - "com.android.window.flags.window-aconfig", - "com.android.text.flags-aconfig", - "com.android.net.flags-aconfig", + java_aconfig_libraries: [ + // !!! KEEP THIS LIST ALPHABETICAL !!! + "aconfig_mediacodec_flags_java_lib", + "android.content.pm.flags-aconfig-java", + "android.content.res.flags-aconfig-java", + "android.crashrecovery.flags-aconfig-java", + "android.hardware.biometrics.flags-aconfig-java", + "android.media.codec-aconfig-java", + "android.media.playback.flags-aconfig-java", + "android.net.platform.flags-aconfig-java", + "android.net.vcn.flags-aconfig-java", + "android.nfc.flags-aconfig-java", + "android.os.flags-aconfig-java", + "android.security.flags-aconfig-java", + "com.android.hardware.camera2-aconfig-java", + "com.android.hardware.input-aconfig-java", + "com.android.net.thread.flags-aconfig-java", + "com.android.text.flags-aconfig-java", + "com.android.window.flags.window-aconfig-java", + // !!! KEEP THIS LIST ALPHABETICAL !!! ], } filegroup { name: "framework-minus-apex-aconfig-srcjars", - srcs: aconfig_srcjars, + srcs: [ + ":framework-minus-apex-aconfig-declarations{.srcjars}", + ], } // Aconfig declarations and libraries for the core framework @@ -65,7 +50,9 @@ java_defaults { // Add java_aconfig_libraries to here to add them to the core framework // Add aconfig-annotations-lib as a dependency for the optimization - srcs: aconfig_srcjars, + srcs: [ + ":framework-minus-apex-aconfig-declarations{.srcjars}", + ], libs: ["aconfig-annotations-lib"], } @@ -246,9 +233,10 @@ java_aconfig_library { // Networking aconfig_declarations { - name: "com.android.net.flags-aconfig", - package: "com.android.net.flags", + name: "android.net.platform.flags-aconfig", + package: "android.net.platform.flags", srcs: ["core/java/android/net/flags.aconfig"], + visibility: [":__subpackages__"], } // Thread network @@ -259,9 +247,10 @@ aconfig_declarations { } java_aconfig_library { - name: "com.android.net.flags-aconfig-java", - aconfig_declarations: "com.android.net.flags-aconfig", + name: "android.net.platform.flags-aconfig-java", + aconfig_declarations: "android.net.platform.flags-aconfig", defaults: ["framework-minus-apex-aconfig-java-defaults"], + visibility: [":__subpackages__"], } java_aconfig_library { diff --git a/Android.bp b/Android.bp index 6f4593b1595d..65ec01592fce 100644 --- a/Android.bp +++ b/Android.bp @@ -479,6 +479,8 @@ java_library { lint: { baseline_filename: "lint-baseline.xml", }, + // For jarjar repackaging + jarjar_prefix: "com.android.internal.hidden_from_bootclasspath", } java_library { diff --git a/api/Android.bp b/api/Android.bp index 1b84ce7ea5fb..14320c96aafc 100644 --- a/api/Android.bp +++ b/api/Android.bp @@ -310,7 +310,7 @@ packages_to_document = [ // classpath (or sources) somehow. stubs_defaults { name: "android-non-updatable-stubs-defaults", - defaults: ["framework-minus-apex-aconfig-declarations"], + aconfig_declarations: ["framework-minus-apex-aconfig-declarations"], srcs: [":android-non-updatable-stub-sources"], sdk_version: "none", system_modules: "none", @@ -374,7 +374,10 @@ stubs_defaults { previous_api: ":android.api.public.latest", merge_annotations_dirs: ["metalava-manual"], defaults_visibility: ["//frameworks/base/api"], - visibility: ["//frameworks/base/api"], + visibility: [ + "//frameworks/base/api", + "//frameworks/base/core/api", + ], } // We resolve dependencies on APIs in modules by depending on a prebuilt of the whole diff --git a/api/StubLibraries.bp b/api/StubLibraries.bp index 852abdfdf602..2edbd9138f6e 100644 --- a/api/StubLibraries.bp +++ b/api/StubLibraries.bp @@ -225,6 +225,7 @@ java_defaults { java_version: "1.8", compile_dex: true, visibility: ["//visibility:public"], + is_stubs_module: true, } java_defaults { @@ -233,6 +234,7 @@ java_defaults { system_modules: "none", java_version: "1.8", compile_dex: true, + is_stubs_module: true, } java_defaults { @@ -716,6 +718,7 @@ java_library { // with its own package-private android.annotation.Nullable. "private-stub-annotations-jar", ], + is_stubs_module: true, } java_genrule { @@ -770,6 +773,7 @@ java_defaults { // annotations found, thus should exist inside android.jar. "private-stub-annotations-jar", ], + is_stubs_module: true, } // Listing of API domains contribution and dependencies per API surfaces diff --git a/api/api.go b/api/api.go index fa2be21db09f..b31a26c90789 100644 --- a/api/api.go +++ b/api/api.go @@ -79,7 +79,45 @@ func registerBuildComponents(ctx android.RegistrationContext) { var PrepareForCombinedApisTest = android.FixtureRegisterWithContext(registerBuildComponents) +func (a *CombinedApis) apiFingerprintStubDeps() []string { + ret := []string{} + ret = append( + ret, + transformArray(a.properties.Bootclasspath, "", ".stubs")..., + ) + ret = append( + ret, + transformArray(a.properties.Bootclasspath, "", ".stubs.system")..., + ) + ret = append( + ret, + transformArray(a.properties.Bootclasspath, "", ".stubs.module_lib")..., + ) + ret = append( + ret, + transformArray(a.properties.System_server_classpath, "", ".stubs.system_server")..., + ) + return ret +} + +func (a *CombinedApis) DepsMutator(ctx android.BottomUpMutatorContext) { + ctx.AddDependency(ctx.Module(), nil, a.apiFingerprintStubDeps()...) +} + func (a *CombinedApis) GenerateAndroidBuildActions(ctx android.ModuleContext) { + ctx.WalkDeps(func(child, parent android.Module) bool { + if _, ok := child.(java.AndroidLibraryDependency); ok && child.Name() != "framework-res" { + // Stubs of BCP and SSCP libraries should not have any dependencies on apps + // This check ensures that we do not run into circular dependencies when UNBUNDLED_BUILD_TARGET_SDK_WITH_API_FINGERPRINT=true + ctx.ModuleErrorf( + "Module %s is not a valid dependency of the stub library %s\n."+ + "If this dependency has been added via `libs` of java_sdk_library, please move it to `impl_only_libs`\n", + child.Name(), parent.Name()) + return false // error detected + } + return true + }) + } type genruleProps struct { @@ -93,11 +131,12 @@ type genruleProps struct { } type libraryProps struct { - Name *string - Sdk_version *string - Static_libs []string - Visibility []string - Defaults []string + Name *string + Sdk_version *string + Static_libs []string + Visibility []string + Defaults []string + Is_stubs_module *bool } type fgProps struct { @@ -130,7 +169,7 @@ type MergedTxtDefinition struct { Scope string } -func createMergedTxt(ctx android.LoadHookContext, txt MergedTxtDefinition) { +func createMergedTxt(ctx android.LoadHookContext, txt MergedTxtDefinition, stubsTypeSuffix string, doDist bool) { metalavaCmd := "$(location metalava)" // Silence reflection warnings. See b/168689341 metalavaCmd += " -J--add-opens=java.base/java.util=ALL-UNNAMED " @@ -140,7 +179,7 @@ func createMergedTxt(ctx android.LoadHookContext, txt MergedTxtDefinition) { if txt.Scope != "public" { filename = txt.Scope + "-" + filename } - moduleName := ctx.ModuleName() + "-" + filename + moduleName := ctx.ModuleName() + stubsTypeSuffix + filename props := genruleProps{} props.Name = proptools.StringPtr(moduleName) @@ -148,17 +187,19 @@ func createMergedTxt(ctx android.LoadHookContext, txt MergedTxtDefinition) { props.Out = []string{filename} props.Cmd = proptools.StringPtr(metalavaCmd + "$(in) --out $(out)") props.Srcs = append([]string{txt.BaseTxt}, createSrcs(txt.Modules, txt.ModuleTag)...) - props.Dists = []android.Dist{ - { - Targets: []string{"droidcore"}, - Dir: proptools.StringPtr("api"), - Dest: proptools.StringPtr(filename), - }, - { - Targets: []string{"api_txt", "sdk"}, - Dir: proptools.StringPtr("apistubs/android/" + txt.Scope + "/api"), - Dest: proptools.StringPtr(txt.DistFilename), - }, + if doDist { + props.Dists = []android.Dist{ + { + Targets: []string{"droidcore"}, + Dir: proptools.StringPtr("api"), + Dest: proptools.StringPtr(filename), + }, + { + Targets: []string{"api_txt", "sdk"}, + Dir: proptools.StringPtr("apistubs/android/" + txt.Scope + "/api"), + Dest: proptools.StringPtr(txt.DistFilename), + }, + } } props.Visibility = []string{"//visibility:public"} ctx.CreateModule(genrule.GenRuleFactory, &props) @@ -201,6 +242,7 @@ func createMergedPublicStubs(ctx android.LoadHookContext, modules []string) { props.Static_libs = transformArray(modules, "", ".stubs") props.Sdk_version = proptools.StringPtr("module_current") props.Visibility = []string{"//frameworks/base"} + props.Is_stubs_module = proptools.BoolPtr(true) ctx.CreateModule(java.LibraryFactory, &props) } @@ -210,6 +252,7 @@ func createMergedPublicExportableStubs(ctx android.LoadHookContext, modules []st props.Static_libs = transformArray(modules, "", ".stubs.exportable") props.Sdk_version = proptools.StringPtr("module_current") props.Visibility = []string{"//frameworks/base"} + props.Is_stubs_module = proptools.BoolPtr(true) ctx.CreateModule(java.LibraryFactory, &props) } @@ -222,6 +265,7 @@ func createMergedSystemStubs(ctx android.LoadHookContext, modules []string) { props.Static_libs = transformArray(updatable_modules, "", ".stubs.system") props.Sdk_version = proptools.StringPtr("module_current") props.Visibility = []string{"//frameworks/base"} + props.Is_stubs_module = proptools.BoolPtr(true) ctx.CreateModule(java.LibraryFactory, &props) } // Now merge all-updatable-modules-system-stubs and stubs from non-updatable modules @@ -233,6 +277,7 @@ func createMergedSystemStubs(ctx android.LoadHookContext, modules []string) { props.Static_libs = append(props.Static_libs, "all-updatable-modules-system-stubs") props.Sdk_version = proptools.StringPtr("module_current") props.Visibility = []string{"//frameworks/base"} + props.Is_stubs_module = proptools.BoolPtr(true) ctx.CreateModule(java.LibraryFactory, &props) } } @@ -246,6 +291,7 @@ func createMergedSystemExportableStubs(ctx android.LoadHookContext, modules []st props.Static_libs = transformArray(updatable_modules, "", ".stubs.exportable.system") props.Sdk_version = proptools.StringPtr("module_current") props.Visibility = []string{"//frameworks/base"} + props.Is_stubs_module = proptools.BoolPtr(true) ctx.CreateModule(java.LibraryFactory, &props) } // Now merge all-updatable-modules-system-stubs and stubs from non-updatable modules @@ -257,6 +303,7 @@ func createMergedSystemExportableStubs(ctx android.LoadHookContext, modules []st 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"} + props.Is_stubs_module = proptools.BoolPtr(true) ctx.CreateModule(java.LibraryFactory, &props) } } @@ -267,6 +314,7 @@ func createMergedTestStubsForNonUpdatableModules(ctx android.LoadHookContext) { props.Static_libs = transformArray(non_updatable_modules, "", ".stubs.test") props.Sdk_version = proptools.StringPtr("module_current") props.Visibility = []string{"//frameworks/base"} + props.Is_stubs_module = proptools.BoolPtr(true) ctx.CreateModule(java.LibraryFactory, &props) } @@ -276,6 +324,7 @@ func createMergedTestExportableStubsForNonUpdatableModules(ctx android.LoadHookC props.Static_libs = transformArray(non_updatable_modules, "", ".stubs.exportable.test") props.Sdk_version = proptools.StringPtr("module_current") props.Visibility = []string{"//frameworks/base"} + props.Is_stubs_module = proptools.BoolPtr(true) ctx.CreateModule(java.LibraryFactory, &props) } @@ -319,6 +368,7 @@ func createMergedFrameworkModuleLibExportableStubs(ctx android.LoadHookContext, props.Static_libs = transformArray(modules, "", ".stubs.exportable.module_lib") props.Sdk_version = proptools.StringPtr("module_current") props.Visibility = []string{"//frameworks/base"} + props.Is_stubs_module = proptools.BoolPtr(true) ctx.CreateModule(java.LibraryFactory, &props) } @@ -332,6 +382,7 @@ func createMergedFrameworkModuleLibStubs(ctx android.LoadHookContext, modules [] props.Static_libs = transformArray(modules, "", ".stubs.module_lib") props.Sdk_version = proptools.StringPtr("module_current") props.Visibility = []string{"//frameworks/base"} + props.Is_stubs_module = proptools.BoolPtr(true) ctx.CreateModule(java.LibraryFactory, &props) } @@ -343,7 +394,7 @@ func createPublicStubsSourceFilegroup(ctx android.LoadHookContext, modules []str ctx.CreateModule(android.FileGroupFactory, &props) } -func createMergedTxts(ctx android.LoadHookContext, bootclasspath, system_server_classpath []string) { +func createMergedTxts(ctx android.LoadHookContext, bootclasspath, system_server_classpath []string, baseTxtModulePrefix, stubsTypeSuffix string, doDist bool) { var textFiles []MergedTxtDefinition tagSuffix := []string{".api.txt}", ".removed-api.txt}"} @@ -352,7 +403,7 @@ func createMergedTxts(ctx android.LoadHookContext, bootclasspath, system_server_ textFiles = append(textFiles, MergedTxtDefinition{ TxtFilename: f, DistFilename: distFilename[i], - BaseTxt: ":non-updatable-" + f, + BaseTxt: ":" + baseTxtModulePrefix + f, Modules: bootclasspath, ModuleTag: "{.public" + tagSuffix[i], Scope: "public", @@ -360,7 +411,7 @@ func createMergedTxts(ctx android.LoadHookContext, bootclasspath, system_server_ textFiles = append(textFiles, MergedTxtDefinition{ TxtFilename: f, DistFilename: distFilename[i], - BaseTxt: ":non-updatable-system-" + f, + BaseTxt: ":" + baseTxtModulePrefix + "system-" + f, Modules: bootclasspath, ModuleTag: "{.system" + tagSuffix[i], Scope: "system", @@ -368,7 +419,7 @@ func createMergedTxts(ctx android.LoadHookContext, bootclasspath, system_server_ textFiles = append(textFiles, MergedTxtDefinition{ TxtFilename: f, DistFilename: distFilename[i], - BaseTxt: ":non-updatable-module-lib-" + f, + BaseTxt: ":" + baseTxtModulePrefix + "module-lib-" + f, Modules: bootclasspath, ModuleTag: "{.module-lib" + tagSuffix[i], Scope: "module-lib", @@ -376,14 +427,14 @@ func createMergedTxts(ctx android.LoadHookContext, bootclasspath, system_server_ textFiles = append(textFiles, MergedTxtDefinition{ TxtFilename: f, DistFilename: distFilename[i], - BaseTxt: ":non-updatable-system-server-" + f, + BaseTxt: ":" + baseTxtModulePrefix + "system-server-" + f, Modules: system_server_classpath, ModuleTag: "{.system-server" + tagSuffix[i], Scope: "system-server", }) } for _, txt := range textFiles { - createMergedTxt(ctx, txt) + createMergedTxt(ctx, txt, stubsTypeSuffix, doDist) } } @@ -432,6 +483,7 @@ func createFullApiLibraries(ctx android.LoadHookContext) { props.Static_libs = []string{staticLib} props.Defaults = []string{"android.jar_defaults"} props.Visibility = []string{"//visibility:public"} + props.Is_stubs_module = proptools.BoolPtr(true) ctx.CreateModule(java.LibraryFactory, &props) } @@ -453,6 +505,7 @@ func createFullExportableApiLibraries(ctx android.LoadHookContext) { props.Static_libs = []string{staticLib} props.Defaults = []string{"android.jar_defaults"} props.Visibility = []string{"//visibility:public"} + props.Is_stubs_module = proptools.BoolPtr(true) ctx.CreateModule(java.LibraryFactory, &props) } @@ -465,7 +518,8 @@ func (a *CombinedApis) createInternalModules(ctx android.LoadHookContext) { bootclasspath = append(bootclasspath, a.properties.Conditional_bootclasspath...) sort.Strings(bootclasspath) } - createMergedTxts(ctx, bootclasspath, system_server_classpath) + createMergedTxts(ctx, bootclasspath, system_server_classpath, "non-updatable-", "-", false) + createMergedTxts(ctx, bootclasspath, system_server_classpath, "non-updatable-exportable-", "-exportable-", true) createMergedPublicStubs(ctx, bootclasspath) createMergedSystemStubs(ctx, bootclasspath) diff --git a/core/api/Android.bp b/core/api/Android.bp index 8d8a82b69b55..77594b758d19 100644 --- a/core/api/Android.bp +++ b/core/api/Android.bp @@ -96,3 +96,54 @@ filegroup { name: "non-updatable-test-lint-baseline.txt", srcs: ["test-lint-baseline.txt"], } + +// Exportable stub artifacts +filegroup { + name: "non-updatable-exportable-current.txt", + srcs: [":api-stubs-docs-non-updatable{.exportable.api.txt}"], +} + +filegroup { + name: "non-updatable-exportable-removed.txt", + srcs: [":api-stubs-docs-non-updatable{.exportable.removed-api.txt}"], +} + +filegroup { + name: "non-updatable-exportable-system-current.txt", + srcs: [":system-api-stubs-docs-non-updatable{.exportable.api.txt}"], +} + +filegroup { + name: "non-updatable-exportable-system-removed.txt", + srcs: [":system-api-stubs-docs-non-updatable{.exportable.removed-api.txt}"], +} + +filegroup { + name: "non-updatable-exportable-module-lib-current.txt", + srcs: [":module-lib-api-stubs-docs-non-updatable{.exportable.api.txt}"], +} + +filegroup { + name: "non-updatable-exportable-module-lib-removed.txt", + srcs: [":module-lib-api-stubs-docs-non-updatable{.exportable.removed-api.txt}"], +} + +filegroup { + name: "non-updatable-exportable-test-current.txt", + srcs: [":test-api-stubs-docs-non-updatable{.exportable.api.txt}"], +} + +filegroup { + name: "non-updatable-exportable-test-removed.txt", + srcs: [":test-api-stubs-docs-non-updatable{.exportable.removed-api.txt}"], +} + +filegroup { + name: "non-updatable-exportable-system-server-current.txt", + srcs: [":services-non-updatable-stubs{.exportable.api.txt}"], +} + +filegroup { + name: "non-updatable-exportable-system-server-removed.txt", + srcs: [":services-non-updatable-stubs{.exportable.removed-api.txt}"], +} diff --git a/core/api/current.txt b/core/api/current.txt index ea1cd21d5aee..8f5374c9dbc6 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -12739,7 +12739,7 @@ package android.content.pm { field public static final String FEATURE_TELEPHONY_RADIO_ACCESS = "android.hardware.telephony.radio.access"; field public static final String FEATURE_TELEPHONY_SUBSCRIPTION = "android.hardware.telephony.subscription"; field @Deprecated public static final String FEATURE_TELEVISION = "android.hardware.type.television"; - field @FlaggedApi("com.android.net.thread.flags.thread_enabled") public static final String FEATURE_THREAD_NETWORK = "android.hardware.thread_network"; + field @FlaggedApi("com.android.net.thread.flags.thread_enabled_platform") public static final String FEATURE_THREAD_NETWORK = "android.hardware.thread_network"; field public static final String FEATURE_TOUCHSCREEN = "android.hardware.touchscreen"; field public static final String FEATURE_TOUCHSCREEN_MULTITOUCH = "android.hardware.touchscreen.multitouch"; field public static final String FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT = "android.hardware.touchscreen.multitouch.distinct"; @@ -22552,6 +22552,7 @@ package android.media { method @NonNull public static android.view.Surface createPersistentInputSurface(); method public int dequeueInputBuffer(long); method public int dequeueOutputBuffer(@NonNull android.media.MediaCodec.BufferInfo, long); + method @FlaggedApi("android.media.codec.null_output_surface") public void detachOutputSurface(); method protected void finalize(); method public void flush(); method @NonNull public String getCanonicalName(); @@ -22575,6 +22576,7 @@ package android.media { method public void queueInputBuffer(int, int, int, long, int) throws android.media.MediaCodec.CryptoException; method @FlaggedApi("com.android.media.codec.flags.large_audio_frame") public void queueInputBuffers(int, @NonNull java.util.ArrayDeque<android.media.MediaCodec.BufferInfo>); method public void queueSecureInputBuffer(int, int, @NonNull android.media.MediaCodec.CryptoInfo, long, int) throws android.media.MediaCodec.CryptoException; + method @FlaggedApi("com.android.media.codec.flags.large_audio_frame") public void queueSecureInputBuffers(int, @NonNull java.util.ArrayDeque<android.media.MediaCodec.BufferInfo>, @NonNull java.util.ArrayDeque<android.media.MediaCodec.CryptoInfo>); method public void release(); method public void releaseOutputBuffer(int, boolean); method public void releaseOutputBuffer(int, long); @@ -22599,6 +22601,7 @@ package android.media { field public static final int BUFFER_FLAG_KEY_FRAME = 1; // 0x1 field public static final int BUFFER_FLAG_PARTIAL_FRAME = 8; // 0x8 field @Deprecated public static final int BUFFER_FLAG_SYNC_FRAME = 1; // 0x1 + field @FlaggedApi("android.media.codec.null_output_surface") public static final int CONFIGURE_FLAG_DETACHED_SURFACE = 8; // 0x8 field public static final int CONFIGURE_FLAG_ENCODE = 1; // 0x1 field public static final int CONFIGURE_FLAG_USE_BLOCK_MODEL = 2; // 0x2 field public static final int CONFIGURE_FLAG_USE_CRYPTO_ASYNC = 4; // 0x4 @@ -22611,6 +22614,8 @@ package android.media { field public static final String PARAMETER_KEY_HDR10_PLUS_INFO = "hdr10-plus-info"; field public static final String PARAMETER_KEY_LOW_LATENCY = "low-latency"; field public static final String PARAMETER_KEY_OFFSET_TIME = "time-offset-us"; + field @FlaggedApi("android.media.codec.region_of_interest") public static final String PARAMETER_KEY_QP_OFFSET_MAP = "qp-offset-map"; + field @FlaggedApi("android.media.codec.region_of_interest") public static final String PARAMETER_KEY_QP_OFFSET_RECTS = "qp-offset-rects"; field public static final String PARAMETER_KEY_REQUEST_SYNC_FRAME = "request-sync"; field public static final String PARAMETER_KEY_SUSPEND = "drop-input-frames"; field public static final String PARAMETER_KEY_SUSPEND_TIME = "drop-start-time-us"; @@ -22739,7 +22744,6 @@ package android.media { public final class MediaCodec.QueueRequest { method public void queue(); - method @FlaggedApi("com.android.media.codec.flags.large_audio_frame") @NonNull public android.media.MediaCodec.QueueRequest setBufferInfos(@NonNull java.util.ArrayDeque<android.media.MediaCodec.BufferInfo>); method @NonNull public android.media.MediaCodec.QueueRequest setByteBufferParameter(@NonNull String, @NonNull java.nio.ByteBuffer); method @NonNull public android.media.MediaCodec.QueueRequest setEncryptedLinearBlock(@NonNull android.media.MediaCodec.LinearBlock, int, int, @NonNull android.media.MediaCodec.CryptoInfo); method @NonNull public android.media.MediaCodec.QueueRequest setFlags(int); @@ -22748,6 +22752,8 @@ package android.media { method @NonNull public android.media.MediaCodec.QueueRequest setIntegerParameter(@NonNull String, int); method @NonNull public android.media.MediaCodec.QueueRequest setLinearBlock(@NonNull android.media.MediaCodec.LinearBlock, int, int); method @NonNull public android.media.MediaCodec.QueueRequest setLongParameter(@NonNull String, long); + method @FlaggedApi("com.android.media.codec.flags.large_audio_frame") @NonNull public android.media.MediaCodec.QueueRequest setMultiFrameEncryptedLinearBlock(@NonNull android.media.MediaCodec.LinearBlock, @NonNull java.util.ArrayDeque<android.media.MediaCodec.BufferInfo>, @NonNull java.util.ArrayDeque<android.media.MediaCodec.CryptoInfo>); + method @FlaggedApi("com.android.media.codec.flags.large_audio_frame") @NonNull public android.media.MediaCodec.QueueRequest setMultiFrameLinearBlock(@NonNull android.media.MediaCodec.LinearBlock, @NonNull java.util.ArrayDeque<android.media.MediaCodec.BufferInfo>); method @NonNull public android.media.MediaCodec.QueueRequest setPresentationTimeUs(long); method @NonNull public android.media.MediaCodec.QueueRequest setStringParameter(@NonNull String, @NonNull String); } @@ -22756,12 +22762,16 @@ package android.media { method @NonNull public String getCanonicalName(); method public android.media.MediaCodecInfo.CodecCapabilities getCapabilitiesForType(String); method @NonNull public String getName(); + method @FlaggedApi("android.media.codec.in_process_sw_audio_codec") public int getSecurityModel(); method public String[] getSupportedTypes(); method public boolean isAlias(); method public boolean isEncoder(); method public boolean isHardwareAccelerated(); method public boolean isSoftwareOnly(); method public boolean isVendor(); + field @FlaggedApi("android.media.codec.in_process_sw_audio_codec") public static final int SECURITY_MODEL_MEMORY_SAFE = 1; // 0x1 + field @FlaggedApi("android.media.codec.in_process_sw_audio_codec") public static final int SECURITY_MODEL_SANDBOXED = 0; // 0x0 + field @FlaggedApi("android.media.codec.in_process_sw_audio_codec") public static final int SECURITY_MODEL_TRUSTED_CONTENT_ONLY = 2; // 0x2 } public static final class MediaCodecInfo.AudioCapabilities { @@ -22842,15 +22852,19 @@ package android.media { field @Deprecated public static final int COLOR_QCOM_FormatYUV420SemiPlanar = 2141391872; // 0x7fa30c00 field @Deprecated public static final int COLOR_TI_FormatYUV420PackedSemiPlanar = 2130706688; // 0x7f000100 field public static final String FEATURE_AdaptivePlayback = "adaptive-playback"; + field @FlaggedApi("android.media.codec.null_output_surface") public static final String FEATURE_DetachedSurface = "detached-surface"; + field @FlaggedApi("android.media.codec.dynamic_color_aspects") public static final String FEATURE_DynamicColorAspects = "dynamic-color-aspects"; field public static final String FEATURE_DynamicTimestamp = "dynamic-timestamp"; field public static final String FEATURE_EncodingStatistics = "encoding-statistics"; field public static final String FEATURE_FrameParsing = "frame-parsing"; field public static final String FEATURE_HdrEditing = "hdr-editing"; + field @FlaggedApi("android.media.codec.hlg_editing") public static final String FEATURE_HlgEditing = "hlg-editing"; field public static final String FEATURE_IntraRefresh = "intra-refresh"; field public static final String FEATURE_LowLatency = "low-latency"; field public static final String FEATURE_MultipleFrames = "multiple-frames"; field public static final String FEATURE_PartialFrame = "partial-frame"; field public static final String FEATURE_QpBounds = "qp-bounds"; + field @FlaggedApi("android.media.codec.region_of_interest") public static final String FEATURE_Roi = "region-of-interest"; field public static final String FEATURE_SecurePlayback = "secure-playback"; field public static final String FEATURE_TunneledPlayback = "tunneled-playback"; field public int[] colorFormats; @@ -23592,6 +23606,9 @@ package android.media { field public static final int COLOR_TRANSFER_LINEAR = 1; // 0x1 field public static final int COLOR_TRANSFER_SDR_VIDEO = 3; // 0x3 field public static final int COLOR_TRANSFER_ST2084 = 6; // 0x6 + field @FlaggedApi("android.media.codec.in_process_sw_audio_codec") public static final int FLAG_SECURITY_MODEL_MEMORY_SAFE = 2; // 0x2 + field @FlaggedApi("android.media.codec.in_process_sw_audio_codec") public static final int FLAG_SECURITY_MODEL_SANDBOXED = 1; // 0x1 + field @FlaggedApi("android.media.codec.in_process_sw_audio_codec") public static final int FLAG_SECURITY_MODEL_TRUSTED_CONTENT_ONLY = 4; // 0x4 field public static final String KEY_AAC_DRC_ALBUM_MODE = "aac-drc-album-mode"; field public static final String KEY_AAC_DRC_ATTENUATION_FACTOR = "aac-drc-cut-level"; field public static final String KEY_AAC_DRC_BOOST_FACTOR = "aac-drc-boost-level"; @@ -23673,6 +23690,7 @@ package android.media { field public static final String KEY_REPEAT_PREVIOUS_FRAME_AFTER = "repeat-previous-frame-after"; field public static final String KEY_ROTATION = "rotation-degrees"; field public static final String KEY_SAMPLE_RATE = "sample-rate"; + field @FlaggedApi("android.media.codec.in_process_sw_audio_codec") public static final String KEY_SECURITY_MODEL = "security-model"; field public static final String KEY_SLICE_HEIGHT = "slice-height"; field public static final String KEY_SLOW_MOTION_MARKERS = "slow-motion-markers"; field public static final String KEY_STRIDE = "stride"; @@ -39158,7 +39176,7 @@ package android.security.keystore { method @Nullable public java.util.Date getKeyValidityStart(); method @NonNull public String getKeystoreAlias(); method public int getMaxUsageCount(); - method @FlaggedApi("android.security.mgf1_digest_setter") @NonNull public java.util.Set<java.lang.String> getMgf1Digests(); + method @FlaggedApi("android.security.mgf1_digest_setter_v2") @NonNull public java.util.Set<java.lang.String> getMgf1Digests(); method public int getPurposes(); method @NonNull public String[] getSignaturePaddings(); method public int getUserAuthenticationType(); @@ -39166,7 +39184,7 @@ package android.security.keystore { method public boolean isDevicePropertiesAttestationIncluded(); method @NonNull public boolean isDigestsSpecified(); method public boolean isInvalidatedByBiometricEnrollment(); - method @FlaggedApi("android.security.mgf1_digest_setter") @NonNull public boolean isMgf1DigestsSpecified(); + method @FlaggedApi("android.security.mgf1_digest_setter_v2") @NonNull public boolean isMgf1DigestsSpecified(); method public boolean isRandomizedEncryptionRequired(); method public boolean isStrongBoxBacked(); method public boolean isUnlockedDeviceRequired(); @@ -39198,7 +39216,7 @@ package android.security.keystore { method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setKeyValidityForOriginationEnd(java.util.Date); method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setKeyValidityStart(java.util.Date); method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setMaxUsageCount(int); - method @FlaggedApi("android.security.mgf1_digest_setter") @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setMgf1Digests(@NonNull java.lang.String...); + method @FlaggedApi("android.security.mgf1_digest_setter_v2") @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setMgf1Digests(@NonNull java.lang.String...); method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setRandomizedEncryptionRequired(boolean); method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setSignaturePaddings(java.lang.String...); method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setUnlockedDeviceRequired(boolean); @@ -39303,14 +39321,14 @@ package android.security.keystore { method @Nullable public java.util.Date getKeyValidityForOriginationEnd(); method @Nullable public java.util.Date getKeyValidityStart(); method public int getMaxUsageCount(); - method @FlaggedApi("android.security.mgf1_digest_setter") @NonNull public java.util.Set<java.lang.String> getMgf1Digests(); + method @FlaggedApi("android.security.mgf1_digest_setter_v2") @NonNull public java.util.Set<java.lang.String> getMgf1Digests(); method public int getPurposes(); method @NonNull public String[] getSignaturePaddings(); method public int getUserAuthenticationType(); method public int getUserAuthenticationValidityDurationSeconds(); method public boolean isDigestsSpecified(); method public boolean isInvalidatedByBiometricEnrollment(); - method @FlaggedApi("android.security.mgf1_digest_setter") @NonNull public boolean isMgf1DigestsSpecified(); + method @FlaggedApi("android.security.mgf1_digest_setter_v2") @NonNull public boolean isMgf1DigestsSpecified(); method public boolean isRandomizedEncryptionRequired(); method public boolean isUnlockedDeviceRequired(); method public boolean isUserAuthenticationRequired(); @@ -39332,7 +39350,7 @@ package android.security.keystore { method @NonNull public android.security.keystore.KeyProtection.Builder setKeyValidityForOriginationEnd(java.util.Date); method @NonNull public android.security.keystore.KeyProtection.Builder setKeyValidityStart(java.util.Date); method @NonNull public android.security.keystore.KeyProtection.Builder setMaxUsageCount(int); - method @FlaggedApi("android.security.mgf1_digest_setter") @NonNull public android.security.keystore.KeyProtection.Builder setMgf1Digests(@Nullable java.lang.String...); + method @FlaggedApi("android.security.mgf1_digest_setter_v2") @NonNull public android.security.keystore.KeyProtection.Builder setMgf1Digests(@Nullable java.lang.String...); method @NonNull public android.security.keystore.KeyProtection.Builder setRandomizedEncryptionRequired(boolean); method @NonNull public android.security.keystore.KeyProtection.Builder setSignaturePaddings(java.lang.String...); method @NonNull public android.security.keystore.KeyProtection.Builder setUnlockedDeviceRequired(boolean); diff --git a/core/api/system-current.txt b/core/api/system-current.txt index cdeddfbba467..eca138b83dbe 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -357,7 +357,7 @@ package android { field public static final String SYSTEM_APPLICATION_OVERLAY = "android.permission.SYSTEM_APPLICATION_OVERLAY"; field public static final String SYSTEM_CAMERA = "android.permission.SYSTEM_CAMERA"; field public static final String TETHER_PRIVILEGED = "android.permission.TETHER_PRIVILEGED"; - field @FlaggedApi("com.android.net.thread.flags.thread_enabled") public static final String THREAD_NETWORK_PRIVILEGED = "android.permission.THREAD_NETWORK_PRIVILEGED"; + field @FlaggedApi("com.android.net.thread.flags.thread_enabled_platform") public static final String THREAD_NETWORK_PRIVILEGED = "android.permission.THREAD_NETWORK_PRIVILEGED"; field public static final String TIS_EXTENSION_INTERFACE = "android.permission.TIS_EXTENSION_INTERFACE"; field public static final String TOGGLE_AUTOMOTIVE_PROJECTION = "android.permission.TOGGLE_AUTOMOTIVE_PROJECTION"; field public static final String TRIGGER_LOST_MODE = "android.permission.TRIGGER_LOST_MODE"; @@ -3482,7 +3482,7 @@ package android.content { field public static final String SYSTEM_CONFIG_SERVICE = "system_config"; field public static final String SYSTEM_UPDATE_SERVICE = "system_update"; field public static final String TETHERING_SERVICE = "tethering"; - field @FlaggedApi("com.android.net.thread.flags.thread_enabled") public static final String THREAD_NETWORK_SERVICE = "thread_network"; + field @FlaggedApi("com.android.net.thread.flags.thread_enabled_platform") public static final String THREAD_NETWORK_SERVICE = "thread_network"; field public static final String TIME_MANAGER_SERVICE = "time_manager"; field public static final String TRANSLATION_MANAGER_SERVICE = "translation"; field public static final String UI_TRANSLATION_SERVICE = "ui_translation"; @@ -3860,6 +3860,7 @@ package android.content.pm { method public void setInstallAsInstantApp(boolean); method public void setInstallAsVirtualPreload(); method public void setRequestDowngrade(boolean); + method @FlaggedApi("android.content.pm.recoverability_detection") @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) public void setRollbackImpactLevel(int); method @FlaggedApi("android.content.pm.rollback_lifetime") @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) public void setRollbackLifetimeMillis(long); method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void setStaged(); } @@ -4023,6 +4024,9 @@ package android.content.pm { field public static final int ROLLBACK_DATA_POLICY_RESTORE = 0; // 0x0 field public static final int ROLLBACK_DATA_POLICY_RETAIN = 2; // 0x2 field public static final int ROLLBACK_DATA_POLICY_WIPE = 1; // 0x1 + field @FlaggedApi("android.content.pm.recoverability_detection") public static final int ROLLBACK_USER_IMPACT_HIGH = 1; // 0x1 + field @FlaggedApi("android.content.pm.recoverability_detection") public static final int ROLLBACK_USER_IMPACT_LOW = 0; // 0x0 + field @FlaggedApi("android.content.pm.recoverability_detection") public static final int ROLLBACK_USER_IMPACT_ONLY_MANUAL = 2; // 0x2 field public static final int SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN = 0; // 0x0 field public static final int SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_VISIBLE = 1; // 0x1 field public static final int SYSTEM_APP_STATE_INSTALLED = 2; // 0x2 diff --git a/core/api/test-current.txt b/core/api/test-current.txt index e3bb53adba9b..32b031b0eef3 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -1148,6 +1148,10 @@ package android.content.res { package android.content.rollback { + public final class RollbackInfo implements android.os.Parcelable { + method @FlaggedApi("android.content.pm.recoverability_detection") public int getRollbackImpactLevel(); + } + public final class RollbackManager { method @RequiresPermission(android.Manifest.permission.TEST_MANAGE_ROLLBACKS) public void blockRollbackManager(long); method @RequiresPermission(android.Manifest.permission.TEST_MANAGE_ROLLBACKS) public void expireRollbackForPackage(@NonNull String); diff --git a/core/java/android/app/COMPONENT_CALLER_OWNERS b/core/java/android/app/COMPONENT_CALLER_OWNERS new file mode 100644 index 000000000000..f8fdeae4919e --- /dev/null +++ b/core/java/android/app/COMPONENT_CALLER_OWNERS @@ -0,0 +1,5 @@ +# Bug component: 315013 +brufino@google.com +mpgroover@google.com + +include /services/core/java/com/android/server/uri/OWNERS diff --git a/core/java/android/app/OWNERS b/core/java/android/app/OWNERS index 41d79329f4f2..32de38597181 100644 --- a/core/java/android/app/OWNERS +++ b/core/java/android/app/OWNERS @@ -31,6 +31,7 @@ per-file Service* = file:/services/core/java/com/android/server/am/OWNERS per-file SystemServiceRegistry.java = file:/services/core/java/com/android/server/am/OWNERS per-file *UserSwitchObserver* = file:/services/core/java/com/android/server/am/OWNERS per-file *UiAutomation* = file:/services/accessibility/OWNERS +per-file *UiAutomation* = file:/core/java/android/permission/OWNERS per-file GameManager* = file:/GAME_MANAGER_OWNERS per-file GameMode* = file:/GAME_MANAGER_OWNERS per-file GameState* = file:/GAME_MANAGER_OWNERS @@ -55,6 +56,13 @@ per-file IBackupAgent.aidl = file:/services/backup/OWNERS per-file Broadcast* = file:/BROADCASTS_OWNERS per-file ReceiverInfo* = file:/BROADCASTS_OWNERS +# ComponentCaller +per-file ComponentCaller.java = file:COMPONENT_CALLER_OWNERS + +# GrammaticalInflectionManager +per-file *GrammaticalInflection* = file:/services/core/java/com/android/server/grammaticalinflection/OWNERS +per-file grammatical_inflection_manager.aconfig = file:/services/core/java/com/android/server/grammaticalinflection/OWNERS + # KeyguardManager per-file KeyguardManager.java = file:/services/core/java/com/android/server/locksettings/OWNERS diff --git a/core/java/android/app/ondeviceintelligence/OWNERS b/core/java/android/app/ondeviceintelligence/OWNERS new file mode 100644 index 000000000000..6932ba23a8ac --- /dev/null +++ b/core/java/android/app/ondeviceintelligence/OWNERS @@ -0,0 +1,7 @@ +# Bug component: 1363385 + +sandeepbandaru@google.com +shivanker@google.com +hackz@google.com +volnov@google.com + diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 95fc3ac623ca..bfb041cf3edd 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -4767,7 +4767,7 @@ public abstract class Context { * @see android.net.thread.ThreadNetworkManager * @hide */ - @FlaggedApi("com.android.net.thread.flags.thread_enabled") + @FlaggedApi(com.android.net.thread.flags.Flags.FLAG_THREAD_ENABLED_PLATFORM) @SystemApi public static final String THREAD_NETWORK_SERVICE = "thread_network"; diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java index f946754bd9a1..01ea4e93f074 100644 --- a/core/java/android/content/IntentFilter.java +++ b/core/java/android/content/IntentFilter.java @@ -664,7 +664,7 @@ public class IntentFilter implements Parcelable { * has at least one HTTP or HTTPS data URI pattern defined, and optionally * does not define any non-http/https data URI patterns. * - * This will check if if the Intent action is {@link android.content.Intent#ACTION_VIEW} and + * This will check if the Intent action is {@link android.content.Intent#ACTION_VIEW} and * the Intent category is {@link android.content.Intent#CATEGORY_BROWSABLE} and the Intent * data scheme is "http" or "https". * @@ -705,7 +705,7 @@ public class IntentFilter implements Parcelable { } // We get here if: - // 1) onlyWebSchemes and no non-web schemes were found, i.e success; or + // 1) onlyWebSchemes and no non-web schemes were found, i.e. success; or // 2) !onlyWebSchemes and no http/https schemes were found, i.e. failure. return onlyWebSchemes; } @@ -715,7 +715,7 @@ public class IntentFilter implements Parcelable { * * @return True if the filter needs to be automatically verified. False otherwise. * - * This will check if if the Intent action is {@link android.content.Intent#ACTION_VIEW} and + * This will check if the Intent action is {@link android.content.Intent#ACTION_VIEW} and * the Intent category is {@link android.content.Intent#CATEGORY_BROWSABLE} and the Intent * data scheme is "http" or "https". * diff --git a/core/java/android/content/pm/OWNERS b/core/java/android/content/pm/OWNERS index 5bdcc1cd55dc..d7a0cbd3f601 100644 --- a/core/java/android/content/pm/OWNERS +++ b/core/java/android/content/pm/OWNERS @@ -3,10 +3,20 @@ file:/PACKAGE_MANAGER_OWNERS per-file PackageParser.java = set noparent -per-file PackageParser.java = chiuwinson@google.com,patb@google.com +per-file PackageParser.java = file:/PACKAGE_MANAGER_OWNERS + +# Bug component: 166829 = per-file *Capability* per-file *Capability* = file:/core/java/android/content/pm/SHORTCUT_OWNERS +# Bug component: 166829 = per-file *Shortcut* per-file *Shortcut* = file:/core/java/android/content/pm/SHORTCUT_OWNERS + +# Bug component: 860423 = per-file *Launcher* per-file *Launcher* = file:/core/java/android/content/pm/LAUNCHER_OWNERS + +# Bug component: 578329 = per-file *UserInfo* per-file UserInfo* = file:/MULTIUSER_OWNERS +# Bug component: 578329 = per-file *UserProperties* per-file *UserProperties* = file:/MULTIUSER_OWNERS -per-file IBackgroundInstallControlService.aidl = file:/services/core/java/com/android/server/pm/BACKGROUND_INSTALL_OWNERS
\ No newline at end of file + +# Bug component: 1219020 = per-file *BackgroundInstallControl* +per-file *BackgroundInstallControl* = file:/services/core/java/com/android/server/pm/BACKGROUND_INSTALL_OWNERS
\ No newline at end of file diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java index 920cc57a8575..6ca6194ca7b9 100644 --- a/core/java/android/content/pm/PackageInstaller.java +++ b/core/java/android/content/pm/PackageInstaller.java @@ -2374,6 +2374,8 @@ public class PackageInstaller { /** @hide */ public long rollbackLifetimeMillis = 0; /** {@hide} */ + public int rollbackImpactLevel = PackageManager.ROLLBACK_USER_IMPACT_LOW; + /** {@hide} */ public boolean forceQueryableOverride; /** {@hide} */ public int requireUserAction = USER_ACTION_UNSPECIFIED; @@ -2428,6 +2430,7 @@ public class PackageInstaller { } rollbackDataPolicy = source.readInt(); rollbackLifetimeMillis = source.readLong(); + rollbackImpactLevel = source.readInt(); requireUserAction = source.readInt(); packageSource = source.readInt(); applicationEnabledSettingPersistent = source.readBoolean(); @@ -2461,6 +2464,7 @@ public class PackageInstaller { ret.dataLoaderParams = dataLoaderParams; ret.rollbackDataPolicy = rollbackDataPolicy; ret.rollbackLifetimeMillis = rollbackLifetimeMillis; + ret.rollbackImpactLevel = rollbackImpactLevel; ret.requireUserAction = requireUserAction; ret.packageSource = packageSource; ret.applicationEnabledSettingPersistent = applicationEnabledSettingPersistent; @@ -2772,13 +2776,14 @@ public class PackageInstaller { } /** - * If rollback enabled for this session (via {@link #setEnableRollback}, set time - * after which rollback will no longer be possible + * If rollback enabled for this session (via {@link #setEnableRollback}, set period + * after which rollback files will be deleted due to expiration + * {@link RollbackManagerServiceImpl#deleteRollback}. * * <p>For multi-package installs, this value must be set on the parent session. * Child session rollback lifetime will be ignored. * - * @param lifetimeMillis time after which rollback expires + * @param lifetimeMillis period after which rollback expires * @throws IllegalArgumentException if lifetimeMillis is negative or rollback is not * enabled via setEnableRollback. * @hide @@ -2798,6 +2803,28 @@ public class PackageInstaller { } /** + * rollbackImpactLevel is a measure of impact a rollback has on the user. This can take one + * of 3 values: + * <ul> + * <li>{@link PackageManager#ROLLBACK_USER_IMPACT_LOW} (default)</li> + * <li>{@link PackageManager#ROLLBACK_USER_IMPACT_HIGH} (1)</li> + * <li>{@link PackageManager#ROLLBACK_USER_IMPACT_ONLY_MANUAL} (2)</li> + * </ul> + * + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) + @FlaggedApi(Flags.FLAG_RECOVERABILITY_DETECTION) + public void setRollbackImpactLevel(@PackageManager.RollbackImpactLevel int impactLevel) { + if ((installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) == 0) { + throw new IllegalArgumentException( + "Can't set rollbackImpactLevel when rollback is not enabled"); + } + rollbackImpactLevel = impactLevel; + } + + /** * @deprecated use {@link #setRequestDowngrade(boolean)}. * {@hide} */ @@ -3151,6 +3178,7 @@ public class PackageInstaller { pw.printPair("dataLoaderParams", dataLoaderParams); pw.printPair("rollbackDataPolicy", rollbackDataPolicy); pw.printPair("rollbackLifetimeMillis", rollbackLifetimeMillis); + pw.printPair("rollbackImpactLevel", rollbackImpactLevel); pw.printPair("applicationEnabledSettingPersistent", applicationEnabledSettingPersistent); pw.printHexPair("developmentInstallFlags", developmentInstallFlags); @@ -3193,6 +3221,7 @@ public class PackageInstaller { } dest.writeInt(rollbackDataPolicy); dest.writeLong(rollbackLifetimeMillis); + dest.writeInt(rollbackImpactLevel); dest.writeInt(requireUserAction); dest.writeInt(packageSource); dest.writeBoolean(applicationEnabledSettingPersistent); @@ -3390,6 +3419,9 @@ public class PackageInstaller { public long rollbackLifetimeMillis; /** {@hide} */ + public int rollbackImpactLevel; + + /** {@hide} */ public int requireUserAction; /** {@hide} */ @@ -3457,6 +3489,7 @@ public class PackageInstaller { isPreapprovalRequested = source.readBoolean(); rollbackDataPolicy = source.readInt(); rollbackLifetimeMillis = source.readLong(); + rollbackImpactLevel = source.readInt(); createdMillis = source.readLong(); requireUserAction = source.readInt(); installerUid = source.readInt(); @@ -4081,6 +4114,7 @@ public class PackageInstaller { dest.writeBoolean(isPreapprovalRequested); dest.writeInt(rollbackDataPolicy); dest.writeLong(rollbackLifetimeMillis); + dest.writeInt(rollbackImpactLevel); dest.writeLong(createdMillis); dest.writeInt(requireUserAction); dest.writeInt(installerUid); diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 1bc0418ef19c..c943789c2e33 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -1429,6 +1429,44 @@ public abstract class PackageManager { public static final int ROLLBACK_DATA_POLICY_RETAIN = 2; /** @hide */ + @IntDef(prefix = {"ROLLBACK_USER_IMPACT_"}, value = { + ROLLBACK_USER_IMPACT_LOW, + ROLLBACK_USER_IMPACT_HIGH, + ROLLBACK_USER_IMPACT_ONLY_MANUAL, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface RollbackImpactLevel {} + + /** + * Rollback will be performed automatically in response to native crashes on startup or + * persistent service crashes. More suitable for apps that do not store any user data. + * + * @hide + */ + @SystemApi + @FlaggedApi(android.content.pm.Flags.FLAG_RECOVERABILITY_DETECTION) + public static final int ROLLBACK_USER_IMPACT_LOW = 0; + + /** + * Rollback will be performed automatically only when the device is found to be unrecoverable. + * More suitable for apps that store user data and have higher impact on user. + * + * @hide + */ + @SystemApi + @FlaggedApi(android.content.pm.Flags.FLAG_RECOVERABILITY_DETECTION) + public static final int ROLLBACK_USER_IMPACT_HIGH = 1; + + /** + * Rollback will not be performed automatically. It can be triggered externally. + * + * @hide + */ + @SystemApi + @FlaggedApi(android.content.pm.Flags.FLAG_RECOVERABILITY_DETECTION) + public static final int ROLLBACK_USER_IMPACT_ONLY_MANUAL = 2; + + /** @hide */ @IntDef(flag = true, prefix = { "INSTALL_" }, value = { INSTALL_REPLACE_EXISTING, INSTALL_ALLOW_TEST, @@ -3718,7 +3756,7 @@ public abstract class PackageManager { * The device is capable of communicating with other devices via * <a href="https://www.threadgroup.org">Thread</a> networking protocol. */ - @FlaggedApi("com.android.net.thread.flags.thread_enabled") + @FlaggedApi(com.android.net.thread.flags.Flags.FLAG_THREAD_ENABLED_PLATFORM) @SdkConstant(SdkConstantType.FEATURE) public static final String FEATURE_THREAD_NETWORK = "android.hardware.thread_network"; diff --git a/core/java/android/content/pm/flags.aconfig b/core/java/android/content/pm/flags.aconfig index d07de72d6cf5..ab8fd5e50fd5 100644 --- a/core/java/android/content/pm/flags.aconfig +++ b/core/java/android/content/pm/flags.aconfig @@ -14,3 +14,11 @@ flag { bug: "299670324" is_fixed_read_only: true } + +flag { + name: "recoverability_detection" + namespace: "package_manager_service" + description: "Feature flag to enable recoverability detection feature. It includes GMS core rollback and improvements to rescue party." + bug: "291135724" + is_fixed_read_only: true +}
\ No newline at end of file diff --git a/core/java/android/content/rollback/RollbackInfo.java b/core/java/android/content/rollback/RollbackInfo.java index a363718a8b1d..d128055fec6d 100644 --- a/core/java/android/content/rollback/RollbackInfo.java +++ b/core/java/android/content/rollback/RollbackInfo.java @@ -16,8 +16,12 @@ package android.content.rollback; +import android.annotation.FlaggedApi; import android.annotation.NonNull; import android.annotation.SystemApi; +import android.annotation.TestApi; +import android.content.pm.Flags; +import android.content.pm.PackageManager; import android.content.pm.VersionedPackage; import android.os.Parcel; import android.os.Parcelable; @@ -25,17 +29,14 @@ import android.os.Parcelable; import java.util.List; /** - * Information about a set of packages that can be, or already have been - * rolled back together. + * Information about a set of packages that can be, or already have been rolled back together. * * @hide */ @SystemApi public final class RollbackInfo implements Parcelable { - /** - * A unique identifier for the rollback. - */ + /** A unique identifier for the rollback. */ private final int mRollbackId; private final List<PackageRollbackInfo> mPackages; @@ -44,15 +45,39 @@ public final class RollbackInfo implements Parcelable { private final boolean mIsStaged; private int mCommittedSessionId; + private int mRollbackImpactLevel; /** @hide */ - public RollbackInfo(int rollbackId, List<PackageRollbackInfo> packages, boolean isStaged, - List<VersionedPackage> causePackages, int committedSessionId) { + public RollbackInfo( + int rollbackId, + List<PackageRollbackInfo> packages, + boolean isStaged, + List<VersionedPackage> causePackages, + int committedSessionId, + @PackageManager.RollbackImpactLevel int rollbackImpactLevel) { this.mRollbackId = rollbackId; this.mPackages = packages; this.mIsStaged = isStaged; this.mCausePackages = causePackages; this.mCommittedSessionId = committedSessionId; + this.mRollbackImpactLevel = rollbackImpactLevel; + } + + /** @hide */ + public RollbackInfo( + int rollbackId, + List<PackageRollbackInfo> packages, + boolean isStaged, + List<VersionedPackage> causePackages, + int committedSessionId) { + // If impact level is not set default to 0 + this( + rollbackId, + packages, + isStaged, + causePackages, + committedSessionId, + PackageManager.ROLLBACK_USER_IMPACT_LOW); } private RollbackInfo(Parcel in) { @@ -61,34 +86,28 @@ public final class RollbackInfo implements Parcelable { mIsStaged = in.readBoolean(); mCausePackages = in.createTypedArrayList(VersionedPackage.CREATOR); mCommittedSessionId = in.readInt(); + mRollbackImpactLevel = in.readInt(); } - /** - * Returns a unique identifier for this rollback. - */ + /** Returns a unique identifier for this rollback. */ public int getRollbackId() { return mRollbackId; } - /** - * Returns the list of package that are rolled back. - */ + /** Returns the list of package that are rolled back. */ @NonNull public List<PackageRollbackInfo> getPackages() { return mPackages; } - /** - * Returns true if this rollback requires reboot to take effect after - * being committed. - */ + /** Returns true if this rollback requires reboot to take effect after being committed. */ public boolean isStaged() { return mIsStaged; } /** - * Returns the session ID for the committed rollback for staged rollbacks. - * Only applicable for rollbacks that have been committed. + * Returns the session ID for the committed rollback for staged rollbacks. Only applicable for + * rollbacks that have been committed. */ public int getCommittedSessionId() { return mCommittedSessionId; @@ -96,6 +115,7 @@ public final class RollbackInfo implements Parcelable { /** * Sets the session ID for the committed rollback for staged rollbacks. + * * @hide */ public void setCommittedSessionId(int sessionId) { @@ -103,15 +123,40 @@ public final class RollbackInfo implements Parcelable { } /** - * Gets the list of package versions that motivated this rollback. - * As provided to {@link #commitRollback} when the rollback was committed. - * This is only applicable for rollbacks that have been committed. + * Gets the list of package versions that motivated this rollback. As provided to {@link + * #commitRollback} when the rollback was committed. This is only applicable for rollbacks that + * have been committed. */ @NonNull public List<VersionedPackage> getCausePackages() { return mCausePackages; } + /** + * Get rollback impact level. Refer {@link + * android.content.pm.PackageInstaller.SessionParams#setRollbackImpactLevel(int)} for more info + * on impact level. + * + * @hide + */ + @TestApi + @FlaggedApi(Flags.FLAG_RECOVERABILITY_DETECTION) + public @PackageManager.RollbackImpactLevel int getRollbackImpactLevel() { + return mRollbackImpactLevel; + } + + /** + * Set rollback impact level. Refer {@link + * android.content.pm.PackageInstaller.SessionParams#setRollbackImpactLevel(int)} for more info + * on impact level. + * + * @hide + */ + public void setRollbackImpactLevel( + @PackageManager.RollbackImpactLevel int rollbackImpactLevel) { + mRollbackImpactLevel = rollbackImpactLevel; + } + @Override public int describeContents() { return 0; @@ -124,16 +169,17 @@ public final class RollbackInfo implements Parcelable { out.writeBoolean(mIsStaged); out.writeTypedList(mCausePackages); out.writeInt(mCommittedSessionId); + out.writeInt(mRollbackImpactLevel); } public static final @android.annotation.NonNull Parcelable.Creator<RollbackInfo> CREATOR = new Parcelable.Creator<RollbackInfo>() { - public RollbackInfo createFromParcel(Parcel in) { - return new RollbackInfo(in); - } - - public RollbackInfo[] newArray(int size) { - return new RollbackInfo[size]; - } - }; + public RollbackInfo createFromParcel(Parcel in) { + return new RollbackInfo(in); + } + + public RollbackInfo[] newArray(int size) { + return new RollbackInfo[size]; + } + }; } diff --git a/core/java/android/net/flags.aconfig b/core/java/android/net/flags.aconfig index 0ad1804f402c..311dc09eb516 100644 --- a/core/java/android/net/flags.aconfig +++ b/core/java/android/net/flags.aconfig @@ -1,50 +1,11 @@ -package: "com.android.net.flags" +package: "android.net.platform.flags" -flag { - name: "track_multiple_network_activities" - namespace: "android_core_networking" - description: "NetworkActivityTracker tracks multiple networks including non default networks" - bug: "267870186" -} - -flag { - name: "forbidden_capability" - namespace: "android_core_networking" - description: "This flag controls the forbidden capability API" - bug: "302997505" -} - -flag { - name: "set_data_saver_via_cm" - namespace: "android_core_networking" - description: "Set data saver through ConnectivityManager API" - bug: "297836825" -} - -flag { - name: "support_is_uid_networking_blocked" - namespace: "android_core_networking" - description: "This flag controls whether isUidNetworkingBlocked is supported" - bug: "297836825" -} - -flag { - name: "basic_background_restrictions_enabled" - namespace: "android_core_networking" - description: "Block network access for apps in a low importance background state" - bug: "304347838" -} - -flag { - name: "register_nsd_offload_engine" - namespace: "android_core_networking" - description: "The flag controls the access for registerOffloadEngine API in NsdManager" - bug: "294777050" -} +# This file contains aconfig flags used from platform code +# Flags used for module APIs must be in aconfig files under each modules flag { name: "ipsec_transform_state" - namespace: "android_core_networking_ipsec" + namespace: "core_networking_ipsec" description: "The flag controls the access for getIpSecTransformState and IpSecTransformState" bug: "308011229" } diff --git a/core/java/android/net/thread/flags.aconfig b/core/java/android/net/thread/flags.aconfig index 6e72f8ebd8d1..ff762d78c412 100644 --- a/core/java/android/net/thread/flags.aconfig +++ b/core/java/android/net/thread/flags.aconfig @@ -1,8 +1,18 @@ package: "com.android.net.thread.flags" +# This file contains aconfig flags used from platform code +# Flags used for module APIs must be in aconfig files under each modules + flag { name: "thread_user_restriction_enabled" namespace: "thread_network" description: "Controls whether user restriction on thread networks is enabled" bug: "307679182" } + +flag { + name: "thread_enabled_platform" + namespace: "thread_network" + description: "Controls whether the Android Thread feature is enabled" + bug: "301473012" +} diff --git a/core/java/android/os/OWNERS b/core/java/android/os/OWNERS index 2145c1aa82c8..19a3ba01a4ba 100644 --- a/core/java/android/os/OWNERS +++ b/core/java/android/os/OWNERS @@ -95,3 +95,6 @@ per-file *SecurityStateManager* = file:/SECURITY_STATE_OWNERS # SystemConfig per-file ISystemConfig.aidl = file:/PACKAGE_MANAGER_OWNERS per-file SystemConfigManager.java = file:/PACKAGE_MANAGER_OWNERS + +# ProfilingService +per-file ProfilingServiceManager.java = file:/PERFORMANCE_OWNERS diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index cdef20afb11d..f60a8a48289c 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -1867,7 +1867,7 @@ public class UserManager { * @see DevicePolicyManager#clearUserRestriction(ComponentName, String) * @see #getUserRestrictions() */ - @FlaggedApi("com.android.net.thread.flags.thread_user_restriction_enabled") + @FlaggedApi(com.android.net.thread.flags.Flags.FLAG_THREAD_USER_RESTRICTION_ENABLED) public static final String DISALLOW_THREAD_NETWORK = "no_thread_network"; /** diff --git a/core/java/android/os/storage/OWNERS b/core/java/android/os/storage/OWNERS index bf22dccce9d4..5e0a5635d4bd 100644 --- a/core/java/android/os/storage/OWNERS +++ b/core/java/android/os/storage/OWNERS @@ -10,7 +10,6 @@ gargshivam@google.com krishang@google.com riyaghai@google.com sahanas@google.com -sergeynv@google.com shikhamalhotra@google.com shubhisaxena@google.com tylersaunders@google.com diff --git a/core/java/android/security/flags.aconfig b/core/java/android/security/flags.aconfig index 43163b3b9051..76314546b4f0 100644 --- a/core/java/android/security/flags.aconfig +++ b/core/java/android/security/flags.aconfig @@ -15,10 +15,11 @@ flag { } flag { - name: "mgf1_digest_setter" + name: "mgf1_digest_setter_v2" namespace: "hardware_backed_security" description: "Feature flag for mgf1 digest setter in key generation and import parameters." bug: "308378912" + is_fixed_read_only: true } flag { diff --git a/core/java/android/service/ondeviceintelligence/OWNERS b/core/java/android/service/ondeviceintelligence/OWNERS new file mode 100644 index 000000000000..09774f78d712 --- /dev/null +++ b/core/java/android/service/ondeviceintelligence/OWNERS @@ -0,0 +1 @@ +file:/core/java/android/app/ondeviceintelligence/OWNERS diff --git a/core/java/android/service/voice/OWNERS b/core/java/android/service/voice/OWNERS index ec4410086edf..763c79e20846 100644 --- a/core/java/android/service/voice/OWNERS +++ b/core/java/android/service/voice/OWNERS @@ -4,4 +4,4 @@ include /core/java/android/app/assist/OWNERS # The owner here should not be assist owner liangyuchen@google.com -tuanng@google.com +adudani@google.com diff --git a/core/java/android/tracing/OWNERS b/core/java/android/tracing/OWNERS index 2ebe2e9e2761..f67844de44ea 100644 --- a/core/java/android/tracing/OWNERS +++ b/core/java/android/tracing/OWNERS @@ -1,6 +1,4 @@ carmenjackson@google.com kevinjeon@google.com -pablogamito@google.com -natanieljr@google.com -keanmariotti@google.com +include platform/development:/tools/winscope/OWNERS include platform/external/perfetto:/OWNERS diff --git a/core/java/com/android/internal/colorextraction/OWNERS b/core/java/com/android/internal/colorextraction/OWNERS index ffade1ec4ebd..041559cd048d 100644 --- a/core/java/com/android/internal/colorextraction/OWNERS +++ b/core/java/com/android/internal/colorextraction/OWNERS @@ -1,3 +1,2 @@ -dupin@google.com cinek@google.com -jamesoleary@google.com +arteiro@google.com diff --git a/core/java/com/android/internal/protolog/OWNERS b/core/java/com/android/internal/protolog/OWNERS new file mode 100644 index 000000000000..18cf2be9f7df --- /dev/null +++ b/core/java/com/android/internal/protolog/OWNERS @@ -0,0 +1,3 @@ +# ProtoLog owners +# Bug component: 1157642 +include platform/development:/tools/winscope/OWNERS diff --git a/core/jni/android_os_VintfObject.cpp b/core/jni/android_os_VintfObject.cpp index ce4a33735c6d..8dc9d0aa578e 100644 --- a/core/jni/android_os_VintfObject.cpp +++ b/core/jni/android_os_VintfObject.cpp @@ -39,6 +39,7 @@ using vintf::CompatibilityMatrix; using vintf::HalManifest; using vintf::Level; using vintf::SchemaType; +using vintf::SepolicyVersion; using vintf::to_string; using vintf::toXml; using vintf::Version; @@ -139,7 +140,7 @@ static jstring android_os_VintfObject_getPlatformSepolicyVersion(JNIEnv* env, jc return nullptr; } - Version latest; + SepolicyVersion latest; for (const auto& range : versions) { latest = std::max(latest, range.maxVer()); } diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp index 9c40a28dfd81..2a2e9038c27a 100644 --- a/core/jni/com_android_internal_os_Zygote.cpp +++ b/core/jni/com_android_internal_os_Zygote.cpp @@ -665,8 +665,9 @@ static void EnableKeepCapabilities(fail_fn_t fail_fn) { } } -static void DropCapabilitiesBoundingSet(fail_fn_t fail_fn) { +static void DropCapabilitiesBoundingSet(fail_fn_t fail_fn, jlong bounding_capabilities) { for (int i = 0; prctl(PR_CAPBSET_READ, i, 0, 0, 0) >= 0; i++) {; + if ((1LL << i) & bounding_capabilities) continue; if (prctl(PR_CAPBSET_DROP, i, 0, 0, 0) == -1) { if (errno == EINVAL) { ALOGE("prctl(PR_CAPBSET_DROP) failed with EINVAL. Please verify " @@ -678,6 +679,27 @@ static void DropCapabilitiesBoundingSet(fail_fn_t fail_fn) { } } +static bool MatchGid(JNIEnv* env, jintArray gids, jint gid, jint gid_to_find) { + if (gid == gid_to_find) return true; + + if (gids == nullptr) return false; + + jsize gids_num = env->GetArrayLength(gids); + ScopedIntArrayRO native_gid_proxy(env, gids); + + if (native_gid_proxy.get() == nullptr) { + RuntimeAbort(env, __LINE__, "Bad gids array"); + } + + for (int gids_index = 0; gids_index < gids_num; ++gids_index) { + if (native_gid_proxy[gids_index] == gid_to_find) { + return true; + } + } + + return false; +} + static void SetInheritable(uint64_t inheritable, fail_fn_t fail_fn) { __user_cap_header_struct capheader; memset(&capheader, 0, sizeof(capheader)); @@ -1742,9 +1764,9 @@ static void BindMountStorageDirs(JNIEnv* env, jobjectArray pkg_data_info_list, // Utility routine to specialize a zygote child process. static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jlong permitted_capabilities, - jlong effective_capabilities, jint mount_external, - jstring managed_se_info, jstring managed_nice_name, - bool is_system_server, bool is_child_zygote, + jlong effective_capabilities, jlong bounding_capabilities, + jint mount_external, jstring managed_se_info, + jstring managed_nice_name, bool is_system_server, bool is_child_zygote, jstring managed_instruction_set, jstring managed_app_data_dir, bool is_top_app, jobjectArray pkg_data_info_list, jobjectArray allowlisted_data_info_list, bool mount_data_dirs, @@ -1758,6 +1780,9 @@ static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids, auto instruction_set = extract_fn(managed_instruction_set); auto app_data_dir = extract_fn(managed_app_data_dir); + // Permit bounding capabilities + permitted_capabilities |= bounding_capabilities; + // Keep capabilities across UID change, unless we're staying root. if (uid != 0) { EnableKeepCapabilities(fail_fn); @@ -1765,7 +1790,7 @@ static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids, SetInheritable(permitted_capabilities, fail_fn); - DropCapabilitiesBoundingSet(fail_fn); + DropCapabilitiesBoundingSet(fail_fn, bounding_capabilities); bool need_pre_initialize_native_bridge = !is_system_server && instruction_set.has_value() && android::NativeBridgeAvailable() && @@ -2028,6 +2053,23 @@ static uint64_t GetEffectiveCapabilityMask(JNIEnv* env) { return capdata[0].effective | (static_cast<uint64_t>(capdata[1].effective) << 32); } +static jlong CalculateBoundingCapabilities(JNIEnv* env, jint uid, jint gid, jintArray gids) { + jlong capabilities = 0; + + /* + * Grant CAP_SYS_NICE to CapInh/CapPrm/CapBnd for processes that can spawn + * VMs. This enables processes to execve on binaries with elevated + * capabilities if its file capability bits are set. This does not grant + * capability to the parent process(that spawns the VM) as the effective + * bits are not set. + */ + if (MatchGid(env, gids, gid, AID_VIRTUALMACHINE)) { + capabilities |= (1LL << CAP_SYS_NICE); + } + + return capabilities; +} + static jlong CalculateCapabilities(JNIEnv* env, jint uid, jint gid, jintArray gids, bool is_child_zygote) { jlong capabilities = 0; @@ -2061,26 +2103,7 @@ static jlong CalculateCapabilities(JNIEnv* env, jint uid, jint gid, jintArray gi * Grant CAP_BLOCK_SUSPEND to processes that belong to GID "wakelock" */ - bool gid_wakelock_found = false; - if (gid == AID_WAKELOCK) { - gid_wakelock_found = true; - } else if (gids != nullptr) { - jsize gids_num = env->GetArrayLength(gids); - ScopedIntArrayRO native_gid_proxy(env, gids); - - if (native_gid_proxy.get() == nullptr) { - RuntimeAbort(env, __LINE__, "Bad gids array"); - } - - for (int gids_index = 0; gids_index < gids_num; ++gids_index) { - if (native_gid_proxy[gids_index] == AID_WAKELOCK) { - gid_wakelock_found = true; - break; - } - } - } - - if (gid_wakelock_found) { + if (MatchGid(env, gids, gid, AID_WAKELOCK)) { capabilities |= (1LL << CAP_BLOCK_SUSPEND); } @@ -2256,6 +2279,11 @@ pid_t zygote::ForkCommon(JNIEnv* env, bool is_system_server, const std::vector<int>& fds_to_ignore, bool is_priority_fork, bool purge) { + ATRACE_CALL(); + if (is_priority_fork) { + setpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_MAX); + } + SetSignalHandlers(); // Curry a failure function. @@ -2341,6 +2369,10 @@ pid_t zygote::ForkCommon(JNIEnv* env, bool is_system_server, // We blocked SIGCHLD prior to a fork, we unblock it here. UnblockSignal(SIGCHLD, fail_fn); + if (is_priority_fork && pid != 0) { + setpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_DEFAULT); + } + return pid; } @@ -2357,6 +2389,7 @@ static jint com_android_internal_os_Zygote_nativeForkAndSpecialize( jobjectArray pkg_data_info_list, jobjectArray allowlisted_data_info_list, jboolean mount_data_dirs, jboolean mount_storage_dirs) { jlong capabilities = CalculateCapabilities(env, uid, gid, gids, is_child_zygote); + jlong bounding_capabilities = CalculateBoundingCapabilities(env, uid, gid, gids); if (UNLIKELY(managed_fds_to_close == nullptr)) { zygote::ZygoteFailure(env, "zygote", nice_name, @@ -2395,10 +2428,10 @@ static jint com_android_internal_os_Zygote_nativeForkAndSpecialize( if (pid == 0) { SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits, capabilities, capabilities, - mount_external, se_info, nice_name, false, is_child_zygote == JNI_TRUE, - instruction_set, app_data_dir, is_top_app == JNI_TRUE, pkg_data_info_list, - allowlisted_data_info_list, mount_data_dirs == JNI_TRUE, - mount_storage_dirs == JNI_TRUE); + bounding_capabilities, mount_external, se_info, nice_name, false, + is_child_zygote == JNI_TRUE, instruction_set, app_data_dir, + is_top_app == JNI_TRUE, pkg_data_info_list, allowlisted_data_info_list, + mount_data_dirs == JNI_TRUE, mount_storage_dirs == JNI_TRUE); } return pid; } @@ -2408,6 +2441,7 @@ static jint com_android_internal_os_Zygote_nativeForkSystemServer( JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jlong permitted_capabilities, jlong effective_capabilities) { + ATRACE_CALL(); std::vector<int> fds_to_close(MakeUsapPipeReadFDVector()), fds_to_ignore(fds_to_close); @@ -2431,7 +2465,7 @@ static jint com_android_internal_os_Zygote_nativeForkSystemServer( // System server prcoess does not need data isolation so no need to // know pkg_data_info_list. SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits, permitted_capabilities, - effective_capabilities, MOUNT_EXTERNAL_DEFAULT, nullptr, nullptr, true, + effective_capabilities, 0, MOUNT_EXTERNAL_DEFAULT, nullptr, nullptr, true, false, nullptr, nullptr, /* is_top_app= */ false, /* pkg_data_info_list */ nullptr, /* allowlisted_data_info_list */ nullptr, false, false); @@ -2483,6 +2517,7 @@ static jint com_android_internal_os_Zygote_nativeForkApp(JNIEnv* env, jintArray managed_session_socket_fds, jboolean args_known, jboolean is_priority_fork) { + ATRACE_CALL(); std::vector<int> session_socket_fds = ExtractJIntArray(env, "USAP", nullptr, managed_session_socket_fds) .value_or(std::vector<int>()); @@ -2498,6 +2533,7 @@ int zygote::forkApp(JNIEnv* env, bool args_known, bool is_priority_fork, bool purge) { + ATRACE_CALL(); std::vector<int> fds_to_close(MakeUsapPipeReadFDVector()), fds_to_ignore(fds_to_close); @@ -2588,12 +2624,13 @@ static void com_android_internal_os_Zygote_nativeSpecializeAppProcess( jobjectArray allowlisted_data_info_list, jboolean mount_data_dirs, jboolean mount_storage_dirs) { jlong capabilities = CalculateCapabilities(env, uid, gid, gids, is_child_zygote); + jlong bounding_capabilities = CalculateBoundingCapabilities(env, uid, gid, gids); SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits, capabilities, capabilities, - mount_external, se_info, nice_name, false, is_child_zygote == JNI_TRUE, - instruction_set, app_data_dir, is_top_app == JNI_TRUE, pkg_data_info_list, - allowlisted_data_info_list, mount_data_dirs == JNI_TRUE, - mount_storage_dirs == JNI_TRUE); + bounding_capabilities, mount_external, se_info, nice_name, false, + is_child_zygote == JNI_TRUE, instruction_set, app_data_dir, + is_top_app == JNI_TRUE, pkg_data_info_list, allowlisted_data_info_list, + mount_data_dirs == JNI_TRUE, mount_storage_dirs == JNI_TRUE); } /** diff --git a/core/proto/OWNERS b/core/proto/OWNERS index 381580b7628e..00d90cc19c80 100644 --- a/core/proto/OWNERS +++ b/core/proto/OWNERS @@ -21,7 +21,6 @@ per-file background_install_control.proto = wenhaowang@google.com,georgechan@goo per-file android/content/intent.proto = file:/PACKAGE_MANAGER_OWNERS # Biometrics -jaggies@google.com jbolinger@google.com # Launcher diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index f5635f450268..04a70df6920f 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -2237,7 +2237,7 @@ <!-- @SystemApi @hide Allows changing Thread network state and access to Thread network credentials such as Network Key and PSKc. <p>Not for use by third-party applications. - @FlaggedApi("com.android.net.thread.flags.thread_enabled") --> + @FlaggedApi("com.android.net.thread.flags.thread_enabled_platform") --> <permission android:name="android.permission.THREAD_NETWORK_PRIVILEGED" android:protectionLevel="signature|privileged" /> @@ -5758,7 +5758,7 @@ <permission android:name="android.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS" android:protectionLevel="signature|privileged" /> - <!-- Allows an application to collect usage infomation about brightness slider changes. + <!-- Allows an application to collect usage information about brightness slider changes. <p>Not for use by third-party applications.</p> @hide @SystemApi diff --git a/core/res/OWNERS b/core/res/OWNERS index f24c3f59155a..36daa7d5c836 100644 --- a/core/res/OWNERS +++ b/core/res/OWNERS @@ -8,7 +8,6 @@ dupin@google.com hackbod@android.com hackbod@google.com ilyamaty@google.com -jaggies@google.com jbolinger@google.com jsharkey@android.com jsharkey@google.com diff --git a/core/res/res/layout/app_perms_summary.xml b/core/res/res/layout/app_perms_summary.xml index b8d93aca755b..509b98829883 100644 --- a/core/res/res/layout/app_perms_summary.xml +++ b/core/res/res/layout/app_perms_summary.xml @@ -14,7 +14,7 @@ limitations under the License. --> -<!-- Describes permission item consisting of a group name and the list of permisisons under the group --> +<!-- Describes permission item consisting of a group name and the list of permissions under the group --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" diff --git a/core/res/res/xml/sms_short_codes.xml b/core/res/res/xml/sms_short_codes.xml index 9bb249999d99..61e6a36839ff 100644 --- a/core/res/res/xml/sms_short_codes.xml +++ b/core/res/res/xml/sms_short_codes.xml @@ -127,7 +127,7 @@ <!-- France: 5 digits, free: 3xxxx, premium [4-8]xxxx, plus EU: http://clients.txtnation.com/entries/161972-france-premium-sms-short-code-requirements, visual voicemail code for Orange: 21101 --> - <shortcode country="fr" premium="[4-8]\\d{4}" free="3\\d{4}|116\\d{3}|21101|20366|555|2051" /> + <shortcode country="fr" premium="[4-8]\\d{4}" free="3\\d{4}|116\\d{3}|21101|20366|555|2051|33033" /> <!-- United Kingdom (Great Britain): 4-6 digits, common codes [5-8]xxxx, plus EU: http://www.short-codes.com/media/Co-regulatoryCodeofPracticeforcommonshortcodes170206.pdf, @@ -150,6 +150,9 @@ http://clients.txtnation.com/entries/209633-hungary-premium-sms-short-code-regulations --> <shortcode country="hu" pattern="[01](?:\\d{3}|\\d{9})" premium="0691227910|1784" free="116\\d{3}" /> + <!-- Honduras --> + <shortcode country="hn" pattern="\\d{4,6}" free="466453" /> + <!-- India: 1-5 digits (standard system default, not country specific) --> <shortcode country="in" pattern="\\d{1,5}" free="59336|53969" /> @@ -171,7 +174,7 @@ <shortcode country="jp" pattern="\\d{1,5}" free="8083" /> <!-- Kenya: 5 digits, known premium codes listed --> - <shortcode country="ke" pattern="\\d{5}" free="21725|21562|40520|23342|40023" /> + <shortcode country="ke" pattern="\\d{5}" free="21725|21562|40520|23342|40023|24088|23054" /> <!-- Kyrgyzstan: 4 digits, known premium codes listed --> <shortcode country="kg" pattern="\\d{4}" premium="415[2367]|444[69]" /> @@ -183,7 +186,7 @@ <shortcode country="kz" pattern="\\d{4}" premium="335[02]|4161|444[469]|77[2359]0|8444|919[3-5]|968[2-5]" /> <!-- Kuwait: 1-5 digits (standard system default, not country specific) --> - <shortcode country="kw" pattern="\\d{1,5}" free="1378|50420|94006|55991" /> + <shortcode country="kw" pattern="\\d{1,5}" free="1378|50420|94006|55991|50976" /> <!-- Lithuania: 3-5 digits, known premium codes listed, plus EU --> <shortcode country="lt" pattern="\\d{3,5}" premium="13[89]1|1394|16[34]5" free="116\\d{3}|1399|1324" /> @@ -195,9 +198,18 @@ <!-- Latvia: 4 digits, known premium codes listed, plus EU --> <shortcode country="lv" pattern="\\d{4}" premium="18(?:19|63|7[1-4])" free="116\\d{3}|1399" /> + <!-- Morocco: 1-5 digits (standard system default, not country specific) --> + <shortcode country="ma" pattern="\\d{1,5}" free="53819" /> + <!-- Macedonia: 1-6 digits (not confirmed), known premium codes listed --> <shortcode country="mk" pattern="\\d{1,6}" free="129005|122" /> + <!-- Malawi: 1-5 digits (standard system default, not country specific) --> + <shortcode country="mw" pattern="\\d{1,5}" free="4276" /> + + <!-- Mozambique: 1-5 digits (standard system default, not country specific) --> + <shortcode country="mz" pattern="\\d{1,5}" free="1714" /> + <!-- Mexico: 4-5 digits (not confirmed), known premium codes listed --> <shortcode country="mx" pattern="\\d{4,6}" premium="53035|7766" free="26259|46645|50025|50052|5050|76551|88778|9963|91101|45453|550346" /> @@ -207,6 +219,9 @@ <!-- Namibia: 1-5 digits (standard system default, not country specific) --> <shortcode country="na" pattern="\\d{1,5}" free="40005" /> + <!-- Nicaragua --> + <shortcode country="ni" pattern="\\d{4,6}" free="466453" /> + <!-- The Netherlands, 4 digits, known premium codes listed, plus EU --> <shortcode country="nl" pattern="\\d{4}" premium="4466|5040" free="116\\d{3}|2223|6225|2223|1662" /> @@ -219,8 +234,8 @@ <!-- New Zealand: 3-4 digits, known premium codes listed --> <shortcode country="nz" pattern="\\d{3,4}" premium="3903|8995|4679" free="1737|176|2141|3067|3068|3110|3876|4006|4053|4061|4062|4202|4300|4334|4412|4575|5626|8006|8681" /> - <!-- Peru: 4-5 digits (not confirmed), known premium codes listed --> - <shortcode country="pe" pattern="\\d{4,5}" free="9963|40778" /> + <!-- Peru: 4-6 digits (not confirmed), known premium codes listed --> + <shortcode country="pe" pattern="\\d{4,6}" free="9963|40778|301303" /> <!-- Philippines --> <shortcode country="ph" pattern="\\d{1,5}" free="2147|5495|5496" /> @@ -269,6 +284,12 @@ <!-- Slovakia: 4 digits (premium), plus EU: http://www.cmtelecom.com/premium-sms/slovakia --> <shortcode country="sk" premium="\\d{4}" free="116\\d{3}|8000" /> + <!-- Senegal(SN): 1-5 digits (standard system default, not country specific) --> + <shortcode country="sn" pattern="\\d{1,5}" free="21215" /> + + <!-- El Salvador(SV): 1-5 digits (standard system default, not country specific) --> + <shortcode country="sv" pattern="\\d{4,6}" free="466453" /> + <!-- Taiwan --> <shortcode country="tw" pattern="\\d{4}" free="1922" /> @@ -278,15 +299,21 @@ <!-- Tajikistan: 4 digits, known premium codes listed --> <shortcode country="tj" pattern="\\d{4}" premium="11[3-7]1|4161|4333|444[689]" /> + <!-- Tanzania: 1-5 digits (standard system default, not country specific) --> + <shortcode country="tz" pattern="\\d{1,5}" free="15046|15234" /> + <!-- Turkey --> <shortcode country="tr" pattern="\\d{1,5}" free="7529|5528|6493|3193" /> <!-- Ukraine: 4 digits, known premium codes listed --> <shortcode country="ua" pattern="\\d{4}" premium="444[3-9]|70[579]4|7540" /> + <!-- Uganda(UG): 4 digits (standard system default, not country specific) --> + <shortcode country="ug" pattern="\\d{4}" free="8000" /> + <!-- USA: 5-6 digits (premium codes from https://www.premiumsmsrefunds.com/ShortCodes.htm), visual voicemail code for T-Mobile: 122 --> - <shortcode country="us" pattern="\\d{5,6}" premium="20433|21(?:344|472)|22715|23(?:333|847)|24(?:15|28)0|25209|27(?:449|606|663)|28498|305(?:00|83)|32(?:340|941)|33(?:166|786|849)|34746|35(?:182|564)|37975|38(?:135|146|254)|41(?:366|463)|42335|43(?:355|500)|44(?:578|711|811)|45814|46(?:157|173|327)|46666|47553|48(?:221|277|669)|50(?:844|920)|51(?:062|368)|52944|54(?:723|892)|55928|56483|57370|59(?:182|187|252|342)|60339|61(?:266|982)|62478|64(?:219|898)|65(?:108|500)|69(?:208|388)|70877|71851|72(?:078|087|465)|73(?:288|588|882|909|997)|74(?:034|332|815)|76426|79213|81946|83177|84(?:103|685)|85797|86(?:234|236|666)|89616|90(?:715|842|938)|91(?:362|958)|94719|95297|96(?:040|666|835|969)|97(?:142|294|688)|99(?:689|796|807)" standard="44567|244444" free="122|87902|21696|24614|28003|30356|33669|40196|41064|41270|43753|44034|46645|52413|56139|57969|61785|66975|75136|76227|81398|83952|85140|86566|86799|95737|96684|99245|611611" /> + <shortcode country="us" pattern="\\d{5,6}" premium="20433|21(?:344|472)|22715|23(?:333|847)|24(?:15|28)0|25209|27(?:449|606|663)|28498|305(?:00|83)|32(?:340|941)|33(?:166|786|849)|34746|35(?:182|564)|37975|38(?:135|146|254)|41(?:366|463)|42335|43(?:355|500)|44(?:578|711|811)|45814|46(?:157|173|327)|46666|47553|48(?:221|277|669)|50(?:844|920)|51(?:062|368)|52944|54(?:723|892)|55928|56483|57370|59(?:182|187|252|342)|60339|61(?:266|982)|62478|64(?:219|898)|65(?:108|500)|69(?:208|388)|70877|71851|72(?:078|087|465)|73(?:288|588|882|909|997)|74(?:034|332|815)|76426|79213|81946|83177|84(?:103|685)|85797|86(?:234|236|666)|89616|90(?:715|842|938)|91(?:362|958)|94719|95297|96(?:040|666|835|969)|97(?:142|294|688)|99(?:689|796|807)" standard="44567|244444" free="122|87902|21696|24614|28003|30356|33669|40196|41064|41270|43753|44034|46645|52413|56139|57969|61785|66975|75136|76227|81398|83952|85140|86566|86799|95737|96684|99245|611611|96831" /> <!-- Vietnam: 1-5 digits (standard system default, not country specific) --> <shortcode country="vn" pattern="\\d{1,5}" free="5001|9055" /> diff --git a/core/tests/BroadcastRadioTests/Android.bp b/core/tests/BroadcastRadioTests/Android.bp index 054d10c336e6..39ea6e645201 100644 --- a/core/tests/BroadcastRadioTests/Android.bp +++ b/core/tests/BroadcastRadioTests/Android.bp @@ -18,6 +18,7 @@ package { // all of the 'license_kinds' from "frameworks_base_license" // to get the below license kinds: // SPDX-license-identifier-Apache-2.0 + default_team: "trendy_team_aaos_framework", default_applicable_licenses: ["frameworks_base_license"], } diff --git a/core/tests/BroadcastRadioTests/src/android/hardware/radio/TunerAdapterTest.java b/core/tests/BroadcastRadioTests/src/android/hardware/radio/TunerAdapterTest.java index 6a6a951c94c8..00afba8d3a7f 100644 --- a/core/tests/BroadcastRadioTests/src/android/hardware/radio/TunerAdapterTest.java +++ b/core/tests/BroadcastRadioTests/src/android/hardware/radio/TunerAdapterTest.java @@ -264,7 +264,7 @@ public final class TunerAdapterTest { int scanStatus = mRadioTuner.scan(RadioTuner.DIRECTION_DOWN, /* skipSubChannel= */ false); verify(mTunerMock).seek(/* directionDown= */ true, /* skipSubChannel= */ false); - assertWithMessage("Status for scaning") + assertWithMessage("Status for scanning") .that(scanStatus).isEqualTo(RadioManager.STATUS_OK); verify(mCallbackMock, timeout(CALLBACK_TIMEOUT_MS)).onProgramInfoChanged(FM_PROGRAM_INFO); } diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerStressTestRunner.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerStressTestRunner.java index 0806fa0b9879..db95d7af5d52 100644 --- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerStressTestRunner.java +++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerStressTestRunner.java @@ -99,7 +99,7 @@ public class ConnectivityManagerStressTestRunner extends InstrumentationTestRunn } } - public int getSoftApInterations() { + public int getSoftApIterations() { return mSoftApIterations; } diff --git a/data/etc/platform.xml b/data/etc/platform.xml index c4530f64a82d..cb803f7babfa 100644 --- a/data/etc/platform.xml +++ b/data/etc/platform.xml @@ -124,6 +124,10 @@ <group gid="security_log_writer" /> </permission> + <permission name="android.permission.MANAGE_VIRTUAL_MACHINE"> + <group gid="virtualmachine" /> + </permission> + <!-- These are permissions that were mapped to gids but we need to keep them here until an upgrade from L to the current version is to be supported. These permissions are built-in diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java index 1da8e189d768..d915b746e0cc 100644 --- a/graphics/java/android/graphics/BitmapFactory.java +++ b/graphics/java/android/graphics/BitmapFactory.java @@ -25,10 +25,13 @@ import android.content.res.AssetManager; import android.content.res.Resources; import android.os.Build; import android.os.Trace; +import android.system.OsConstants; import android.util.DisplayMetrics; import android.util.Log; import android.util.TypedValue; +import libcore.io.IoBridge; + import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.IOException; @@ -523,19 +526,19 @@ public class BitmapFactory { public static Bitmap decodeFile(String pathName, Options opts) { validate(opts); Bitmap bm = null; - InputStream stream = null; + FileDescriptor fd = null; try { - stream = new FileInputStream(pathName); - bm = decodeStream(stream, null, opts); + fd = IoBridge.open(pathName, OsConstants.O_RDONLY); + bm = decodeFileDescriptor(fd, null, opts); } catch (Exception e) { /* do nothing. If the exception happened on open, bm will be null. */ - Log.e("BitmapFactory", "Unable to decode stream: " + e); + Log.e("BitmapFactory", "Unable to decode file: " + e); } finally { - if (stream != null) { + if (fd != null) { try { - stream.close(); + IoBridge.closeAndSignalBlockedThreads(fd); } catch (IOException e) { // do nothing here } diff --git a/graphics/java/android/view/PixelCopy.java b/graphics/java/android/view/PixelCopy.java index 0e198d5c56ec..1200ff9f2ba2 100644 --- a/graphics/java/android/view/PixelCopy.java +++ b/graphics/java/android/view/PixelCopy.java @@ -96,7 +96,7 @@ public final class PixelCopy { * * The contents of the source will be scaled to fit exactly inside the bitmap. * The pixel format of the source buffer will be converted, as part of the copy, - * to fit the the bitmap's {@link Bitmap.Config}. The most recently queued buffer + * to fit the bitmap's {@link Bitmap.Config}. The most recently queued buffer * in the SurfaceView's Surface will be used as the source of the copy. * * @param source The source from which to copy @@ -117,7 +117,7 @@ public final class PixelCopy { * * The contents of the source will be scaled to fit exactly inside the bitmap. * The pixel format of the source buffer will be converted, as part of the copy, - * to fit the the bitmap's {@link Bitmap.Config}. The most recently queued buffer + * to fit the bitmap's {@link Bitmap.Config}. The most recently queued buffer * in the SurfaceView's Surface will be used as the source of the copy. * * @param source The source from which to copy @@ -143,7 +143,7 @@ public final class PixelCopy { * * The contents of the source will be scaled to fit exactly inside the bitmap. * The pixel format of the source buffer will be converted, as part of the copy, - * to fit the the bitmap's {@link Bitmap.Config}. The most recently queued buffer + * to fit the bitmap's {@link Bitmap.Config}. The most recently queued buffer * in the Surface will be used as the source of the copy. * * @param source The source from which to copy @@ -164,7 +164,7 @@ public final class PixelCopy { * * The contents of the source rect will be scaled to fit exactly inside the bitmap. * The pixel format of the source buffer will be converted, as part of the copy, - * to fit the the bitmap's {@link Bitmap.Config}. The most recently queued buffer + * to fit the bitmap's {@link Bitmap.Config}. The most recently queued buffer * in the Surface will be used as the source of the copy. * * @param source The source from which to copy @@ -201,7 +201,7 @@ public final class PixelCopy { * * The contents of the source will be scaled to fit exactly inside the bitmap. * The pixel format of the source buffer will be converted, as part of the copy, - * to fit the the bitmap's {@link Bitmap.Config}. The most recently queued buffer + * to fit the bitmap's {@link Bitmap.Config}. The most recently queued buffer * in the Window's Surface will be used as the source of the copy. * * Note: This is limited to being able to copy from Window's with a non-null @@ -231,7 +231,7 @@ public final class PixelCopy { * * The contents of the source rect will be scaled to fit exactly inside the bitmap. * The pixel format of the source buffer will be converted, as part of the copy, - * to fit the the bitmap's {@link Bitmap.Config}. The most recently queued buffer + * to fit the bitmap's {@link Bitmap.Config}. The most recently queued buffer * in the Window's Surface will be used as the source of the copy. * * Note: This is limited to being able to copy from Window's with a non-null diff --git a/keystore/aaid/aidl/android/security/keystore/IKeyAttestationApplicationIdProvider.aidl b/keystore/aaid/aidl/android/security/keystore/IKeyAttestationApplicationIdProvider.aidl index c360cb8f281a..cfc5980e009a 100644 --- a/keystore/aaid/aidl/android/security/keystore/IKeyAttestationApplicationIdProvider.aidl +++ b/keystore/aaid/aidl/android/security/keystore/IKeyAttestationApplicationIdProvider.aidl @@ -20,8 +20,14 @@ import android.security.keystore.KeyAttestationApplicationId; /** @hide */ interface IKeyAttestationApplicationIdProvider { + const int ERROR_GET_ATTESTATION_APPLICATION_ID_FAILED = 1; + /** * Provides information describing the possible applications identified by a UID. + * + * In case of not getting package ids from uid return + * {@link #ERROR_GET_ATTESTATION_APPLICATION_ID_FAILED} to the caller. + * * @hide */ KeyAttestationApplicationId getKeyAttestationApplicationId(int uid); diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java index 4982f3732089..244fe3033dca 100644 --- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java +++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java @@ -618,7 +618,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu * @see #isMgf1DigestsSpecified() */ @NonNull - @FlaggedApi(android.security.Flags.FLAG_MGF1_DIGEST_SETTER) + @FlaggedApi(android.security.Flags.FLAG_MGF1_DIGEST_SETTER_V2) public @KeyProperties.DigestEnum Set<String> getMgf1Digests() { if (mMgf1Digests.isEmpty()) { throw new IllegalStateException("Mask generation function (MGF) not specified"); @@ -633,7 +633,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu * @see #getMgf1Digests() */ @NonNull - @FlaggedApi(android.security.Flags.FLAG_MGF1_DIGEST_SETTER) + @FlaggedApi(android.security.Flags.FLAG_MGF1_DIGEST_SETTER_V2) public boolean isMgf1DigestsSpecified() { return !mMgf1Digests.isEmpty(); } @@ -1292,7 +1292,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu * <p>See {@link KeyProperties}.{@code DIGEST} constants. */ @NonNull - @FlaggedApi(android.security.Flags.FLAG_MGF1_DIGEST_SETTER) + @FlaggedApi(android.security.Flags.FLAG_MGF1_DIGEST_SETTER_V2) public Builder setMgf1Digests(@NonNull @KeyProperties.DigestEnum String... mgf1Digests) { mMgf1Digests = Set.of(mgf1Digests); return this; diff --git a/keystore/java/android/security/keystore/KeyProtection.java b/keystore/java/android/security/keystore/KeyProtection.java index 7b6b2d142f95..2495d1a85864 100644 --- a/keystore/java/android/security/keystore/KeyProtection.java +++ b/keystore/java/android/security/keystore/KeyProtection.java @@ -401,7 +401,7 @@ public final class KeyProtection implements ProtectionParameter, UserAuthArgs { * @see #isMgf1DigestsSpecified() */ @NonNull - @FlaggedApi(android.security.Flags.FLAG_MGF1_DIGEST_SETTER) + @FlaggedApi(android.security.Flags.FLAG_MGF1_DIGEST_SETTER_V2) public @KeyProperties.DigestEnum Set<String> getMgf1Digests() { if (mMgf1Digests.isEmpty()) { throw new IllegalStateException("Mask generation function (MGF) not specified"); @@ -416,7 +416,7 @@ public final class KeyProtection implements ProtectionParameter, UserAuthArgs { * @see #getMgf1Digests() */ @NonNull - @FlaggedApi(android.security.Flags.FLAG_MGF1_DIGEST_SETTER) + @FlaggedApi(android.security.Flags.FLAG_MGF1_DIGEST_SETTER_V2) public boolean isMgf1DigestsSpecified() { return !mMgf1Digests.isEmpty(); } @@ -799,7 +799,7 @@ public final class KeyProtection implements ProtectionParameter, UserAuthArgs { * <p>See {@link KeyProperties}.{@code DIGEST} constants. */ @NonNull - @FlaggedApi(android.security.Flags.FLAG_MGF1_DIGEST_SETTER) + @FlaggedApi(android.security.Flags.FLAG_MGF1_DIGEST_SETTER_V2) public Builder setMgf1Digests(@Nullable @KeyProperties.DigestEnum String... mgf1Digests) { mMgf1Digests = Set.of(mgf1Digests); return this; diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java index 83ddfc5cf1a1..e6c652c14c71 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java @@ -974,7 +974,7 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato private static boolean getMgf1DigestSetterFlag() { try { - return Flags.mgf1DigestSetter(); + return Flags.mgf1DigestSetterV2(); } catch (SecurityException e) { Log.w(TAG, "Cannot read MGF1 Digest setter flag value", e); return false; diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java index 2d8c5a380c6b..e6a63b9c4c17 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java @@ -259,7 +259,7 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi { private static boolean getMgf1DigestSetterFlag() { try { - return Flags.mgf1DigestSetter(); + return Flags.mgf1DigestSetterV2(); } catch (SecurityException e) { Log.w(NAME, "Cannot read MGF1 Digest setter flag value", e); return false; diff --git a/media/java/android/media/AudioDevicePort.java b/media/java/android/media/AudioDevicePort.java index 9211c53a17bc..65cc1c478ce5 100644 --- a/media/java/android/media/AudioDevicePort.java +++ b/media/java/android/media/AudioDevicePort.java @@ -31,7 +31,7 @@ import java.util.List; * device at the boundary of the audio system. * In addition to base audio port attributes, the device descriptor contains: * - the device type (e.g AudioManager.DEVICE_OUT_SPEAKER) - * - the device address (e.g MAC adddress for AD2P sink). + * - the device address (e.g MAC address for AD2P sink). * @see AudioPort * @hide */ diff --git a/media/java/android/media/AudioHalVersionInfo.java b/media/java/android/media/AudioHalVersionInfo.java index efb33950022c..472cb3fefa97 100644 --- a/media/java/android/media/AudioHalVersionInfo.java +++ b/media/java/android/media/AudioHalVersionInfo.java @@ -76,9 +76,12 @@ public final class AudioHalVersionInfo implements Parcelable, Comparable<AudioHa /** * List of all valid Audio HAL versions. This list need to be in sync with sAudioHALVersions * defined in frameworks/av/media/libaudiohal/FactoryHal.cpp. + * + * Note: update {@link android.media.audio.cts.AudioHalVersionInfoTest} CTS accordingly if + * there is a change to supported versions. */ public static final @NonNull List<AudioHalVersionInfo> VERSIONS = - List.of(AIDL_1_0, HIDL_7_1, HIDL_7_0, HIDL_6_0, HIDL_5_0, HIDL_4_0); + List.of(AIDL_1_0, HIDL_7_1, HIDL_7_0, HIDL_6_0, HIDL_5_0); private static final String TAG = "AudioHalVersionInfo"; private AudioHalVersion mHalVersion = new AudioHalVersion(); diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java index 862ae8d7fcaf..5b479b5f9c11 100644 --- a/media/java/android/media/MediaCodec.java +++ b/media/java/android/media/MediaCodec.java @@ -16,6 +16,11 @@ package android.media; +import static android.media.codec.Flags.FLAG_NULL_OUTPUT_SURFACE; +import static android.media.codec.Flags.FLAG_REGION_OF_INTEREST; + +import static com.android.media.codec.flags.Flags.FLAG_LARGE_AUDIO_FRAME; + import android.Manifest; import android.annotation.FlaggedApi; import android.annotation.IntDef; @@ -51,7 +56,6 @@ import java.util.BitSet; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Objects; @@ -62,7 +66,6 @@ import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; -import static com.android.media.codec.flags.Flags.FLAG_LARGE_AUDIO_FRAME; /** MediaCodec class can be used to access low-level media codecs, i.e. encoder/decoder components. It is part of the Android low-level multimedia support infrastructure (normally used together @@ -2211,6 +2214,18 @@ final public class MediaCodec { */ public static final int CONFIGURE_FLAG_USE_CRYPTO_ASYNC = 4; + /** + * Configure the codec with a detached output surface. + * <p> + * This flag is only defined for a video decoder. MediaCodec + * configured with this flag will be in Surface mode even though + * the surface parameter is null. + * + * @see detachOutputSurface + */ + @FlaggedApi(FLAG_NULL_OUTPUT_SURFACE) + public static final int CONFIGURE_FLAG_DETACHED_SURFACE = 8; + /** @hide */ @IntDef( flag = true, @@ -2393,6 +2408,31 @@ final public class MediaCodec { private native void native_setSurface(@NonNull Surface surface); /** + * Detach the current output surface of a codec. + * <p> + * Detaches the currently associated output Surface from the + * MediaCodec decoder. This allows the SurfaceView or other + * component holding the Surface to be safely destroyed or + * modified without affecting the decoder's operation. After + * calling this method (and after it returns), the decoder will + * enter detached-Surface mode and will no longer render + * output. + * + * @throws IllegalStateException if the codec was not + * configured in surface mode. + * @see CONFIGURE_FLAG_DETACHED_SURFACE + */ + @FlaggedApi(FLAG_NULL_OUTPUT_SURFACE) + public void detachOutputSurface() { + if (!mHasSurface) { + throw new IllegalStateException("codec was not configured for an output surface"); + } + // note: we still have a surface in detached mode, so keep mHasSurface + // we also technically allow calling detachOutputSurface multiple times in a row + // native_detachSurface(); + } + + /** * Create a persistent input surface that can be used with codecs that normally have an input * surface, such as video encoders. A persistent input can be reused by subsequent * {@link MediaCodec} or {@link MediaRecorder} instances, but can only be used by at @@ -3210,6 +3250,51 @@ final public class MediaCodec { } } + /** + * Similar to {@link #queueInputBuffers queueInputBuffers} but submits multiple access units + * in a buffer that is potentially encrypted. + * <strong>Check out further notes at {@link #queueInputBuffers queueInputBuffers}.</strong> + * + * @param index The index of a client-owned input buffer previously returned + * in a call to {@link #dequeueInputBuffer}. + * @param bufferInfos ArrayDeque of {@link MediaCodec.BufferInfo} that describes the + * contents in the buffer. The ArrayDeque and the BufferInfo objects provided + * can be recycled by the caller for re-use. + * @param cryptoInfos ArrayDeque of {@link MediaCodec.CryptoInfo} objects to facilitate the + * decryption of the contents. The ArrayDeque and the CryptoInfo objects + * provided can be reused immediately after the call returns. These objects + * should correspond to bufferInfo objects to ensure correct decryption. + * @throws IllegalStateException if not in the Executing state or not in asynchronous mode. + * @throws MediaCodec.CodecException upon codec error. + * @throws IllegalArgumentException upon if bufferInfos is empty, contains null, or if the + * access units are not contiguous. + * @throws CryptoException if an error occurs while attempting to decrypt the buffer. + * An error code associated with the exception helps identify the + * reason for the failure. + */ + @FlaggedApi(FLAG_LARGE_AUDIO_FRAME) + public final void queueSecureInputBuffers( + int index, + @NonNull ArrayDeque<BufferInfo> bufferInfos, + @NonNull ArrayDeque<CryptoInfo> cryptoInfos) { + synchronized(mBufferLock) { + if (mBufferMode == BUFFER_MODE_BLOCK) { + throw new IncompatibleWithBlockModelException("queueSecureInputBuffers() " + + "is not compatible with CONFIGURE_FLAG_USE_BLOCK_MODEL. " + + "Please use getQueueRequest() to queue buffers"); + } + invalidateByteBufferLocked(mCachedInputBuffers, index, true /* input */); + mDequeuedInputBuffers.remove(index); + } + try { + native_queueSecureInputBuffers( + index, bufferInfos.toArray(), cryptoInfos.toArray()); + } catch (CryptoException | IllegalStateException | IllegalArgumentException e) { + revalidateByteBuffer(mCachedInputBuffers, index, true /* input */); + throw e; + } + } + private native final void native_queueSecureInputBuffer( int index, int offset, @@ -3217,6 +3302,11 @@ final public class MediaCodec { long presentationTimeUs, int flags) throws CryptoException; + private native final void native_queueSecureInputBuffers( + int index, + @NonNull Object[] bufferInfos, + @NonNull Object[] cryptoInfos) throws CryptoException, CodecException; + /** * Returns the index of an input buffer to be filled with valid data * or -1 if no such buffer is currently available. @@ -3462,7 +3552,37 @@ final public class MediaCodec { mLinearBlock = block; mOffset = offset; mSize = size; - mCryptoInfo = null; + mCryptoInfos.clear(); + return this; + } + + /** + * Set a linear block that contain multiple non-encrypted access unit to this + * queue request. Exactly one buffer must be set for a queue request before + * calling {@link #queue}. Multiple access units if present must be laid out contiguously + * and without gaps and in order. An IllegalArgumentException will be thrown + * during {@link #queue} if access units are not laid out contiguously. + * + * @param block The linear block object + * @param infos Represents {@link MediaCodec.BufferInfo} objects to mark + * individual access-unit boundaries and the timestamps associated with it. + * @return this object + * @throws IllegalStateException if a buffer is already set + */ + @FlaggedApi(FLAG_LARGE_AUDIO_FRAME) + public @NonNull QueueRequest setMultiFrameLinearBlock( + @NonNull LinearBlock block, + @NonNull ArrayDeque<BufferInfo> infos) { + if (!isAccessible()) { + throw new IllegalStateException("The request is stale"); + } + if (mLinearBlock != null || mHardwareBuffer != null) { + throw new IllegalStateException("Cannot set block twice"); + } + mLinearBlock = block; + mBufferInfos.clear(); + mBufferInfos.addAll(infos); + mCryptoInfos.clear(); return this; } @@ -3496,7 +3616,44 @@ final public class MediaCodec { mLinearBlock = block; mOffset = offset; mSize = size; - mCryptoInfo = cryptoInfo; + mCryptoInfos.clear(); + mCryptoInfos.add(cryptoInfo); + return this; + } + + /** + * Set an encrypted linear block to this queue request. Exactly one buffer must be + * set for a queue request before calling {@link #queue}. The block can contain multiple + * access units and if present should be laid out contiguously and without gaps. + * + * @param block The linear block object + * @param bufferInfos ArrayDeque of {@link MediaCodec.BufferInfo} that describes the + * contents in the buffer. The ArrayDeque and the BufferInfo objects + * provided can be recycled by the caller for re-use. + * @param cryptoInfos ArrayDeque of {@link MediaCodec.CryptoInfo} that describes the + * structure of the encrypted input samples. The ArrayDeque and the + * BufferInfo objects provided can be recycled by the caller for re-use. + * @return this object + * @throws IllegalStateException if a buffer is already set + * @throws IllegalArgumentException upon if bufferInfos is empty, contains null, or if the + * access units are not contiguous. + */ + @FlaggedApi(FLAG_LARGE_AUDIO_FRAME) + public @NonNull QueueRequest setMultiFrameEncryptedLinearBlock( + @NonNull LinearBlock block, + @NonNull ArrayDeque<MediaCodec.BufferInfo> bufferInfos, + @NonNull ArrayDeque<MediaCodec.CryptoInfo> cryptoInfos) { + if (!isAccessible()) { + throw new IllegalStateException("The request is stale"); + } + if (mLinearBlock != null || mHardwareBuffer != null) { + throw new IllegalStateException("Cannot set block twice"); + } + mLinearBlock = block; + mBufferInfos.clear(); + mBufferInfos.addAll(bufferInfos); + mCryptoInfos.clear(); + mCryptoInfos.addAll(cryptoInfos); return this; } @@ -3562,26 +3719,6 @@ final public class MediaCodec { } /** - * Sets MediaCodec.BufferInfo objects describing the access units - * contained in this queue request. Access units must be laid out - * contiguously without gaps and in order. - * - * @param infos Represents {@link MediaCodec.BufferInfo} objects to mark - * individual access-unit boundaries and the timestamps associated with it. - * The buffer is expected to contain the data in a continuous manner. - * @return this object - */ - @FlaggedApi(FLAG_LARGE_AUDIO_FRAME) - public @NonNull QueueRequest setBufferInfos(@NonNull ArrayDeque<BufferInfo> infos) { - if (!isAccessible()) { - throw new IllegalStateException("The request is stale"); - } - mBufferInfos.clear(); - mBufferInfos.addAll(infos); - return this; - } - - /** * Add an integer parameter. * See {@link MediaFormat} for an exhaustive list of supported keys with * values of type int, that can also be set with {@link MediaFormat#setInteger}. @@ -3706,8 +3843,10 @@ final public class MediaCodec { mBufferInfos.add(info); } if (mLinearBlock != null) { + mCodec.native_queueLinearBlock( - mIndex, mLinearBlock, mCryptoInfo, + mIndex, mLinearBlock, + mCryptoInfos.isEmpty() ? null : mCryptoInfos.toArray(), mBufferInfos.toArray(), mTuningKeys, mTuningValues); } else if (mHardwareBuffer != null) { @@ -3722,11 +3861,11 @@ final public class MediaCodec { mLinearBlock = null; mOffset = 0; mSize = 0; - mCryptoInfo = null; mHardwareBuffer = null; mPresentationTimeUs = 0; mFlags = 0; mBufferInfos.clear(); + mCryptoInfos.clear(); mTuningKeys.clear(); mTuningValues.clear(); return this; @@ -3746,11 +3885,11 @@ final public class MediaCodec { private LinearBlock mLinearBlock = null; private int mOffset = 0; private int mSize = 0; - private MediaCodec.CryptoInfo mCryptoInfo = null; private HardwareBuffer mHardwareBuffer = null; private long mPresentationTimeUs = 0; private @BufferFlag int mFlags = 0; private final ArrayDeque<BufferInfo> mBufferInfos = new ArrayDeque<>(); + private final ArrayDeque<CryptoInfo> mCryptoInfos = new ArrayDeque<>(); private final ArrayList<String> mTuningKeys = new ArrayList<>(); private final ArrayList<Object> mTuningValues = new ArrayList<>(); @@ -3760,7 +3899,7 @@ final public class MediaCodec { private native void native_queueLinearBlock( int index, @NonNull LinearBlock block, - @Nullable CryptoInfo cryptoInfo, + @Nullable Object[] cryptoInfos, @NonNull Object[] bufferInfos, @NonNull ArrayList<String> keys, @NonNull ArrayList<Object> values); @@ -4936,6 +5075,68 @@ final public class MediaCodec { public static final String PARAMETER_KEY_TUNNEL_PEEK = "tunnel-peek"; /** + * Set the region of interest as QpOffset-Map on the next queued input frame. + * <p> + * The associated value is a byte array containing quantization parameter (QP) offsets in + * raster scan order for the entire frame at 16x16 granularity. The size of the byte array + * shall be ((frame_width + 15) / 16) * ((frame_height + 15) / 16), where frame_width and + * frame_height correspond to width and height configured using {@link MediaFormat#KEY_WIDTH} + * and {@link MediaFormat#KEY_HEIGHT} keys respectively. During encoding, if the coding unit + * size is larger than 16x16, then the qpOffset information of all 16x16 blocks that + * encompass the coding unit is combined and used. The QP of target block will be calculated + * as 'frameQP + offsetQP'. If the result exceeds minQP or maxQP configured then the value + * may be clamped. Negative offset results in blocks encoded at lower QP than frame QP and + * positive offsets will result in encoding blocks at higher QP than frame QP. If the areas + * of negative QP and positive QP are chosen wisely, the overall viewing experience can be + * improved. + * <p> + * If byte array size is too small than the expected size, components may ignore the + * configuration silently. If the byte array exceeds the expected size, components shall use + * the initial portion and ignore the rest. + * <p> + * The scope of this key is throughout the encoding session until it is reconfigured during + * running state. + * <p> + * @see #setParameters(Bundle) + */ + @FlaggedApi(FLAG_REGION_OF_INTEREST) + public static final String PARAMETER_KEY_QP_OFFSET_MAP = "qp-offset-map"; + + /** + * Set the region of interest as QpOffset-Rects on the next queued input frame. + * <p> + * The associated value is a String in the format "Top1,Left1-Bottom1,Right1=Offset1;Top2, + * Left2-Bottom2,Right2=Offset2;...". Co-ordinates (Top, Left), (Top, Right), (Bottom, Left) + * and (Bottom, Right) form the vertices of bounding box of region of interest in pixels. + * Pixel (0, 0) points to the top-left corner of the frame. Offset is the suggested + * quantization parameter (QP) offset of the blocks in the bounding box. The bounding box + * will get stretched outwards to align to LCU boundaries during encoding. The Qp Offset is + * integral and shall be in the range [-128, 127]. The QP of target block will be calculated + * as frameQP + offsetQP. If the result exceeds minQP or maxQP configured then the value may + * be clamped. Negative offset results in blocks encoded at lower QP than frame QP and + * positive offsets will result in blocks encoded at higher QP than frame QP. If the areas of + * negative QP and positive QP are chosen wisely, the overall viewing experience can be + * improved. + * <p> + * If Roi rect is not valid that is bounding box width is < 0 or bounding box height is < 0, + * components may ignore the configuration silently. If Roi rect extends outside frame + * boundaries, then rect shall be clamped to the frame boundaries. + * <p> + * The scope of this key is throughout the encoding session until it is reconfigured during + * running state. + * <p> + * The maximum number of contours (rectangles) that can be specified for a given input frame + * is device specific. Implementations will drop/ignore the rectangles that are beyond their + * supported limit. Hence it is preferable to place the rects in descending order of + * importance. Transitively, if the bounding boxes overlap, then the most preferred + * rectangle's qp offset (earlier rectangle qp offset) will be used to quantize the block. + * <p> + * @see #setParameters(Bundle) + */ + @FlaggedApi(FLAG_REGION_OF_INTEREST) + public static final String PARAMETER_KEY_QP_OFFSET_RECTS = "qp-offset-rects"; + + /** * Communicate additional parameter changes to the component instance. * <b>Note:</b> Some of these parameter changes may silently fail to apply. * diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java index 88b9643c12c1..1e7bc4764dd7 100644 --- a/media/java/android/media/MediaCodecInfo.java +++ b/media/java/android/media/MediaCodecInfo.java @@ -18,7 +18,14 @@ package android.media; import static android.media.Utils.intersectSortedDistinctRanges; import static android.media.Utils.sortDistinctRanges; - +import static android.media.codec.Flags.FLAG_DYNAMIC_COLOR_ASPECTS; +import static android.media.codec.Flags.FLAG_HLG_EDITING; +import static android.media.codec.Flags.FLAG_IN_PROCESS_SW_AUDIO_CODEC; +import static android.media.codec.Flags.FLAG_NULL_OUTPUT_SURFACE; +import static android.media.codec.Flags.FLAG_REGION_OF_INTEREST; + +import android.annotation.FlaggedApi; +import android.annotation.IntDef; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; @@ -35,6 +42,8 @@ import android.util.Range; import android.util.Rational; import android.util.Size; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -692,6 +701,99 @@ public final class MediaCodecInfo { public static final String FEATURE_HdrEditing = "hdr-editing"; /** + * <b>video encoder only</b>: codec supports HLG editing. + * <p> + * HLG editing support means that the codec accepts 10-bit HDR + * input surface in both YUV and RGB pixel format. This feature + * is only meaningful when using a 10-bit (HLG) profile and + * 10-bit input. + * <p> + * This feature implies that the codec is capable of encoding + * 10-bit format, and that it supports RGBA_1010102 as + * well as P010, and optionally RGBA_FP16 input formats. + * <p> + * The difference between this feature and {@link + * FEATURE_HdrEditing} is that HLG does not require the + * generation of HDR metadata and does not use an explicit HDR + * profile. + */ + @SuppressLint("AllUpper") + @FlaggedApi(FLAG_HLG_EDITING) + public static final String FEATURE_HlgEditing = "hlg-editing"; + + /** + * <b>video decoder only</b>: codec supports dynamically + * changing color aspects. + * <p> + * If true, the codec can propagate color aspect changes during + * decoding. This is only meaningful at session boundaries, e.g. + * upon processing Picture Parameter Sets prior to a new IDR. + * The color aspects may come from the bitstream, or may be + * provided using {@link MediaCodec#setParameters} calls. + * <p> + * If the codec supports both 8-bit and 10-bit profiles, this + * feature means that the codec can dynamically switch between 8 + * and 10-bit profiles, but this is restricted to Surface mode + * only. + * <p> + * If the device supports HDR transfer functions, switching + * between SDR and HDR transfer is also supported. Together with + * the previous clause this means that switching between SDR and + * HDR sessions are supported in Surface mode, as SDR is + * typically encoded at 8-bit and HDR at 10-bit. + */ + @SuppressLint("AllUpper") + @FlaggedApi(FLAG_DYNAMIC_COLOR_ASPECTS) + public static final String FEATURE_DynamicColorAspects = "dynamic-color-aspects"; + + /** + * <b>video encoder only</b>: codec supports region of interest encoding. + * <p> + * RoI encoding support means the codec accepts information that specifies the relative + * importance of different portions of each video frame. This allows the encoder to + * separate a video frame into critical and non-critical regions, and use more bits + * (better quality) to represent the critical regions and de-prioritize non-critical + * regions. In other words, the encoder chooses a negative qp bias for the critical + * portions and a zero or positive qp bias for the non-critical portions. + * <p> + * At a basic level, if the encoder decides to encode each frame with a uniform + * quantization value 'qpFrame' and a 'qpBias' is chosen/suggested for an LCU of the + * frame, then the actual qp of the LCU will be 'qpFrame + qpBias', although this value + * can be clamped basing on the min-max configured qp bounds for the current encoding + * session. + * <p> + * In a shot, if a group of LCUs pan out quickly they can be marked as non-critical + * thereby enabling the encoder to reserve fewer bits during their encoding. Contrarily, + * LCUs that remain in shot for a prolonged duration can be encoded at better quality in + * one frame thereby setting-up an excellent long-term reference for all future frames. + * <p> + * Note that by offsetting the quantization of each LCU, the overall bit allocation will + * differ from the originally estimated bit allocation, and the encoder will adjust the + * frame quantization for subsequent frames to meet the bitrate target. An effective + * selection of critical regions can set-up a golden reference and this can compensate + * for the bit burden that was introduced due to encoding RoI's at better quality. + * On the other hand, an ineffective choice of critical regions might increase the + * quality of certain parts of the image but this can hamper quality in subsequent frames. + * <p> + * @see MediaCodec#PARAMETER_KEY_QP_OFFSET_MAP + * @see MediaCodec#PARAMETER_KEY_QP_OFFSET_RECTS + */ + @SuppressLint("AllUpper") + @FlaggedApi(FLAG_REGION_OF_INTEREST) + public static final String FEATURE_Roi = "region-of-interest"; + + /** + * <b>video decoder only</b>: codec supports detaching the + * output surface when in Surface mode. + * <p> If true, the codec can be configured in Surface mode + * without an actual surface (in detached surface mode). + * @see MediaCodec#CONFIGURE_FLAG_DETACHED_SURFACE + */ + @SuppressLint("AllUpper") + @FlaggedApi(FLAG_NULL_OUTPUT_SURFACE) + public static final String FEATURE_DetachedSurface = "detached-surface"; + + /** * Query codec feature capabilities. * <p> * These features are supported to be used by the codec. These @@ -712,29 +814,66 @@ public final class MediaCodecInfo { return checkFeature(name, mFlagsRequired); } - private static final Feature[] decoderFeatures = { - new Feature(FEATURE_AdaptivePlayback, (1 << 0), true), - new Feature(FEATURE_SecurePlayback, (1 << 1), false), - new Feature(FEATURE_TunneledPlayback, (1 << 2), false), - new Feature(FEATURE_PartialFrame, (1 << 3), false), - new Feature(FEATURE_FrameParsing, (1 << 4), false), - new Feature(FEATURE_MultipleFrames, (1 << 5), false), - new Feature(FEATURE_DynamicTimestamp, (1 << 6), false), - new Feature(FEATURE_LowLatency, (1 << 7), true), - // feature to exclude codec from REGULAR codec list - new Feature(FEATURE_SpecialCodec, (1 << 30), false, true), - }; + // Flags are used for feature list creation so separate this into a private + // static class to delay reading the flags only when constructing the list. + private static class FeatureList { + private static Feature[] getDecoderFeatures() { + ArrayList<Feature> features = new ArrayList(); + features.add(new Feature(FEATURE_AdaptivePlayback, (1 << 0), true)); + features.add(new Feature(FEATURE_SecurePlayback, (1 << 1), false)); + features.add(new Feature(FEATURE_TunneledPlayback, (1 << 2), false)); + features.add(new Feature(FEATURE_PartialFrame, (1 << 3), false)); + features.add(new Feature(FEATURE_FrameParsing, (1 << 4), false)); + features.add(new Feature(FEATURE_MultipleFrames, (1 << 5), false)); + features.add(new Feature(FEATURE_DynamicTimestamp, (1 << 6), false)); + features.add(new Feature(FEATURE_LowLatency, (1 << 7), true)); + if (android.media.codec.Flags.dynamicColorAspects()) { + features.add(new Feature(FEATURE_DynamicColorAspects, (1 << 8), true)); + } + if (android.media.codec.Flags.nullOutputSurface()) { + features.add(new Feature(FEATURE_DetachedSurface, (1 << 9), true)); + } - private static final Feature[] encoderFeatures = { - new Feature(FEATURE_IntraRefresh, (1 << 0), false), - new Feature(FEATURE_MultipleFrames, (1 << 1), false), - new Feature(FEATURE_DynamicTimestamp, (1 << 2), false), - new Feature(FEATURE_QpBounds, (1 << 3), false), - new Feature(FEATURE_EncodingStatistics, (1 << 4), false), - new Feature(FEATURE_HdrEditing, (1 << 5), false), - // feature to exclude codec from REGULAR codec list - new Feature(FEATURE_SpecialCodec, (1 << 30), false, true), - }; + // feature to exclude codec from REGULAR codec list + features.add(new Feature(FEATURE_SpecialCodec, (1 << 30), false, true)); + + return features.toArray(new Feature[0]); + }; + + private static Feature[] decoderFeatures = getDecoderFeatures(); + + private static Feature[] getEncoderFeatures() { + ArrayList<Feature> features = new ArrayList(); + + features.add(new Feature(FEATURE_IntraRefresh, (1 << 0), false)); + features.add(new Feature(FEATURE_MultipleFrames, (1 << 1), false)); + features.add(new Feature(FEATURE_DynamicTimestamp, (1 << 2), false)); + features.add(new Feature(FEATURE_QpBounds, (1 << 3), false)); + features.add(new Feature(FEATURE_EncodingStatistics, (1 << 4), false)); + features.add(new Feature(FEATURE_HdrEditing, (1 << 5), false)); + if (android.media.codec.Flags.hlgEditing()) { + features.add(new Feature(FEATURE_HlgEditing, (1 << 6), true)); + } + if (android.media.codec.Flags.regionOfInterest()) { + features.add(new Feature(FEATURE_Roi, (1 << 7), true)); + } + + // feature to exclude codec from REGULAR codec list + features.add(new Feature(FEATURE_SpecialCodec, (1 << 30), false, true)); + + return features.toArray(new Feature[0]); + }; + + private static Feature[] encoderFeatures = getEncoderFeatures(); + + public static Feature[] getFeatures(boolean isEncoder) { + if (isEncoder) { + return encoderFeatures; + } else { + return decoderFeatures; + } + } + } /** @hide */ public String[] validFeatures() { @@ -749,10 +888,7 @@ public final class MediaCodecInfo { } private Feature[] getValidFeatures() { - if (!isEncoder()) { - return decoderFeatures; - } - return encoderFeatures; + return FeatureList.getFeatures(isEncoder()); } private boolean checkFeature(String name, int flags) { @@ -1676,6 +1812,55 @@ public final class MediaCodecInfo { } } + /** @hide */ + @IntDef(prefix = {"SECURITY_MODEL_"}, value = { + SECURITY_MODEL_SANDBOXED, + SECURITY_MODEL_MEMORY_SAFE, + SECURITY_MODEL_TRUSTED_CONTENT_ONLY, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface SecurityModel {} + + /** + * In this model the codec is running in a sandboxed process. Even if a + * malicious content was fed to the codecs in this model, the impact will + * be contained in the sandboxed process. + */ + @FlaggedApi(FLAG_IN_PROCESS_SW_AUDIO_CODEC) + public static final int SECURITY_MODEL_SANDBOXED = 0; + /** + * In this model the codec is not running in a sandboxed process, but + * written in a memory-safe way. It typically means that the software + * implementation of the codec is written in a memory-safe language such + * as Rust. + */ + @FlaggedApi(FLAG_IN_PROCESS_SW_AUDIO_CODEC) + public static final int SECURITY_MODEL_MEMORY_SAFE = 1; + /** + * In this model the codec is suitable only for trusted content where + * the input can be verified to be well-formed and no malicious actor + * can alter it. For example, codecs in this model are not suitable + * for arbitrary media downloaded from the internet or present in a user + * directory. On the other hand, they could be suitable for media encoded + * in the backend that the app developer wholly controls. + * <p> + * Codecs with this security model is not included in + * {@link MediaCodecList#REGULAR_CODECS}, but included in + * {@link MediaCodecList#ALL_CODECS}. + */ + @FlaggedApi(FLAG_IN_PROCESS_SW_AUDIO_CODEC) + public static final int SECURITY_MODEL_TRUSTED_CONTENT_ONLY = 2; + + /** + * Query the security model of the codec. + */ + @FlaggedApi(FLAG_IN_PROCESS_SW_AUDIO_CODEC) + @SecurityModel + public int getSecurityModel() { + // TODO b/297922713 --- detect security model of out-of-sandbox codecs + return SECURITY_MODEL_SANDBOXED; + } + /** * A class that supports querying the video capabilities of a codec. */ diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java index 5e40eee26886..7b83842a9fb2 100644 --- a/media/java/android/media/MediaFormat.java +++ b/media/java/android/media/MediaFormat.java @@ -16,6 +16,8 @@ package android.media; +import static android.media.codec.Flags.FLAG_IN_PROCESS_SW_AUDIO_CODEC; + import static com.android.media.codec.flags.Flags.FLAG_CODEC_IMPORTANCE; import static com.android.media.codec.flags.Flags.FLAG_LARGE_AUDIO_FRAME; @@ -1715,6 +1717,58 @@ public final class MediaFormat { @FlaggedApi(FLAG_CODEC_IMPORTANCE) public static final String KEY_IMPORTANCE = "importance"; + /** @hide */ + @IntDef(flag = true, prefix = {"FLAG_SECURITY_MODEL_"}, value = { + FLAG_SECURITY_MODEL_SANDBOXED, + FLAG_SECURITY_MODEL_MEMORY_SAFE, + FLAG_SECURITY_MODEL_TRUSTED_CONTENT_ONLY, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface SecurityModelFlag {} + + /** + * Flag for {@link MediaCodecInfo#SECURITY_MODEL_SANDBOXED}. + */ + @FlaggedApi(FLAG_IN_PROCESS_SW_AUDIO_CODEC) + public static final int FLAG_SECURITY_MODEL_SANDBOXED = + (1 << MediaCodecInfo.SECURITY_MODEL_SANDBOXED); + /** + * Flag for {@link MediaCodecInfo#SECURITY_MODEL_MEMORY_SAFE}. + */ + @FlaggedApi(FLAG_IN_PROCESS_SW_AUDIO_CODEC) + public static final int FLAG_SECURITY_MODEL_MEMORY_SAFE = + (1 << MediaCodecInfo.SECURITY_MODEL_MEMORY_SAFE); + /** + * Flag for {@link MediaCodecInfo#SECURITY_MODEL_TRUSTED_CONTENT_ONLY}. + */ + @FlaggedApi(FLAG_IN_PROCESS_SW_AUDIO_CODEC) + public static final int FLAG_SECURITY_MODEL_TRUSTED_CONTENT_ONLY = + (1 << MediaCodecInfo.SECURITY_MODEL_TRUSTED_CONTENT_ONLY); + + /** + * A key describing the requested security model as flags. + * <p> + * The associated value is a flag of the following values: + * {@link FLAG_SECURITY_MODEL_SANDBOXED}, + * {@link FLAG_SECURITY_MODEL_MEMORY_SAFE}, + * {@link FLAG_SECURITY_MODEL_TRUSTED_CONTENT_ONLY}. The default value is + * {@link FLAG_SECURITY_MODEL_SANDBOXED}. + * <p> + * When passed to {@link MediaCodecList#findDecoderForFormat} or + * {@link MediaCodecList#findEncoderForFormat}, MediaCodecList filters + * the security model of the codecs according to this flag value. + * <p> + * When passed to {@link MediaCodec#configure}, MediaCodec verifies + * the security model matches the flag value passed, and throws + * {@link java.lang.IllegalArgumentException} if the model does not match. + * <p> + * @see MediaCodecInfo#getSecurityModel + * @see MediaCodecList#findDecoderForFormat + * @see MediaCodecList#findEncoderForFormat + */ + @FlaggedApi(FLAG_IN_PROCESS_SW_AUDIO_CODEC) + public static final String KEY_SECURITY_MODEL = "security-model"; + /* package private */ MediaFormat(@NonNull Map<String, Object> map) { mMap = map; } diff --git a/media/java/android/media/OWNERS b/media/java/android/media/OWNERS index 058c5be6af6c..5d470ae7f04d 100644 --- a/media/java/android/media/OWNERS +++ b/media/java/android/media/OWNERS @@ -14,3 +14,5 @@ per-file ExifInterface.java,ExifInterfaceUtils.java,IMediaHTTPConnection.aidl,IM # Haptics team also works on Ringtone per-file *Ringtone* = file:/services/core/java/com/android/server/vibrator/OWNERS + +per-file flags/projection.aconfig = file:projection/OWNERS
\ No newline at end of file diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp index 8cdd59e51ffe..8396005b1b63 100644 --- a/media/jni/android_media_MediaCodec.cpp +++ b/media/jni/android_media_MediaCodec.cpp @@ -458,6 +458,24 @@ status_t JMediaCodec::queueSecureInputBuffer( presentationTimeUs, flags, errorDetailMsg); } +status_t JMediaCodec::queueSecureInputBuffers( + size_t index, + size_t offset, + size_t size, + const sp<RefBase> &auInfos_, + const sp<RefBase> &cryptoInfos_, + AString *errorDetailMsg) { + sp<BufferInfosWrapper> auInfos((BufferInfosWrapper *)auInfos_.get()); + sp<CryptoInfosWrapper> cryptoInfos((CryptoInfosWrapper *)cryptoInfos_.get()); + return mCodec->queueSecureInputBuffers( + index, + offset, + size, + auInfos, + cryptoInfos, + errorDetailMsg); +} + status_t JMediaCodec::queueBuffer( size_t index, const std::shared_ptr<C2Buffer> &buffer, const sp<RefBase> &infos, const sp<AMessage> &tunings, AString *errorDetailMsg) { @@ -470,19 +488,16 @@ status_t JMediaCodec::queueEncryptedLinearBlock( size_t index, const sp<hardware::HidlMemory> &buffer, size_t offset, - const CryptoPlugin::SubSample *subSamples, - size_t numSubSamples, - const uint8_t key[16], - const uint8_t iv[16], - CryptoPlugin::Mode mode, - const CryptoPlugin::Pattern &pattern, + size_t size, const sp<RefBase> &infos, + const sp<RefBase> &cryptoInfos_, const sp<AMessage> &tunings, AString *errorDetailMsg) { sp<BufferInfosWrapper> auInfo((BufferInfosWrapper *)infos.get()); + sp<CryptoInfosWrapper> cryptoInfos((CryptoInfosWrapper *)cryptoInfos_.get()); return mCodec->queueEncryptedBuffer( - index, buffer, offset, subSamples, numSubSamples, key, iv, mode, pattern, - auInfo, tunings, errorDetailMsg); + index, buffer, offset, size, auInfo, cryptoInfos, + tunings, errorDetailMsg); } status_t JMediaCodec::dequeueInputBuffer(size_t *index, int64_t timeoutUs) { @@ -2262,6 +2277,61 @@ struct NativeCryptoInfo { CryptoPlugin::Pattern mPattern; }; +// This class takes away all dependencies on java(env and jni) and +// could be used for taking cryptoInfo objects to MediaCodec. +struct MediaCodecCryptoInfo: public CodecCryptoInfo { + explicit MediaCodecCryptoInfo(const NativeCryptoInfo &cryptoInfo) { + if (cryptoInfo.mErr == OK) { + mNumSubSamples = cryptoInfo.mNumSubSamples; + mMode = cryptoInfo.mMode; + mPattern = cryptoInfo.mPattern; + if (cryptoInfo.mKey != nullptr) { + mKeyBuffer = ABuffer::CreateAsCopy(cryptoInfo.mKey, 16); + mKey = (uint8_t*)(mKeyBuffer.get() != nullptr ? mKeyBuffer.get()->data() : nullptr); + } + if (cryptoInfo.mIv != nullptr) { + mIvBuffer = ABuffer::CreateAsCopy(cryptoInfo.mIv, 16); + mIv = (uint8_t*)(mIvBuffer.get() != nullptr ? mIvBuffer.get()->data() : nullptr); + } + if (cryptoInfo.mSubSamples != nullptr) { + mSubSamplesBuffer = new ABuffer(sizeof(CryptoPlugin::SubSample) * mNumSubSamples); + if (mSubSamplesBuffer.get()) { + CryptoPlugin::SubSample * samples = + (CryptoPlugin::SubSample *)(mSubSamplesBuffer.get()->data()); + for (int s = 0 ; s < mNumSubSamples ; s++) { + samples[s].mNumBytesOfClearData = + cryptoInfo.mSubSamples[s].mNumBytesOfClearData; + samples[s].mNumBytesOfEncryptedData = + cryptoInfo.mSubSamples[s].mNumBytesOfEncryptedData; + } + mSubSamples = (CryptoPlugin::SubSample *)mSubSamplesBuffer.get()->data(); + } + } + + } + } + + explicit MediaCodecCryptoInfo(jint size) { + mSubSamplesBuffer = new ABuffer(sizeof(CryptoPlugin::SubSample) * 1); + mNumSubSamples = 1; + if (mSubSamplesBuffer.get()) { + CryptoPlugin::SubSample * samples = + (CryptoPlugin::SubSample *)(mSubSamplesBuffer.get()->data()); + samples[0].mNumBytesOfClearData = size; + samples[0].mNumBytesOfEncryptedData = 0; + mSubSamples = (CryptoPlugin::SubSample *)mSubSamplesBuffer.get()->data(); + } + } + ~MediaCodecCryptoInfo() {} + +protected: + // all backup buffers for the base object. + sp<ABuffer> mKeyBuffer; + sp<ABuffer> mIvBuffer; + sp<ABuffer> mSubSamplesBuffer; + +}; + static void android_media_MediaCodec_queueSecureInputBuffer( JNIEnv *env, jobject thiz, @@ -2430,6 +2500,99 @@ static void android_media_MediaCodec_queueSecureInputBuffer( codec->getExceptionMessage(errorDetailMsg.c_str()).c_str(), codec->getCrypto()); } +static status_t extractCryptoInfosFromObjectArray(JNIEnv * const env, + jint * const totalSize, + std::vector<std::unique_ptr<CodecCryptoInfo>> * const cryptoInfoObjs, + const jobjectArray &objArray, + AString * const errorDetailMsg) { + if (env == nullptr + || cryptoInfoObjs == nullptr + || totalSize == nullptr) { + if (errorDetailMsg) { + *errorDetailMsg = "Error: Null Parameters provided for extracting CryptoInfo"; + } + return BAD_VALUE; + } + const jsize numEntries = env->GetArrayLength(objArray); + if (numEntries <= 0) { + if (errorDetailMsg) { + *errorDetailMsg = "Error: No CryptoInfo found while queuing for large frame input"; + } + return BAD_VALUE; + } + cryptoInfoObjs->clear(); + *totalSize = 0; + jint size = 0; + for (jsize i = 0; i < numEntries ; i++) { + jobject param = env->GetObjectArrayElement(objArray, i); + if (param == NULL) { + if (errorDetailMsg) { + *errorDetailMsg = "Error: Null Parameters provided for extracting CryptoInfo"; + } + return BAD_VALUE; + } + NativeCryptoInfo nativeInfo(env, param); + std::unique_ptr<CodecCryptoInfo> info(new MediaCodecCryptoInfo(nativeInfo)); + for (int i = 0; i < info->mNumSubSamples; i++) { + size += info->mSubSamples[i].mNumBytesOfClearData; + size += info->mSubSamples[i].mNumBytesOfEncryptedData; + } + cryptoInfoObjs->push_back(std::move(info)); + } + *totalSize = size; + return OK; +} + + +static void android_media_MediaCodec_queueSecureInputBuffers( + JNIEnv *env, + jobject thiz, + jint index, + jobjectArray bufferInfosObjs, + jobjectArray cryptoInfoObjs) { + ALOGV("android_media_MediaCodec_queueSecureInputBuffers"); + + sp<JMediaCodec> codec = getMediaCodec(env, thiz); + + if (codec == NULL || codec->initCheck() != OK) { + throwExceptionAsNecessary(env, INVALID_OPERATION, codec); + return; + } + sp<BufferInfosWrapper> auInfos = + new BufferInfosWrapper{decltype(auInfos->value)()}; + sp<CryptoInfosWrapper> cryptoInfos = + new CryptoInfosWrapper{decltype(cryptoInfos->value)()}; + AString errorDetailMsg; + jint initialOffset = 0; + jint totalSize = 0; + status_t err = extractInfosFromObject( + env, + &initialOffset, + &totalSize, + &auInfos->value, + bufferInfosObjs, + &errorDetailMsg); + if (err == OK) { + err = extractCryptoInfosFromObjectArray(env, + &totalSize, + &cryptoInfos->value, + cryptoInfoObjs, + &errorDetailMsg); + } + if (err == OK) { + err = codec->queueSecureInputBuffers( + index, + initialOffset, + totalSize, + auInfos, + cryptoInfos, + &errorDetailMsg); + } + throwExceptionAsNecessary( + env, err, ACTION_CODE_FATAL, + codec->getExceptionMessage(errorDetailMsg.c_str()).c_str(), codec->getCrypto()); +} + static jobject android_media_MediaCodec_mapHardwareBuffer(JNIEnv *env, jclass, jobject bufferObj) { ALOGV("android_media_MediaCodec_mapHardwareBuffer"); AHardwareBuffer *hardwareBuffer = android_hardware_HardwareBuffer_getNativeHardwareBuffer( @@ -2762,7 +2925,7 @@ static void extractBufferFromContext( static void android_media_MediaCodec_native_queueLinearBlock( JNIEnv *env, jobject thiz, jint index, jobject bufferObj, - jobject cryptoInfoObj, jobjectArray objArray, jobject keys, jobject values) { + jobjectArray cryptoInfoArray, jobjectArray objArray, jobject keys, jobject values) { ALOGV("android_media_MediaCodec_native_queueLinearBlock"); sp<JMediaCodec> codec = getMediaCodec(env, thiz); @@ -2780,8 +2943,8 @@ static void android_media_MediaCodec_native_queueLinearBlock( "error occurred while converting tunings from Java to native"); return; } - jint totalSize; - jint initialOffset; + jint totalSize = 0; + jint initialOffset = 0; std::vector<AccessUnitInfo> infoVec; AString errorDetailMsg; err = extractInfosFromObject(env, @@ -2832,8 +2995,19 @@ static void android_media_MediaCodec_native_queueLinearBlock( "MediaCodec.LinearBlock#obtain method to obtain a compatible buffer."); return; } - auto cryptoInfo = - cryptoInfoObj ? NativeCryptoInfo{env, cryptoInfoObj} : NativeCryptoInfo{totalSize}; + sp<CryptoInfosWrapper> cryptoInfos = new CryptoInfosWrapper{decltype(cryptoInfos->value)()}; + jint sampleSize = 0; + if (cryptoInfoArray != nullptr) { + extractCryptoInfosFromObjectArray(env, + &sampleSize, + &cryptoInfos->value, + cryptoInfoArray, + &errorDetailMsg); + } else { + sampleSize = totalSize; + std::unique_ptr<CodecCryptoInfo> cryptoInfo{new MediaCodecCryptoInfo(totalSize)}; + cryptoInfos->value.push_back(std::move(cryptoInfo)); + } if (env->ExceptionCheck()) { // Creation of cryptoInfo failed. Let the exception bubble up. return; @@ -2842,11 +3016,9 @@ static void android_media_MediaCodec_native_queueLinearBlock( index, memory, initialOffset, - cryptoInfo.mSubSamples, cryptoInfo.mNumSubSamples, - (const uint8_t *)cryptoInfo.mKey, (const uint8_t *)cryptoInfo.mIv, - cryptoInfo.mMode, - cryptoInfo.mPattern, + sampleSize, infos, + cryptoInfos, tunings, &errorDetailMsg); ALOGI_IF(err != OK, "queueEncryptedLinearBlock returned err = %d", err); @@ -3950,6 +4122,9 @@ static const JNINativeMethod gMethods[] = { { "native_queueSecureInputBuffer", "(IILandroid/media/MediaCodec$CryptoInfo;JI)V", (void *)android_media_MediaCodec_queueSecureInputBuffer }, + { "native_queueSecureInputBuffers", "(I[Ljava/lang/Object;[Ljava/lang/Object;)V", + (void *)android_media_MediaCodec_queueSecureInputBuffers }, + { "native_mapHardwareBuffer", "(Landroid/hardware/HardwareBuffer;)Landroid/media/Image;", (void *)android_media_MediaCodec_mapHardwareBuffer }, @@ -3957,7 +4132,7 @@ static const JNINativeMethod gMethods[] = { { "native_closeMediaImage", "(J)V", (void *)android_media_MediaCodec_closeMediaImage }, { "native_queueLinearBlock", - "(ILandroid/media/MediaCodec$LinearBlock;Landroid/media/MediaCodec$CryptoInfo;" + "(ILandroid/media/MediaCodec$LinearBlock;[Ljava/lang/Object;" "[Ljava/lang/Object;Ljava/util/ArrayList;Ljava/util/ArrayList;)V", (void *)android_media_MediaCodec_native_queueLinearBlock }, diff --git a/media/jni/android_media_MediaCodec.h b/media/jni/android_media_MediaCodec.h index 02708efdea3a..abb23f516156 100644 --- a/media/jni/android_media_MediaCodec.h +++ b/media/jni/android_media_MediaCodec.h @@ -114,6 +114,14 @@ struct JMediaCodec : public AHandler { uint32_t flags, AString *errorDetailMsg); + status_t queueSecureInputBuffers( + size_t index, + size_t offset, + size_t size, + const sp<RefBase> &auInfos, + const sp<RefBase> &cryptoInfos, + AString *errorDetailMsg); + status_t queueBuffer( size_t index, const std::shared_ptr<C2Buffer> &buffer, const sp<RefBase> &infos, const sp<AMessage> &tunings, @@ -123,13 +131,9 @@ struct JMediaCodec : public AHandler { size_t index, const sp<hardware::HidlMemory> &buffer, size_t offset, - const CryptoPlugin::SubSample *subSamples, - size_t numSubSamples, - const uint8_t key[16], - const uint8_t iv[16], - CryptoPlugin::Mode mode, - const CryptoPlugin::Pattern &pattern, + size_t size, const sp<RefBase> &infos, + const sp<RefBase> &cryptoInfos, const sp<AMessage> &tunings, AString *errorDetailMsg); diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestUtils.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestUtils.java index 388a65d2a904..00068bda60dd 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestUtils.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestUtils.java @@ -1709,7 +1709,7 @@ public class CameraTestUtils extends Assert { * <p> * Two images are strongly equal if and only if the data, formats, sizes, * and timestamps are same. For {@link ImageFormat#PRIVATE PRIVATE} format - * images, the image data is not not accessible thus the data comparison is + * images, the image data is not accessible thus the data comparison is * effectively skipped as the number of planes is zero. * </p> * <p> @@ -2049,7 +2049,7 @@ public class CameraTestUtils extends Assert { } } else { // Case 2. - collector.expectEquals("Exif orientaiton should match requested orientation", + collector.expectEquals("Exif orientation should match requested orientation", requestedOrientation, getExifOrientationInDegree(exifOrientation, collector)); } diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java index ed70ab996ccd..5dcd1cba337d 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java @@ -1127,8 +1127,8 @@ public class StaticMetadata { * Get aeAvailableModes and do the validation check. * * <p>Depending on the check level this class has, for WAR or COLLECT levels, - * If the aeMode list is invalid, return an empty mode array. The the caller doesn't - * have to abort the execution even the aeMode list is invalid.</p> + * If the aeMode list is invalid, return an empty mode array. The caller doesn't + * have to abort the execution even if the aeMode list is invalid.</p> * @return AE available modes */ public int[] getAeAvailableModesChecked() { diff --git a/nfc/api/system-current.txt b/nfc/api/system-current.txt index d5b3c7df59d4..ece8851df42f 100644 --- a/nfc/api/system-current.txt +++ b/nfc/api/system-current.txt @@ -14,12 +14,20 @@ package android.nfc { method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public boolean isControllerAlwaysOnSupported(); method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean isTagIntentAppPreferenceSupported(); method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public void registerControllerAlwaysOnListener(@NonNull java.util.concurrent.Executor, @NonNull android.nfc.NfcAdapter.ControllerAlwaysOnListener); + method @FlaggedApi("android.nfc.nfc_vendor_cmd") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void registerNfcVendorNciCallback(@NonNull java.util.concurrent.Executor, @NonNull android.nfc.NfcAdapter.NfcVendorNciCallback); method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean removeNfcUnlockHandler(android.nfc.NfcAdapter.NfcUnlockHandler); + method @FlaggedApi("android.nfc.nfc_vendor_cmd") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public int sendVendorNciMessage(int, @IntRange(from=0, to=15) int, @IntRange(from=0) int, @NonNull byte[]); method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public boolean setControllerAlwaysOn(boolean); method @FlaggedApi("android.nfc.enable_nfc_mainline") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setReaderMode(boolean); method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public int setTagIntentAppPreferenceForUser(int, @NonNull String, boolean); method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public void unregisterControllerAlwaysOnListener(@NonNull android.nfc.NfcAdapter.ControllerAlwaysOnListener); + method @FlaggedApi("android.nfc.enable_nfc_mainline") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void unregisterNfcVendorNciCallback(@NonNull android.nfc.NfcAdapter.NfcVendorNciCallback); field @FlaggedApi("android.nfc.enable_nfc_mainline") public static final String ACTION_REQUIRE_UNLOCK_FOR_NFC = "android.nfc.action.REQUIRE_UNLOCK_FOR_NFC"; + field @FlaggedApi("android.nfc.nfc_vendor_cmd") public static final int MESSAGE_TYPE_COMMAND = 1; // 0x1 + field @FlaggedApi("android.nfc.nfc_vendor_cmd") public static final int SEND_VENDOR_NCI_STATUS_FAILED = 3; // 0x3 + field @FlaggedApi("android.nfc.nfc_vendor_cmd") public static final int SEND_VENDOR_NCI_STATUS_MESSAGE_CORRUPTED = 2; // 0x2 + field @FlaggedApi("android.nfc.nfc_vendor_cmd") public static final int SEND_VENDOR_NCI_STATUS_REJECTED = 1; // 0x1 + field @FlaggedApi("android.nfc.nfc_vendor_cmd") public static final int SEND_VENDOR_NCI_STATUS_SUCCESS = 0; // 0x0 field public static final int TAG_INTENT_APP_PREF_RESULT_PACKAGE_NOT_FOUND = -1; // 0xffffffff field public static final int TAG_INTENT_APP_PREF_RESULT_SUCCESS = 0; // 0x0 field public static final int TAG_INTENT_APP_PREF_RESULT_UNAVAILABLE = -2; // 0xfffffffe @@ -33,6 +41,11 @@ package android.nfc { method public boolean onUnlockAttempted(android.nfc.Tag); } + @FlaggedApi("android.nfc.nfc_vendor_cmd") public static interface NfcAdapter.NfcVendorNciCallback { + method @FlaggedApi("android.nfc.nfc_vendor_cmd") public void onVendorNciNotification(@IntRange(from=9, to=15) int, int, @NonNull byte[]); + method @FlaggedApi("android.nfc.nfc_vendor_cmd") public void onVendorNciResponse(@IntRange(from=0, to=15) int, int, @NonNull byte[]); + } + } package android.nfc.cardemulation { diff --git a/nfc/java/android/nfc/INfcAdapter.aidl b/nfc/java/android/nfc/INfcAdapter.aidl index 85879ac56194..8fea5af8fda1 100644 --- a/nfc/java/android/nfc/INfcAdapter.aidl +++ b/nfc/java/android/nfc/INfcAdapter.aidl @@ -24,6 +24,7 @@ import android.nfc.TechListParcel; import android.nfc.IAppCallback; import android.nfc.INfcAdapterExtras; import android.nfc.INfcControllerAlwaysOnListener; +import android.nfc.INfcVendorNciCallback; import android.nfc.INfcTag; import android.nfc.INfcCardEmulation; import android.nfc.INfcFCardEmulation; @@ -87,4 +88,7 @@ interface INfcAdapter boolean isObserveModeSupported(); boolean setObserveMode(boolean enabled); void updateDiscoveryTechnology(IBinder b, int pollFlags, int listenFlags); + int sendVendorNciMessage(int mt, int gid, int oid, in byte[] payload); + void registerVendorExtensionCallback(in INfcVendorNciCallback callbacks); + void unregisterVendorExtensionCallback(in INfcVendorNciCallback callbacks); } diff --git a/nfc/java/android/nfc/INfcVendorNciCallback.aidl b/nfc/java/android/nfc/INfcVendorNciCallback.aidl new file mode 100644 index 000000000000..821dc6f6c868 --- /dev/null +++ b/nfc/java/android/nfc/INfcVendorNciCallback.aidl @@ -0,0 +1,24 @@ +/* + * 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 android.nfc; + +/** + * @hide + */ +oneway interface INfcVendorNciCallback { + void onVendorResponseReceived(int gid, int oid, in byte[] payload); + void onVendorNotificationReceived(int gid, int oid, in byte[] payload); +} diff --git a/nfc/java/android/nfc/NfcAdapter.java b/nfc/java/android/nfc/NfcAdapter.java index 079172142145..40bbe746045c 100644 --- a/nfc/java/android/nfc/NfcAdapter.java +++ b/nfc/java/android/nfc/NfcAdapter.java @@ -19,6 +19,7 @@ package android.nfc; import android.annotation.CallbackExecutor; import android.annotation.FlaggedApi; import android.annotation.IntDef; +import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; @@ -75,6 +76,7 @@ public final class NfcAdapter { static final String TAG = "NFC"; private final NfcControllerAlwaysOnListener mControllerAlwaysOnListener; + private final NfcVendorNciCallbackListener mNfcVendorNciCallbackListener; /** * Intent to start an activity when a tag with NDEF payload is discovered. @@ -861,6 +863,7 @@ public final class NfcAdapter { mTagRemovedListener = null; mLock = new Object(); mControllerAlwaysOnListener = new NfcControllerAlwaysOnListener(getService()); + mNfcVendorNciCallbackListener = new NfcVendorNciCallbackListener(getService()); } /** @@ -2757,4 +2760,163 @@ public final class NfcAdapter { return false; } } + + /** + * Vendor NCI command success. + * @hide + */ + @SystemApi + @FlaggedApi(Flags.FLAG_NFC_VENDOR_CMD) + public static final int SEND_VENDOR_NCI_STATUS_SUCCESS = 0; + /** + * Vendor NCI command rejected. + * @hide + */ + @SystemApi + @FlaggedApi(Flags.FLAG_NFC_VENDOR_CMD) + public static final int SEND_VENDOR_NCI_STATUS_REJECTED = 1; + /** + * Vendor NCI command corrupted. + * @hide + */ + @SystemApi + @FlaggedApi(Flags.FLAG_NFC_VENDOR_CMD) + public static final int SEND_VENDOR_NCI_STATUS_MESSAGE_CORRUPTED = 2; + /** + * Vendor NCI command failed with unknown reason. + * @hide + */ + @SystemApi + @FlaggedApi(Flags.FLAG_NFC_VENDOR_CMD) + public static final int SEND_VENDOR_NCI_STATUS_FAILED = 3; + + /** + * @hide + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = { + SEND_VENDOR_NCI_STATUS_SUCCESS, + SEND_VENDOR_NCI_STATUS_REJECTED, + SEND_VENDOR_NCI_STATUS_MESSAGE_CORRUPTED, + SEND_VENDOR_NCI_STATUS_FAILED, + }) + @interface SendVendorNciStatus {} + + /** + * Message Type for NCI Command. + * @hide + */ + @SystemApi + @FlaggedApi(Flags.FLAG_NFC_VENDOR_CMD) + public static final int MESSAGE_TYPE_COMMAND = 1; + + /** + * @hide + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = { + MESSAGE_TYPE_COMMAND, + }) + @interface MessageType {} + + /** + * Send Vendor specific Nci Messages with custom message type. + * + * The format of the NCI messages are defined in the NCI specification. The platform is + * responsible for fragmenting the payload if necessary. + * + * Note that mt (message type) is added at the beginning of method parameters as it is more + * distinctive than other parameters and was requested from vendor. + * + * @param mt message Type of the command + * @param gid group ID of the command. This needs to be one of the vendor reserved GIDs from + * the NCI specification + * @param oid opcode ID of the command. This is left to the OEM / vendor to decide + * @param payload containing vendor Nci message payload + * @return message send status + * @hide + */ + @SystemApi + @FlaggedApi(Flags.FLAG_NFC_VENDOR_CMD) + @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) + public @SendVendorNciStatus int sendVendorNciMessage(@MessageType int mt, + @IntRange(from = 0, to = 15) int gid, @IntRange(from = 0) int oid, + @NonNull byte[] payload) { + Objects.requireNonNull(payload, "Payload must not be null"); + try { + return sService.sendVendorNciMessage(mt, gid, oid, payload); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Register an {@link NfcVendorNciCallback} to listen for Nfc vendor responses and notifications + * <p>The provided callback will be invoked by the given {@link Executor}. + * + * <p>When first registering a callback, the callbacks's + * {@link NfcVendorNciCallback#onVendorNciCallBack(byte[])} is immediately invoked to + * notify the vendor notification. + * + * @param executor an {@link Executor} to execute given callback + * @param callback user implementation of the {@link NfcVendorNciCallback} + * @hide + */ + @SystemApi + @FlaggedApi(Flags.FLAG_NFC_VENDOR_CMD) + @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) + public void registerNfcVendorNciCallback(@NonNull @CallbackExecutor Executor executor, + @NonNull NfcVendorNciCallback callback) { + mNfcVendorNciCallbackListener.register(executor, callback); + } + + /** + * Unregister the specified {@link NfcVendorNciCallback} + * + * <p>The same {@link NfcVendorNciCallback} object used when calling + * {@link #registerNfcVendorNciCallback(Executor, NfcVendorNciCallback)} must be used. + * + * <p>Callbacks are automatically unregistered when application process goes away + * + * @param callback user implementation of the {@link NfcVendorNciCallback} + * @hide + */ + @SystemApi + @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) + @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) + public void unregisterNfcVendorNciCallback(@NonNull NfcVendorNciCallback callback) { + mNfcVendorNciCallbackListener.unregister(callback); + } + + /** + * Interface for receiving vendor NCI responses and notifications. + * @hide + */ + @SystemApi + @FlaggedApi(Flags.FLAG_NFC_VENDOR_CMD) + public interface NfcVendorNciCallback { + /** + * Invoked when a vendor specific NCI response is received. + * + * @param gid group ID of the command. This needs to be one of the vendor reserved GIDs from + * the NCI specification. + * @param oid opcode ID of the command. This is left to the OEM / vendor to decide. + * @param payload containing vendor Nci message payload. + */ + @FlaggedApi(Flags.FLAG_NFC_VENDOR_CMD) + void onVendorNciResponse( + @IntRange(from = 0, to = 15) int gid, int oid, @NonNull byte[] payload); + + /** + * Invoked when a vendor specific NCI notification is received. + * + * @param gid group ID of the command. This needs to be one of the vendor reserved GIDs from + * the NCI specification. + * @param oid opcode ID of the command. This is left to the OEM / vendor to decide. + * @param payload containing vendor Nci message payload. + */ + @FlaggedApi(Flags.FLAG_NFC_VENDOR_CMD) + void onVendorNciNotification( + @IntRange(from = 9, to = 15) int gid, int oid, @NonNull byte[] payload); + } } diff --git a/nfc/java/android/nfc/NfcVendorNciCallbackListener.java b/nfc/java/android/nfc/NfcVendorNciCallbackListener.java new file mode 100644 index 000000000000..742d75fe4bc3 --- /dev/null +++ b/nfc/java/android/nfc/NfcVendorNciCallbackListener.java @@ -0,0 +1,115 @@ +/* + * 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 android.nfc; + +import android.annotation.NonNull; +import android.nfc.NfcAdapter.NfcVendorNciCallback; +import android.os.Binder; +import android.os.RemoteException; +import android.util.Log; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.Executor; + +/** + * @hide + */ +public final class NfcVendorNciCallbackListener extends INfcVendorNciCallback.Stub { + private static final String TAG = "Nfc.NfcVendorNciCallbacks"; + private final INfcAdapter mAdapter; + private boolean mIsRegistered = false; + private final Map<NfcVendorNciCallback, Executor> mCallbackMap = new HashMap<>(); + + public NfcVendorNciCallbackListener(@NonNull INfcAdapter adapter) { + mAdapter = adapter; + } + + public void register(@NonNull Executor executor, @NonNull NfcVendorNciCallback callback) { + synchronized (this) { + if (mCallbackMap.containsKey(callback)) { + return; + } + mCallbackMap.put(callback, executor); + if (!mIsRegistered) { + try { + mAdapter.registerVendorExtensionCallback(this); + mIsRegistered = true; + } catch (RemoteException e) { + Log.w(TAG, "Failed to register adapter state callback"); + mCallbackMap.remove(callback); + throw e.rethrowFromSystemServer(); + } + } + } + } + + public void unregister(@NonNull NfcVendorNciCallback callback) { + synchronized (this) { + if (!mCallbackMap.containsKey(callback) || !mIsRegistered) { + return; + } + if (mCallbackMap.size() == 1) { + try { + mAdapter.unregisterVendorExtensionCallback(this); + mIsRegistered = false; + mCallbackMap.remove(callback); + } catch (RemoteException e) { + Log.w(TAG, "Failed to unregister AdapterStateCallback with service"); + throw e.rethrowFromSystemServer(); + } + } else { + mCallbackMap.remove(callback); + } + } + } + + @Override + public void onVendorResponseReceived(int gid, int oid, @NonNull byte[] payload) + throws RemoteException { + synchronized (this) { + final long identity = Binder.clearCallingIdentity(); + try { + for (NfcVendorNciCallback callback : mCallbackMap.keySet()) { + Executor executor = mCallbackMap.get(callback); + executor.execute(() -> callback.onVendorNciResponse(gid, oid, payload)); + } + } catch (RuntimeException ex) { + throw ex; + } finally { + Binder.restoreCallingIdentity(identity); + } + } + } + + @Override + public void onVendorNotificationReceived(int gid, int oid, @NonNull byte[] payload) + throws RemoteException { + synchronized (this) { + final long identity = Binder.clearCallingIdentity(); + try { + for (NfcVendorNciCallback callback : mCallbackMap.keySet()) { + Executor executor = mCallbackMap.get(callback); + executor.execute(() -> callback.onVendorNciNotification(gid, oid, payload)); + } + } catch (RuntimeException ex) { + throw ex; + } finally { + Binder.restoreCallingIdentity(identity); + } + } + } +} diff --git a/nfc/java/android/nfc/flags.aconfig b/nfc/java/android/nfc/flags.aconfig index 11be905c41ca..cb1a542b2b36 100644 --- a/nfc/java/android/nfc/flags.aconfig +++ b/nfc/java/android/nfc/flags.aconfig @@ -62,3 +62,10 @@ flag { description: "Flag for NFC set discovery tech API" bug: "300351519" } + +flag { + name: "nfc_vendor_cmd" + namespace: "nfc" + description: "Enable NFC vendor command support" + bug: "289879306" +} diff --git a/packages/CrashRecovery/services/java/com/android/server/PackageWatchdog.java b/packages/CrashRecovery/services/java/com/android/server/PackageWatchdog.java index d256aead97e8..b5cf011c32a6 100644 --- a/packages/CrashRecovery/services/java/com/android/server/PackageWatchdog.java +++ b/packages/CrashRecovery/services/java/com/android/server/PackageWatchdog.java @@ -33,12 +33,12 @@ import android.os.Looper; import android.os.Process; import android.os.SystemProperties; import android.provider.DeviceConfig; +import android.sysprop.CrashRecoveryProperties; import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; import android.util.AtomicFile; import android.util.LongArrayQueue; -import android.util.MathUtils; import android.util.Slog; import android.util.Xml; @@ -128,18 +128,9 @@ public class PackageWatchdog { @VisibleForTesting static final int DEFAULT_BOOT_LOOP_TRIGGER_COUNT = 5; + @VisibleForTesting static final long DEFAULT_BOOT_LOOP_TRIGGER_WINDOW_MS = TimeUnit.MINUTES.toMillis(10); - // These properties track individual system server boot events, and are reset once the boot - // threshold is met, or the boot loop trigger window is exceeded between boot events. - private static final String PROP_RESCUE_BOOT_COUNT = "sys.rescue_boot_count"; - private static final String PROP_RESCUE_BOOT_START = "sys.rescue_boot_start"; - - // These properties track multiple calls made to observers tracking boot loops. They are reset - // when the de-escalation window is exceeded between boot events. - private static final String PROP_BOOT_MITIGATION_WINDOW_START = "sys.boot_mitigation_start"; - private static final String PROP_BOOT_MITIGATION_COUNT = "sys.boot_mitigation_count"; - private long mNumberOfNativeCrashPollsRemaining; private static final int DB_VERSION = 1; @@ -1702,42 +1693,45 @@ public class PackageWatchdog { setCount(0); } - private int getCount() { - return SystemProperties.getInt(PROP_RESCUE_BOOT_COUNT, 0); + protected int getCount() { + return CrashRecoveryProperties.rescueBootCount().orElse(0); } - private void setCount(int count) { - SystemProperties.set(PROP_RESCUE_BOOT_COUNT, Integer.toString(count)); + protected void setCount(int count) { + CrashRecoveryProperties.rescueBootCount(count); } public long getStart() { - return SystemProperties.getLong(PROP_RESCUE_BOOT_START, 0); + return CrashRecoveryProperties.rescueBootStart().orElse(0L); } public int getMitigationCount() { - return SystemProperties.getInt(PROP_BOOT_MITIGATION_COUNT, 0); + return CrashRecoveryProperties.bootMitigationCount().orElse(0); } public void setStart(long start) { - setPropertyStart(PROP_RESCUE_BOOT_START, start); + CrashRecoveryProperties.rescueBootStart(getStartTime(start)); } public void setMitigationStart(long start) { - setPropertyStart(PROP_BOOT_MITIGATION_WINDOW_START, start); + CrashRecoveryProperties.bootMitigationStart(getStartTime(start)); } public long getMitigationStart() { - return SystemProperties.getLong(PROP_BOOT_MITIGATION_WINDOW_START, 0); + return CrashRecoveryProperties.bootMitigationStart().orElse(0L); } public void setMitigationCount(int count) { - SystemProperties.set(PROP_BOOT_MITIGATION_COUNT, Integer.toString(count)); + CrashRecoveryProperties.bootMitigationCount(count); + } + + private static long constrain(long amount, long low, long high) { + return amount < low ? low : (amount > high ? high : amount); } - public void setPropertyStart(String property, long start) { + public long getStartTime(long start) { final long now = mSystemClock.uptimeMillis(); - final long newStart = MathUtils.constrain(start, 0, now); - SystemProperties.set(property, Long.toString(newStart)); + return constrain(start, 0, now); } public void saveMitigationCountToMetadata() { diff --git a/packages/CrashRecovery/services/java/com/android/server/RescueParty.java b/packages/CrashRecovery/services/java/com/android/server/RescueParty.java index 5d03ef578995..9217e7012e7e 100644 --- a/packages/CrashRecovery/services/java/com/android/server/RescueParty.java +++ b/packages/CrashRecovery/services/java/com/android/server/RescueParty.java @@ -37,9 +37,9 @@ import android.os.SystemProperties; import android.os.UserHandle; import android.provider.DeviceConfig; import android.provider.Settings; +import android.sysprop.CrashRecoveryProperties; import android.text.TextUtils; import android.util.ArraySet; -import android.util.ExceptionUtils; import android.util.Log; import android.util.Slog; @@ -76,10 +76,6 @@ import java.util.concurrent.TimeUnit; public class RescueParty { @VisibleForTesting static final String PROP_ENABLE_RESCUE = "persist.sys.enable_rescue"; - static final String PROP_ATTEMPTING_FACTORY_RESET = "sys.attempting_factory_reset"; - static final String PROP_ATTEMPTING_REBOOT = "sys.attempting_reboot"; - static final String PROP_MAX_RESCUE_LEVEL_ATTEMPTED = "sys.max_rescue_level_attempted"; - static final String PROP_LAST_FACTORY_RESET_TIME_MS = "persist.sys.last_factory_reset"; @VisibleForTesting static final int LEVEL_NONE = 0; @VisibleForTesting @@ -93,8 +89,6 @@ public class RescueParty { @VisibleForTesting static final int LEVEL_FACTORY_RESET = 5; @VisibleForTesting - static final String PROP_RESCUE_BOOT_COUNT = "sys.rescue_boot_count"; - @VisibleForTesting static final String TAG = "RescueParty"; @VisibleForTesting static final long DEFAULT_OBSERVING_DURATION_MS = TimeUnit.DAYS.toMillis(2); @@ -143,7 +137,7 @@ public class RescueParty { } // We're disabled on all engineering devices - if (Build.IS_ENG) { + if (Build.TYPE.equals("eng")) { Slog.v(TAG, "Disabled because of eng build"); return true; } @@ -151,7 +145,7 @@ public class RescueParty { // We're disabled on userdebug devices connected over USB, since that's // a decent signal that someone is actively trying to debug the device, // or that it's in a lab environment. - if (Build.IS_USERDEBUG && isUsbActive()) { + if (Build.TYPE.equals("userdebug") && isUsbActive()) { Slog.v(TAG, "Disabled because of active USB connection"); return true; } @@ -177,11 +171,34 @@ public class RescueParty { } static boolean isFactoryResetPropertySet() { - return SystemProperties.getBoolean(PROP_ATTEMPTING_FACTORY_RESET, false); + return CrashRecoveryProperties.attemptingFactoryReset().orElse(false); } static boolean isRebootPropertySet() { - return SystemProperties.getBoolean(PROP_ATTEMPTING_REBOOT, false); + return CrashRecoveryProperties.attemptingReboot().orElse(false); + } + + protected static long getLastFactoryResetTimeMs() { + return CrashRecoveryProperties.lastFactoryResetTimeMs().orElse(0L); + } + + protected static int getMaxRescueLevelAttempted() { + return CrashRecoveryProperties.maxRescueLevelAttempted().orElse(LEVEL_NONE); + } + + protected static void setFactoryResetProperty(boolean value) { + CrashRecoveryProperties.attemptingFactoryReset(value); + } + protected static void setRebootProperty(boolean value) { + CrashRecoveryProperties.attemptingReboot(value); + } + + protected static void setLastFactoryResetTimeMs(long value) { + CrashRecoveryProperties.lastFactoryResetTimeMs(value); + } + + protected static void setMaxRescueLevelAttempted(int level) { + CrashRecoveryProperties.maxRescueLevelAttempted(level); } /** @@ -440,7 +457,7 @@ public class RescueParty { case LEVEL_WARM_REBOOT: // Request the reboot from a separate thread to avoid deadlock on PackageWatchdog // when device shutting down. - SystemProperties.set(PROP_ATTEMPTING_REBOOT, "true"); + setRebootProperty(true); runnable = () -> { try { PowerManager pm = context.getSystemService(PowerManager.class); @@ -462,9 +479,9 @@ public class RescueParty { if (isRebootPropertySet()) { break; } - SystemProperties.set(PROP_ATTEMPTING_FACTORY_RESET, "true"); + setFactoryResetProperty(true); long now = System.currentTimeMillis(); - SystemProperties.set(PROP_LAST_FACTORY_RESET_TIME_MS, Long.toString(now)); + setLastFactoryResetTimeMs(now); runnable = new Runnable() { @Override public void run() { @@ -485,9 +502,18 @@ public class RescueParty { } } + private static String getCompleteMessage(Throwable t) { + final StringBuilder builder = new StringBuilder(); + builder.append(t.getMessage()); + while ((t = t.getCause()) != null) { + builder.append(": ").append(t.getMessage()); + } + return builder.toString(); + } + private static void logRescueException(int level, @Nullable String failedPackageName, Throwable t) { - final String msg = ExceptionUtils.getCompleteMessage(t); + final String msg = getCompleteMessage(t); EventLogTags.writeRescueFailure(level, msg); String failureMsg = "Failed rescue level " + levelToString(level); if (!TextUtils.isEmpty(failedPackageName)) { @@ -514,10 +540,10 @@ public class RescueParty { private static void resetAllSettingsIfNecessary(Context context, int mode, int level) throws Exception { // No need to reset Settings again if they are already reset in the current level once. - if (SystemProperties.getInt(PROP_MAX_RESCUE_LEVEL_ATTEMPTED, LEVEL_NONE) >= level) { + if (getMaxRescueLevelAttempted() >= level) { return; } - SystemProperties.set(PROP_MAX_RESCUE_LEVEL_ATTEMPTED, Integer.toString(level)); + setMaxRescueLevelAttempted(level); // Try our best to reset all settings possible, and once finished // rethrow any exception that we encountered Exception res = null; @@ -732,7 +758,7 @@ public class RescueParty { * Will return {@code false} if a factory reset was already offered recently. */ private boolean shouldThrottleReboot() { - Long lastResetTime = SystemProperties.getLong(PROP_LAST_FACTORY_RESET_TIME_MS, 0); + Long lastResetTime = getLastFactoryResetTimeMs(); long now = System.currentTimeMillis(); long throttleDurationMin = SystemProperties.getLong(PROP_THROTTLE_DURATION_MIN_FLAG, DEFAULT_FACTORY_RESET_THROTTLE_DURATION_MIN); diff --git a/packages/CrashRecovery/services/java/com/android/server/rollback/RollbackPackageHealthObserver.java b/packages/CrashRecovery/services/java/com/android/server/rollback/RollbackPackageHealthObserver.java index 50322f09640f..dd74a2a978b2 100644 --- a/packages/CrashRecovery/services/java/com/android/server/rollback/RollbackPackageHealthObserver.java +++ b/packages/CrashRecovery/services/java/com/android/server/rollback/RollbackPackageHealthObserver.java @@ -34,6 +34,7 @@ import android.os.Handler; import android.os.HandlerThread; import android.os.PowerManager; import android.os.SystemProperties; +import android.sysprop.CrashRecoveryProperties; import android.util.ArraySet; import android.util.Slog; import android.util.SparseArray; @@ -70,7 +71,6 @@ import java.util.function.Consumer; final class RollbackPackageHealthObserver implements PackageHealthObserver { private static final String TAG = "RollbackPackageHealthObserver"; private static final String NAME = "rollback-observer"; - private static final String PROP_ATTEMPTING_REBOOT = "sys.attempting_reboot"; private static final int PERSISTENT_MASK = ApplicationInfo.FLAG_PERSISTENT | ApplicationInfo.FLAG_SYSTEM; @@ -450,7 +450,7 @@ final class RollbackPackageHealthObserver implements PackageHealthObserver { markStagedSessionHandled(rollback.getRollbackId()); // Wait for all pending staged sessions to get handled before rebooting. if (isPendingStagedSessionsEmpty()) { - SystemProperties.set(PROP_ATTEMPTING_REBOOT, "true"); + CrashRecoveryProperties.attemptingReboot(true); mContext.getSystemService(PowerManager.class).reboot("Rollback staged install"); } } diff --git a/packages/SettingsLib/res/values/arrays.xml b/packages/SettingsLib/res/values/arrays.xml index 3adb882bc1b1..e067a088fdf8 100644 --- a/packages/SettingsLib/res/values/arrays.xml +++ b/packages/SettingsLib/res/values/arrays.xml @@ -526,7 +526,7 @@ </string-array> <!-- USB configuration values for Developer Settings. - These are lists of USB functions passed to the USB Manager to change USB configuraton. + These are lists of USB functions passed to the USB Manager to change USB configuration. This can be overridden by devices with additional USB configurations. Do not translate. --> <string-array name="usb_configuration_values" translatable="false"> diff --git a/packages/SystemUI/OWNERS b/packages/SystemUI/OWNERS index 967a36b38090..78cacec6d4db 100644 --- a/packages/SystemUI/OWNERS +++ b/packages/SystemUI/OWNERS @@ -39,7 +39,6 @@ hwwang@google.com hyunyoungs@google.com ikateryna@google.com iyz@google.com -jaggies@google.com jamesoleary@google.com jbolinger@google.com jdemeulenaere@google.com diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/OWNERS b/packages/SystemUI/src/com/android/systemui/statusbar/tv/OWNERS index a601e9b86ef4..0b9f559abe5f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/OWNERS +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/OWNERS @@ -4,5 +4,4 @@ valiiftime@google.com galinap@google.com patrikf@google.com robhor@google.com -sergeynv@google.com diff --git a/services/core/Android.bp b/services/core/Android.bp index 2dda76e06c56..2ed75d9d2a2e 100644 --- a/services/core/Android.bp +++ b/services/core/Android.bp @@ -191,6 +191,7 @@ java_library_static { "ImmutabilityAnnotation", "securebox", "net_flags_lib", + "core_os_flags_lib", ], javac_shard_size: 50, javacflags: [ diff --git a/services/core/java/com/android/server/OWNERS b/services/core/java/com/android/server/OWNERS index 5335cc310af1..89fb9ce0859e 100644 --- a/services/core/java/com/android/server/OWNERS +++ b/services/core/java/com/android/server/OWNERS @@ -38,6 +38,7 @@ per-file NetIdManager.java = file:/services/core/java/com/android/server/net/OWN per-file PackageWatchdog.java, RescueParty.java = file:/services/core/java/com/android/server/rollback/OWNERS per-file PinnerService.java = file:/apct-tests/perftests/OWNERS per-file RescueParty.java = shuc@google.com, ancr@google.com, harshitmahajan@google.com +per-file SensitiveContentProtectionManagerService.java = file:/core/java/android/permission/OWNERS per-file SystemClockTime.java = file:/services/core/java/com/android/server/timedetector/OWNERS per-file SystemTimeZone.java = file:/services/core/java/com/android/server/timezonedetector/OWNERS per-file TelephonyRegistry.java = file:/telephony/OWNERS diff --git a/services/core/java/com/android/server/adb/AdbDebuggingManager.java b/services/core/java/com/android/server/adb/AdbDebuggingManager.java index 627a62ee0496..34c3d7ec8433 100644 --- a/services/core/java/com/android/server/adb/AdbDebuggingManager.java +++ b/services/core/java/com/android/server/adb/AdbDebuggingManager.java @@ -246,16 +246,6 @@ public class AdbDebuggingManager { @Override public void run() { - if (mGuid.isEmpty()) { - Slog.e(TAG, "adbwifi guid was not set"); - return; - } - mPort = native_pairing_start(mGuid, mPairingCode); - if (mPort <= 0 || mPort > 65535) { - Slog.e(TAG, "Unable to start pairing server"); - return; - } - // Register the mdns service NsdServiceInfo serviceInfo = new NsdServiceInfo(); serviceInfo.setServiceName(mServiceName); @@ -288,6 +278,28 @@ public class AdbDebuggingManager { mHandler.sendMessage(message); } + @Override + public void start() { + /* + * If a user is fast enough to click cancel, native_pairing_cancel can be invoked + * while native_pairing_start is running which run the destruction of the object + * while it is being constructed. Here we start the pairing server on foreground + * Thread so native_pairing_cancel can never be called concurrently. Then we let + * the pairing server run on a background Thread. + */ + if (mGuid.isEmpty()) { + Slog.e(TAG, "adbwifi guid was not set"); + return; + } + mPort = native_pairing_start(mGuid, mPairingCode); + if (mPort <= 0) { + Slog.e(TAG, "Unable to start pairing server"); + return; + } + + super.start(); + } + public void cancelPairing() { native_pairing_cancel(); } diff --git a/services/core/java/com/android/server/am/ProcessServiceRecord.java b/services/core/java/com/android/server/am/ProcessServiceRecord.java index 7ff6d116baaf..1420671688e5 100644 --- a/services/core/java/com/android/server/am/ProcessServiceRecord.java +++ b/services/core/java/com/android/server/am/ProcessServiceRecord.java @@ -341,8 +341,10 @@ final class ProcessServiceRecord { mHasAboveClient = false; for (int i = mConnections.size() - 1; i >= 0; i--) { ConnectionRecord cr = mConnections.valueAt(i); - if (cr.binding.service.app.mServices != this - && cr.hasFlag(Context.BIND_ABOVE_CLIENT)) { + + final boolean isSameProcess = cr.binding.service.app != null + && cr.binding.service.app.mServices == this; + if (!isSameProcess && cr.hasFlag(Context.BIND_ABOVE_CLIENT)) { mHasAboveClient = true; break; } diff --git a/services/core/java/com/android/server/biometrics/OWNERS b/services/core/java/com/android/server/biometrics/OWNERS index 1bf2aeffdf0c..4703efbcd7be 100644 --- a/services/core/java/com/android/server/biometrics/OWNERS +++ b/services/core/java/com/android/server/biometrics/OWNERS @@ -2,7 +2,6 @@ set noparent graciecheng@google.com ilyamaty@google.com -jaggies@google.com jbolinger@google.com jeffpu@google.com joshmccloskey@google.com diff --git a/services/core/java/com/android/server/locksettings/OWNERS b/services/core/java/com/android/server/locksettings/OWNERS index 5d4986307835..48da270180e6 100644 --- a/services/core/java/com/android/server/locksettings/OWNERS +++ b/services/core/java/com/android/server/locksettings/OWNERS @@ -1,4 +1,3 @@ # Bug component: 1333694 ebiggers@google.com -jaggies@google.com rubinxu@google.com diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index b47458b88f40..c11356b7308e 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -26,6 +26,8 @@ import static android.Manifest.permission.NETWORK_STACK; import static android.Manifest.permission.OBSERVE_NETWORK_POLICY; import static android.Manifest.permission.READ_PHONE_STATE; import static android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE; +import static android.app.ActivityManager.PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK; +import static android.app.ActivityManager.PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK; import static android.app.ActivityManager.PROCESS_STATE_UNKNOWN; import static android.app.ActivityManager.isProcStateConsideredInteraction; import static android.app.ActivityManager.printCapabilitiesSummary; @@ -85,8 +87,10 @@ import static android.net.NetworkPolicyManager.ALLOWED_REASON_POWER_SAVE_EXCEPT_ import static android.net.NetworkPolicyManager.ALLOWED_REASON_RESTRICTED_MODE_PERMISSIONS; import static android.net.NetworkPolicyManager.ALLOWED_REASON_SYSTEM; import static android.net.NetworkPolicyManager.ALLOWED_REASON_TOP; +import static android.net.NetworkPolicyManager.BACKGROUND_THRESHOLD_STATE; import static android.net.NetworkPolicyManager.EXTRA_NETWORK_TEMPLATE; import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT; +import static android.net.NetworkPolicyManager.FOREGROUND_THRESHOLD_STATE; import static android.net.NetworkPolicyManager.POLICY_ALLOW_METERED_BACKGROUND; import static android.net.NetworkPolicyManager.POLICY_NONE; import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND; @@ -97,6 +101,7 @@ import static android.net.NetworkPolicyManager.RULE_REJECT_METERED; import static android.net.NetworkPolicyManager.RULE_REJECT_RESTRICTED_MODE; import static android.net.NetworkPolicyManager.RULE_TEMPORARY_ALLOW_METERED; import static android.net.NetworkPolicyManager.SUBSCRIPTION_OVERRIDE_UNMETERED; +import static android.net.NetworkPolicyManager.TOP_THRESHOLD_STATE; import static android.net.NetworkPolicyManager.allowedReasonsToString; import static android.net.NetworkPolicyManager.blockedReasonsToString; import static android.net.NetworkPolicyManager.isProcStateAllowedNetworkWhileBackground; @@ -334,6 +339,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { static final String TAG = NetworkPolicyLogger.TAG; private static final boolean LOGD = NetworkPolicyLogger.LOGD; private static final boolean LOGV = NetworkPolicyLogger.LOGV; + // TODO: b/304347838 - Remove once the feature is in staging. + private static final boolean ALWAYS_RESTRICT_BACKGROUND_NETWORK = false; /** * No opportunistic quota could be calculated from user data plan or data settings. @@ -468,7 +475,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { */ private static final int MSG_PROCESS_BACKGROUND_TRANSITIONING_UIDS = 24; - private static final int UID_MSG_STATE_CHANGED = 100; + @VisibleForTesting + static final int UID_MSG_STATE_CHANGED = 100; private static final int UID_MSG_GONE = 101; private static final String PROP_SUB_PLAN_OWNER = "persist.sys.sub_plan_owner"; @@ -1054,7 +1062,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } // The flag is boot-stable. - mBackgroundNetworkRestricted = Flags.networkBlockedForTopSleepingAndAbove(); + mBackgroundNetworkRestricted = ALWAYS_RESTRICT_BACKGROUND_NETWORK + && Flags.networkBlockedForTopSleepingAndAbove(); if (mBackgroundNetworkRestricted) { // Firewall rules and UidBlockedState will get updated in // updateRulesForGlobalChangeAL below. @@ -1074,8 +1083,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { final int cutpoint = mBackgroundNetworkRestricted ? PROCESS_STATE_UNKNOWN : NetworkPolicyManager.FOREGROUND_THRESHOLD_STATE; - // TODO (b/319728914): Filter out the unnecessary changes when using no cutpoint. - mActivityManagerInternal.registerNetworkPolicyUidObserver(mUidObserver, changes, cutpoint, "android"); mNetworkManager.registerObserver(mAlertObserver); @@ -1184,6 +1191,51 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } final private IUidObserver mUidObserver = new UidObserver() { + + /** + * Returns whether the uid state change information is relevant for the service. If the + * state information does not lead to any change in the network rules, it can safely be + * ignored. + */ + @GuardedBy("mUidStateCallbackInfos") + private boolean isUidStateChangeRelevant(UidStateCallbackInfo previousInfo, + int newProcState, long newProcStateSeq, int newCapability) { + if (previousInfo.procStateSeq == -1) { + // No previous record. Always process the first state change callback. + return true; + } + if (newProcStateSeq <= previousInfo.procStateSeq) { + // Stale callback. Ignore. + return false; + } + final int previousProcState = previousInfo.procState; + if (mBackgroundNetworkRestricted && (previousProcState >= BACKGROUND_THRESHOLD_STATE) + != (newProcState >= BACKGROUND_THRESHOLD_STATE)) { + // Proc-state change crossed BACKGROUND_THRESHOLD_STATE: Network rules for the + // BACKGROUND chain may change. + return true; + } + if ((previousProcState <= TOP_THRESHOLD_STATE) + != (newProcState <= TOP_THRESHOLD_STATE)) { + // Proc-state change crossed TOP_THRESHOLD_STATE: Network rules for the + // LOW_POWER_STANDBY chain may change. + return true; + } + if ((previousProcState <= FOREGROUND_THRESHOLD_STATE) + != (newProcState <= FOREGROUND_THRESHOLD_STATE)) { + // Proc-state change crossed FOREGROUND_THRESHOLD_STATE: Network rules for many + // different chains may change. + return true; + } + final int networkCapabilities = PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK + | PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK; + if ((previousInfo.capability & networkCapabilities) + != (newCapability & networkCapabilities)) { + return true; + } + return false; + } + @Override public void onUidStateChanged(int uid, int procState, long procStateSeq, @ProcessCapability int capability) { synchronized (mUidStateCallbackInfos) { @@ -1192,13 +1244,13 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { callbackInfo = new UidStateCallbackInfo(); mUidStateCallbackInfos.put(uid, callbackInfo); } - if (callbackInfo.procStateSeq == -1 || procStateSeq > callbackInfo.procStateSeq) { + if (isUidStateChangeRelevant(callbackInfo, procState, procStateSeq, capability)) { callbackInfo.update(uid, procState, procStateSeq, capability); - } - if (!callbackInfo.isPending) { - mUidEventHandler.obtainMessage(UID_MSG_STATE_CHANGED, callbackInfo) - .sendToTarget(); - callbackInfo.isPending = true; + if (!callbackInfo.isPending) { + mUidEventHandler.obtainMessage(UID_MSG_STATE_CHANGED, callbackInfo) + .sendToTarget(); + callbackInfo.isPending = true; + } } } } diff --git a/services/core/java/com/android/server/ondeviceintelligence/OWNERS b/services/core/java/com/android/server/ondeviceintelligence/OWNERS new file mode 100644 index 000000000000..09774f78d712 --- /dev/null +++ b/services/core/java/com/android/server/ondeviceintelligence/OWNERS @@ -0,0 +1 @@ +file:/core/java/android/app/ondeviceintelligence/OWNERS diff --git a/services/core/java/com/android/server/os/Android.bp b/services/core/java/com/android/server/os/Android.bp new file mode 100644 index 000000000000..565dc3b644ea --- /dev/null +++ b/services/core/java/com/android/server/os/Android.bp @@ -0,0 +1,12 @@ +aconfig_declarations { + name: "core_os_flags", + package: "com.android.server.os", + srcs: [ + "*.aconfig", + ], +} + +java_aconfig_library { + name: "core_os_flags_lib", + aconfig_declarations: "core_os_flags", +} diff --git a/services/core/java/com/android/server/os/core_os_flags.aconfig b/services/core/java/com/android/server/os/core_os_flags.aconfig new file mode 100644 index 000000000000..cbc0d54046df --- /dev/null +++ b/services/core/java/com/android/server/os/core_os_flags.aconfig @@ -0,0 +1,8 @@ +package: "com.android.server.os" + +flag { + name: "proto_tombstone" + namespace: "proto_tombstone_ns" + description: "Use proto tombstones as source of truth for adding to dropbox" + bug: "323857385" +} diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java index 988a32f3ffc7..8e31e766c1d8 100644 --- a/services/core/java/com/android/server/pm/InstallPackageHelper.java +++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java @@ -4331,7 +4331,7 @@ final class InstallPackageHelper { + "; old: " + pkgSetting.getPathString() + " @ " + pkgSetting.getVersionCode() + "; new: " + parsedPackage.getPath() + " @ " - + parsedPackage.getPath()); + + parsedPackage.getLongVersionCode()); } } diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java index 7c307bd536dc..57b89e30f7bd 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerService.java +++ b/services/core/java/com/android/server/pm/PackageInstallerService.java @@ -762,6 +762,24 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements } } + if (Flags.recoverabilityDetection()) { + if (params.rollbackImpactLevel == PackageManager.ROLLBACK_USER_IMPACT_HIGH + || params.rollbackImpactLevel + == PackageManager.ROLLBACK_USER_IMPACT_ONLY_MANUAL) { + if ((params.installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) == 0) { + throw new IllegalArgumentException( + "Can't set rollbackImpactLevel when rollback is not enabled"); + } + if (mContext.checkCallingOrSelfPermission(Manifest.permission.MANAGE_ROLLBACKS) + != PackageManager.PERMISSION_GRANTED) { + throw new SecurityException( + "Setting rollbackImpactLevel requires the MANAGE_ROLLBACKS permission"); + } + } else if (params.rollbackImpactLevel < 0) { + throw new IllegalArgumentException("rollbackImpactLevel can't be negative."); + } + } + boolean isApex = (params.installFlags & PackageManager.INSTALL_APEX) != 0; if (isApex) { if (mContext.checkCallingOrSelfPermission(Manifest.permission.INSTALL_PACKAGE_UPDATES) diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index 94c6b8b2016c..fbd652602962 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -1207,6 +1207,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { info.autoRevokePermissionsMode = params.autoRevokePermissionsMode; info.installFlags = params.installFlags; info.rollbackLifetimeMillis = params.rollbackLifetimeMillis; + info.rollbackImpactLevel = params.rollbackImpactLevel; info.isMultiPackage = params.isMultiPackage; info.isStaged = params.isStaged; info.rollbackDataPolicy = params.rollbackDataPolicy; diff --git a/services/core/java/com/android/server/pm/permission/Permission.java b/services/core/java/com/android/server/pm/permission/Permission.java index c81d6d7d0918..1440a1e2fafe 100644 --- a/services/core/java/com/android/server/pm/permission/Permission.java +++ b/services/core/java/com/android/server/pm/permission/Permission.java @@ -146,6 +146,10 @@ public final class Permission { return mPermissionInfo.packageName; } + public boolean isReconciled() { + return mReconciled; + } + public int getType() { return mType; } diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java index 574f121b033a..b92ae23fdd85 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java @@ -4137,6 +4137,10 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt // being uninstalled, continue; } + // Don't remove config permissions and lose their GIDs. + if (bp.getType() == Permission.TYPE_CONFIG && !bp.isReconciled()) { + continue; + } // The target package is the source of the current permission // Set to changed for either install or uninstall changed = true; diff --git a/services/core/java/com/android/server/rollback/Rollback.java b/services/core/java/com/android/server/rollback/Rollback.java index a5b90f12a5cc..a580bb7c741a 100644 --- a/services/core/java/com/android/server/rollback/Rollback.java +++ b/services/core/java/com/android/server/rollback/Rollback.java @@ -215,7 +215,8 @@ class Rollback { /* packages */ new ArrayList<>(), /* isStaged */ isStaged, /* causePackages */ new ArrayList<>(), - /* committedSessionId */ -1); + /* committedSessionId */ -1, + /* rollbackImpactLevel */ PackageManager.ROLLBACK_USER_IMPACT_LOW); mUserId = userId; mInstallerPackageName = installerPackageName; mBackupDir = backupDir; @@ -394,7 +395,8 @@ class Rollback { */ @WorkerThread boolean enableForPackage(String packageName, long newVersion, long installedVersion, - boolean isApex, String sourceDir, String[] splitSourceDirs, int rollbackDataPolicy) { + boolean isApex, String sourceDir, String[] splitSourceDirs, int rollbackDataPolicy, + @PackageManager.RollbackImpactLevel int rollbackImpactLevel) { assertInWorkerThread(); try { RollbackStore.backupPackageCodePath(this, packageName, sourceDir); @@ -415,6 +417,10 @@ class Rollback { isApex, false /* isApkInApex */, new ArrayList<>(), rollbackDataPolicy); info.getPackages().add(packageRollbackInfo); + + if (info.getRollbackImpactLevel() < rollbackImpactLevel) { + info.setRollbackImpactLevel(rollbackImpactLevel); + } return true; } diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java index b38d6c7f1146..d96fc332ce5a 100644 --- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java +++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java @@ -954,7 +954,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub implements Rollba ApplicationInfo appInfo = pkgInfo.applicationInfo; return rollback.enableForPackage(packageName, newPackage.getVersionCode(), pkgInfo.getLongVersionCode(), isApex, appInfo.sourceDir, - appInfo.splitSourceDirs, rollbackDataPolicy); + appInfo.splitSourceDirs, rollbackDataPolicy, session.rollbackImpactLevel); } @ExtThread diff --git a/services/core/java/com/android/server/rollback/RollbackStore.java b/services/core/java/com/android/server/rollback/RollbackStore.java index 0af137faf5b4..14539d544bf9 100644 --- a/services/core/java/com/android/server/rollback/RollbackStore.java +++ b/services/core/java/com/android/server/rollback/RollbackStore.java @@ -193,16 +193,27 @@ class RollbackStore { json.put("isStaged", rollback.isStaged()); json.put("causePackages", versionedPackagesToJson(rollback.getCausePackages())); json.put("committedSessionId", rollback.getCommittedSessionId()); + if (Flags.recoverabilityDetection()) { + json.put("rollbackImpactLevel", rollback.getRollbackImpactLevel()); + } return json; } private static RollbackInfo rollbackInfoFromJson(JSONObject json) throws JSONException { - return new RollbackInfo( + RollbackInfo rollbackInfo = new RollbackInfo( json.getInt("rollbackId"), packageRollbackInfosFromJson(json.getJSONArray("packages")), json.getBoolean("isStaged"), versionedPackagesFromJson(json.getJSONArray("causePackages")), json.getInt("committedSessionId")); + + if (Flags.recoverabilityDetection()) { + // to make it backward compatible. + rollbackInfo.setRollbackImpactLevel(json.optInt("rollbackImpactLevel", + PackageManager.ROLLBACK_USER_IMPACT_LOW)); + } + + return rollbackInfo; } /** diff --git a/services/core/java/com/android/server/security/KeyAttestationApplicationIdProviderService.java b/services/core/java/com/android/server/security/KeyAttestationApplicationIdProviderService.java index d5bc91278aa8..b69ccb348fa7 100644 --- a/services/core/java/com/android/server/security/KeyAttestationApplicationIdProviderService.java +++ b/services/core/java/com/android/server/security/KeyAttestationApplicationIdProviderService.java @@ -14,7 +14,6 @@ * limitations under the License. */ - package com.android.server.security; import android.content.Context; @@ -23,6 +22,7 @@ import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.os.Binder; import android.os.RemoteException; +import android.os.ServiceSpecificException; import android.os.UserHandle; import android.security.keystore.IKeyAttestationApplicationIdProvider; import android.security.keystore.KeyAttestationApplicationId; @@ -57,7 +57,10 @@ public class KeyAttestationApplicationIdProviderService try { String[] packageNames = mPackageManager.getPackagesForUid(uid); if (packageNames == null) { - throw new RemoteException("No packages for uid"); + throw new ServiceSpecificException( + IKeyAttestationApplicationIdProvider + .ERROR_GET_ATTESTATION_APPLICATION_ID_FAILED, + "No package for uid: " + uid); } int userId = UserHandle.getUserId(uid); keyAttestationPackageInfos = new KeyAttestationPackageInfo[packageNames.length]; diff --git a/services/core/java/com/android/server/selinux/OWNERS b/services/core/java/com/android/server/selinux/OWNERS new file mode 100644 index 000000000000..6ca4da2fd740 --- /dev/null +++ b/services/core/java/com/android/server/selinux/OWNERS @@ -0,0 +1,3 @@ +# Bug component: 1117393 + +sandrom@google.com diff --git a/services/core/java/com/android/server/vcn/VcnContext.java b/services/core/java/com/android/server/vcn/VcnContext.java index ed04e5fde024..1383708d8a5c 100644 --- a/services/core/java/com/android/server/vcn/VcnContext.java +++ b/services/core/java/com/android/server/vcn/VcnContext.java @@ -34,7 +34,7 @@ public class VcnContext { @NonNull private final Looper mLooper; @NonNull private final VcnNetworkProvider mVcnNetworkProvider; @NonNull private final FeatureFlags mFeatureFlags; - @NonNull private final com.android.net.flags.FeatureFlags mCoreNetFeatureFlags; + @NonNull private final android.net.platform.flags.FeatureFlags mCoreNetFeatureFlags; private final boolean mIsInTestMode; public VcnContext( @@ -49,7 +49,7 @@ public class VcnContext { // Auto-generated class mFeatureFlags = new FeatureFlagsImpl(); - mCoreNetFeatureFlags = new com.android.net.flags.FeatureFlagsImpl(); + mCoreNetFeatureFlags = new android.net.platform.flags.FeatureFlagsImpl(); } @NonNull diff --git a/services/core/java/com/android/server/vcn/routeselection/IpSecPacketLossDetector.java b/services/core/java/com/android/server/vcn/routeselection/IpSecPacketLossDetector.java index 5f4852f77727..a25d67ab66af 100644 --- a/services/core/java/com/android/server/vcn/routeselection/IpSecPacketLossDetector.java +++ b/services/core/java/com/android/server/vcn/routeselection/IpSecPacketLossDetector.java @@ -252,7 +252,7 @@ public class IpSecPacketLossDetector extends NetworkMetricMonitor { } getInboundTransformInternal() - .getIpSecTransformState( + .requestIpSecTransformState( new HandlerExecutor(mHandler), new IpSecTransformStateReceiver()); // Schedule for next poll @@ -302,7 +302,8 @@ public class IpSecPacketLossDetector extends NetworkMetricMonitor { "packetLossRate: " + packetLossRate + "% in the past " - + (state.getTimestamp() - mLastIpSecTransformState.getTimestamp()) + + (state.getTimestampMillis() + - mLastIpSecTransformState.getTimestampMillis()) + "ms"; mLastIpSecTransformState = state; diff --git a/services/core/java/com/android/server/vcn/routeselection/NetworkMetricMonitor.java b/services/core/java/com/android/server/vcn/routeselection/NetworkMetricMonitor.java index a79f188713e1..1704aa117a2b 100644 --- a/services/core/java/com/android/server/vcn/routeselection/NetworkMetricMonitor.java +++ b/services/core/java/com/android/server/vcn/routeselection/NetworkMetricMonitor.java @@ -138,10 +138,10 @@ public abstract class NetworkMetricMonitor implements AutoCloseable { } /** Poll an IpSecTransformState */ - public void getIpSecTransformState( + public void requestIpSecTransformState( @NonNull Executor executor, @NonNull OutcomeReceiver<IpSecTransformState, RuntimeException> callback) { - ipSecTransform.getIpSecTransformState(executor, callback); + ipSecTransform.requestIpSecTransformState(executor, callback); } /** Close this instance and release the underlying resources */ diff --git a/services/tests/mockingservicestests/Android.bp b/services/tests/mockingservicestests/Android.bp index 8f25c0d6b013..cd1891817915 100644 --- a/services/tests/mockingservicestests/Android.bp +++ b/services/tests/mockingservicestests/Android.bp @@ -53,6 +53,7 @@ android_test { "mockito-target-extended-minus-junit4", "platform-compat-test-rules", "platform-test-annotations", + "PlatformProperties", "service-blobstore", "service-jobscheduler", "service-permission.impl", diff --git a/services/tests/mockingservicestests/src/com/android/server/OWNERS b/services/tests/mockingservicestests/src/com/android/server/OWNERS index c0f0ce047da6..f80156021408 100644 --- a/services/tests/mockingservicestests/src/com/android/server/OWNERS +++ b/services/tests/mockingservicestests/src/com/android/server/OWNERS @@ -1,3 +1,5 @@ per-file *Alarm* = file:/apex/jobscheduler/OWNERS per-file *AppStateTracker* = file:/apex/jobscheduler/OWNERS per-file *DeviceIdleController* = file:/apex/jobscheduler/OWNERS +per-file SensitiveContentProtectionManagerServiceTest.java = file:/core/java/android/permission/OWNERS +per-file RescuePartyTest.java = file:/packages/CrashRecovery/OWNERS diff --git a/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java b/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java index 7b771aff0055..211a83d8588e 100644 --- a/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java @@ -33,6 +33,7 @@ import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import android.content.ContentResolver; @@ -63,6 +64,7 @@ import org.mockito.MockitoSession; import org.mockito.quality.Strictness; import org.mockito.stubbing.Answer; +import java.lang.reflect.Field; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; @@ -95,12 +97,12 @@ public class RescuePartyTest { "persist.device_config.configuration.disable_rescue_party"; private static final String PROP_DISABLE_FACTORY_RESET_FLAG = "persist.device_config.configuration.disable_rescue_party_factory_reset"; - private static final String PROP_LAST_FACTORY_RESET_TIME_MS = "persist.sys.last_factory_reset"; private static final int THROTTLING_DURATION_MIN = 10; private MockitoSession mSession; private HashMap<String, String> mSystemSettingsMap; + private HashMap<String, String> mCrashRecoveryPropertiesMap; //Records the namespaces wiped by setProperties(). private HashSet<String> mNamespacesWiped; @@ -113,6 +115,9 @@ public class RescuePartyTest { @Mock(answer = Answers.RETURNS_DEEP_STUBS) private PackageManager mPackageManager; + // Mock only sysprop apis + private PackageWatchdog.BootThreshold mSpyBootThreshold; + @Captor private ArgumentCaptor<DeviceConfig.MonitorCallback> mMonitorCallbackCaptor; @Captor @@ -208,10 +213,11 @@ public class RescuePartyTest { // Mock PackageWatchdog doAnswer((Answer<PackageWatchdog>) invocationOnMock -> mMockPackageWatchdog) .when(() -> PackageWatchdog.getInstance(mMockContext)); + mockCrashRecoveryProperties(mMockPackageWatchdog); doReturn(CURRENT_NETWORK_TIME_MILLIS).when(() -> RescueParty.getElapsedRealtime()); - SystemProperties.set(RescueParty.PROP_RESCUE_BOOT_COUNT, Integer.toString(0)); + setCrashRecoveryPropRescueBootCount(0); SystemProperties.set(RescueParty.PROP_ENABLE_RESCUE, Boolean.toString(true)); SystemProperties.set(PROP_DEVICE_CONFIG_DISABLE_FLAG, Boolean.toString(false)); } @@ -255,7 +261,7 @@ public class RescuePartyTest { noteBoot(4); assertTrue(RescueParty.isRebootPropertySet()); - SystemProperties.set(RescueParty.PROP_ATTEMPTING_REBOOT, Boolean.toString(false)); + setCrashRecoveryPropAttemptingReboot(false); noteBoot(5); assertTrue(RescueParty.isFactoryResetPropertySet()); } @@ -280,7 +286,7 @@ public class RescuePartyTest { noteAppCrash(4, true); assertTrue(RescueParty.isRebootPropertySet()); - SystemProperties.set(RescueParty.PROP_ATTEMPTING_REBOOT, Boolean.toString(false)); + setCrashRecoveryPropAttemptingReboot(false); noteAppCrash(5, true); assertTrue(RescueParty.isFactoryResetPropertySet()); } @@ -438,7 +444,7 @@ public class RescuePartyTest { noteBoot(i + 1); } assertFalse(RescueParty.isFactoryResetPropertySet()); - SystemProperties.set(RescueParty.PROP_ATTEMPTING_REBOOT, Boolean.toString(false)); + setCrashRecoveryPropAttemptingReboot(false); noteBoot(LEVEL_FACTORY_RESET + 1); assertTrue(RescueParty.isAttemptingFactoryReset()); assertTrue(RescueParty.isFactoryResetPropertySet()); @@ -456,7 +462,7 @@ public class RescuePartyTest { noteBoot(mitigationCount++); assertFalse(RescueParty.isFactoryResetPropertySet()); noteBoot(mitigationCount++); - SystemProperties.set(RescueParty.PROP_ATTEMPTING_REBOOT, Boolean.toString(false)); + setCrashRecoveryPropAttemptingReboot(false); noteBoot(mitigationCount + 1); assertTrue(RescueParty.isAttemptingFactoryReset()); assertTrue(RescueParty.isFactoryResetPropertySet()); @@ -464,10 +470,10 @@ public class RescuePartyTest { @Test public void testThrottlingOnBootFailures() { - SystemProperties.set(RescueParty.PROP_ATTEMPTING_REBOOT, Boolean.toString(false)); + setCrashRecoveryPropAttemptingReboot(false); long now = System.currentTimeMillis(); long beforeTimeout = now - TimeUnit.MINUTES.toMillis(THROTTLING_DURATION_MIN - 1); - SystemProperties.set(PROP_LAST_FACTORY_RESET_TIME_MS, Long.toString(beforeTimeout)); + setCrashRecoveryPropLastFactoryReset(beforeTimeout); for (int i = 1; i <= LEVEL_FACTORY_RESET; i++) { noteBoot(i); } @@ -476,10 +482,10 @@ public class RescuePartyTest { @Test public void testThrottlingOnAppCrash() { - SystemProperties.set(RescueParty.PROP_ATTEMPTING_REBOOT, Boolean.toString(false)); + setCrashRecoveryPropAttemptingReboot(false); long now = System.currentTimeMillis(); long beforeTimeout = now - TimeUnit.MINUTES.toMillis(THROTTLING_DURATION_MIN - 1); - SystemProperties.set(PROP_LAST_FACTORY_RESET_TIME_MS, Long.toString(beforeTimeout)); + setCrashRecoveryPropLastFactoryReset(beforeTimeout); for (int i = 0; i <= LEVEL_FACTORY_RESET; i++) { noteAppCrash(i + 1, true); } @@ -488,10 +494,10 @@ public class RescuePartyTest { @Test public void testNotThrottlingAfterTimeoutOnBootFailures() { - SystemProperties.set(RescueParty.PROP_ATTEMPTING_REBOOT, Boolean.toString(false)); + setCrashRecoveryPropAttemptingReboot(false); long now = System.currentTimeMillis(); long afterTimeout = now - TimeUnit.MINUTES.toMillis(THROTTLING_DURATION_MIN + 1); - SystemProperties.set(PROP_LAST_FACTORY_RESET_TIME_MS, Long.toString(afterTimeout)); + setCrashRecoveryPropLastFactoryReset(afterTimeout); for (int i = 1; i <= LEVEL_FACTORY_RESET; i++) { noteBoot(i); } @@ -499,10 +505,10 @@ public class RescuePartyTest { } @Test public void testNotThrottlingAfterTimeoutOnAppCrash() { - SystemProperties.set(RescueParty.PROP_ATTEMPTING_REBOOT, Boolean.toString(false)); + setCrashRecoveryPropAttemptingReboot(false); long now = System.currentTimeMillis(); long afterTimeout = now - TimeUnit.MINUTES.toMillis(THROTTLING_DURATION_MIN + 1); - SystemProperties.set(PROP_LAST_FACTORY_RESET_TIME_MS, Long.toString(afterTimeout)); + setCrashRecoveryPropLastFactoryReset(afterTimeout); for (int i = 0; i <= LEVEL_FACTORY_RESET; i++) { noteAppCrash(i + 1, true); } @@ -753,4 +759,138 @@ public class RescuePartyTest { RescuePartyObserver.getInstance(mMockContext).execute(new VersionedPackage( packageName, 1), PackageWatchdog.FAILURE_REASON_APP_CRASH, mitigationCount); } + + // Mock CrashRecoveryProperties as they cannot be accessed due to SEPolicy restrictions + private void mockCrashRecoveryProperties(PackageWatchdog watchdog) { + // mock properties in RescueParty + try { + + doAnswer((Answer<Boolean>) invocationOnMock -> { + String storedValue = mCrashRecoveryPropertiesMap + .getOrDefault("crashrecovery.attempting_factory_reset", "false"); + return Boolean.parseBoolean(storedValue); + }).when(() -> RescueParty.isFactoryResetPropertySet()); + doAnswer((Answer<Void>) invocationOnMock -> { + boolean value = invocationOnMock.getArgument(0); + mCrashRecoveryPropertiesMap.put("crashrecovery.attempting_factory_reset", + Boolean.toString(value)); + return null; + }).when(() -> RescueParty.setFactoryResetProperty(anyBoolean())); + + doAnswer((Answer<Boolean>) invocationOnMock -> { + String storedValue = mCrashRecoveryPropertiesMap + .getOrDefault("crashrecovery.attempting_reboot", "false"); + return Boolean.parseBoolean(storedValue); + }).when(() -> RescueParty.isRebootPropertySet()); + doAnswer((Answer<Void>) invocationOnMock -> { + boolean value = invocationOnMock.getArgument(0); + setCrashRecoveryPropAttemptingReboot(value); + return null; + }).when(() -> RescueParty.setRebootProperty(anyBoolean())); + + doAnswer((Answer<Long>) invocationOnMock -> { + String storedValue = mCrashRecoveryPropertiesMap + .getOrDefault("persist.crashrecovery.last_factory_reset", "0"); + return Long.parseLong(storedValue); + }).when(() -> RescueParty.getLastFactoryResetTimeMs()); + doAnswer((Answer<Void>) invocationOnMock -> { + long value = invocationOnMock.getArgument(0); + setCrashRecoveryPropLastFactoryReset(value); + return null; + }).when(() -> RescueParty.setLastFactoryResetTimeMs(anyLong())); + + doAnswer((Answer<Integer>) invocationOnMock -> { + String storedValue = mCrashRecoveryPropertiesMap + .getOrDefault("crashrecovery.max_rescue_level_attempted", "0"); + return Integer.parseInt(storedValue); + }).when(() -> RescueParty.getMaxRescueLevelAttempted()); + doAnswer((Answer<Void>) invocationOnMock -> { + int value = invocationOnMock.getArgument(0); + mCrashRecoveryPropertiesMap.put("crashrecovery.max_rescue_level_attempted", + Integer.toString(value)); + return null; + }).when(() -> RescueParty.setMaxRescueLevelAttempted(anyInt())); + + } catch (Exception e) { + // tests will fail, just printing the error + System.out.println("Error while mocking crashrecovery properties " + e.getMessage()); + } + + // mock properties in BootThreshold + try { + mSpyBootThreshold = spy(watchdog.new BootThreshold( + PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_COUNT, + PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_WINDOW_MS)); + mCrashRecoveryPropertiesMap = new HashMap<>(); + + doAnswer((Answer<Integer>) invocationOnMock -> { + String storedValue = mCrashRecoveryPropertiesMap + .getOrDefault("crashrecovery.rescue_boot_count", "0"); + return Integer.parseInt(storedValue); + }).when(mSpyBootThreshold).getCount(); + doAnswer((Answer<Void>) invocationOnMock -> { + int count = invocationOnMock.getArgument(0); + setCrashRecoveryPropRescueBootCount(count); + return null; + }).when(mSpyBootThreshold).setCount(anyInt()); + + doAnswer((Answer<Integer>) invocationOnMock -> { + String storedValue = mCrashRecoveryPropertiesMap + .getOrDefault("crashrecovery.boot_mitigation_count", "0"); + return Integer.parseInt(storedValue); + }).when(mSpyBootThreshold).getMitigationCount(); + doAnswer((Answer<Void>) invocationOnMock -> { + int count = invocationOnMock.getArgument(0); + mCrashRecoveryPropertiesMap.put("crashrecovery.boot_mitigation_count", + Integer.toString(count)); + return null; + }).when(mSpyBootThreshold).setMitigationCount(anyInt()); + + doAnswer((Answer<Long>) invocationOnMock -> { + String storedValue = mCrashRecoveryPropertiesMap + .getOrDefault("crashrecovery.rescue_boot_start", "0"); + return Long.parseLong(storedValue); + }).when(mSpyBootThreshold).getStart(); + doAnswer((Answer<Void>) invocationOnMock -> { + long count = invocationOnMock.getArgument(0); + mCrashRecoveryPropertiesMap.put("crashrecovery.rescue_boot_start", + Long.toString(count)); + return null; + }).when(mSpyBootThreshold).setStart(anyLong()); + + doAnswer((Answer<Long>) invocationOnMock -> { + String storedValue = mCrashRecoveryPropertiesMap + .getOrDefault("crashrecovery.boot_mitigation_start", "0"); + return Long.parseLong(storedValue); + }).when(mSpyBootThreshold).getMitigationStart(); + doAnswer((Answer<Void>) invocationOnMock -> { + long count = invocationOnMock.getArgument(0); + mCrashRecoveryPropertiesMap.put("crashrecovery.boot_mitigation_start", + Long.toString(count)); + return null; + }).when(mSpyBootThreshold).setMitigationStart(anyLong()); + + Field mBootThresholdField = watchdog.getClass().getDeclaredField("mBootThreshold"); + mBootThresholdField.setAccessible(true); + mBootThresholdField.set(watchdog, mSpyBootThreshold); + } catch (Exception e) { + // tests will fail, just printing the error + System.out.println("Error while spying BootThreshold " + e.getMessage()); + } + } + + private void setCrashRecoveryPropRescueBootCount(int count) { + mCrashRecoveryPropertiesMap.put("crashrecovery.rescue_boot_count", + Integer.toString(count)); + } + + private void setCrashRecoveryPropAttemptingReboot(boolean value) { + mCrashRecoveryPropertiesMap.put("crashrecovery.attempting_reboot", + Boolean.toString(value)); + } + + private void setCrashRecoveryPropLastFactoryReset(long value) { + mCrashRecoveryPropertiesMap.put("persist.crashrecovery.last_factory_reset", + Long.toString(value)); + } } diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java index 050434490e31..732d0ce0bd02 100644 --- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java +++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java @@ -2578,6 +2578,31 @@ public class MockingOomAdjusterTests { assertTrue(CACHED_APP_MAX_ADJ >= app3.mState.getSetAdj()); } + @SuppressWarnings("GuardedBy") + @Test + public void testUpdateOomAdj_DoOne_AboveClient_NotStarted() { + ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID, + MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true)); + doReturn(PROCESS_STATE_TOP).when(sService.mAtmInternal).getTopProcessState(); + doReturn(app).when(sService).getTopApp(); + sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE); + sService.mOomAdjuster.updateOomAdjLocked(app, OOM_ADJ_REASON_NONE); + + assertEquals(FOREGROUND_APP_ADJ, app.mState.getSetAdj()); + + // Start binding to a service that isn't running yet. + ServiceRecord sr = makeServiceRecord(app); + sr.app = null; + bindService(null, app, sr, Context.BIND_ABOVE_CLIENT, mock(IBinder.class)); + + // Since sr.app is null, this service cannot be in the same process as the + // client so we expect the BIND_ABOVE_CLIENT adjustment to take effect. + app.mServices.updateHasAboveClientLocked(); + sService.mOomAdjuster.updateOomAdjLocked(app, OOM_ADJ_REASON_NONE); + assertTrue(app.mServices.hasAboveClient()); + assertNotEquals(FOREGROUND_APP_ADJ, app.mState.getSetAdj()); + } + private ProcessRecord makeDefaultProcessRecord(int pid, int uid, String processName, String packageName, boolean hasShownUi) { long now = SystemClock.uptimeMillis(); diff --git a/services/tests/mockingservicestests/src/com/android/server/selinux/OWNERS b/services/tests/mockingservicestests/src/com/android/server/selinux/OWNERS new file mode 100644 index 000000000000..49a0934ec642 --- /dev/null +++ b/services/tests/mockingservicestests/src/com/android/server/selinux/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/selinux/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java index 4451cae8db42..a529382bfb26 100644 --- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java @@ -18,6 +18,7 @@ package com.android.server.net; import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS; import static android.Manifest.permission.NETWORK_STACK; +import static android.app.ActivityManager.PROCESS_CAPABILITY_ALL; import static android.app.ActivityManager.PROCESS_CAPABILITY_NONE; import static android.app.ActivityManager.PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK; import static android.app.ActivityManager.PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK; @@ -58,9 +59,11 @@ import static android.net.NetworkPolicyManager.ALLOWED_REASON_SYSTEM; import static android.net.NetworkPolicyManager.ALLOWED_REASON_TOP; import static android.net.NetworkPolicyManager.BACKGROUND_THRESHOLD_STATE; import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT; +import static android.net.NetworkPolicyManager.FOREGROUND_THRESHOLD_STATE; import static android.net.NetworkPolicyManager.POLICY_ALLOW_METERED_BACKGROUND; import static android.net.NetworkPolicyManager.POLICY_NONE; import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND; +import static android.net.NetworkPolicyManager.TOP_THRESHOLD_STATE; import static android.net.NetworkPolicyManager.allowedReasonsToString; import static android.net.NetworkPolicyManager.blockedReasonsToString; import static android.net.NetworkPolicyManager.uidPoliciesToString; @@ -88,6 +91,7 @@ import static com.android.server.net.NetworkPolicyManagerService.TYPE_LIMIT; import static com.android.server.net.NetworkPolicyManagerService.TYPE_LIMIT_SNOOZED; import static com.android.server.net.NetworkPolicyManagerService.TYPE_RAPID; import static com.android.server.net.NetworkPolicyManagerService.TYPE_WARNING; +import static com.android.server.net.NetworkPolicyManagerService.UID_MSG_STATE_CHANGED; import static com.android.server.net.NetworkPolicyManagerService.UidBlockedState.getEffectiveBlockedReasons; import static com.android.server.net.NetworkPolicyManagerService.normalizeTemplate; @@ -196,13 +200,12 @@ import com.android.server.LocalServices; import com.android.server.pm.pkg.AndroidPackage; import com.android.server.usage.AppStandbyInternal; -import com.google.common.util.concurrent.AbstractFuture; - import libcore.io.Streams; import org.junit.After; import org.junit.Assume; import org.junit.Before; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.MethodRule; @@ -241,10 +244,8 @@ import java.util.Map; import java.util.Set; import java.util.TimeZone; import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; import java.util.function.Consumer; import java.util.stream.Collectors; @@ -2143,13 +2144,14 @@ public class NetworkPolicyManagerServiceTest { assertFalse(mService.isUidNetworkingBlocked(UID_E, false)); } + @Ignore("Temporarily disabled until the feature is enabled") @Test @RequiresFlagsEnabled(Flags.FLAG_NETWORK_BLOCKED_FOR_TOP_SLEEPING_AND_ABOVE) public void testBackgroundChainEnabled() throws Exception { verify(mNetworkManager).setFirewallChainEnabled(FIREWALL_CHAIN_BACKGROUND, true); } - + @Ignore("Temporarily disabled until the feature is enabled") @Test @RequiresFlagsEnabled(Flags.FLAG_NETWORK_BLOCKED_FOR_TOP_SLEEPING_AND_ABOVE) public void testBackgroundChainOnProcStateChange() throws Exception { @@ -2179,6 +2181,7 @@ public class NetworkPolicyManagerServiceTest { assertTrue(mService.isUidNetworkingBlocked(UID_A, false)); } + @Ignore("Temporarily disabled until the feature is enabled") @Test @RequiresFlagsEnabled(Flags.FLAG_NETWORK_BLOCKED_FOR_TOP_SLEEPING_AND_ABOVE) public void testBackgroundChainOnAllowlistChange() throws Exception { @@ -2217,6 +2220,7 @@ public class NetworkPolicyManagerServiceTest { assertFalse(mService.isUidNetworkingBlocked(UID_B, false)); } + @Ignore("Temporarily disabled until the feature is enabled") @Test @RequiresFlagsEnabled(Flags.FLAG_NETWORK_BLOCKED_FOR_TOP_SLEEPING_AND_ABOVE) public void testBackgroundChainOnTempAllowlistChange() throws Exception { @@ -2246,6 +2250,126 @@ public class NetworkPolicyManagerServiceTest { assertTrue(mService.isUidNetworkingBlocked(UID_A, false)); } + @Ignore("Temporarily disabled until the feature is enabled") + @Test + @RequiresFlagsEnabled(Flags.FLAG_NETWORK_BLOCKED_FOR_TOP_SLEEPING_AND_ABOVE) + public void testUidObserverFiltersProcStateChanges() throws Exception { + int testProcStateSeq = 0; + try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) { + // First callback for uid. + callOnUidStatechanged(UID_A, BACKGROUND_THRESHOLD_STATE + 1, testProcStateSeq++, + PROCESS_CAPABILITY_NONE); + assertTrue(mService.mUidEventHandler.hasMessages(UID_MSG_STATE_CHANGED)); + } + waitForUidEventHandlerIdle(); + try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) { + // Doesn't cross the background threshold. + callOnUidStatechanged(UID_A, BACKGROUND_THRESHOLD_STATE, testProcStateSeq++, + PROCESS_CAPABILITY_NONE); + assertFalse(mService.mUidEventHandler.hasMessages(UID_MSG_STATE_CHANGED)); + } + waitForUidEventHandlerIdle(); + try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) { + // Crosses the background threshold. + callOnUidStatechanged(UID_A, BACKGROUND_THRESHOLD_STATE - 1, testProcStateSeq++, + PROCESS_CAPABILITY_NONE); + assertTrue(mService.mUidEventHandler.hasMessages(UID_MSG_STATE_CHANGED)); + } + waitForUidEventHandlerIdle(); + try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) { + // Doesn't cross the foreground threshold. + callOnUidStatechanged(UID_A, FOREGROUND_THRESHOLD_STATE + 1, testProcStateSeq++, + PROCESS_CAPABILITY_NONE); + assertFalse(mService.mUidEventHandler.hasMessages(UID_MSG_STATE_CHANGED)); + } + waitForUidEventHandlerIdle(); + try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) { + // Crosses the foreground threshold. + callOnUidStatechanged(UID_A, FOREGROUND_THRESHOLD_STATE, testProcStateSeq++, + PROCESS_CAPABILITY_NONE); + assertTrue(mService.mUidEventHandler.hasMessages(UID_MSG_STATE_CHANGED)); + } + waitForUidEventHandlerIdle(); + try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) { + // Doesn't cross the top threshold. + callOnUidStatechanged(UID_A, TOP_THRESHOLD_STATE + 1, testProcStateSeq++, + PROCESS_CAPABILITY_NONE); + assertFalse(mService.mUidEventHandler.hasMessages(UID_MSG_STATE_CHANGED)); + } + waitForUidEventHandlerIdle(); + try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) { + // Crosses the top threshold. + callOnUidStatechanged(UID_A, TOP_THRESHOLD_STATE, testProcStateSeq++, + PROCESS_CAPABILITY_NONE); + assertTrue(mService.mUidEventHandler.hasMessages(UID_MSG_STATE_CHANGED)); + } + waitForUidEventHandlerIdle(); + try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) { + // Doesn't cross any other threshold. + callOnUidStatechanged(UID_A, TOP_THRESHOLD_STATE - 1, testProcStateSeq++, + PROCESS_CAPABILITY_NONE); + assertFalse(mService.mUidEventHandler.hasMessages(UID_MSG_STATE_CHANGED)); + } + waitForUidEventHandlerIdle(); + } + + @Ignore("Temporarily disabled until the feature is enabled") + @Test + @RequiresFlagsEnabled(Flags.FLAG_NETWORK_BLOCKED_FOR_TOP_SLEEPING_AND_ABOVE) + public void testUidObserverFiltersStaleChanges() throws Exception { + final int testProcStateSeq = 51; + try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) { + // First callback for uid. + callOnUidStatechanged(UID_B, BACKGROUND_THRESHOLD_STATE + 100, testProcStateSeq, + PROCESS_CAPABILITY_NONE); + assertTrue(mService.mUidEventHandler.hasMessages(UID_MSG_STATE_CHANGED)); + } + waitForUidEventHandlerIdle(); + try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) { + // Stale callback because the procStateSeq is smaller. + callOnUidStatechanged(UID_B, BACKGROUND_THRESHOLD_STATE - 100, testProcStateSeq - 10, + PROCESS_CAPABILITY_NONE); + assertFalse(mService.mUidEventHandler.hasMessages(UID_MSG_STATE_CHANGED)); + } + waitForUidEventHandlerIdle(); + } + + @Ignore("Temporarily disabled until the feature is enabled") + @Test + @RequiresFlagsEnabled(Flags.FLAG_NETWORK_BLOCKED_FOR_TOP_SLEEPING_AND_ABOVE) + public void testUidObserverFiltersCapabilityChanges() throws Exception { + int testProcStateSeq = 0; + try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) { + // First callback for uid. + callOnUidStatechanged(UID_A, TOP_THRESHOLD_STATE, testProcStateSeq++, + PROCESS_CAPABILITY_NONE); + assertTrue(mService.mUidEventHandler.hasMessages(UID_MSG_STATE_CHANGED)); + } + waitForUidEventHandlerIdle(); + try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) { + // The same process-state with one network capability added. + callOnUidStatechanged(UID_A, TOP_THRESHOLD_STATE, testProcStateSeq++, + PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK); + assertTrue(mService.mUidEventHandler.hasMessages(UID_MSG_STATE_CHANGED)); + } + waitForUidEventHandlerIdle(); + try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) { + // The same process-state with another network capability added. + callOnUidStatechanged(UID_A, TOP_THRESHOLD_STATE, testProcStateSeq++, + PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK + | PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK); + assertTrue(mService.mUidEventHandler.hasMessages(UID_MSG_STATE_CHANGED)); + } + waitForUidEventHandlerIdle(); + try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) { + // The same process-state with all capabilities, but no change in network capabilities. + callOnUidStatechanged(UID_A, TOP_THRESHOLD_STATE, testProcStateSeq++, + PROCESS_CAPABILITY_ALL); + assertFalse(mService.mUidEventHandler.hasMessages(UID_MSG_STATE_CHANGED)); + } + waitForUidEventHandlerIdle(); + } + @Test public void testLowPowerStandbyAllowlist() throws Exception { // Chain background is also enabled but these procstates are important enough to be exempt. @@ -2559,17 +2683,6 @@ public class NetworkPolicyManagerServiceTest { verify(mStatsManager).setDefaultGlobalAlert(anyLong()); } - private static class TestAbstractFuture<T> extends AbstractFuture<T> { - @Override - public T get() throws InterruptedException, ExecutionException { - try { - return get(5, TimeUnit.SECONDS); - } catch (TimeoutException e) { - throw new RuntimeException(e); - } - } - } - private static void assertTimeEquals(long expected, long actual) { if (expected != actual) { fail("expected " + formatTime(expected) + " but was actually " + formatTime(actual)); diff --git a/services/tests/servicestests/src/com/android/server/rollback/RollbackStoreTest.java b/services/tests/servicestests/src/com/android/server/rollback/RollbackStoreTest.java index 9d56a36196bb..5e11e17f9414 100644 --- a/services/tests/servicestests/src/com/android/server/rollback/RollbackStoreTest.java +++ b/services/tests/servicestests/src/com/android/server/rollback/RollbackStoreTest.java @@ -18,6 +18,7 @@ package com.android.server.rollback; import static com.google.common.truth.Truth.assertThat; +import android.content.pm.PackageManager; import android.content.pm.VersionedPackage; import android.content.rollback.PackageRollbackInfo; import android.util.SparseIntArray; @@ -81,7 +82,8 @@ public class RollbackStoreTest { + "'installedUsers':[55,79]," + "'ceSnapshotInodes':[]}],'isStaged':false,'causePackages':[{'packageName':'hello'," + "'longVersionCode':23},{'packageName':'something','longVersionCode':999}]," - + "'committedSessionId':45654465},'timestamp':'2019-10-01T12:29:08.855Z'," + + "'committedSessionId':45654465, 'rollbackImpactLevel':1}," + + "'timestamp':'2019-10-01T12:29:08.855Z'," + "'originalSessionId':567,'state':'enabling','apkSessionId':-1," + "'restoreUserDataInProgress':true, 'userId':0," + "'installerPackageName':'some.installer'}"; @@ -138,6 +140,8 @@ public class RollbackStoreTest { assertThat(rollback.getOriginalSessionId()).isEqualTo(567); assertThat(rollback.info.getRollbackId()).isEqualTo(ID); assertThat(rollback.info.getPackages()).isEmpty(); + assertThat(rollback.info.getRollbackImpactLevel()).isEqualTo( + PackageManager.ROLLBACK_USER_IMPACT_LOW); assertThat(rollback.isEnabling()).isTrue(); assertThat(rollback.getExtensionVersions().toString()) .isEqualTo(extensionVersions.toString()); @@ -158,6 +162,8 @@ public class RollbackStoreTest { assertThat(rollback.info.getRollbackId()).isEqualTo(ID); assertThat(rollback.info.getPackages()).isEmpty(); + assertThat(rollback.info.getRollbackImpactLevel()).isEqualTo( + PackageManager.ROLLBACK_USER_IMPACT_LOW); assertThat(rollback.isEnabling()).isTrue(); assertThat(rollback.getExtensionVersions().toString()) .isEqualTo(extensionVersions.toString()); @@ -175,6 +181,7 @@ public class RollbackStoreTest { origRb.info.getCausePackages().add(new VersionedPackage("com.made.up", 2)); origRb.info.getCausePackages().add(new VersionedPackage("com.pack.age", 99)); origRb.info.setCommittedSessionId(123456); + origRb.info.setRollbackImpactLevel(PackageManager.ROLLBACK_USER_IMPACT_HIGH); PackageRollbackInfo pkgInfo1 = new PackageRollbackInfo(new VersionedPackage("com.made.up", 18), @@ -226,6 +233,7 @@ public class RollbackStoreTest { expectedRb.info.getCausePackages().add(new VersionedPackage("hello", 23)); expectedRb.info.getCausePackages().add(new VersionedPackage("something", 999)); expectedRb.info.setCommittedSessionId(45654465); + expectedRb.info.setRollbackImpactLevel(PackageManager.ROLLBACK_USER_IMPACT_HIGH); PackageRollbackInfo pkgInfo1 = new PackageRollbackInfo(new VersionedPackage("blah", 55), new VersionedPackage("blah1", 50), new ArrayList<>(), new ArrayList<>(), diff --git a/tests/BootImageProfileTest/AndroidTest.xml b/tests/BootImageProfileTest/AndroidTest.xml index 7e97fa3a8ff1..9b527dc159ee 100644 --- a/tests/BootImageProfileTest/AndroidTest.xml +++ b/tests/BootImageProfileTest/AndroidTest.xml @@ -14,6 +14,7 @@ limitations under the License. --> <configuration description="Config for BootImageProfileTest"> + <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" /> <!-- do not use DeviceSetup#set-property because it reboots the device b/136200738. furthermore the changes in /data/local.prop don't actually seem to get picked up. --> diff --git a/tests/Input/AndroidTest.xml b/tests/Input/AndroidTest.xml index c62db1ea5ca9..13b5f0d99ba8 100644 --- a/tests/Input/AndroidTest.xml +++ b/tests/Input/AndroidTest.xml @@ -4,6 +4,7 @@ --> <configuration description="Runs Input Tests"> <option name="test-tag" value="InputTests" /> + <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" /> <target_preparer class="com.android.tradefed.targetprep.DeviceSetup"> <!-- keeps the screen on during tests --> <option name="screen-always-on" value="on" /> diff --git a/tests/Internal/src/com/android/internal/protolog/OWNERS b/tests/Internal/src/com/android/internal/protolog/OWNERS new file mode 100644 index 000000000000..18cf2be9f7df --- /dev/null +++ b/tests/Internal/src/com/android/internal/protolog/OWNERS @@ -0,0 +1,3 @@ +# ProtoLog owners +# Bug component: 1157642 +include platform/development:/tools/winscope/OWNERS diff --git a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java index d7fa124623ce..755636aef7ed 100644 --- a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java +++ b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java @@ -70,6 +70,7 @@ import org.mockito.stubbing.Answer; import java.io.File; import java.io.FileOutputStream; +import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -107,10 +108,13 @@ public class PackageWatchdogTest { private ConnectivityModuleConnector mConnectivityModuleConnector; @Mock private PackageManager mMockPackageManager; + // Mock only sysprop apis + private PackageWatchdog.BootThreshold mSpyBootThreshold; @Captor private ArgumentCaptor<ConnectivityModuleHealthListener> mConnectivityModuleCallbackCaptor; private MockitoSession mSession; private HashMap<String, String> mSystemSettingsMap; + private HashMap<String, String> mCrashRecoveryPropertiesMap; private boolean retry(Supplier<Boolean> supplier) throws Exception { for (int i = 0; i < RETRY_MAX_COUNT; ++i) { @@ -1416,6 +1420,8 @@ public class PackageWatchdogTest { PackageWatchdog watchdog = new PackageWatchdog(mSpyContext, policyFile, handler, handler, controller, mConnectivityModuleConnector, mTestClock); + mockCrashRecoveryProperties(watchdog); + // Verify controller is not automatically started assertThat(controller.mIsEnabled).isFalse(); if (withPackagesReady) { @@ -1432,6 +1438,71 @@ public class PackageWatchdogTest { return watchdog; } + // Mock CrashRecoveryProperties as they cannot be accessed due to SEPolicy restrictions + private void mockCrashRecoveryProperties(PackageWatchdog watchdog) { + try { + mSpyBootThreshold = spy(watchdog.new BootThreshold( + PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_COUNT, + PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_WINDOW_MS)); + mCrashRecoveryPropertiesMap = new HashMap<>(); + + doAnswer((Answer<Integer>) invocationOnMock -> { + String storedValue = mCrashRecoveryPropertiesMap + .getOrDefault("crashrecovery.rescue_boot_count", "0"); + return Integer.parseInt(storedValue); + }).when(mSpyBootThreshold).getCount(); + doAnswer((Answer<Void>) invocationOnMock -> { + int count = invocationOnMock.getArgument(0); + mCrashRecoveryPropertiesMap.put("crashrecovery.rescue_boot_count", + Integer.toString(count)); + return null; + }).when(mSpyBootThreshold).setCount(anyInt()); + + doAnswer((Answer<Integer>) invocationOnMock -> { + String storedValue = mCrashRecoveryPropertiesMap + .getOrDefault("crashrecovery.boot_mitigation_count", "0"); + return Integer.parseInt(storedValue); + }).when(mSpyBootThreshold).getMitigationCount(); + doAnswer((Answer<Void>) invocationOnMock -> { + int count = invocationOnMock.getArgument(0); + mCrashRecoveryPropertiesMap.put("crashrecovery.boot_mitigation_count", + Integer.toString(count)); + return null; + }).when(mSpyBootThreshold).setMitigationCount(anyInt()); + + doAnswer((Answer<Long>) invocationOnMock -> { + String storedValue = mCrashRecoveryPropertiesMap + .getOrDefault("crashrecovery.rescue_boot_start", "0"); + return Long.parseLong(storedValue); + }).when(mSpyBootThreshold).getStart(); + doAnswer((Answer<Void>) invocationOnMock -> { + long count = invocationOnMock.getArgument(0); + mCrashRecoveryPropertiesMap.put("crashrecovery.rescue_boot_start", + Long.toString(count)); + return null; + }).when(mSpyBootThreshold).setStart(anyLong()); + + doAnswer((Answer<Long>) invocationOnMock -> { + String storedValue = mCrashRecoveryPropertiesMap + .getOrDefault("crashrecovery.boot_mitigation_start", "0"); + return Long.parseLong(storedValue); + }).when(mSpyBootThreshold).getMitigationStart(); + doAnswer((Answer<Void>) invocationOnMock -> { + long count = invocationOnMock.getArgument(0); + mCrashRecoveryPropertiesMap.put("crashrecovery.boot_mitigation_start", + Long.toString(count)); + return null; + }).when(mSpyBootThreshold).setMitigationStart(anyLong()); + + Field mBootThresholdField = watchdog.getClass().getDeclaredField("mBootThreshold"); + mBootThresholdField.setAccessible(true); + mBootThresholdField.set(watchdog, mSpyBootThreshold); + } catch (Exception e) { + // tests will fail, just printing the error + System.out.println("Error detected while spying BootThreshold" + e.getMessage()); + } + } + private static class TestObserver implements PackageHealthObserver { private final String mName; private int mImpact; diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java index cbdcb8869628..518183f9cd64 100644 --- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java +++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java @@ -30,6 +30,7 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.pm.PackageManager; import android.content.rollback.RollbackInfo; import android.content.rollback.RollbackManager; import android.os.UserManager; @@ -146,7 +147,8 @@ public class RollbackTest { assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1); // Upgrade from v1 to v2, with rollbacks enabled. - Install.single(TestApp.A2).setEnableRollback().commit(); + Install.single(TestApp.A2).setEnableRollback().setRollbackImpactLevel( + PackageManager.ROLLBACK_USER_IMPACT_HIGH).commit(); assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); // The app should now be available for rollback. @@ -154,6 +156,8 @@ public class RollbackTest { assertThat(available).isNotStaged(); assertThat(available).packagesContainsExactly( Rollback.from(TestApp.A2).to(TestApp.A1)); + assertThat(available.getRollbackImpactLevel()).isEqualTo( + PackageManager.ROLLBACK_USER_IMPACT_HIGH); // We should not have received any rollback requests yet. // TODO: Possibly flaky if, by chance, some other app on device @@ -264,6 +268,8 @@ public class RollbackTest { RollbackInfo rollbackB = waitForAvailableRollback(TestApp.B); assertThat(rollbackB).packagesContainsExactly( Rollback.from(TestApp.B2).to(TestApp.B1)); + assertThat(rollbackB.getRollbackImpactLevel()).isEqualTo( + PackageManager.ROLLBACK_USER_IMPACT_LOW); // Register rollback committed receiver RollbackBroadcastReceiver rollbackReceiver = new RollbackBroadcastReceiver(); diff --git a/tests/vcn/java/com/android/server/vcn/routeselection/IpSecPacketLossDetectorTest.java b/tests/vcn/java/com/android/server/vcn/routeselection/IpSecPacketLossDetectorTest.java index 9daba6a79a27..1d7be2f4f039 100644 --- a/tests/vcn/java/com/android/server/vcn/routeselection/IpSecPacketLossDetectorTest.java +++ b/tests/vcn/java/com/android/server/vcn/routeselection/IpSecPacketLossDetectorTest.java @@ -144,7 +144,7 @@ public class IpSecPacketLossDetectorTest extends NetworkEvaluationTestBase { mTestLooper.dispatchAll(); verify(mIpSecTransform) - .getIpSecTransformState(any(), mTransformStateReceiverCaptor.capture()); + .requestIpSecTransformState(any(), mTransformStateReceiverCaptor.capture()); return mTransformStateReceiverCaptor.getValue(); } @@ -210,7 +210,7 @@ public class IpSecPacketLossDetectorTest extends NetworkEvaluationTestBase { assertNull(mIpSecPacketLossDetector.getLastTransformState()); mTestLooper.moveTimeForward(POLL_IPSEC_STATE_INTERVAL_MS); mTestLooper.dispatchAll(); - verify(newTransform).getIpSecTransformState(any(), any()); + verify(newTransform).requestIpSecTransformState(any(), any()); } @Test 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 6015e9318464..381c57496878 100644 --- a/tests/vcn/java/com/android/server/vcn/routeselection/NetworkEvaluationTestBase.java +++ b/tests/vcn/java/com/android/server/vcn/routeselection/NetworkEvaluationTestBase.java @@ -101,7 +101,7 @@ public abstract class NetworkEvaluationTestBase { @Mock protected Context mContext; @Mock protected Network mNetwork; @Mock protected FeatureFlags mFeatureFlags; - @Mock protected com.android.net.flags.FeatureFlags mCoreNetFeatureFlags; + @Mock protected android.net.platform.flags.FeatureFlags mCoreNetFeatureFlags; @Mock protected TelephonySubscriptionSnapshot mSubscriptionSnapshot; @Mock protected TelephonyManager mTelephonyManager; @Mock protected IPowerManager mPowerManagerService; diff --git a/tools/protologtool/OWNERS b/tools/protologtool/OWNERS new file mode 100644 index 000000000000..18cf2be9f7df --- /dev/null +++ b/tools/protologtool/OWNERS @@ -0,0 +1,3 @@ +# ProtoLog owners +# Bug component: 1157642 +include platform/development:/tools/winscope/OWNERS diff --git a/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt b/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt index 3c55237ce443..ce856cd49614 100644 --- a/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt +++ b/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt @@ -25,6 +25,7 @@ import java.io.File import java.io.FileInputStream import java.io.FileOutputStream import java.io.OutputStream +import java.time.LocalDateTime import java.util.concurrent.ExecutorService import java.util.concurrent.Executors import java.util.jar.JarOutputStream @@ -42,6 +43,13 @@ object ProtoLogTool { return source.contains(protoLogSimpleClassName) } + private fun zipEntry(path: String): ZipEntry { + val entry = ZipEntry(path) + // Use a constant time to improve the cachability of build actions. + entry.timeLocal = LocalDateTime.of(2008, 1, 1, 0, 0, 0) + return entry + } + private fun processClasses(command: CommandOptions) { val groups = injector.readLogGroups( command.protoLogGroupsJarArg, @@ -77,7 +85,7 @@ object ProtoLogTool { } }.map { future -> val (path, outSrc) = future.get() - outJar.putNextEntry(ZipEntry(path)) + outJar.putNextEntry(zipEntry(path)) outJar.write(outSrc.toByteArray()) outJar.closeEntry() } @@ -90,7 +98,7 @@ object ProtoLogTool { val cachePackage = cacheSplit.dropLast(1).joinToString(".") val cachePath = "gen/${cacheSplit.joinToString("/")}.java" - outJar.putNextEntry(ZipEntry(cachePath)) + outJar.putNextEntry(zipEntry(cachePath)) outJar.write(generateLogGroupCache(cachePackage, cacheName, groups, command.protoLogImplClassNameArg, command.protoLogGroupsClassNameArg).toByteArray()) |