diff options
243 files changed, 8544 insertions, 4629 deletions
diff --git a/Android.bp b/Android.bp index 9e65646154b8..5bd332947057 100644 --- a/Android.bp +++ b/Android.bp @@ -65,7 +65,6 @@ filegroup { // Java/AIDL sources under frameworks/base ":framework-annotations", ":framework-blobstore-sources", - ":framework-bluetooth-sources", // TODO(b/214988855) : Remove once framework-bluetooth jar is ready ":framework-connectivity-tiramisu-sources", ":framework-core-sources", ":framework-drm-sources", @@ -141,21 +140,8 @@ java_library { name: "framework-all", installable: false, static_libs: [ - "android.net.ipsec.ike.impl", + "all-framework-module-impl", "framework-minus-apex", - "framework-appsearch.impl", - "framework-connectivity.impl", - "framework-connectivity-tiramisu.impl", - "framework-graphics.impl", - "framework-mediaprovider.impl", - "framework-permission.impl", - "framework-permission-s.impl", - "framework-scheduling.impl", - "framework-sdkextensions.impl", - "framework-statsd.impl", - "framework-tethering.impl", - "framework-wifi.impl", - "updatable-media", ], apex_available: ["//apex_available:platform"], sdk_version: "core_platform", @@ -273,6 +259,7 @@ java_defaults { defaults: ["framework-aidl-export-defaults"], srcs: [ ":framework-non-updatable-sources", + ":framework-bluetooth-sources", // TODO(b/214988855) : Remove once framework-bluetooth jar is ready "core/java/**/*.logtags", ":apex-info-list", ], @@ -284,6 +271,8 @@ java_defaults { include_dirs: [ "frameworks/av/aidl", "frameworks/native/libs/permission/aidl", + // TODO: remove when moved to the below package + "frameworks/base/packages/ConnectivityT/framework-t/aidl-export", "packages/modules/Connectivity/framework/aidl-export", ], }, @@ -409,7 +398,6 @@ filegroup { // TODO: remove these annotations as soon as we can use andoid.support.annotations.* ":framework-annotations", ":modules-utils-preconditions-srcs", - "core/java/android/net/DhcpResults.java", "core/java/android/util/IndentingPrintWriter.java", "core/java/android/util/LocalLog.java", "core/java/com/android/internal/util/HexDump.java", @@ -521,6 +509,9 @@ stubs_defaults { include_dirs: [ "frameworks/av/aidl", "frameworks/native/libs/permission/aidl", + // TODO: remove when moved to the below package + "frameworks/base/packages/ConnectivityT/framework-t/aidl-export", + "packages/modules/Connectivity/framework/aidl-export", ], }, // These are libs from framework-internal-utils that are required (i.e. being referenced) @@ -568,6 +559,7 @@ stubs_defaults { libs: [ "art.module.public.api", "sdk_module-lib_current_framework-tethering", + "sdk_public_current_framework-bluetooth", // There are a few classes from modules used by the core that // need to be resolved by metalava. We use a prebuilt stub of the // full sdk to ensure we can resolve them. If a new class gets added, diff --git a/ApiDocs.bp b/ApiDocs.bp index 27e1def78bf2..5595e95631ad 100644 --- a/ApiDocs.bp +++ b/ApiDocs.bp @@ -55,12 +55,10 @@ framework_docs_only_libs = [ "android-support-multidex-instrumentation", ] +// These defaults enable doc-stub generation, api lint database generation and sdk value generation. stubs_defaults { name: "android-non-updatable-doc-stubs-defaults", - defaults: [ - "android-non-updatable-stubs-defaults", - "module-classpath-stubs-defaults", - ], + defaults: ["android-non-updatable-stubs-defaults"], srcs: [ // No longer part of the stubs, but are included in the docs. ":android-test-base-sources", @@ -72,47 +70,10 @@ stubs_defaults { write_sdk_values: true, } -stubs_defaults { - name: "framework-doc-stubs-default", - srcs: [ - ":android-non-updatable-stub-sources", - - // No longer part of the stubs, but are included in the docs. - ":android-test-base-sources", - ":android-test-mock-sources", - ":android-test-runner-sources", - ], - arg_files: [ - "core/res/AndroidManifest.xml", - ], - libs: framework_docs_only_libs, - create_doc_stubs: true, - annotations_enabled: true, - filter_packages: packages_to_document, - api_levels_annotations_enabled: true, - api_levels_annotations_dirs: [ - "sdk-dir", - "api-versions-jars-dir", - ], - previous_api: ":android.api.public.latest", - merge_annotations_dirs: [ - "metalava-manual", - ], - write_sdk_values: true, - // TODO(b/169090544): remove below aidl includes. - aidl: { - local_include_dirs: ["media/aidl"], - include_dirs: [ - "frameworks/av/aidl", - "frameworks/native/libs/permission/aidl", - ], - }, -} - // Defaults module for doc-stubs targets that use module source code as input. stubs_defaults { name: "framework-doc-stubs-sources-default", - defaults: ["framework-doc-stubs-default"], + defaults: ["android-non-updatable-doc-stubs-defaults"], srcs: [ ":art.module.public.api{.public.stubs.source}", ":conscrypt.module.public.api{.public.stubs.source}", @@ -120,6 +81,7 @@ stubs_defaults { ":framework-appsearch-sources", ":framework-connectivity-sources", + ":framework-bluetooth-sources", ":framework-connectivity-tiramisu-updatable-sources", ":framework-graphics-srcs", ":framework-mediaprovider-sources", @@ -137,13 +99,19 @@ stubs_defaults { droidstubs { name: "android-non-updatable-doc-stubs", - defaults: ["android-non-updatable-doc-stubs-defaults"], + defaults: [ + "android-non-updatable-doc-stubs-defaults", + "module-classpath-stubs-defaults", + ], args: metalava_framework_docs_args, } droidstubs { name: "android-non-updatable-doc-stubs-system", - defaults: ["android-non-updatable-doc-stubs-defaults"], + defaults: [ + "android-non-updatable-doc-stubs-defaults", + "module-classpath-stubs-defaults", + ], args: metalava_framework_docs_args + " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS\\) ", } @@ -153,14 +121,24 @@ droidstubs { defaults: ["framework-doc-stubs-sources-default"], args: metalava_framework_docs_args + " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS\\) ", + api_levels_annotations_enabled: true, + api_levels_annotations_dirs: [ + "sdk-dir", + "api-versions-jars-dir", + ], api_levels_sdk_type: "system", } droidstubs { name: "framework-doc-stubs", - defaults: ["framework-doc-stubs-default"], + defaults: ["android-non-updatable-doc-stubs-defaults"], srcs: [":all-modules-public-stubs-source"], args: metalava_framework_docs_args, + api_levels_annotations_enabled: true, + api_levels_annotations_dirs: [ + "sdk-dir", + "api-versions-jars-dir", + ], aidl: { local_include_dirs: [ "apex/media/aidl/stable", diff --git a/StubLibraries.bp b/StubLibraries.bp index 9e8b7071d0c7..5cb0a785bc2b 100644 --- a/StubLibraries.bp +++ b/StubLibraries.bp @@ -207,46 +207,6 @@ droidstubs { // from stub sources ///////////////////////////////////////////////////////////////////// -modules_public_stubs = [ - "android.net.ipsec.ike.stubs", - "art.module.public.api.stubs", - "conscrypt.module.public.api.stubs", - "framework-appsearch.stubs", - "framework-connectivity.stubs", - "framework-connectivity-tiramisu.stubs", - "framework-graphics.stubs", - "framework-media.stubs", - "framework-mediaprovider.stubs", - "framework-permission.stubs", - "framework-permission-s.stubs", - "framework-scheduling.stubs", - "framework-sdkextensions.stubs", - "framework-statsd.stubs", - "framework-tethering.stubs", - "framework-wifi.stubs", - "i18n.module.public.api.stubs", -] - -modules_system_stubs = [ - "android.net.ipsec.ike.stubs.system", - "art.module.public.api.stubs.system", - "conscrypt.module.public.api.stubs", // Only has public stubs - "framework-appsearch.stubs.system", - "framework-connectivity.stubs.system", - "framework-connectivity-tiramisu.stubs.system", - "framework-graphics.stubs.system", - "framework-media.stubs.system", - "framework-mediaprovider.stubs.system", - "framework-permission.stubs.system", - "framework-permission-s.stubs.system", - "framework-scheduling.stubs.system", - "framework-sdkextensions.stubs.system", - "framework-statsd.stubs.system", - "framework-tethering.stubs.system", - "framework-wifi.stubs.system", - "i18n.module.public.api.stubs", // Only has public stubs -] - java_defaults { name: "android-non-updatable_defaults_stubs_current", libs: ["stub-annotations"], @@ -268,7 +228,7 @@ java_library { name: "android-non-updatable.stubs", defaults: ["android-non-updatable_defaults_stubs_current"], srcs: [":api-stubs-docs-non-updatable"], - libs: modules_public_stubs, + libs: ["all-modules-public-stubs"], dist: { dir: "apistubs/android/public", }, @@ -278,7 +238,7 @@ java_library { name: "android-non-updatable.stubs.system", defaults: ["android-non-updatable_defaults_stubs_current"], srcs: [":system-api-stubs-docs-non-updatable"], - libs: modules_system_stubs, + libs: ["all-modules-system-stubs"], dist: { dir: "apistubs/android/system", }, @@ -290,6 +250,8 @@ java_library { srcs: [":module-lib-api-stubs-docs-non-updatable"], libs: [ "sdk_module-lib_current_framework-tethering", + "sdk_public_current_framework-bluetooth", + // NOTE: The below can be removed once the prebuilt stub contains bluetooth. "sdk_system_current_android", // NOTE: The below can be removed once the prebuilt stub contains IKE. "sdk_system_current_android.net.ipsec.ike", @@ -303,7 +265,7 @@ java_library { name: "android-non-updatable.stubs.test", defaults: ["android-non-updatable_defaults_stubs_current"], srcs: [":test-api-stubs-docs-non-updatable"], - libs: modules_system_stubs, + libs: ["all-modules-system-stubs"], dist: { dir: "apistubs/android/test", }, @@ -321,7 +283,8 @@ java_defaults { java_library { name: "android_stubs_current", - static_libs: modules_public_stubs + [ + static_libs: [ + "all-modules-public-stubs", "android-non-updatable.stubs", "private-stub-annotations-jar", ], @@ -330,7 +293,8 @@ java_library { java_library { name: "android_system_stubs_current", - static_libs: modules_system_stubs + [ + static_libs: [ + "all-modules-system-stubs", "android-non-updatable.stubs.system", "private-stub-annotations-jar", ], @@ -355,7 +319,8 @@ java_library { name: "android_test_stubs_current", // Modules do not have test APIs, but we want to include their SystemApis, like we include // the SystemApi of framework-non-updatable-sources. - static_libs: modules_system_stubs + [ + static_libs: [ + "all-modules-system-stubs", "android-non-updatable.stubs.test", "private-stub-annotations-jar", ], diff --git a/apex/media/framework/Android.bp b/apex/media/framework/Android.bp index d963e68d80ec..6195f257ecd9 100644 --- a/apex/media/framework/Android.bp +++ b/apex/media/framework/Android.bp @@ -63,8 +63,8 @@ java_library { min_sdk_version: "29", visibility: [ "//frameworks/av/apex:__subpackages__", - "//frameworks/base", // For framework-all "//frameworks/base/apex/media/service", + "//frameworks/base/api", // For framework-all ], } diff --git a/api/Android.bp b/api/Android.bp index 0c3a3e60bd9a..15356bdc0797 100644 --- a/api/Android.bp +++ b/api/Android.bp @@ -110,6 +110,7 @@ combined_apis { "art.module.public.api", "conscrypt.module.public.api", "framework-appsearch", + "framework-bluetooth", "framework-connectivity", "framework-connectivity-tiramisu", "framework-graphics", diff --git a/api/OWNERS b/api/OWNERS index a0272709ffc0..4d8ed0347f43 100644 --- a/api/OWNERS +++ b/api/OWNERS @@ -4,3 +4,6 @@ hansson@google.com file:platform/packages/modules/common:/OWNERS per-file Android.bp = file:platform/build/soong:/OWNERS + +# For metalava team to disable lint checks in platform +per-file Android.bp = aurimas@google.com,emberrose@google.com,sjgilbert@google.com
\ No newline at end of file diff --git a/api/api.go b/api/api.go index 4b6ebc1947e9..5e5f60ee993f 100644 --- a/api/api.go +++ b/api/api.go @@ -27,6 +27,7 @@ import ( const art = "art.module.public.api" const conscrypt = "conscrypt.module.public.api" const i18n = "i18n.module.public.api" +var core_libraries_modules = []string{art, conscrypt, i18n} // The intention behind this soong plugin is to generate a number of "merged" // API-related modules that would otherwise require a large amount of very @@ -148,8 +149,6 @@ func createMergedStubsSrcjar(ctx android.LoadHookContext, modules []string) { // This produces the same annotations.zip as framework-doc-stubs, but by using // outputs from individual modules instead of all the source code. func createMergedAnnotations(ctx android.LoadHookContext, modules []string) { - // Conscrypt and i18n currently do not enable annotations - modules = removeAll(modules, []string{conscrypt, i18n}) props := genruleProps{} props.Name = proptools.StringPtr("sdk-annotations.zip") props.Tools = []string{"merge_annotation_zips", "soong_zip"} @@ -183,9 +182,46 @@ func createFilteredApiVersions(ctx android.LoadHookContext, modules []string) { ctx.CreateModule(genrule.GenRuleFactory, &props) } -func createMergedModuleLibStubs(ctx android.LoadHookContext, modules []string) { +func createMergedPublicStubs(ctx android.LoadHookContext, modules []string) { + props := libraryProps{} + props.Name = proptools.StringPtr("all-modules-public-stubs") + props.Static_libs = transformArray(modules, "", ".stubs") + props.Sdk_version = proptools.StringPtr("module_current") + props.Visibility = []string{"//frameworks/base"} + ctx.CreateModule(java.LibraryFactory, &props) +} + +func createMergedSystemStubs(ctx android.LoadHookContext, modules []string) { + props := libraryProps{} + props.Name = proptools.StringPtr("all-modules-system-stubs") + props.Static_libs = transformArray(modules, "", ".stubs.system") + props.Sdk_version = proptools.StringPtr("module_current") + props.Visibility = []string{"//frameworks/base"} + ctx.CreateModule(java.LibraryFactory, &props) +} + +func createMergedFrameworkImpl(ctx android.LoadHookContext, modules []string) { + // This module is for the "framework-all" module, which should not include the core libraries. + modules = removeAll(modules, core_libraries_modules) + // TODO(b/214988855): remove the line below when framework-bluetooth has an impl jar. + modules = remove(modules, "framework-bluetooth") + props := libraryProps{} + props.Name = proptools.StringPtr("all-framework-module-impl") + props.Static_libs = transformArray(modules, "", ".impl") + // Media module's impl jar is called "updatable-media" + for i, v := range props.Static_libs { + if v == "framework-media.impl" { + props.Static_libs[i] = "updatable-media" + } + } + props.Sdk_version = proptools.StringPtr("module_current") + props.Visibility = []string{"//frameworks/base"} + ctx.CreateModule(java.LibraryFactory, &props) +} + +func createMergedFrameworkModuleLibStubs(ctx android.LoadHookContext, modules []string) { // The user of this module compiles against the "core" SDK, so remove core libraries to avoid dupes. - modules = removeAll(modules, []string{art, conscrypt, i18n}) + modules = removeAll(modules, core_libraries_modules) props := libraryProps{} props.Name = proptools.StringPtr("framework-updatable-stubs-module_libs_api") props.Static_libs = transformArray(modules, "", ".stubs.module_lib") @@ -204,8 +240,6 @@ func createPublicStubsSourceFilegroup(ctx android.LoadHookContext, modules []str func createMergedTxts(ctx android.LoadHookContext, bootclasspath, system_server_classpath []string) { var textFiles []MergedTxtDefinition - // Two module libraries currently do not support @SystemApi so only have the public scope. - bcpWithSystemApi := removeAll(bootclasspath, []string{conscrypt, i18n}) tagSuffix := []string{".api.txt}", ".removed-api.txt}"} for i, f := range []string{"current.txt", "removed.txt"} { @@ -219,14 +253,14 @@ func createMergedTxts(ctx android.LoadHookContext, bootclasspath, system_server_ textFiles = append(textFiles, MergedTxtDefinition{ TxtFilename: f, BaseTxt: ":non-updatable-system-" + f, - Modules: bcpWithSystemApi, + Modules: bootclasspath, ModuleTag: "{.system" + tagSuffix[i], Scope: "system", }) textFiles = append(textFiles, MergedTxtDefinition{ TxtFilename: f, BaseTxt: ":non-updatable-module-lib-" + f, - Modules: bcpWithSystemApi, + Modules: bootclasspath, ModuleTag: "{.module-lib" + tagSuffix[i], Scope: "module-lib", }) @@ -253,7 +287,10 @@ func (a *CombinedApis) createInternalModules(ctx android.LoadHookContext) { createMergedStubsSrcjar(ctx, bootclasspath) - createMergedModuleLibStubs(ctx, bootclasspath) + createMergedPublicStubs(ctx, bootclasspath) + createMergedSystemStubs(ctx, bootclasspath) + createMergedFrameworkModuleLibStubs(ctx, bootclasspath) + createMergedFrameworkImpl(ctx, bootclasspath) createMergedAnnotations(ctx, bootclasspath) diff --git a/cmds/incidentd/src/WorkDirectory.cpp b/cmds/incidentd/src/WorkDirectory.cpp index 23d80d7953b7..0d8bd40a4de1 100644 --- a/cmds/incidentd/src/WorkDirectory.cpp +++ b/cmds/incidentd/src/WorkDirectory.cpp @@ -280,7 +280,7 @@ void ReportFile::addReport(const IncidentReportArgs& args) { // Lower privacy policy (less restrictive) wins. report->set_privacy_policy(args.getPrivacyPolicy()); } - report->set_all_sections(report->all_sections() | args.all()); + report->set_all_sections(report->all_sections() || args.all()); for (int section: args.sections()) { if (!has_section(*report, section)) { report->add_section(section); diff --git a/core/api/current.txt b/core/api/current.txt index dfdbd75cbafe..0ffc2c5198db 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -7185,6 +7185,7 @@ package android.app.admin { method @Nullable public java.util.List<java.lang.String> getPermittedCrossProfileNotificationListeners(@NonNull android.content.ComponentName); method @Nullable public java.util.List<java.lang.String> getPermittedInputMethods(@NonNull android.content.ComponentName); method public int getPersonalAppsSuspendedReasons(@NonNull android.content.ComponentName); + method @NonNull public android.app.admin.PreferentialNetworkServiceConfig getPreferentialNetworkServiceConfig(); method public int getRequiredPasswordComplexity(); method public long getRequiredStrongAuthTimeout(@Nullable android.content.ComponentName); method public boolean getScreenCaptureDisabled(@Nullable android.content.ComponentName); @@ -7327,6 +7328,7 @@ package android.app.admin { method public boolean setPermittedCrossProfileNotificationListeners(@NonNull android.content.ComponentName, @Nullable java.util.List<java.lang.String>); method public boolean setPermittedInputMethods(@NonNull android.content.ComponentName, java.util.List<java.lang.String>); method public void setPersonalAppsSuspended(@NonNull android.content.ComponentName, boolean); + method public void setPreferentialNetworkServiceConfig(@NonNull android.app.admin.PreferentialNetworkServiceConfig); method public void setPreferentialNetworkServiceEnabled(boolean); method public void setProfileEnabled(@NonNull android.content.ComponentName); method public void setProfileName(@NonNull android.content.ComponentName, String); @@ -7572,6 +7574,32 @@ package android.app.admin { field @NonNull public static final android.os.Parcelable.Creator<android.app.admin.NetworkEvent> CREATOR; } + public final class PreferentialNetworkServiceConfig implements android.os.Parcelable { + method public int describeContents(); + method @NonNull public int[] getExcludedUids(); + method @NonNull public int[] getIncludedUids(); + method public int getNetworkId(); + method public boolean isEnabled(); + method public boolean isFallbackToDefaultConnectionAllowed(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.app.admin.PreferentialNetworkServiceConfig> CREATOR; + field public static final int PREFERENTIAL_NETWORK_ID_1 = 1; // 0x1 + field public static final int PREFERENTIAL_NETWORK_ID_2 = 2; // 0x2 + field public static final int PREFERENTIAL_NETWORK_ID_3 = 3; // 0x3 + field public static final int PREFERENTIAL_NETWORK_ID_4 = 4; // 0x4 + field public static final int PREFERENTIAL_NETWORK_ID_5 = 5; // 0x5 + } + + public static final class PreferentialNetworkServiceConfig.Builder { + ctor public PreferentialNetworkServiceConfig.Builder(); + method @NonNull public android.app.admin.PreferentialNetworkServiceConfig build(); + method @NonNull public android.app.admin.PreferentialNetworkServiceConfig.Builder setEnabled(boolean); + method @NonNull public android.app.admin.PreferentialNetworkServiceConfig.Builder setExcludedUids(@NonNull int[]); + method @NonNull public android.app.admin.PreferentialNetworkServiceConfig.Builder setFallbackToDefaultConnectionAllowed(boolean); + method @NonNull public android.app.admin.PreferentialNetworkServiceConfig.Builder setIncludedUids(@NonNull int[]); + method @NonNull public android.app.admin.PreferentialNetworkServiceConfig.Builder setNetworkId(int); + } + public class SecurityLog { ctor public SecurityLog(); field public static final int LEVEL_ERROR = 3; // 0x3 @@ -8616,1321 +8644,6 @@ package android.appwidget { } -package android.bluetooth { - - public final class BluetoothA2dp implements android.bluetooth.BluetoothProfile { - method public void finalize(); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices(); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getConnectionState(android.bluetooth.BluetoothDevice); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean isA2dpPlaying(android.bluetooth.BluetoothDevice); - field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED"; - field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_PLAYING_STATE_CHANGED = "android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED"; - field public static final int STATE_NOT_PLAYING = 11; // 0xb - field public static final int STATE_PLAYING = 10; // 0xa - } - - public final class BluetoothAdapter { - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public boolean cancelDiscovery(); - method public static boolean checkBluetoothAddress(String); - method public void closeProfileProxy(int, android.bluetooth.BluetoothProfile); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean disable(); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean enable(); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, "android.permission.LOCAL_MAC_ADDRESS"}) public String getAddress(); - method public android.bluetooth.le.BluetoothLeAdvertiser getBluetoothLeAdvertiser(); - method public android.bluetooth.le.BluetoothLeScanner getBluetoothLeScanner(); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.Set<android.bluetooth.BluetoothDevice> getBondedDevices(); - method @Deprecated public static android.bluetooth.BluetoothAdapter getDefaultAdapter(); - method public int getLeMaximumAdvertisingDataLength(); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public String getName(); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getProfileConnectionState(int); - method public boolean getProfileProxy(android.content.Context, android.bluetooth.BluetoothProfile.ServiceListener, int); - method public android.bluetooth.BluetoothDevice getRemoteDevice(String); - method public android.bluetooth.BluetoothDevice getRemoteDevice(byte[]); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public int getScanMode(); - method public int getState(); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public boolean isDiscovering(); - method public boolean isEnabled(); - method public boolean isLe2MPhySupported(); - method public int isLeAudioBroadcastAssistantSupported(); - method public int isLeAudioBroadcastSourceSupported(); - method public int isLeAudioSupported(); - method public boolean isLeCodedPhySupported(); - method public boolean isLeExtendedAdvertisingSupported(); - method public boolean isLePeriodicAdvertisingSupported(); - method public boolean isMultipleAdvertisementSupported(); - method public boolean isOffloadedFilteringSupported(); - method public boolean isOffloadedScanBatchingSupported(); - method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothServerSocket listenUsingInsecureL2capChannel() throws java.io.IOException; - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothServerSocket listenUsingInsecureRfcommWithServiceRecord(String, java.util.UUID) throws java.io.IOException; - method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothServerSocket listenUsingL2capChannel() throws java.io.IOException; - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothServerSocket listenUsingRfcommWithServiceRecord(String, java.util.UUID) throws java.io.IOException; - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean setName(String); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public boolean startDiscovery(); - method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public boolean startLeScan(android.bluetooth.BluetoothAdapter.LeScanCallback); - method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public boolean startLeScan(java.util.UUID[], android.bluetooth.BluetoothAdapter.LeScanCallback); - method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public void stopLeScan(android.bluetooth.BluetoothAdapter.LeScanCallback); - field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED"; - field @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public static final String ACTION_DISCOVERY_FINISHED = "android.bluetooth.adapter.action.DISCOVERY_FINISHED"; - field @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public static final String ACTION_DISCOVERY_STARTED = "android.bluetooth.adapter.action.DISCOVERY_STARTED"; - field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_LOCAL_NAME_CHANGED = "android.bluetooth.adapter.action.LOCAL_NAME_CHANGED"; - field @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public static final String ACTION_REQUEST_DISCOVERABLE = "android.bluetooth.adapter.action.REQUEST_DISCOVERABLE"; - field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_REQUEST_ENABLE = "android.bluetooth.adapter.action.REQUEST_ENABLE"; - field @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public static final String ACTION_SCAN_MODE_CHANGED = "android.bluetooth.adapter.action.SCAN_MODE_CHANGED"; - field public static final String ACTION_STATE_CHANGED = "android.bluetooth.adapter.action.STATE_CHANGED"; - field public static final int ERROR = -2147483648; // 0x80000000 - field public static final String EXTRA_CONNECTION_STATE = "android.bluetooth.adapter.extra.CONNECTION_STATE"; - field public static final String EXTRA_DISCOVERABLE_DURATION = "android.bluetooth.adapter.extra.DISCOVERABLE_DURATION"; - field public static final String EXTRA_LOCAL_NAME = "android.bluetooth.adapter.extra.LOCAL_NAME"; - field public static final String EXTRA_PREVIOUS_CONNECTION_STATE = "android.bluetooth.adapter.extra.PREVIOUS_CONNECTION_STATE"; - field public static final String EXTRA_PREVIOUS_SCAN_MODE = "android.bluetooth.adapter.extra.PREVIOUS_SCAN_MODE"; - field public static final String EXTRA_PREVIOUS_STATE = "android.bluetooth.adapter.extra.PREVIOUS_STATE"; - field public static final String EXTRA_SCAN_MODE = "android.bluetooth.adapter.extra.SCAN_MODE"; - field public static final String EXTRA_STATE = "android.bluetooth.adapter.extra.STATE"; - field public static final int SCAN_MODE_CONNECTABLE = 21; // 0x15 - field public static final int SCAN_MODE_CONNECTABLE_DISCOVERABLE = 23; // 0x17 - field public static final int SCAN_MODE_NONE = 20; // 0x14 - field public static final int STATE_CONNECTED = 2; // 0x2 - field public static final int STATE_CONNECTING = 1; // 0x1 - field public static final int STATE_DISCONNECTED = 0; // 0x0 - field public static final int STATE_DISCONNECTING = 3; // 0x3 - field public static final int STATE_OFF = 10; // 0xa - field public static final int STATE_ON = 12; // 0xc - field public static final int STATE_TURNING_OFF = 13; // 0xd - field public static final int STATE_TURNING_ON = 11; // 0xb - } - - public static interface BluetoothAdapter.LeScanCallback { - method public void onLeScan(android.bluetooth.BluetoothDevice, int, byte[]); - } - - public class BluetoothAssignedNumbers { - field public static final int AAMP_OF_AMERICA = 190; // 0xbe - field public static final int ACCEL_SEMICONDUCTOR = 74; // 0x4a - field public static final int ACE_SENSOR = 188; // 0xbc - field public static final int ADIDAS = 195; // 0xc3 - field public static final int ADVANCED_PANMOBIL_SYSTEMS = 145; // 0x91 - field public static final int AIROHA_TECHNOLOGY = 148; // 0x94 - field public static final int ALCATEL = 36; // 0x24 - field public static final int ALPWISE = 154; // 0x9a - field public static final int AMICCOM_ELECTRONICS = 192; // 0xc0 - field public static final int APLIX = 189; // 0xbd - field public static final int APPLE = 76; // 0x4c - field public static final int APT_LICENSING = 79; // 0x4f - field public static final int ARCHOS = 207; // 0xcf - field public static final int ARP_DEVICES = 168; // 0xa8 - field public static final int ATHEROS_COMMUNICATIONS = 69; // 0x45 - field public static final int ATMEL = 19; // 0x13 - field public static final int AUSTCO_COMMUNICATION_SYSTEMS = 213; // 0xd5 - field public static final int AUTONET_MOBILE = 127; // 0x7f - field public static final int AVAGO = 78; // 0x4e - field public static final int AVM_BERLIN = 31; // 0x1f - field public static final int A_AND_D_ENGINEERING = 105; // 0x69 - field public static final int A_AND_R_CAMBRIDGE = 124; // 0x7c - field public static final int BANDSPEED = 32; // 0x20 - field public static final int BAND_XI_INTERNATIONAL = 100; // 0x64 - field public static final int BDE_TECHNOLOGY = 180; // 0xb4 - field public static final int BEATS_ELECTRONICS = 204; // 0xcc - field public static final int BEAUTIFUL_ENTERPRISE = 108; // 0x6c - field public static final int BEKEY = 178; // 0xb2 - field public static final int BELKIN_INTERNATIONAL = 92; // 0x5c - field public static final int BINAURIC = 203; // 0xcb - field public static final int BIOSENTRONICS = 219; // 0xdb - field public static final int BLUEGIGA = 71; // 0x47 - field public static final int BLUERADIOS = 133; // 0x85 - field public static final int BLUETOOTH_SIG = 63; // 0x3f - field public static final int BLUETREK_TECHNOLOGIES = 151; // 0x97 - field public static final int BOSE = 158; // 0x9e - field public static final int BRIARTEK = 109; // 0x6d - field public static final int BROADCOM = 15; // 0xf - field public static final int CAEN_RFID = 170; // 0xaa - field public static final int CAMBRIDGE_SILICON_RADIO = 10; // 0xa - field public static final int CATC = 52; // 0x34 - field public static final int CINETIX = 175; // 0xaf - field public static final int CLARINOX_TECHNOLOGIES = 179; // 0xb3 - field public static final int COLORFY = 156; // 0x9c - field public static final int COMMIL = 51; // 0x33 - field public static final int CONEXANT_SYSTEMS = 28; // 0x1c - field public static final int CONNECTBLUE = 113; // 0x71 - field public static final int CONTINENTAL_AUTOMOTIVE = 75; // 0x4b - field public static final int CONWISE_TECHNOLOGY = 66; // 0x42 - field public static final int CREATIVE_TECHNOLOGY = 118; // 0x76 - field public static final int C_TECHNOLOGIES = 38; // 0x26 - field public static final int DANLERS = 225; // 0xe1 - field public static final int DELORME_PUBLISHING_COMPANY = 128; // 0x80 - field public static final int DEXCOM = 208; // 0xd0 - field public static final int DIALOG_SEMICONDUCTOR = 210; // 0xd2 - field public static final int DIGIANSWER = 12; // 0xc - field public static final int ECLIPSE = 53; // 0x35 - field public static final int ECOTEST = 136; // 0x88 - field public static final int ELGATO_SYSTEMS = 206; // 0xce - field public static final int EM_MICROELECTRONIC_MARIN = 90; // 0x5a - field public static final int EQUINOX_AG = 134; // 0x86 - field public static final int ERICSSON_TECHNOLOGY = 0; // 0x0 - field public static final int EVLUMA = 201; // 0xc9 - field public static final int FREE2MOVE = 83; // 0x53 - field public static final int FUNAI_ELECTRIC = 144; // 0x90 - field public static final int GARMIN_INTERNATIONAL = 135; // 0x87 - field public static final int GCT_SEMICONDUCTOR = 45; // 0x2d - field public static final int GELO = 200; // 0xc8 - field public static final int GENEQ = 194; // 0xc2 - field public static final int GENERAL_MOTORS = 104; // 0x68 - field public static final int GENNUM = 59; // 0x3b - field public static final int GEOFORCE = 157; // 0x9d - field public static final int GIBSON_GUITARS = 98; // 0x62 - field public static final int GN_NETCOM = 103; // 0x67 - field public static final int GN_RESOUND = 137; // 0x89 - field public static final int GOOGLE = 224; // 0xe0 - field public static final int GREEN_THROTTLE_GAMES = 172; // 0xac - field public static final int GROUP_SENSE = 115; // 0x73 - field public static final int HANLYNN_TECHNOLOGIES = 123; // 0x7b - field public static final int HARMAN_INTERNATIONAL = 87; // 0x57 - field public static final int HEWLETT_PACKARD = 101; // 0x65 - field public static final int HITACHI = 41; // 0x29 - field public static final int HOSIDEN = 221; // 0xdd - field public static final int IBM = 3; // 0x3 - field public static final int INFINEON_TECHNOLOGIES = 9; // 0x9 - field public static final int INGENIEUR_SYSTEMGRUPPE_ZAHN = 171; // 0xab - field public static final int INTEGRATED_SILICON_SOLUTION = 65; // 0x41 - field public static final int INTEGRATED_SYSTEM_SOLUTION = 57; // 0x39 - field public static final int INTEL = 2; // 0x2 - field public static final int INVENTEL = 30; // 0x1e - field public static final int IPEXTREME = 61; // 0x3d - field public static final int I_TECH_DYNAMIC_GLOBAL_DISTRIBUTION = 153; // 0x99 - field public static final int JAWBONE = 138; // 0x8a - field public static final int JIANGSU_TOPPOWER_AUTOMOTIVE_ELECTRONICS = 155; // 0x9b - field public static final int JOHNSON_CONTROLS = 185; // 0xb9 - field public static final int J_AND_M = 82; // 0x52 - field public static final int KAWANTECH = 212; // 0xd4 - field public static final int KC_TECHNOLOGY = 22; // 0x16 - field public static final int KENSINGTON_COMPUTER_PRODUCTS_GROUP = 160; // 0xa0 - field public static final int LAIRD_TECHNOLOGIES = 119; // 0x77 - field public static final int LESSWIRE = 121; // 0x79 - field public static final int LG_ELECTRONICS = 196; // 0xc4 - field public static final int LINAK = 164; // 0xa4 - field public static final int LUCENT = 7; // 0x7 - field public static final int LUDUS_HELSINKI = 132; // 0x84 - field public static final int MACRONIX = 44; // 0x2c - field public static final int MAGNETI_MARELLI = 169; // 0xa9 - field public static final int MANSELLA = 33; // 0x21 - field public static final int MARVELL = 72; // 0x48 - field public static final int MATSUSHITA_ELECTRIC = 58; // 0x3a - field public static final int MC10 = 202; // 0xca - field public static final int MEDIATEK = 70; // 0x46 - field public static final int MESO_INTERNATIONAL = 182; // 0xb6 - field public static final int META_WATCH = 163; // 0xa3 - field public static final int MEWTEL_TECHNOLOGY = 47; // 0x2f - field public static final int MICOMMAND = 99; // 0x63 - field public static final int MICROCHIP_TECHNOLOGY = 205; // 0xcd - field public static final int MICROSOFT = 6; // 0x6 - field public static final int MINDTREE = 106; // 0x6a - field public static final int MISFIT_WEARABLES = 223; // 0xdf - field public static final int MITEL_SEMICONDUCTOR = 16; // 0x10 - field public static final int MITSUBISHI_ELECTRIC = 20; // 0x14 - field public static final int MOBILIAN_CORPORATION = 55; // 0x37 - field public static final int MONSTER = 112; // 0x70 - field public static final int MOTOROLA = 8; // 0x8 - field public static final int MSTAR_SEMICONDUCTOR = 122; // 0x7a - field public static final int MUZIK = 222; // 0xde - field public static final int NEC = 34; // 0x22 - field public static final int NEC_LIGHTING = 149; // 0x95 - field public static final int NEWLOGIC = 23; // 0x17 - field public static final int NIKE = 120; // 0x78 - field public static final int NINE_SOLUTIONS = 102; // 0x66 - field public static final int NOKIA_MOBILE_PHONES = 1; // 0x1 - field public static final int NORDIC_SEMICONDUCTOR = 89; // 0x59 - field public static final int NORWOOD_SYSTEMS = 46; // 0x2e - field public static final int ODM_TECHNOLOGY = 150; // 0x96 - field public static final int OMEGAWAVE = 174; // 0xae - field public static final int ONSET_COMPUTER = 197; // 0xc5 - field public static final int OPEN_INTERFACE = 39; // 0x27 - field public static final int OTL_DYNAMICS = 165; // 0xa5 - field public static final int PANDA_OCEAN = 166; // 0xa6 - field public static final int PARROT = 67; // 0x43 - field public static final int PARTHUS_TECHNOLOGIES = 14; // 0xe - field public static final int PASSIF_SEMICONDUCTOR = 176; // 0xb0 - field public static final int PETER_SYSTEMTECHNIK = 173; // 0xad - field public static final int PHILIPS_SEMICONDUCTORS = 37; // 0x25 - field public static final int PLANTRONICS = 85; // 0x55 - field public static final int POLAR_ELECTRO = 107; // 0x6b - field public static final int POLAR_ELECTRO_EUROPE = 209; // 0xd1 - field public static final int PROCTER_AND_GAMBLE = 220; // 0xdc - field public static final int QUALCOMM = 29; // 0x1d - field public static final int QUALCOMM_CONNECTED_EXPERIENCES = 216; // 0xd8 - field public static final int QUALCOMM_INNOVATION_CENTER = 184; // 0xb8 - field public static final int QUALCOMM_LABS = 140; // 0x8c - field public static final int QUALCOMM_TECHNOLOGIES = 215; // 0xd7 - field public static final int QUINTIC = 142; // 0x8e - field public static final int QUUPPA = 199; // 0xc7 - field public static final int RALINK_TECHNOLOGY = 91; // 0x5b - field public static final int RDA_MICROELECTRONICS = 97; // 0x61 - field public static final int REALTEK_SEMICONDUCTOR = 93; // 0x5d - field public static final int RED_M = 50; // 0x32 - field public static final int RENESAS_TECHNOLOGY = 54; // 0x36 - field public static final int RESEARCH_IN_MOTION = 60; // 0x3c - field public static final int RF_MICRO_DEVICES = 40; // 0x28 - field public static final int RIVIERAWAVES = 96; // 0x60 - field public static final int ROHDE_AND_SCHWARZ = 25; // 0x19 - field public static final int RTX_TELECOM = 21; // 0x15 - field public static final int SAMSUNG_ELECTRONICS = 117; // 0x75 - field public static final int SARIS_CYCLING_GROUP = 177; // 0xb1 - field public static final int SEERS_TECHNOLOGY = 125; // 0x7d - field public static final int SEIKO_EPSON = 64; // 0x40 - field public static final int SELFLY = 198; // 0xc6 - field public static final int SEMILINK = 226; // 0xe2 - field public static final int SENNHEISER_COMMUNICATIONS = 130; // 0x82 - field public static final int SHANGHAI_SUPER_SMART_ELECTRONICS = 114; // 0x72 - field public static final int SHENZHEN_EXCELSECU_DATA_TECHNOLOGY = 193; // 0xc1 - field public static final int SIGNIA_TECHNOLOGIES = 27; // 0x1b - field public static final int SILICON_WAVE = 11; // 0xb - field public static final int SIRF_TECHNOLOGY = 80; // 0x50 - field public static final int SOCKET_MOBILE = 68; // 0x44 - field public static final int SONY_ERICSSON = 86; // 0x56 - field public static final int SOUND_ID = 111; // 0x6f - field public static final int SPORTS_TRACKING_TECHNOLOGIES = 126; // 0x7e - field public static final int SR_MEDIZINELEKTRONIK = 161; // 0xa1 - field public static final int STACCATO_COMMUNICATIONS = 77; // 0x4d - field public static final int STALMART_TECHNOLOGY = 191; // 0xbf - field public static final int STARKEY_LABORATORIES = 186; // 0xba - field public static final int STOLLMAN_E_PLUS_V = 143; // 0x8f - field public static final int STONESTREET_ONE = 94; // 0x5e - field public static final int ST_MICROELECTRONICS = 48; // 0x30 - field public static final int SUMMIT_DATA_COMMUNICATIONS = 110; // 0x6e - field public static final int SUUNTO = 159; // 0x9f - field public static final int SWIRL_NETWORKS = 181; // 0xb5 - field public static final int SYMBOL_TECHNOLOGIES = 42; // 0x2a - field public static final int SYNOPSYS = 49; // 0x31 - field public static final int SYSTEMS_AND_CHIPS = 62; // 0x3e - field public static final int S_POWER_ELECTRONICS = 187; // 0xbb - field public static final int TAIXINGBANG_TECHNOLOGY = 211; // 0xd3 - field public static final int TENOVIS = 43; // 0x2b - field public static final int TERAX = 56; // 0x38 - field public static final int TEXAS_INSTRUMENTS = 13; // 0xd - field public static final int THINKOPTICS = 146; // 0x92 - field public static final int THREECOM = 5; // 0x5 - field public static final int THREE_DIJOY = 84; // 0x54 - field public static final int THREE_DSP = 73; // 0x49 - field public static final int TIMEKEEPING_SYSTEMS = 131; // 0x83 - field public static final int TIMEX_GROUP_USA = 214; // 0xd6 - field public static final int TOPCORN_POSITIONING_SYSTEMS = 139; // 0x8b - field public static final int TOSHIBA = 4; // 0x4 - field public static final int TRANSILICA = 24; // 0x18 - field public static final int TRELAB = 183; // 0xb7 - field public static final int TTPCOM = 26; // 0x1a - field public static final int TXTR = 218; // 0xda - field public static final int TZERO_TECHNOLOGIES = 81; // 0x51 - field public static final int UNIVERSAL_ELECTRONICS = 147; // 0x93 - field public static final int VERTU = 162; // 0xa2 - field public static final int VISTEON = 167; // 0xa7 - field public static final int VIZIO = 88; // 0x58 - field public static final int VOYETRA_TURTLE_BEACH = 217; // 0xd9 - field public static final int WAVEPLUS_TECHNOLOGY = 35; // 0x23 - field public static final int WICENTRIC = 95; // 0x5f - field public static final int WIDCOMM = 17; // 0x11 - field public static final int WUXI_VIMICRO = 129; // 0x81 - field public static final int ZEEVO = 18; // 0x12 - field public static final int ZER01_TV = 152; // 0x98 - field public static final int ZOMM = 116; // 0x74 - field public static final int ZSCAN_SOFTWARE = 141; // 0x8d - } - - public final class BluetoothClass implements android.os.Parcelable { - method public int describeContents(); - method public int getDeviceClass(); - method public int getMajorDeviceClass(); - method public boolean hasService(int); - method public void writeToParcel(android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothClass> CREATOR; - } - - public static class BluetoothClass.Device { - ctor public BluetoothClass.Device(); - field public static final int AUDIO_VIDEO_CAMCORDER = 1076; // 0x434 - field public static final int AUDIO_VIDEO_CAR_AUDIO = 1056; // 0x420 - field public static final int AUDIO_VIDEO_HANDSFREE = 1032; // 0x408 - field public static final int AUDIO_VIDEO_HEADPHONES = 1048; // 0x418 - field public static final int AUDIO_VIDEO_HIFI_AUDIO = 1064; // 0x428 - field public static final int AUDIO_VIDEO_LOUDSPEAKER = 1044; // 0x414 - field public static final int AUDIO_VIDEO_MICROPHONE = 1040; // 0x410 - field public static final int AUDIO_VIDEO_PORTABLE_AUDIO = 1052; // 0x41c - field public static final int AUDIO_VIDEO_SET_TOP_BOX = 1060; // 0x424 - field public static final int AUDIO_VIDEO_UNCATEGORIZED = 1024; // 0x400 - field public static final int AUDIO_VIDEO_VCR = 1068; // 0x42c - field public static final int AUDIO_VIDEO_VIDEO_CAMERA = 1072; // 0x430 - field public static final int AUDIO_VIDEO_VIDEO_CONFERENCING = 1088; // 0x440 - field public static final int AUDIO_VIDEO_VIDEO_DISPLAY_AND_LOUDSPEAKER = 1084; // 0x43c - field public static final int AUDIO_VIDEO_VIDEO_GAMING_TOY = 1096; // 0x448 - field public static final int AUDIO_VIDEO_VIDEO_MONITOR = 1080; // 0x438 - field public static final int AUDIO_VIDEO_WEARABLE_HEADSET = 1028; // 0x404 - field public static final int COMPUTER_DESKTOP = 260; // 0x104 - field public static final int COMPUTER_HANDHELD_PC_PDA = 272; // 0x110 - field public static final int COMPUTER_LAPTOP = 268; // 0x10c - field public static final int COMPUTER_PALM_SIZE_PC_PDA = 276; // 0x114 - field public static final int COMPUTER_SERVER = 264; // 0x108 - field public static final int COMPUTER_UNCATEGORIZED = 256; // 0x100 - field public static final int COMPUTER_WEARABLE = 280; // 0x118 - field public static final int HEALTH_BLOOD_PRESSURE = 2308; // 0x904 - field public static final int HEALTH_DATA_DISPLAY = 2332; // 0x91c - field public static final int HEALTH_GLUCOSE = 2320; // 0x910 - field public static final int HEALTH_PULSE_OXIMETER = 2324; // 0x914 - field public static final int HEALTH_PULSE_RATE = 2328; // 0x918 - field public static final int HEALTH_THERMOMETER = 2312; // 0x908 - field public static final int HEALTH_UNCATEGORIZED = 2304; // 0x900 - field public static final int HEALTH_WEIGHING = 2316; // 0x90c - field public static final int PHONE_CELLULAR = 516; // 0x204 - field public static final int PHONE_CORDLESS = 520; // 0x208 - field public static final int PHONE_ISDN = 532; // 0x214 - field public static final int PHONE_MODEM_OR_GATEWAY = 528; // 0x210 - field public static final int PHONE_SMART = 524; // 0x20c - field public static final int PHONE_UNCATEGORIZED = 512; // 0x200 - field public static final int TOY_CONTROLLER = 2064; // 0x810 - field public static final int TOY_DOLL_ACTION_FIGURE = 2060; // 0x80c - field public static final int TOY_GAME = 2068; // 0x814 - field public static final int TOY_ROBOT = 2052; // 0x804 - field public static final int TOY_UNCATEGORIZED = 2048; // 0x800 - field public static final int TOY_VEHICLE = 2056; // 0x808 - field public static final int WEARABLE_GLASSES = 1812; // 0x714 - field public static final int WEARABLE_HELMET = 1808; // 0x710 - field public static final int WEARABLE_JACKET = 1804; // 0x70c - field public static final int WEARABLE_PAGER = 1800; // 0x708 - field public static final int WEARABLE_UNCATEGORIZED = 1792; // 0x700 - field public static final int WEARABLE_WRIST_WATCH = 1796; // 0x704 - } - - public static class BluetoothClass.Device.Major { - ctor public BluetoothClass.Device.Major(); - field public static final int AUDIO_VIDEO = 1024; // 0x400 - field public static final int COMPUTER = 256; // 0x100 - field public static final int HEALTH = 2304; // 0x900 - field public static final int IMAGING = 1536; // 0x600 - field public static final int MISC = 0; // 0x0 - field public static final int NETWORKING = 768; // 0x300 - field public static final int PERIPHERAL = 1280; // 0x500 - field public static final int PHONE = 512; // 0x200 - field public static final int TOY = 2048; // 0x800 - field public static final int UNCATEGORIZED = 7936; // 0x1f00 - field public static final int WEARABLE = 1792; // 0x700 - } - - public static final class BluetoothClass.Service { - ctor public BluetoothClass.Service(); - field public static final int AUDIO = 2097152; // 0x200000 - field public static final int CAPTURE = 524288; // 0x80000 - field public static final int INFORMATION = 8388608; // 0x800000 - field public static final int LE_AUDIO = 16384; // 0x4000 - field public static final int LIMITED_DISCOVERABILITY = 8192; // 0x2000 - field public static final int NETWORKING = 131072; // 0x20000 - field public static final int OBJECT_TRANSFER = 1048576; // 0x100000 - field public static final int POSITIONING = 65536; // 0x10000 - field public static final int RENDER = 262144; // 0x40000 - field public static final int TELEPHONY = 4194304; // 0x400000 - } - - public final class BluetoothCodecConfig implements android.os.Parcelable { - ctor public BluetoothCodecConfig(int); - method public int describeContents(); - method public int getBitsPerSample(); - method public int getChannelMode(); - method public int getCodecPriority(); - method public long getCodecSpecific1(); - method public long getCodecSpecific2(); - method public long getCodecSpecific3(); - method public long getCodecSpecific4(); - method public int getCodecType(); - method public static int getMaxCodecType(); - method public int getSampleRate(); - method public void writeToParcel(android.os.Parcel, int); - field public static final int BITS_PER_SAMPLE_16 = 1; // 0x1 - field public static final int BITS_PER_SAMPLE_24 = 2; // 0x2 - field public static final int BITS_PER_SAMPLE_32 = 4; // 0x4 - field public static final int BITS_PER_SAMPLE_NONE = 0; // 0x0 - field public static final int CHANNEL_MODE_MONO = 1; // 0x1 - field public static final int CHANNEL_MODE_NONE = 0; // 0x0 - field public static final int CHANNEL_MODE_STEREO = 2; // 0x2 - field public static final int CODEC_PRIORITY_DEFAULT = 0; // 0x0 - field public static final int CODEC_PRIORITY_DISABLED = -1; // 0xffffffff - field public static final int CODEC_PRIORITY_HIGHEST = 1000000; // 0xf4240 - field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothCodecConfig> CREATOR; - field public static final int SAMPLE_RATE_176400 = 16; // 0x10 - field public static final int SAMPLE_RATE_192000 = 32; // 0x20 - field public static final int SAMPLE_RATE_44100 = 1; // 0x1 - field public static final int SAMPLE_RATE_48000 = 2; // 0x2 - field public static final int SAMPLE_RATE_88200 = 4; // 0x4 - field public static final int SAMPLE_RATE_96000 = 8; // 0x8 - field public static final int SAMPLE_RATE_NONE = 0; // 0x0 - field public static final int SOURCE_CODEC_TYPE_AAC = 1; // 0x1 - field public static final int SOURCE_CODEC_TYPE_APTX = 2; // 0x2 - field public static final int SOURCE_CODEC_TYPE_APTX_HD = 3; // 0x3 - field public static final int SOURCE_CODEC_TYPE_INVALID = 1000000; // 0xf4240 - field public static final int SOURCE_CODEC_TYPE_LC3 = 5; // 0x5 - field public static final int SOURCE_CODEC_TYPE_LDAC = 4; // 0x4 - field public static final int SOURCE_CODEC_TYPE_SBC = 0; // 0x0 - } - - public static final class BluetoothCodecConfig.Builder { - ctor public BluetoothCodecConfig.Builder(); - method @NonNull public android.bluetooth.BluetoothCodecConfig build(); - method @NonNull public android.bluetooth.BluetoothCodecConfig.Builder setBitsPerSample(int); - method @NonNull public android.bluetooth.BluetoothCodecConfig.Builder setChannelMode(int); - method @NonNull public android.bluetooth.BluetoothCodecConfig.Builder setCodecPriority(int); - method @NonNull public android.bluetooth.BluetoothCodecConfig.Builder setCodecSpecific1(long); - method @NonNull public android.bluetooth.BluetoothCodecConfig.Builder setCodecSpecific2(long); - method @NonNull public android.bluetooth.BluetoothCodecConfig.Builder setCodecSpecific3(long); - method @NonNull public android.bluetooth.BluetoothCodecConfig.Builder setCodecSpecific4(long); - method @NonNull public android.bluetooth.BluetoothCodecConfig.Builder setCodecType(int); - method @NonNull public android.bluetooth.BluetoothCodecConfig.Builder setSampleRate(int); - } - - public final class BluetoothCodecStatus implements android.os.Parcelable { - ctor public BluetoothCodecStatus(@Nullable android.bluetooth.BluetoothCodecConfig, @Nullable java.util.List<android.bluetooth.BluetoothCodecConfig>, @Nullable java.util.List<android.bluetooth.BluetoothCodecConfig>); - method public int describeContents(); - method @Nullable public android.bluetooth.BluetoothCodecConfig getCodecConfig(); - method @NonNull public java.util.List<android.bluetooth.BluetoothCodecConfig> getCodecsLocalCapabilities(); - method @NonNull public java.util.List<android.bluetooth.BluetoothCodecConfig> getCodecsSelectableCapabilities(); - method public boolean isCodecConfigSelectable(@Nullable android.bluetooth.BluetoothCodecConfig); - method public void writeToParcel(@NonNull android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothCodecStatus> CREATOR; - field public static final String EXTRA_CODEC_STATUS = "android.bluetooth.extra.CODEC_STATUS"; - } - - public final class BluetoothCsipSetCoordinator implements java.lang.AutoCloseable android.bluetooth.BluetoothProfile { - method public void close(); - method protected void finalize(); - method @NonNull public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices(); - method public int getConnectionState(@Nullable android.bluetooth.BluetoothDevice); - method @NonNull public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(@NonNull int[]); - field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CSIS_CONNECTION_STATE_CHANGED = "android.bluetooth.action.CSIS_CONNECTION_STATE_CHANGED"; - } - - public final class BluetoothDevice implements android.os.Parcelable { - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int, int); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int, int, android.os.Handler); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean createBond(); - method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothSocket createInsecureL2capChannel(int) throws java.io.IOException; - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothSocket createInsecureRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException; - method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothSocket createL2capChannel(int) throws java.io.IOException; - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothSocket createRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException; - method public int describeContents(); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean fetchUuidsWithSdp(); - method public String getAddress(); - method @Nullable @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public String getAlias(); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothClass getBluetoothClass(); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getBondState(); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public String getName(); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getType(); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.os.ParcelUuid[] getUuids(); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int setAlias(@Nullable String); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setPairingConfirmation(boolean); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean setPin(byte[]); - method public void writeToParcel(android.os.Parcel, int); - field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_ACL_CONNECTED = "android.bluetooth.device.action.ACL_CONNECTED"; - field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_ACL_DISCONNECTED = "android.bluetooth.device.action.ACL_DISCONNECTED"; - field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_ACL_DISCONNECT_REQUESTED = "android.bluetooth.device.action.ACL_DISCONNECT_REQUESTED"; - field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_ALIAS_CHANGED = "android.bluetooth.device.action.ALIAS_CHANGED"; - field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_BOND_STATE_CHANGED = "android.bluetooth.device.action.BOND_STATE_CHANGED"; - field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CLASS_CHANGED = "android.bluetooth.device.action.CLASS_CHANGED"; - field @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public static final String ACTION_FOUND = "android.bluetooth.device.action.FOUND"; - field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_NAME_CHANGED = "android.bluetooth.device.action.NAME_CHANGED"; - field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_PAIRING_REQUEST = "android.bluetooth.device.action.PAIRING_REQUEST"; - field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_UUID = "android.bluetooth.device.action.UUID"; - field public static final int ADDRESS_TYPE_PUBLIC = 0; // 0x0 - field public static final int ADDRESS_TYPE_RANDOM = 1; // 0x1 - field public static final int BOND_BONDED = 12; // 0xc - field public static final int BOND_BONDING = 11; // 0xb - field public static final int BOND_NONE = 10; // 0xa - field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothDevice> CREATOR; - field public static final int DEVICE_TYPE_CLASSIC = 1; // 0x1 - field public static final int DEVICE_TYPE_DUAL = 3; // 0x3 - field public static final int DEVICE_TYPE_LE = 2; // 0x2 - field public static final int DEVICE_TYPE_UNKNOWN = 0; // 0x0 - field public static final int ERROR = -2147483648; // 0x80000000 - field public static final String EXTRA_BOND_STATE = "android.bluetooth.device.extra.BOND_STATE"; - field public static final String EXTRA_CLASS = "android.bluetooth.device.extra.CLASS"; - field public static final String EXTRA_DEVICE = "android.bluetooth.device.extra.DEVICE"; - field public static final String EXTRA_IS_COORDINATED_SET_MEMBER = "android.bluetooth.extra.IS_COORDINATED_SET_MEMBER"; - field public static final String EXTRA_NAME = "android.bluetooth.device.extra.NAME"; - field public static final String EXTRA_PAIRING_KEY = "android.bluetooth.device.extra.PAIRING_KEY"; - field public static final String EXTRA_PAIRING_VARIANT = "android.bluetooth.device.extra.PAIRING_VARIANT"; - field public static final String EXTRA_PREVIOUS_BOND_STATE = "android.bluetooth.device.extra.PREVIOUS_BOND_STATE"; - field public static final String EXTRA_RSSI = "android.bluetooth.device.extra.RSSI"; - field public static final String EXTRA_UUID = "android.bluetooth.device.extra.UUID"; - field public static final int PAIRING_VARIANT_PASSKEY_CONFIRMATION = 2; // 0x2 - field public static final int PAIRING_VARIANT_PIN = 0; // 0x0 - field public static final int PHY_LE_1M = 1; // 0x1 - field public static final int PHY_LE_1M_MASK = 1; // 0x1 - field public static final int PHY_LE_2M = 2; // 0x2 - field public static final int PHY_LE_2M_MASK = 2; // 0x2 - field public static final int PHY_LE_CODED = 3; // 0x3 - field public static final int PHY_LE_CODED_MASK = 4; // 0x4 - field public static final int PHY_OPTION_NO_PREFERRED = 0; // 0x0 - field public static final int PHY_OPTION_S2 = 1; // 0x1 - field public static final int PHY_OPTION_S8 = 2; // 0x2 - field public static final int TRANSPORT_AUTO = 0; // 0x0 - field public static final int TRANSPORT_BREDR = 1; // 0x1 - field public static final int TRANSPORT_LE = 2; // 0x2 - } - - public final class BluetoothGatt implements android.bluetooth.BluetoothProfile { - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void abortReliableWrite(); - method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void abortReliableWrite(android.bluetooth.BluetoothDevice); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean beginReliableWrite(); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void close(); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean connect(); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void disconnect(); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean discoverServices(); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean executeReliableWrite(); - method @Deprecated public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices(); - method @Deprecated public int getConnectionState(android.bluetooth.BluetoothDevice); - method public android.bluetooth.BluetoothDevice getDevice(); - method @Deprecated public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]); - method public android.bluetooth.BluetoothGattService getService(java.util.UUID); - method public java.util.List<android.bluetooth.BluetoothGattService> getServices(); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean readCharacteristic(android.bluetooth.BluetoothGattCharacteristic); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean readDescriptor(android.bluetooth.BluetoothGattDescriptor); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void readPhy(); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean readRemoteRssi(); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean requestConnectionPriority(int); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean requestMtu(int); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean setCharacteristicNotification(android.bluetooth.BluetoothGattCharacteristic, boolean); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void setPreferredPhy(int, int, int); - method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean writeCharacteristic(android.bluetooth.BluetoothGattCharacteristic); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int writeCharacteristic(@NonNull android.bluetooth.BluetoothGattCharacteristic, @NonNull byte[], int); - method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean writeDescriptor(android.bluetooth.BluetoothGattDescriptor); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int writeDescriptor(@NonNull android.bluetooth.BluetoothGattDescriptor, @NonNull byte[]); - field public static final int CONNECTION_PRIORITY_BALANCED = 0; // 0x0 - field public static final int CONNECTION_PRIORITY_HIGH = 1; // 0x1 - field public static final int CONNECTION_PRIORITY_LOW_POWER = 2; // 0x2 - field public static final int GATT_CONNECTION_CONGESTED = 143; // 0x8f - field public static final int GATT_FAILURE = 257; // 0x101 - field public static final int GATT_INSUFFICIENT_AUTHENTICATION = 5; // 0x5 - field public static final int GATT_INSUFFICIENT_AUTHORIZATION = 8; // 0x8 - field public static final int GATT_INSUFFICIENT_ENCRYPTION = 15; // 0xf - field public static final int GATT_INVALID_ATTRIBUTE_LENGTH = 13; // 0xd - field public static final int GATT_INVALID_OFFSET = 7; // 0x7 - field public static final int GATT_READ_NOT_PERMITTED = 2; // 0x2 - field public static final int GATT_REQUEST_NOT_SUPPORTED = 6; // 0x6 - field public static final int GATT_SUCCESS = 0; // 0x0 - field public static final int GATT_WRITE_NOT_PERMITTED = 3; // 0x3 - } - - public abstract class BluetoothGattCallback { - ctor public BluetoothGattCallback(); - method @Deprecated public void onCharacteristicChanged(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic); - method public void onCharacteristicChanged(@NonNull android.bluetooth.BluetoothGatt, @NonNull android.bluetooth.BluetoothGattCharacteristic, @NonNull byte[]); - method @Deprecated public void onCharacteristicRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int); - method public void onCharacteristicRead(@NonNull android.bluetooth.BluetoothGatt, @NonNull android.bluetooth.BluetoothGattCharacteristic, @NonNull byte[], int); - method public void onCharacteristicWrite(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int); - method public void onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int); - method @Deprecated public void onDescriptorRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattDescriptor, int); - method public void onDescriptorRead(@NonNull android.bluetooth.BluetoothGatt, @NonNull android.bluetooth.BluetoothGattDescriptor, int, @NonNull byte[]); - method public void onDescriptorWrite(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattDescriptor, int); - method public void onMtuChanged(android.bluetooth.BluetoothGatt, int, int); - method public void onPhyRead(android.bluetooth.BluetoothGatt, int, int, int); - method public void onPhyUpdate(android.bluetooth.BluetoothGatt, int, int, int); - method public void onReadRemoteRssi(android.bluetooth.BluetoothGatt, int, int); - method public void onReliableWriteCompleted(android.bluetooth.BluetoothGatt, int); - method public void onServiceChanged(@NonNull android.bluetooth.BluetoothGatt); - method public void onServicesDiscovered(android.bluetooth.BluetoothGatt, int); - } - - public class BluetoothGattCharacteristic implements android.os.Parcelable { - ctor public BluetoothGattCharacteristic(java.util.UUID, int, int); - method public boolean addDescriptor(android.bluetooth.BluetoothGattDescriptor); - method public int describeContents(); - method public android.bluetooth.BluetoothGattDescriptor getDescriptor(java.util.UUID); - method public java.util.List<android.bluetooth.BluetoothGattDescriptor> getDescriptors(); - method @Deprecated public Float getFloatValue(int, int); - method public int getInstanceId(); - method @Deprecated public Integer getIntValue(int, int); - method public int getPermissions(); - method public int getProperties(); - method public android.bluetooth.BluetoothGattService getService(); - method @Deprecated public String getStringValue(int); - method public java.util.UUID getUuid(); - method @Deprecated public byte[] getValue(); - method public int getWriteType(); - method @Deprecated public boolean setValue(byte[]); - method @Deprecated public boolean setValue(int, int, int); - method @Deprecated public boolean setValue(int, int, int, int); - method @Deprecated public boolean setValue(String); - method public void setWriteType(int); - method public void writeToParcel(android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothGattCharacteristic> CREATOR; - field public static final int FORMAT_FLOAT = 52; // 0x34 - field public static final int FORMAT_SFLOAT = 50; // 0x32 - field public static final int FORMAT_SINT16 = 34; // 0x22 - field public static final int FORMAT_SINT32 = 36; // 0x24 - field public static final int FORMAT_SINT8 = 33; // 0x21 - field public static final int FORMAT_UINT16 = 18; // 0x12 - field public static final int FORMAT_UINT32 = 20; // 0x14 - field public static final int FORMAT_UINT8 = 17; // 0x11 - field public static final int PERMISSION_READ = 1; // 0x1 - field public static final int PERMISSION_READ_ENCRYPTED = 2; // 0x2 - field public static final int PERMISSION_READ_ENCRYPTED_MITM = 4; // 0x4 - field public static final int PERMISSION_WRITE = 16; // 0x10 - field public static final int PERMISSION_WRITE_ENCRYPTED = 32; // 0x20 - field public static final int PERMISSION_WRITE_ENCRYPTED_MITM = 64; // 0x40 - field public static final int PERMISSION_WRITE_SIGNED = 128; // 0x80 - field public static final int PERMISSION_WRITE_SIGNED_MITM = 256; // 0x100 - field public static final int PROPERTY_BROADCAST = 1; // 0x1 - field public static final int PROPERTY_EXTENDED_PROPS = 128; // 0x80 - field public static final int PROPERTY_INDICATE = 32; // 0x20 - field public static final int PROPERTY_NOTIFY = 16; // 0x10 - field public static final int PROPERTY_READ = 2; // 0x2 - field public static final int PROPERTY_SIGNED_WRITE = 64; // 0x40 - field public static final int PROPERTY_WRITE = 8; // 0x8 - field public static final int PROPERTY_WRITE_NO_RESPONSE = 4; // 0x4 - field public static final int WRITE_TYPE_DEFAULT = 2; // 0x2 - field public static final int WRITE_TYPE_NO_RESPONSE = 1; // 0x1 - field public static final int WRITE_TYPE_SIGNED = 4; // 0x4 - field protected java.util.List<android.bluetooth.BluetoothGattDescriptor> mDescriptors; - } - - public class BluetoothGattDescriptor implements android.os.Parcelable { - ctor public BluetoothGattDescriptor(java.util.UUID, int); - method public int describeContents(); - method public android.bluetooth.BluetoothGattCharacteristic getCharacteristic(); - method public int getPermissions(); - method public java.util.UUID getUuid(); - method @Deprecated public byte[] getValue(); - method @Deprecated public boolean setValue(byte[]); - method public void writeToParcel(android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothGattDescriptor> CREATOR; - field public static final byte[] DISABLE_NOTIFICATION_VALUE; - field public static final byte[] ENABLE_INDICATION_VALUE; - field public static final byte[] ENABLE_NOTIFICATION_VALUE; - field public static final int PERMISSION_READ = 1; // 0x1 - field public static final int PERMISSION_READ_ENCRYPTED = 2; // 0x2 - field public static final int PERMISSION_READ_ENCRYPTED_MITM = 4; // 0x4 - field public static final int PERMISSION_WRITE = 16; // 0x10 - field public static final int PERMISSION_WRITE_ENCRYPTED = 32; // 0x20 - field public static final int PERMISSION_WRITE_ENCRYPTED_MITM = 64; // 0x40 - field public static final int PERMISSION_WRITE_SIGNED = 128; // 0x80 - field public static final int PERMISSION_WRITE_SIGNED_MITM = 256; // 0x100 - } - - public final class BluetoothGattServer implements android.bluetooth.BluetoothProfile { - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean addService(android.bluetooth.BluetoothGattService); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void cancelConnection(android.bluetooth.BluetoothDevice); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void clearServices(); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void close(); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean connect(android.bluetooth.BluetoothDevice, boolean); - method public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices(); - method public int getConnectionState(android.bluetooth.BluetoothDevice); - method public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]); - method public android.bluetooth.BluetoothGattService getService(java.util.UUID); - method public java.util.List<android.bluetooth.BluetoothGattService> getServices(); - method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean notifyCharacteristicChanged(android.bluetooth.BluetoothDevice, android.bluetooth.BluetoothGattCharacteristic, boolean); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int notifyCharacteristicChanged(@NonNull android.bluetooth.BluetoothDevice, @NonNull android.bluetooth.BluetoothGattCharacteristic, boolean, @NonNull byte[]); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void readPhy(android.bluetooth.BluetoothDevice); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean removeService(android.bluetooth.BluetoothGattService); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean sendResponse(android.bluetooth.BluetoothDevice, int, int, int, byte[]); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void setPreferredPhy(android.bluetooth.BluetoothDevice, int, int, int); - } - - public abstract class BluetoothGattServerCallback { - ctor public BluetoothGattServerCallback(); - method public void onCharacteristicReadRequest(android.bluetooth.BluetoothDevice, int, int, android.bluetooth.BluetoothGattCharacteristic); - method public void onCharacteristicWriteRequest(android.bluetooth.BluetoothDevice, int, android.bluetooth.BluetoothGattCharacteristic, boolean, boolean, int, byte[]); - method public void onConnectionStateChange(android.bluetooth.BluetoothDevice, int, int); - method public void onDescriptorReadRequest(android.bluetooth.BluetoothDevice, int, int, android.bluetooth.BluetoothGattDescriptor); - method public void onDescriptorWriteRequest(android.bluetooth.BluetoothDevice, int, android.bluetooth.BluetoothGattDescriptor, boolean, boolean, int, byte[]); - method public void onExecuteWrite(android.bluetooth.BluetoothDevice, int, boolean); - method public void onMtuChanged(android.bluetooth.BluetoothDevice, int); - method public void onNotificationSent(android.bluetooth.BluetoothDevice, int); - method public void onPhyRead(android.bluetooth.BluetoothDevice, int, int, int); - method public void onPhyUpdate(android.bluetooth.BluetoothDevice, int, int, int); - method public void onServiceAdded(int, android.bluetooth.BluetoothGattService); - } - - public class BluetoothGattService implements android.os.Parcelable { - ctor public BluetoothGattService(java.util.UUID, int); - method public boolean addCharacteristic(android.bluetooth.BluetoothGattCharacteristic); - method public boolean addService(android.bluetooth.BluetoothGattService); - method public int describeContents(); - method public android.bluetooth.BluetoothGattCharacteristic getCharacteristic(java.util.UUID); - method public java.util.List<android.bluetooth.BluetoothGattCharacteristic> getCharacteristics(); - method public java.util.List<android.bluetooth.BluetoothGattService> getIncludedServices(); - method public int getInstanceId(); - method public int getType(); - method public java.util.UUID getUuid(); - method public void writeToParcel(android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothGattService> CREATOR; - field public static final int SERVICE_TYPE_PRIMARY = 0; // 0x0 - field public static final int SERVICE_TYPE_SECONDARY = 1; // 0x1 - field protected java.util.List<android.bluetooth.BluetoothGattCharacteristic> mCharacteristics; - field protected java.util.List<android.bluetooth.BluetoothGattService> mIncludedServices; - } - - public final class BluetoothHeadset implements android.bluetooth.BluetoothProfile { - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices(); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getConnectionState(android.bluetooth.BluetoothDevice); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean isAudioConnected(android.bluetooth.BluetoothDevice); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean isNoiseReductionSupported(@NonNull android.bluetooth.BluetoothDevice); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean isVoiceRecognitionSupported(@NonNull android.bluetooth.BluetoothDevice); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean sendVendorSpecificResultCode(android.bluetooth.BluetoothDevice, String, String); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean startVoiceRecognition(android.bluetooth.BluetoothDevice); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean stopVoiceRecognition(android.bluetooth.BluetoothDevice); - field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_AUDIO_STATE_CHANGED = "android.bluetooth.headset.profile.action.AUDIO_STATE_CHANGED"; - field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.headset.profile.action.CONNECTION_STATE_CHANGED"; - field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_VENDOR_SPECIFIC_HEADSET_EVENT = "android.bluetooth.headset.action.VENDOR_SPECIFIC_HEADSET_EVENT"; - field public static final int AT_CMD_TYPE_ACTION = 4; // 0x4 - field public static final int AT_CMD_TYPE_BASIC = 3; // 0x3 - field public static final int AT_CMD_TYPE_READ = 0; // 0x0 - field public static final int AT_CMD_TYPE_SET = 2; // 0x2 - field public static final int AT_CMD_TYPE_TEST = 1; // 0x1 - field public static final String EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_ARGS = "android.bluetooth.headset.extra.VENDOR_SPECIFIC_HEADSET_EVENT_ARGS"; - field public static final String EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD = "android.bluetooth.headset.extra.VENDOR_SPECIFIC_HEADSET_EVENT_CMD"; - field public static final String EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE = "android.bluetooth.headset.extra.VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE"; - field public static final int STATE_AUDIO_CONNECTED = 12; // 0xc - field public static final int STATE_AUDIO_CONNECTING = 11; // 0xb - field public static final int STATE_AUDIO_DISCONNECTED = 10; // 0xa - field public static final String VENDOR_RESULT_CODE_COMMAND_ANDROID = "+ANDROID"; - field public static final String VENDOR_SPECIFIC_HEADSET_EVENT_COMPANY_ID_CATEGORY = "android.bluetooth.headset.intent.category.companyid"; - } - - @Deprecated public final class BluetoothHealth implements android.bluetooth.BluetoothProfile { - method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean connectChannelToSource(android.bluetooth.BluetoothDevice, android.bluetooth.BluetoothHealthAppConfiguration); - method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean disconnectChannel(android.bluetooth.BluetoothDevice, android.bluetooth.BluetoothHealthAppConfiguration, int); - method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices(); - method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getConnectionState(android.bluetooth.BluetoothDevice); - method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]); - method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.os.ParcelFileDescriptor getMainChannelFd(android.bluetooth.BluetoothDevice, android.bluetooth.BluetoothHealthAppConfiguration); - method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean registerSinkAppConfiguration(String, int, android.bluetooth.BluetoothHealthCallback); - method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean unregisterAppConfiguration(android.bluetooth.BluetoothHealthAppConfiguration); - field @Deprecated public static final int APP_CONFIG_REGISTRATION_FAILURE = 1; // 0x1 - field @Deprecated public static final int APP_CONFIG_REGISTRATION_SUCCESS = 0; // 0x0 - field @Deprecated public static final int APP_CONFIG_UNREGISTRATION_FAILURE = 3; // 0x3 - field @Deprecated public static final int APP_CONFIG_UNREGISTRATION_SUCCESS = 2; // 0x2 - field @Deprecated public static final int CHANNEL_TYPE_RELIABLE = 10; // 0xa - field @Deprecated public static final int CHANNEL_TYPE_STREAMING = 11; // 0xb - field @Deprecated public static final int SINK_ROLE = 2; // 0x2 - field @Deprecated public static final int SOURCE_ROLE = 1; // 0x1 - field @Deprecated public static final int STATE_CHANNEL_CONNECTED = 2; // 0x2 - field @Deprecated public static final int STATE_CHANNEL_CONNECTING = 1; // 0x1 - field @Deprecated public static final int STATE_CHANNEL_DISCONNECTED = 0; // 0x0 - field @Deprecated public static final int STATE_CHANNEL_DISCONNECTING = 3; // 0x3 - } - - @Deprecated public final class BluetoothHealthAppConfiguration implements android.os.Parcelable { - method @Deprecated public int describeContents(); - method @Deprecated public int getDataType(); - method @Deprecated public String getName(); - method @Deprecated public int getRole(); - method @Deprecated public void writeToParcel(android.os.Parcel, int); - field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothHealthAppConfiguration> CREATOR; - } - - @Deprecated public abstract class BluetoothHealthCallback { - ctor @Deprecated public BluetoothHealthCallback(); - method @Deprecated @BinderThread public void onHealthAppConfigurationStatusChange(android.bluetooth.BluetoothHealthAppConfiguration, int); - method @Deprecated @BinderThread public void onHealthChannelStateChange(android.bluetooth.BluetoothHealthAppConfiguration, android.bluetooth.BluetoothDevice, int, int, android.os.ParcelFileDescriptor, int); - } - - public final class BluetoothHearingAid implements android.bluetooth.BluetoothProfile { - method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices(); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getConnectionState(@NonNull android.bluetooth.BluetoothDevice); - method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(@NonNull int[]); - field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.hearingaid.profile.action.CONNECTION_STATE_CHANGED"; - } - - public final class BluetoothHidDevice implements android.bluetooth.BluetoothProfile { - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean connect(android.bluetooth.BluetoothDevice); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean disconnect(android.bluetooth.BluetoothDevice); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices(); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getConnectionState(android.bluetooth.BluetoothDevice); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean registerApp(android.bluetooth.BluetoothHidDeviceAppSdpSettings, android.bluetooth.BluetoothHidDeviceAppQosSettings, android.bluetooth.BluetoothHidDeviceAppQosSettings, java.util.concurrent.Executor, android.bluetooth.BluetoothHidDevice.Callback); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean replyReport(android.bluetooth.BluetoothDevice, byte, byte, byte[]); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean reportError(android.bluetooth.BluetoothDevice, byte); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean sendReport(android.bluetooth.BluetoothDevice, int, byte[]); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean unregisterApp(); - field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.hiddevice.profile.action.CONNECTION_STATE_CHANGED"; - field public static final byte ERROR_RSP_INVALID_PARAM = 4; // 0x4 - field public static final byte ERROR_RSP_INVALID_RPT_ID = 2; // 0x2 - field public static final byte ERROR_RSP_NOT_READY = 1; // 0x1 - field public static final byte ERROR_RSP_SUCCESS = 0; // 0x0 - field public static final byte ERROR_RSP_UNKNOWN = 14; // 0xe - field public static final byte ERROR_RSP_UNSUPPORTED_REQ = 3; // 0x3 - field public static final byte PROTOCOL_BOOT_MODE = 0; // 0x0 - field public static final byte PROTOCOL_REPORT_MODE = 1; // 0x1 - field public static final byte REPORT_TYPE_FEATURE = 3; // 0x3 - field public static final byte REPORT_TYPE_INPUT = 1; // 0x1 - field public static final byte REPORT_TYPE_OUTPUT = 2; // 0x2 - field public static final byte SUBCLASS1_COMBO = -64; // 0xffffffc0 - field public static final byte SUBCLASS1_KEYBOARD = 64; // 0x40 - field public static final byte SUBCLASS1_MOUSE = -128; // 0xffffff80 - field public static final byte SUBCLASS1_NONE = 0; // 0x0 - field public static final byte SUBCLASS2_CARD_READER = 6; // 0x6 - field public static final byte SUBCLASS2_DIGITIZER_TABLET = 5; // 0x5 - field public static final byte SUBCLASS2_GAMEPAD = 2; // 0x2 - field public static final byte SUBCLASS2_JOYSTICK = 1; // 0x1 - field public static final byte SUBCLASS2_REMOTE_CONTROL = 3; // 0x3 - field public static final byte SUBCLASS2_SENSING_DEVICE = 4; // 0x4 - field public static final byte SUBCLASS2_UNCATEGORIZED = 0; // 0x0 - } - - public abstract static class BluetoothHidDevice.Callback { - ctor public BluetoothHidDevice.Callback(); - method public void onAppStatusChanged(android.bluetooth.BluetoothDevice, boolean); - method public void onConnectionStateChanged(android.bluetooth.BluetoothDevice, int); - method public void onGetReport(android.bluetooth.BluetoothDevice, byte, byte, int); - method public void onInterruptData(android.bluetooth.BluetoothDevice, byte, byte[]); - method public void onSetProtocol(android.bluetooth.BluetoothDevice, byte); - method public void onSetReport(android.bluetooth.BluetoothDevice, byte, byte, byte[]); - method public void onVirtualCableUnplug(android.bluetooth.BluetoothDevice); - } - - public final class BluetoothHidDeviceAppQosSettings implements android.os.Parcelable { - ctor public BluetoothHidDeviceAppQosSettings(int, int, int, int, int, int); - method public int describeContents(); - method public int getDelayVariation(); - method public int getLatency(); - method public int getPeakBandwidth(); - method public int getServiceType(); - method public int getTokenBucketSize(); - method public int getTokenRate(); - method public void writeToParcel(android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothHidDeviceAppQosSettings> CREATOR; - field public static final int MAX = -1; // 0xffffffff - field public static final int SERVICE_BEST_EFFORT = 1; // 0x1 - field public static final int SERVICE_GUARANTEED = 2; // 0x2 - field public static final int SERVICE_NO_TRAFFIC = 0; // 0x0 - } - - public final class BluetoothHidDeviceAppSdpSettings implements android.os.Parcelable { - ctor public BluetoothHidDeviceAppSdpSettings(String, String, String, byte, byte[]); - method public int describeContents(); - method public String getDescription(); - method public byte[] getDescriptors(); - method public String getName(); - method public String getProvider(); - method public byte getSubclass(); - method public void writeToParcel(android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothHidDeviceAppSdpSettings> CREATOR; - } - - public final class BluetoothLeAudio implements java.lang.AutoCloseable android.bluetooth.BluetoothProfile { - method public void close(); - method protected void finalize(); - method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices(); - method @Nullable @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothDevice getConnectedGroupLeadDevice(int); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getConnectionState(@NonNull android.bluetooth.BluetoothDevice); - method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(@NonNull int[]); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getGroupId(@NonNull android.bluetooth.BluetoothDevice); - field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED = "android.bluetooth.action.LE_AUDIO_CONNECTION_STATE_CHANGED"; - } - - public final class BluetoothLeAudioCodecConfig { - method @NonNull public String getCodecName(); - method public int getCodecType(); - method public static int getMaxCodecType(); - field public static final int SOURCE_CODEC_TYPE_INVALID = 1000000; // 0xf4240 - field public static final int SOURCE_CODEC_TYPE_LC3 = 0; // 0x0 - } - - public static final class BluetoothLeAudioCodecConfig.Builder { - ctor public BluetoothLeAudioCodecConfig.Builder(); - method @NonNull public android.bluetooth.BluetoothLeAudioCodecConfig build(); - method @NonNull public android.bluetooth.BluetoothLeAudioCodecConfig.Builder setCodecType(int); - } - - public final class BluetoothManager { - method public android.bluetooth.BluetoothAdapter getAdapter(); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices(int); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getConnectionState(android.bluetooth.BluetoothDevice, int); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int, int[]); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothGattServer openGattServer(android.content.Context, android.bluetooth.BluetoothGattServerCallback); - } - - public interface BluetoothProfile { - method public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices(); - method public int getConnectionState(android.bluetooth.BluetoothDevice); - method public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]); - field public static final int A2DP = 2; // 0x2 - field public static final int CSIP_SET_COORDINATOR = 25; // 0x19 - field public static final String EXTRA_PREVIOUS_STATE = "android.bluetooth.profile.extra.PREVIOUS_STATE"; - field public static final String EXTRA_STATE = "android.bluetooth.profile.extra.STATE"; - field public static final int GATT = 7; // 0x7 - field public static final int GATT_SERVER = 8; // 0x8 - field public static final int HAP_CLIENT = 28; // 0x1c - field public static final int HEADSET = 1; // 0x1 - field @Deprecated public static final int HEALTH = 3; // 0x3 - field public static final int HEARING_AID = 21; // 0x15 - field public static final int HID_DEVICE = 19; // 0x13 - field public static final int LE_AUDIO = 22; // 0x16 - field public static final int SAP = 10; // 0xa - field public static final int STATE_CONNECTED = 2; // 0x2 - field public static final int STATE_CONNECTING = 1; // 0x1 - field public static final int STATE_DISCONNECTED = 0; // 0x0 - field public static final int STATE_DISCONNECTING = 3; // 0x3 - } - - public static interface BluetoothProfile.ServiceListener { - method public void onServiceConnected(int, android.bluetooth.BluetoothProfile); - method public void onServiceDisconnected(int); - } - - public final class BluetoothServerSocket implements java.io.Closeable { - method public android.bluetooth.BluetoothSocket accept() throws java.io.IOException; - method public android.bluetooth.BluetoothSocket accept(int) throws java.io.IOException; - method public void close() throws java.io.IOException; - method public int getPsm(); - } - - public final class BluetoothSocket implements java.io.Closeable { - method public void close() throws java.io.IOException; - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void connect() throws java.io.IOException; - method public int getConnectionType(); - method public java.io.InputStream getInputStream() throws java.io.IOException; - method public int getMaxReceivePacketSize(); - method public int getMaxTransmitPacketSize(); - method public java.io.OutputStream getOutputStream() throws java.io.IOException; - method public android.bluetooth.BluetoothDevice getRemoteDevice(); - method public boolean isConnected(); - field public static final int TYPE_L2CAP = 3; // 0x3 - field public static final int TYPE_RFCOMM = 1; // 0x1 - field public static final int TYPE_SCO = 2; // 0x2 - } - - public final class BluetoothStatusCodes { - field public static final int ERROR_BLUETOOTH_NOT_ALLOWED = 2; // 0x2 - field public static final int ERROR_BLUETOOTH_NOT_ENABLED = 1; // 0x1 - field public static final int ERROR_DEVICE_NOT_BONDED = 3; // 0x3 - field public static final int ERROR_FEATURE_NOT_SUPPORTED = 10; // 0xa - field public static final int ERROR_GATT_WRITE_NOT_ALLOWED = 101; // 0x65 - field public static final int ERROR_GATT_WRITE_REQUEST_BUSY = 102; // 0x66 - field public static final int ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION = 6; // 0x6 - field public static final int ERROR_MISSING_BLUETOOTH_PRIVILEGED_PERMISSION = 8; // 0x8 - field public static final int ERROR_PROFILE_SERVICE_NOT_BOUND = 9; // 0x9 - field public static final int ERROR_UNKNOWN = 2147483647; // 0x7fffffff - field public static final int SUCCESS = 0; // 0x0 - } - -} - -package android.bluetooth.le { - - public abstract class AdvertiseCallback { - ctor public AdvertiseCallback(); - method public void onStartFailure(int); - method public void onStartSuccess(android.bluetooth.le.AdvertiseSettings); - field public static final int ADVERTISE_FAILED_ALREADY_STARTED = 3; // 0x3 - field public static final int ADVERTISE_FAILED_DATA_TOO_LARGE = 1; // 0x1 - field public static final int ADVERTISE_FAILED_FEATURE_UNSUPPORTED = 5; // 0x5 - field public static final int ADVERTISE_FAILED_INTERNAL_ERROR = 4; // 0x4 - field public static final int ADVERTISE_FAILED_TOO_MANY_ADVERTISERS = 2; // 0x2 - } - - public final class AdvertiseData implements android.os.Parcelable { - method public int describeContents(); - method public boolean getIncludeDeviceName(); - method public boolean getIncludeTxPowerLevel(); - method public android.util.SparseArray<byte[]> getManufacturerSpecificData(); - method public java.util.Map<android.os.ParcelUuid,byte[]> getServiceData(); - method @NonNull public java.util.List<android.os.ParcelUuid> getServiceSolicitationUuids(); - method public java.util.List<android.os.ParcelUuid> getServiceUuids(); - method @NonNull public java.util.List<android.bluetooth.le.TransportDiscoveryData> getTransportDiscoveryData(); - method public void writeToParcel(android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.AdvertiseData> CREATOR; - } - - public static final class AdvertiseData.Builder { - ctor public AdvertiseData.Builder(); - method public android.bluetooth.le.AdvertiseData.Builder addManufacturerData(int, byte[]); - method public android.bluetooth.le.AdvertiseData.Builder addServiceData(android.os.ParcelUuid, byte[]); - method @NonNull public android.bluetooth.le.AdvertiseData.Builder addServiceSolicitationUuid(@NonNull android.os.ParcelUuid); - method public android.bluetooth.le.AdvertiseData.Builder addServiceUuid(android.os.ParcelUuid); - method @NonNull public android.bluetooth.le.AdvertiseData.Builder addTransportDiscoveryData(@NonNull android.bluetooth.le.TransportDiscoveryData); - method public android.bluetooth.le.AdvertiseData build(); - method public android.bluetooth.le.AdvertiseData.Builder setIncludeDeviceName(boolean); - method public android.bluetooth.le.AdvertiseData.Builder setIncludeTxPowerLevel(boolean); - } - - public final class AdvertiseSettings implements android.os.Parcelable { - method public int describeContents(); - method public int getMode(); - method public int getTimeout(); - method public int getTxPowerLevel(); - method public boolean isConnectable(); - method public void writeToParcel(android.os.Parcel, int); - field public static final int ADVERTISE_MODE_BALANCED = 1; // 0x1 - field public static final int ADVERTISE_MODE_LOW_LATENCY = 2; // 0x2 - field public static final int ADVERTISE_MODE_LOW_POWER = 0; // 0x0 - field public static final int ADVERTISE_TX_POWER_HIGH = 3; // 0x3 - field public static final int ADVERTISE_TX_POWER_LOW = 1; // 0x1 - field public static final int ADVERTISE_TX_POWER_MEDIUM = 2; // 0x2 - field public static final int ADVERTISE_TX_POWER_ULTRA_LOW = 0; // 0x0 - field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.AdvertiseSettings> CREATOR; - } - - public static final class AdvertiseSettings.Builder { - ctor public AdvertiseSettings.Builder(); - method public android.bluetooth.le.AdvertiseSettings build(); - method public android.bluetooth.le.AdvertiseSettings.Builder setAdvertiseMode(int); - method public android.bluetooth.le.AdvertiseSettings.Builder setConnectable(boolean); - method public android.bluetooth.le.AdvertiseSettings.Builder setTimeout(int); - method public android.bluetooth.le.AdvertiseSettings.Builder setTxPowerLevel(int); - } - - public final class AdvertisingSet { - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void enableAdvertising(boolean, int, int); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void setAdvertisingData(android.bluetooth.le.AdvertiseData); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void setAdvertisingParameters(android.bluetooth.le.AdvertisingSetParameters); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void setPeriodicAdvertisingData(android.bluetooth.le.AdvertiseData); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void setPeriodicAdvertisingEnabled(boolean); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void setPeriodicAdvertisingParameters(android.bluetooth.le.PeriodicAdvertisingParameters); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void setScanResponseData(android.bluetooth.le.AdvertiseData); - } - - public abstract class AdvertisingSetCallback { - ctor public AdvertisingSetCallback(); - method public void onAdvertisingDataSet(android.bluetooth.le.AdvertisingSet, int); - method public void onAdvertisingEnabled(android.bluetooth.le.AdvertisingSet, boolean, int); - method public void onAdvertisingParametersUpdated(android.bluetooth.le.AdvertisingSet, int, int); - method public void onAdvertisingSetStarted(android.bluetooth.le.AdvertisingSet, int, int); - method public void onAdvertisingSetStopped(android.bluetooth.le.AdvertisingSet); - method public void onPeriodicAdvertisingDataSet(android.bluetooth.le.AdvertisingSet, int); - method public void onPeriodicAdvertisingEnabled(android.bluetooth.le.AdvertisingSet, boolean, int); - method public void onPeriodicAdvertisingParametersUpdated(android.bluetooth.le.AdvertisingSet, int); - method public void onScanResponseDataSet(android.bluetooth.le.AdvertisingSet, int); - field public static final int ADVERTISE_FAILED_ALREADY_STARTED = 3; // 0x3 - field public static final int ADVERTISE_FAILED_DATA_TOO_LARGE = 1; // 0x1 - field public static final int ADVERTISE_FAILED_FEATURE_UNSUPPORTED = 5; // 0x5 - field public static final int ADVERTISE_FAILED_INTERNAL_ERROR = 4; // 0x4 - field public static final int ADVERTISE_FAILED_TOO_MANY_ADVERTISERS = 2; // 0x2 - field public static final int ADVERTISE_SUCCESS = 0; // 0x0 - } - - public final class AdvertisingSetParameters implements android.os.Parcelable { - method public int describeContents(); - method public int getInterval(); - method public int getPrimaryPhy(); - method public int getSecondaryPhy(); - method public int getTxPowerLevel(); - method public boolean includeTxPower(); - method public boolean isAnonymous(); - method public boolean isConnectable(); - method public boolean isLegacy(); - method public boolean isScannable(); - method public void writeToParcel(android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.AdvertisingSetParameters> CREATOR; - field public static final int INTERVAL_HIGH = 1600; // 0x640 - field public static final int INTERVAL_LOW = 160; // 0xa0 - field public static final int INTERVAL_MAX = 16777215; // 0xffffff - field public static final int INTERVAL_MEDIUM = 400; // 0x190 - field public static final int INTERVAL_MIN = 160; // 0xa0 - field public static final int TX_POWER_HIGH = 1; // 0x1 - field public static final int TX_POWER_LOW = -15; // 0xfffffff1 - field public static final int TX_POWER_MAX = 1; // 0x1 - field public static final int TX_POWER_MEDIUM = -7; // 0xfffffff9 - field public static final int TX_POWER_MIN = -127; // 0xffffff81 - field public static final int TX_POWER_ULTRA_LOW = -21; // 0xffffffeb - } - - public static final class AdvertisingSetParameters.Builder { - ctor public AdvertisingSetParameters.Builder(); - method public android.bluetooth.le.AdvertisingSetParameters build(); - method public android.bluetooth.le.AdvertisingSetParameters.Builder setAnonymous(boolean); - method public android.bluetooth.le.AdvertisingSetParameters.Builder setConnectable(boolean); - method public android.bluetooth.le.AdvertisingSetParameters.Builder setIncludeTxPower(boolean); - method public android.bluetooth.le.AdvertisingSetParameters.Builder setInterval(int); - method public android.bluetooth.le.AdvertisingSetParameters.Builder setLegacyMode(boolean); - method public android.bluetooth.le.AdvertisingSetParameters.Builder setPrimaryPhy(int); - method public android.bluetooth.le.AdvertisingSetParameters.Builder setScannable(boolean); - method public android.bluetooth.le.AdvertisingSetParameters.Builder setSecondaryPhy(int); - method public android.bluetooth.le.AdvertisingSetParameters.Builder setTxPowerLevel(int); - } - - public final class BluetoothLeAdvertiser { - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void startAdvertising(android.bluetooth.le.AdvertiseSettings, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseCallback); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void startAdvertising(android.bluetooth.le.AdvertiseSettings, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseCallback); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertisingSetCallback); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertisingSetCallback, android.os.Handler); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, int, int, android.bluetooth.le.AdvertisingSetCallback); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, int, int, android.bluetooth.le.AdvertisingSetCallback, android.os.Handler); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void stopAdvertising(android.bluetooth.le.AdvertiseCallback); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void stopAdvertisingSet(android.bluetooth.le.AdvertisingSetCallback); - } - - public final class BluetoothLeScanner { - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public void flushPendingScanResults(android.bluetooth.le.ScanCallback); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public void startScan(android.bluetooth.le.ScanCallback); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public void startScan(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.bluetooth.le.ScanCallback); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public int startScan(@Nullable java.util.List<android.bluetooth.le.ScanFilter>, @Nullable android.bluetooth.le.ScanSettings, @NonNull android.app.PendingIntent); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public void stopScan(android.bluetooth.le.ScanCallback); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public void stopScan(android.app.PendingIntent); - field public static final String EXTRA_CALLBACK_TYPE = "android.bluetooth.le.extra.CALLBACK_TYPE"; - field public static final String EXTRA_ERROR_CODE = "android.bluetooth.le.extra.ERROR_CODE"; - field public static final String EXTRA_LIST_SCAN_RESULT = "android.bluetooth.le.extra.LIST_SCAN_RESULT"; - } - - public final class PeriodicAdvertisingParameters implements android.os.Parcelable { - method public int describeContents(); - method public boolean getIncludeTxPower(); - method public int getInterval(); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator<android.bluetooth.le.PeriodicAdvertisingParameters> CREATOR; - } - - public static final class PeriodicAdvertisingParameters.Builder { - ctor public PeriodicAdvertisingParameters.Builder(); - method public android.bluetooth.le.PeriodicAdvertisingParameters build(); - method public android.bluetooth.le.PeriodicAdvertisingParameters.Builder setIncludeTxPower(boolean); - method public android.bluetooth.le.PeriodicAdvertisingParameters.Builder setInterval(int); - } - - public abstract class ScanCallback { - ctor public ScanCallback(); - method public void onBatchScanResults(java.util.List<android.bluetooth.le.ScanResult>); - method public void onScanFailed(int); - method public void onScanResult(int, android.bluetooth.le.ScanResult); - field public static final int SCAN_FAILED_ALREADY_STARTED = 1; // 0x1 - field public static final int SCAN_FAILED_APPLICATION_REGISTRATION_FAILED = 2; // 0x2 - field public static final int SCAN_FAILED_FEATURE_UNSUPPORTED = 4; // 0x4 - field public static final int SCAN_FAILED_INTERNAL_ERROR = 3; // 0x3 - } - - public final class ScanFilter implements android.os.Parcelable { - method public int describeContents(); - method @Nullable public String getDeviceAddress(); - method @Nullable public String getDeviceName(); - method @Nullable public byte[] getManufacturerData(); - method @Nullable public byte[] getManufacturerDataMask(); - method public int getManufacturerId(); - method @Nullable public byte[] getServiceData(); - method @Nullable public byte[] getServiceDataMask(); - method @Nullable public android.os.ParcelUuid getServiceDataUuid(); - method @Nullable public android.os.ParcelUuid getServiceSolicitationUuid(); - method @Nullable public android.os.ParcelUuid getServiceSolicitationUuidMask(); - method @Nullable public android.os.ParcelUuid getServiceUuid(); - method @Nullable public android.os.ParcelUuid getServiceUuidMask(); - method public boolean matches(android.bluetooth.le.ScanResult); - method public void writeToParcel(android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.ScanFilter> CREATOR; - } - - public static final class ScanFilter.Builder { - ctor public ScanFilter.Builder(); - method public android.bluetooth.le.ScanFilter build(); - method public android.bluetooth.le.ScanFilter.Builder setDeviceAddress(String); - method public android.bluetooth.le.ScanFilter.Builder setDeviceName(String); - method public android.bluetooth.le.ScanFilter.Builder setManufacturerData(int, byte[]); - method public android.bluetooth.le.ScanFilter.Builder setManufacturerData(int, byte[], byte[]); - method public android.bluetooth.le.ScanFilter.Builder setServiceData(android.os.ParcelUuid, byte[]); - method public android.bluetooth.le.ScanFilter.Builder setServiceData(android.os.ParcelUuid, byte[], byte[]); - method @NonNull public android.bluetooth.le.ScanFilter.Builder setServiceSolicitationUuid(@Nullable android.os.ParcelUuid); - method @NonNull public android.bluetooth.le.ScanFilter.Builder setServiceSolicitationUuid(@Nullable android.os.ParcelUuid, @Nullable android.os.ParcelUuid); - method public android.bluetooth.le.ScanFilter.Builder setServiceUuid(android.os.ParcelUuid); - method public android.bluetooth.le.ScanFilter.Builder setServiceUuid(android.os.ParcelUuid, android.os.ParcelUuid); - } - - public final class ScanRecord { - method public int getAdvertiseFlags(); - method public byte[] getBytes(); - method @Nullable public String getDeviceName(); - method public android.util.SparseArray<byte[]> getManufacturerSpecificData(); - method @Nullable public byte[] getManufacturerSpecificData(int); - method public java.util.Map<android.os.ParcelUuid,byte[]> getServiceData(); - method @Nullable public byte[] getServiceData(android.os.ParcelUuid); - method @NonNull public java.util.List<android.os.ParcelUuid> getServiceSolicitationUuids(); - method public java.util.List<android.os.ParcelUuid> getServiceUuids(); - method public int getTxPowerLevel(); - } - - public final class ScanResult implements android.os.Parcelable { - ctor @Deprecated public ScanResult(android.bluetooth.BluetoothDevice, android.bluetooth.le.ScanRecord, int, long); - ctor public ScanResult(android.bluetooth.BluetoothDevice, int, int, int, int, int, int, int, android.bluetooth.le.ScanRecord, long); - method public int describeContents(); - method public int getAdvertisingSid(); - method public int getDataStatus(); - method public android.bluetooth.BluetoothDevice getDevice(); - method public int getPeriodicAdvertisingInterval(); - method public int getPrimaryPhy(); - method public int getRssi(); - method @Nullable public android.bluetooth.le.ScanRecord getScanRecord(); - method public int getSecondaryPhy(); - method public long getTimestampNanos(); - method public int getTxPower(); - method public boolean isConnectable(); - method public boolean isLegacy(); - method public void writeToParcel(android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.ScanResult> CREATOR; - field public static final int DATA_COMPLETE = 0; // 0x0 - field public static final int DATA_TRUNCATED = 2; // 0x2 - field public static final int PERIODIC_INTERVAL_NOT_PRESENT = 0; // 0x0 - field public static final int PHY_UNUSED = 0; // 0x0 - field public static final int SID_NOT_PRESENT = 255; // 0xff - field public static final int TX_POWER_NOT_PRESENT = 127; // 0x7f - } - - public final class ScanSettings implements android.os.Parcelable { - method public int describeContents(); - method public int getCallbackType(); - method public boolean getLegacy(); - method public int getPhy(); - method public long getReportDelayMillis(); - method public int getScanMode(); - method public int getScanResultType(); - method public void writeToParcel(android.os.Parcel, int); - field public static final int CALLBACK_TYPE_ALL_MATCHES = 1; // 0x1 - field public static final int CALLBACK_TYPE_FIRST_MATCH = 2; // 0x2 - field public static final int CALLBACK_TYPE_MATCH_LOST = 4; // 0x4 - field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.ScanSettings> CREATOR; - field public static final int MATCH_MODE_AGGRESSIVE = 1; // 0x1 - field public static final int MATCH_MODE_STICKY = 2; // 0x2 - field public static final int MATCH_NUM_FEW_ADVERTISEMENT = 2; // 0x2 - field public static final int MATCH_NUM_MAX_ADVERTISEMENT = 3; // 0x3 - field public static final int MATCH_NUM_ONE_ADVERTISEMENT = 1; // 0x1 - field public static final int PHY_LE_ALL_SUPPORTED = 255; // 0xff - field public static final int SCAN_MODE_BALANCED = 1; // 0x1 - field public static final int SCAN_MODE_LOW_LATENCY = 2; // 0x2 - field public static final int SCAN_MODE_LOW_POWER = 0; // 0x0 - field public static final int SCAN_MODE_OPPORTUNISTIC = -1; // 0xffffffff - } - - public static final class ScanSettings.Builder { - ctor public ScanSettings.Builder(); - method public android.bluetooth.le.ScanSettings build(); - method public android.bluetooth.le.ScanSettings.Builder setCallbackType(int); - method public android.bluetooth.le.ScanSettings.Builder setLegacy(boolean); - method public android.bluetooth.le.ScanSettings.Builder setMatchMode(int); - method public android.bluetooth.le.ScanSettings.Builder setNumOfMatches(int); - method public android.bluetooth.le.ScanSettings.Builder setPhy(int); - method public android.bluetooth.le.ScanSettings.Builder setReportDelay(long); - method public android.bluetooth.le.ScanSettings.Builder setScanMode(int); - } - - public final class TransportBlock implements android.os.Parcelable { - ctor public TransportBlock(int, int, int, @Nullable byte[]); - method public int describeContents(); - method public int getOrgId(); - method public int getTdsFlags(); - method @Nullable public byte[] getTransportData(); - method public int getTransportDataLength(); - method @Nullable public byte[] toByteArray(); - method public int totalBytes(); - method public void writeToParcel(@NonNull android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.TransportBlock> CREATOR; - } - - public final class TransportDiscoveryData implements android.os.Parcelable { - ctor public TransportDiscoveryData(int, @NonNull java.util.List<android.bluetooth.le.TransportBlock>); - ctor public TransportDiscoveryData(@NonNull byte[]); - method public int describeContents(); - method @NonNull public java.util.List<android.bluetooth.le.TransportBlock> getTransportBlocks(); - method public int getTransportDataType(); - method @Nullable public byte[] toByteArray(); - method public int totalBytes(); - method public void writeToParcel(@NonNull android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.TransportDiscoveryData> CREATOR; - } - -} - package android.companion { public final class AssociationRequest implements android.os.Parcelable { @@ -20401,6 +19114,7 @@ package android.media { method public boolean isSink(); method public boolean isSource(); field public static final int TYPE_AUX_LINE = 19; // 0x13 + field public static final int TYPE_BLE_BROADCAST = 30; // 0x1e field public static final int TYPE_BLE_HEADSET = 26; // 0x1a field public static final int TYPE_BLE_SPEAKER = 27; // 0x1b field public static final int TYPE_BLUETOOTH_A2DP = 8; // 0x8 @@ -21885,9 +20599,11 @@ package android.media { field public static final int COLOR_Format24bitBGR888 = 12; // 0xc field @Deprecated public static final int COLOR_Format24bitRGB888 = 11; // 0xb field @Deprecated public static final int COLOR_Format25bitARGB1888 = 14; // 0xe + field public static final int COLOR_Format32bitABGR2101010 = 2130750114; // 0x7f00aaa2 field public static final int COLOR_Format32bitABGR8888 = 2130747392; // 0x7f00a000 field @Deprecated public static final int COLOR_Format32bitARGB8888 = 16; // 0x10 field @Deprecated public static final int COLOR_Format32bitBGRA8888 = 15; // 0xf + field public static final int COLOR_Format64bitABGRFloat = 2130710294; // 0x7f000f16 field @Deprecated public static final int COLOR_Format8bitRGB332 = 2; // 0x2 field @Deprecated public static final int COLOR_FormatCbYCrY = 27; // 0x1b field @Deprecated public static final int COLOR_FormatCrYCbY = 28; // 0x1c @@ -21920,6 +20636,7 @@ package android.media { field @Deprecated public static final int COLOR_FormatYUV422SemiPlanar = 24; // 0x18 field public static final int COLOR_FormatYUV444Flexible = 2135181448; // 0x7f444888 field @Deprecated public static final int COLOR_FormatYUV444Interleaved = 29; // 0x1d + field public static final int COLOR_FormatYUVP010 = 54; // 0x36 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"; @@ -22008,11 +20725,14 @@ package android.media { field public static final int AVCProfileHigh422 = 32; // 0x20 field public static final int AVCProfileHigh444 = 64; // 0x40 field public static final int AVCProfileMain = 2; // 0x2 + field public static final int DolbyVisionLevel8k30 = 1024; // 0x400 + field public static final int DolbyVisionLevel8k60 = 2048; // 0x800 field public static final int DolbyVisionLevelFhd24 = 4; // 0x4 field public static final int DolbyVisionLevelFhd30 = 8; // 0x8 field public static final int DolbyVisionLevelFhd60 = 16; // 0x10 field public static final int DolbyVisionLevelHd24 = 1; // 0x1 field public static final int DolbyVisionLevelHd30 = 2; // 0x2 + field public static final int DolbyVisionLevelUhd120 = 512; // 0x200 field public static final int DolbyVisionLevelUhd24 = 32; // 0x20 field public static final int DolbyVisionLevelUhd30 = 64; // 0x40 field public static final int DolbyVisionLevelUhd48 = 128; // 0x80 @@ -26497,15 +25217,18 @@ package android.net { public static final class Ikev2VpnProfile.Builder { ctor public Ikev2VpnProfile.Builder(@NonNull String, @NonNull String); + ctor public Ikev2VpnProfile.Builder(@NonNull android.net.ipsec.ike.IkeTunnelConnectionParams); method @NonNull public android.net.Ikev2VpnProfile build(); method @NonNull public android.net.Ikev2VpnProfile.Builder setAllowedAlgorithms(@NonNull java.util.List<java.lang.String>); method @NonNull public android.net.Ikev2VpnProfile.Builder setAuthDigitalSignature(@NonNull java.security.cert.X509Certificate, @NonNull java.security.PrivateKey, @Nullable java.security.cert.X509Certificate); method @NonNull public android.net.Ikev2VpnProfile.Builder setAuthPsk(@NonNull byte[]); method @NonNull public android.net.Ikev2VpnProfile.Builder setAuthUsernamePassword(@NonNull String, @NonNull String, @Nullable java.security.cert.X509Certificate); method @NonNull public android.net.Ikev2VpnProfile.Builder setBypassable(boolean); + method @NonNull public android.net.Ikev2VpnProfile.Builder setExcludeLocalRoutes(boolean); method @NonNull public android.net.Ikev2VpnProfile.Builder setMaxMtu(int); method @NonNull public android.net.Ikev2VpnProfile.Builder setMetered(boolean); method @NonNull public android.net.Ikev2VpnProfile.Builder setProxy(@Nullable android.net.ProxyInfo); + method @NonNull public android.net.Ikev2VpnProfile.Builder setRequiresInternetValidation(boolean); } public final class IpSecAlgorithm implements android.os.Parcelable { @@ -26648,6 +25371,8 @@ package android.net { } public abstract class PlatformVpnProfile { + method public final boolean getExcludeLocalRoutes(); + method public final boolean getRequiresInternetValidation(); method public final int getType(); method @NonNull public final String getTypeString(); field public static final int TYPE_IKEV2_IPSEC_PSK = 7; // 0x7 @@ -26884,7 +25609,8 @@ package android.net { public class VpnManager { method public void deleteProvisionedVpnProfile(); method @Nullable public android.content.Intent provisionVpnProfile(@NonNull android.net.PlatformVpnProfile); - method public void startProvisionedVpnProfile(); + method @Deprecated public void startProvisionedVpnProfile(); + method @NonNull public String startProvisionedVpnProfileSession(); method public void stopProvisionedVpnProfile(); } @@ -30953,6 +29679,7 @@ package android.os { field public static final int Q = 29; // 0x1d field public static final int R = 30; // 0x1e field public static final int S = 31; // 0x1f + field public static final int S_V2 = 32; // 0x20 field public static final int TIRAMISU = 10000; // 0x2710 } @@ -31547,6 +30274,9 @@ package android.os { method @Nullable public byte[] createByteArray(); method @Nullable public char[] createCharArray(); method @Nullable public double[] createDoubleArray(); + method @Nullable public <T> T createFixedArray(@NonNull Class<T>, @NonNull int...); + method @Nullable public <T, S extends android.os.IInterface> T createFixedArray(@NonNull Class<T>, @NonNull java.util.function.Function<android.os.IBinder,S>, @NonNull int...); + method @Nullable public <T, S extends android.os.Parcelable> T createFixedArray(@NonNull Class<T>, @NonNull android.os.Parcelable.Creator<S>, @NonNull int...); method @Nullable public float[] createFloatArray(); method @Nullable public int[] createIntArray(); method @Nullable public <T extends android.os.IInterface> T[] createInterfaceArray(@NonNull java.util.function.IntFunction<T[]>, @NonNull java.util.function.Function<android.os.IBinder,T>); @@ -31587,6 +30317,9 @@ package android.os { method public void readException(); method public void readException(int, String); method public android.os.ParcelFileDescriptor readFileDescriptor(); + method public <T> void readFixedArray(@NonNull T); + method public <T, S extends android.os.IInterface> void readFixedArray(@NonNull T, @NonNull java.util.function.Function<android.os.IBinder,S>); + method public <T, S extends android.os.Parcelable> void readFixedArray(@NonNull T, @NonNull android.os.Parcelable.Creator<S>); method public float readFloat(); method public void readFloatArray(@NonNull float[]); method @Deprecated @Nullable public java.util.HashMap readHashMap(@Nullable ClassLoader); @@ -31602,7 +30335,7 @@ package android.os { method @Deprecated public void readMap(@NonNull java.util.Map, @Nullable ClassLoader); method public <K, V> void readMap(@NonNull java.util.Map<? super K,? super V>, @Nullable ClassLoader, @NonNull Class<K>, @NonNull Class<V>); method @Deprecated @Nullable public <T extends android.os.Parcelable> T readParcelable(@Nullable ClassLoader); - method @Nullable public <T extends android.os.Parcelable> T readParcelable(@Nullable ClassLoader, @NonNull Class<? super T>); + method @Nullable public <T> T readParcelable(@Nullable ClassLoader, @NonNull Class<T>); method @Deprecated @Nullable public android.os.Parcelable[] readParcelableArray(@Nullable ClassLoader); method @Nullable public <T> T[] readParcelableArray(@Nullable ClassLoader, @NonNull Class<T>); method @Deprecated @Nullable public android.os.Parcelable.Creator<?> readParcelableCreator(@Nullable ClassLoader); @@ -31612,7 +30345,7 @@ package android.os { method @Nullable public android.os.PersistableBundle readPersistableBundle(); method @Nullable public android.os.PersistableBundle readPersistableBundle(@Nullable ClassLoader); method @Deprecated @Nullable public java.io.Serializable readSerializable(); - method @Nullable public <T extends java.io.Serializable> T readSerializable(@Nullable ClassLoader, @NonNull Class<? super T>); + method @Nullable public <T> T readSerializable(@Nullable ClassLoader, @NonNull Class<T>); method @NonNull public android.util.Size readSize(); method @NonNull public android.util.SizeF readSizeF(); method @Deprecated @Nullable public <T> android.util.SparseArray<T> readSparseArray(@Nullable ClassLoader); @@ -31630,6 +30363,7 @@ package android.os { method public void setDataCapacity(int); method public void setDataPosition(int); method public void setDataSize(int); + method public void setPropagateAllowBlocking(); method public void unmarshall(@NonNull byte[], int, int); method public void writeArray(@Nullable Object[]); method public void writeBinderArray(@Nullable android.os.IBinder[]); @@ -31645,6 +30379,7 @@ package android.os { method public void writeDoubleArray(@Nullable double[]); method public void writeException(@NonNull Exception); method public void writeFileDescriptor(@NonNull java.io.FileDescriptor); + method public <T> void writeFixedArray(@Nullable T, int, @NonNull int...); method public void writeFloat(float); method public void writeFloatArray(@Nullable float[]); method public void writeInt(int); @@ -37461,6 +36196,28 @@ package android.security { method @Deprecated @NonNull public android.security.KeyPairGeneratorSpec.Builder setSubject(@NonNull javax.security.auth.x500.X500Principal); } + public class KeyStoreException extends java.lang.Exception { + method public int getNumericErrorCode(); + method public boolean isSystemError(); + method public boolean isTransientFailure(); + method public boolean requiresUserAuthentication(); + field public static final int ERROR_ATTESTATION_CHALLENGE_TOO_LARGE = 9; // 0x9 + field public static final int ERROR_ID_ATTESTATION_FAILURE = 8; // 0x8 + field public static final int ERROR_INCORRECT_USAGE = 13; // 0xd + field public static final int ERROR_INTERNAL_SYSTEM_ERROR = 4; // 0x4 + field public static final int ERROR_KEYMINT_FAILURE = 10; // 0xa + field public static final int ERROR_KEYSTORE_FAILURE = 11; // 0xb + field public static final int ERROR_KEYSTORE_UNINITIALIZED = 3; // 0x3 + field public static final int ERROR_KEY_CORRUPTED = 7; // 0x7 + field public static final int ERROR_KEY_DOES_NOT_EXIST = 6; // 0x6 + field public static final int ERROR_KEY_NOT_TEMPORALLY_VALID = 14; // 0xe + field public static final int ERROR_KEY_OPERATION_EXPIRED = 15; // 0xf + field public static final int ERROR_OTHER = 1; // 0x1 + field public static final int ERROR_PERMISSION_DENIED = 5; // 0x5 + field public static final int ERROR_UNIMPLEMENTED = 12; // 0xc + field public static final int ERROR_USER_AUTHENTICATION_REQUIRED = 2; // 0x2 + } + @Deprecated public final class KeyStoreParameter implements java.security.KeyStore.ProtectionParameter { method @Deprecated public boolean isEncryptionRequired(); } @@ -41014,13 +39771,14 @@ package android.telephony { field public static final String KEY_CARRIER_SETTINGS_ENABLE_BOOL = "carrier_settings_enable_bool"; field public static final String KEY_CARRIER_SUPPORTS_OPP_DATA_AUTO_PROVISIONING_BOOL = "carrier_supports_opp_data_auto_provisioning_bool"; field public static final String KEY_CARRIER_SUPPORTS_SS_OVER_UT_BOOL = "carrier_supports_ss_over_ut_bool"; + field public static final String KEY_CARRIER_SUPPORTS_TETHERING_BOOL = "carrier_supports_tethering_bool"; field public static final String KEY_CARRIER_USE_IMS_FIRST_FOR_EMERGENCY_BOOL = "carrier_use_ims_first_for_emergency_bool"; field public static final String KEY_CARRIER_USSD_METHOD_INT = "carrier_ussd_method_int"; - field public static final String KEY_CARRIER_UT_PROVISIONING_REQUIRED_BOOL = "carrier_ut_provisioning_required_bool"; + field @Deprecated public static final String KEY_CARRIER_UT_PROVISIONING_REQUIRED_BOOL = "carrier_ut_provisioning_required_bool"; field public static final String KEY_CARRIER_VOLTE_AVAILABLE_BOOL = "carrier_volte_available_bool"; field public static final String KEY_CARRIER_VOLTE_OVERRIDE_WFC_PROVISIONING_BOOL = "carrier_volte_override_wfc_provisioning_bool"; - field public static final String KEY_CARRIER_VOLTE_PROVISIONED_BOOL = "carrier_volte_provisioned_bool"; - field public static final String KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL = "carrier_volte_provisioning_required_bool"; + field @Deprecated public static final String KEY_CARRIER_VOLTE_PROVISIONED_BOOL = "carrier_volte_provisioned_bool"; + field @Deprecated public static final String KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL = "carrier_volte_provisioning_required_bool"; field public static final String KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL = "carrier_volte_tty_supported_bool"; field public static final String KEY_CARRIER_VT_AVAILABLE_BOOL = "carrier_vt_available_bool"; field @Deprecated public static final String KEY_CARRIER_VVM_PACKAGE_NAME_STRING = "carrier_vvm_package_name_string"; @@ -41096,6 +39854,7 @@ package android.telephony { field public static final String KEY_IMS_CONFERENCE_SIZE_LIMIT_INT = "ims_conference_size_limit_int"; field public static final String KEY_IMS_DTMF_TONE_DELAY_INT = "ims_dtmf_tone_delay_int"; field public static final String KEY_IS_IMS_CONFERENCE_SIZE_ENFORCED_BOOL = "is_ims_conference_size_enforced_bool"; + field public static final String KEY_IS_OPPORTUNISTIC_SUBSCRIPTION_BOOL = "is_opportunistic_subscription_bool"; field public static final String KEY_LTE_ENABLED_BOOL = "lte_enabled_bool"; field public static final String KEY_LTE_RSRQ_THRESHOLDS_INT_ARRAY = "lte_rsrq_thresholds_int_array"; field public static final String KEY_LTE_RSSNR_THRESHOLDS_INT_ARRAY = "lte_rssnr_thresholds_int_array"; @@ -41180,6 +39939,7 @@ package android.telephony { field public static final String KEY_SIM_NETWORK_UNLOCK_ALLOW_DISMISS_BOOL = "sim_network_unlock_allow_dismiss_bool"; field public static final String KEY_SMDP_SERVER_ADDRESS_STRING = "smdp_server_address_string"; field public static final String KEY_SMS_REQUIRES_DESTINATION_NUMBER_CONVERSION_BOOL = "sms_requires_destination_number_conversion_bool"; + field public static final String KEY_SUBSCRIPTION_GROUP_UUID_STRING = "subscription_group_uuid_string"; field public static final String KEY_SUPPORTS_CALL_COMPOSER_BOOL = "supports_call_composer_bool"; field public static final String KEY_SUPPORTS_DEVICE_TO_DEVICE_COMMUNICATION_USING_DTMF_BOOL = "supports_device_to_device_communication_using_dtmf_bool"; field public static final String KEY_SUPPORTS_DEVICE_TO_DEVICE_COMMUNICATION_USING_RTP_BOOL = "supports_device_to_device_communication_using_rtp_bool"; @@ -41223,6 +39983,7 @@ package android.telephony { field public static final String KEY_WFC_EMERGENCY_ADDRESS_CARRIER_APP_STRING = "wfc_emergency_address_carrier_app_string"; field public static final String KEY_WORLD_MODE_ENABLED_BOOL = "world_mode_enabled_bool"; field public static final String KEY_WORLD_PHONE_BOOL = "world_phone_bool"; + field public static final String REMOVE_GROUP_UUID_STRING = "00000000-0000-0000-0000-000000000000"; field public static final int SERVICE_CLASS_NONE = 0; // 0x0 field public static final int SERVICE_CLASS_VOICE = 1; // 0x1 field public static final int USSD_OVER_CS_ONLY = 2; // 0x2 @@ -41246,14 +40007,23 @@ package android.telephony { } public static final class CarrierConfigManager.Ims { + field public static final String KEY_CAPABILITY_CALL_COMPOSER_INT_ARRAY = "ims.key_capability_type_call_composer_int_array"; + field public static final String KEY_CAPABILITY_TYPE_OPTIONS_UCE_INT_ARRAY = "ims.key_capability_type_options_uce_int_array"; + field public static final String KEY_CAPABILITY_TYPE_PRESENCE_UCE_INT_ARRAY = "ims.key_capability_type_presence_uce_int_array"; + field public static final String KEY_CAPABILITY_TYPE_SMS_INT_ARRAY = "ims.key_capability_type_sms_int_array"; + field public static final String KEY_CAPABILITY_TYPE_UT_INT_ARRAY = "ims.key_capability_type_ut_int_array"; + field public static final String KEY_CAPABILITY_TYPE_VIDEO_INT_ARRAY = "ims.key_capability_type_video_int_array"; + field public static final String KEY_CAPABILITY_TYPE_VOICE_INT_ARRAY = "ims.key_capability_type_voice_int_array"; field public static final String KEY_ENABLE_PRESENCE_CAPABILITY_EXCHANGE_BOOL = "ims.enable_presence_capability_exchange_bool"; field public static final String KEY_ENABLE_PRESENCE_GROUP_SUBSCRIBE_BOOL = "ims.enable_presence_group_subscribe_bool"; field public static final String KEY_ENABLE_PRESENCE_PUBLISH_BOOL = "ims.enable_presence_publish_bool"; field public static final String KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL = "ims.ims_single_registration_required_bool"; + field public static final String KEY_MMTEL_REQUIRES_PROVISIONING_BUNDLE = "ims.mmtel_requires_provisioning_bundle"; field public static final String KEY_NON_RCS_CAPABILITIES_CACHE_EXPIRATION_SEC_INT = "ims.non_rcs_capabilities_cache_expiration_sec_int"; field public static final String KEY_PREFIX = "ims."; field public static final String KEY_RCS_BULK_CAPABILITY_EXCHANGE_BOOL = "ims.rcs_bulk_capability_exchange_bool"; field public static final String KEY_RCS_FEATURE_TAG_ALLOWED_STRING_ARRAY = "ims.rcs_feature_tag_allowed_string_array"; + field public static final String KEY_RCS_REQUIRES_PROVISIONING_BUNDLE = "ims.rcs_requires_provisioning_bundle"; field public static final String KEY_WIFI_OFF_DEFERRING_TIME_MILLIS_INT = "ims.wifi_off_deferring_time_millis_int"; } @@ -42876,6 +41646,7 @@ package android.telephony { method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public boolean doesSwitchMultiSimConfigTriggerReboot(); method public int getActiveModemCount(); method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public java.util.List<android.telephony.CellInfo> getAllCellInfo(); + method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public long getAllowedNetworkTypesForReason(int); method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public int getCallComposerStatus(); method @Deprecated @RequiresPermission(value=android.Manifest.permission.READ_PHONE_STATE, conditional=true) public int getCallState(); method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public int getCallStateForSubscription(); @@ -42936,6 +41707,7 @@ package android.telephony { method public int getSubscriptionId(); method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public int getSubscriptionId(@NonNull android.telecom.PhoneAccountHandle); method public int getSupportedModemCount(); + method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public long getSupportedRadioAccessFamily(); method @Nullable public String getTypeAllocationCode(); method @Nullable public String getTypeAllocationCode(int); method @NonNull @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public java.util.List<android.telephony.UiccCardInfo> getUiccCardsInfo(); @@ -42981,6 +41753,7 @@ package android.telephony { method public String sendEnvelopeWithStatus(String); method @RequiresPermission(android.Manifest.permission.CALL_PHONE) public void sendUssdRequest(String, android.telephony.TelephonyManager.UssdResponseCallback, android.os.Handler); method public void sendVisualVoicemailSms(String, int, String, android.app.PendingIntent); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setAllowedNetworkTypesForReason(int, long); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCallComposerStatus(int); method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataEnabled(boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataEnabledForReason(int, boolean); @@ -43017,6 +41790,8 @@ package android.telephony { field public static final String ACTION_SHOW_VOICEMAIL_NOTIFICATION = "android.telephony.action.SHOW_VOICEMAIL_NOTIFICATION"; field public static final String ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED = "android.telephony.action.SUBSCRIPTION_CARRIER_IDENTITY_CHANGED"; field public static final String ACTION_SUBSCRIPTION_SPECIFIC_CARRIER_IDENTITY_CHANGED = "android.telephony.action.SUBSCRIPTION_SPECIFIC_CARRIER_IDENTITY_CHANGED"; + field public static final int ALLOWED_NETWORK_TYPES_REASON_CARRIER = 2; // 0x2 + field public static final int ALLOWED_NETWORK_TYPES_REASON_USER = 0; // 0x0 field public static final int APPTYPE_CSIM = 4; // 0x4 field public static final int APPTYPE_ISIM = 5; // 0x5 field public static final int APPTYPE_RUIM = 3; // 0x3 @@ -43087,6 +41862,26 @@ package android.telephony { field public static final int NETWORK_SELECTION_MODE_MANUAL = 2; // 0x2 field public static final int NETWORK_SELECTION_MODE_UNKNOWN = 0; // 0x0 field public static final int NETWORK_TYPE_1xRTT = 7; // 0x7 + field public static final long NETWORK_TYPE_BITMASK_1xRTT = 64L; // 0x40L + field public static final long NETWORK_TYPE_BITMASK_CDMA = 8L; // 0x8L + field public static final long NETWORK_TYPE_BITMASK_EDGE = 2L; // 0x2L + field public static final long NETWORK_TYPE_BITMASK_EHRPD = 8192L; // 0x2000L + field public static final long NETWORK_TYPE_BITMASK_EVDO_0 = 16L; // 0x10L + field public static final long NETWORK_TYPE_BITMASK_EVDO_A = 32L; // 0x20L + field public static final long NETWORK_TYPE_BITMASK_EVDO_B = 2048L; // 0x800L + field public static final long NETWORK_TYPE_BITMASK_GPRS = 1L; // 0x1L + field public static final long NETWORK_TYPE_BITMASK_GSM = 32768L; // 0x8000L + field public static final long NETWORK_TYPE_BITMASK_HSDPA = 128L; // 0x80L + field public static final long NETWORK_TYPE_BITMASK_HSPA = 512L; // 0x200L + field public static final long NETWORK_TYPE_BITMASK_HSPAP = 16384L; // 0x4000L + field public static final long NETWORK_TYPE_BITMASK_HSUPA = 256L; // 0x100L + field public static final long NETWORK_TYPE_BITMASK_IWLAN = 131072L; // 0x20000L + field public static final long NETWORK_TYPE_BITMASK_LTE = 4096L; // 0x1000L + field public static final long NETWORK_TYPE_BITMASK_LTE_CA = 262144L; // 0x40000L + field public static final long NETWORK_TYPE_BITMASK_NR = 524288L; // 0x80000L + field public static final long NETWORK_TYPE_BITMASK_TD_SCDMA = 65536L; // 0x10000L + field public static final long NETWORK_TYPE_BITMASK_UMTS = 4L; // 0x4L + field public static final long NETWORK_TYPE_BITMASK_UNKNOWN = 0L; // 0x0L field public static final int NETWORK_TYPE_CDMA = 4; // 0x4 field public static final int NETWORK_TYPE_EDGE = 2; // 0x2 field public static final int NETWORK_TYPE_EHRPD = 14; // 0xe @@ -43668,6 +42463,7 @@ package android.telephony.ims { public class ImsManager { method @NonNull public android.telephony.ims.ImsMmTelManager getImsMmTelManager(int); method @NonNull public android.telephony.ims.ImsRcsManager getImsRcsManager(int); + method @NonNull public android.telephony.ims.ProvisioningManager getProvisioningManager(int); field public static final String ACTION_WFC_IMS_REGISTRATION_ERROR = "android.telephony.ims.action.WFC_IMS_REGISTRATION_ERROR"; field public static final String EXTRA_WFC_REGISTRATION_FAILURE_MESSAGE = "android.telephony.ims.extra.WFC_REGISTRATION_FAILURE_MESSAGE"; field public static final String EXTRA_WFC_REGISTRATION_FAILURE_TITLE = "android.telephony.ims.extra.WFC_REGISTRATION_FAILURE_TITLE"; @@ -43918,6 +42714,23 @@ package android.telephony.ims { field public static final int REASON_UNKNOWN_TEMPORARY_ERROR = 1; // 0x1 } + public class ProvisioningManager { + method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) @WorkerThread public boolean getProvisioningStatusForCapability(int, int); + method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) @WorkerThread public boolean getRcsProvisioningStatusForCapability(int, int); + method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public boolean isProvisioningRequiredForCapability(int, int); + method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public boolean isRcsProvisioningRequiredForCapability(int, int); + method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void registerFeatureProvisioningChangedCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ProvisioningManager.FeatureProvisioningCallback) throws android.telephony.ims.ImsException; + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setProvisioningStatusForCapability(int, int, boolean); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setRcsProvisioningStatusForCapability(int, int, boolean); + method public void unregisterFeatureProvisioningChangedCallback(@NonNull android.telephony.ims.ProvisioningManager.FeatureProvisioningCallback); + } + + public static class ProvisioningManager.FeatureProvisioningCallback { + ctor public ProvisioningManager.FeatureProvisioningCallback(); + method public void onFeatureProvisioningChanged(int, int, boolean); + method public void onRcsFeatureProvisioningChanged(int, int, boolean); + } + public class RcsUceAdapter { method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public boolean isUceSettingEnabled() throws android.telephony.ims.ImsException; } @@ -43958,6 +42771,27 @@ package android.telephony.ims.feature { field public static final int CAPABILITY_TYPE_VOICE = 1; // 0x1 } + public class RcsFeature { + } + + public static class RcsFeature.RcsImsCapabilities { + field public static final int CAPABILITY_TYPE_NONE = 0; // 0x0 + field public static final int CAPABILITY_TYPE_OPTIONS_UCE = 1; // 0x1 + field public static final int CAPABILITY_TYPE_PRESENCE_UCE = 2; // 0x2 + } + +} + +package android.telephony.ims.stub { + + public class ImsRegistrationImplBase { + field public static final int REGISTRATION_TECH_CROSS_SIM = 2; // 0x2 + field public static final int REGISTRATION_TECH_IWLAN = 1; // 0x1 + field public static final int REGISTRATION_TECH_LTE = 0; // 0x0 + field public static final int REGISTRATION_TECH_NONE = -1; // 0xffffffff + field public static final int REGISTRATION_TECH_NR = 3; // 0x3 + } + } package android.telephony.mbms { diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt index 2b0b66447dc4..1e4e787aefa3 100644 --- a/core/api/module-lib-current.txt +++ b/core/api/module-lib-current.txt @@ -55,6 +55,7 @@ package android.app.usage { public class NetworkStatsManager { method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void forceUpdate(); + method public static int getCollapsedRatType(int); method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void notifyNetworkStatus(@NonNull java.util.List<android.net.Network>, @NonNull java.util.List<android.net.NetworkStateSnapshot>, @Nullable String, @NonNull java.util.List<android.net.UnderlyingNetworkInfo>); method @NonNull @WorkerThread public android.app.usage.NetworkStats queryDetailsForDevice(@NonNull android.net.NetworkTemplate, long, long); method @NonNull @WorkerThread public android.app.usage.NetworkStats queryDetailsForUidTagState(@NonNull android.net.NetworkTemplate, long, long, int, int, int) throws java.lang.SecurityException; @@ -66,6 +67,7 @@ package android.app.usage { method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void setPollOnOpen(boolean); method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void setStatsProviderWarningAndLimitAsync(@NonNull String, long, long); method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void setUidForeground(int, boolean); + field public static final int NETWORK_TYPE_5G_NSA = -2; // 0xfffffffe } public abstract static class NetworkStatsManager.UsageCallback { @@ -74,14 +76,6 @@ package android.app.usage { } -package android.bluetooth { - - public final class BluetoothPan implements android.bluetooth.BluetoothProfile { - method @Nullable @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, android.Manifest.permission.TETHER_PRIVILEGED}) public android.net.TetheringManager.TetheredInterfaceRequest requestTetheredInterface(@NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.TetheredInterfaceCallback); - } - -} - package android.content { public abstract class ContentProvider implements android.content.ComponentCallbacks2 { @@ -146,7 +140,7 @@ package android.media { method public void adjustSuggestedStreamVolumeForUid(int, int, int, @NonNull String, int, int, int); method @NonNull public java.util.List<android.bluetooth.BluetoothCodecConfig> getHwOffloadFormatsSupportedForA2dp(); method @NonNull public java.util.List<android.bluetooth.BluetoothLeAudioCodecConfig> getHwOffloadFormatsSupportedForLeAudio(); - method @RequiresPermission("android.permission.BLUETOOTH_STACK") public void handleBluetoothActiveDeviceChanged(@Nullable android.bluetooth.BluetoothDevice, @Nullable android.bluetooth.BluetoothDevice, @NonNull android.media.BtProfileConnectionInfo); + method @RequiresPermission("android.permission.BLUETOOTH_STACK") public void handleBluetoothActiveDeviceChanged(@Nullable android.bluetooth.BluetoothDevice, @Nullable android.bluetooth.BluetoothDevice, @NonNull android.media.BluetoothProfileConnectionInfo); method @RequiresPermission("android.permission.BLUETOOTH_STACK") public void setA2dpSuspended(boolean); method @RequiresPermission("android.permission.BLUETOOTH_STACK") public void setBluetoothHeadsetProperties(@NonNull String, boolean, boolean); method @RequiresPermission("android.permission.BLUETOOTH_STACK") public void setHfpEnabled(boolean); @@ -156,18 +150,18 @@ package android.media { field public static final int FLAG_FROM_KEY = 4096; // 0x1000 } - public final class BtProfileConnectionInfo implements android.os.Parcelable { - method @NonNull public static android.media.BtProfileConnectionInfo a2dpInfo(boolean, int); - method @NonNull public static android.media.BtProfileConnectionInfo a2dpSinkInfo(int); + public final class BluetoothProfileConnectionInfo implements android.os.Parcelable { + method @NonNull public static android.media.BluetoothProfileConnectionInfo createA2dpInfo(boolean, int); + method @NonNull public static android.media.BluetoothProfileConnectionInfo createA2dpSinkInfo(int); + method @NonNull public static android.media.BluetoothProfileConnectionInfo createHearingAidInfo(boolean); + method @NonNull public static android.media.BluetoothProfileConnectionInfo createLeAudioInfo(boolean, boolean); method public int describeContents(); - method public boolean getIsLeOutput(); method public int getProfile(); - method public boolean getSuppressNoisyIntent(); method public int getVolume(); - method @NonNull public static android.media.BtProfileConnectionInfo hearingAidInfo(boolean); - method @NonNull public static android.media.BtProfileConnectionInfo leAudio(boolean, boolean); + method public boolean isLeOutput(); + method public boolean isSuppressNoisyIntent(); method public void writeToParcel(@NonNull android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.media.BtProfileConnectionInfo> CREATOR; + field @NonNull public static final android.os.Parcelable.Creator<android.media.BluetoothProfileConnectionInfo> CREATOR; } public class MediaMetadataRetriever implements java.lang.AutoCloseable { @@ -240,6 +234,10 @@ package android.net { method public int getResourceId(); } + public class LocalSocket implements java.io.Closeable { + ctor public LocalSocket(@NonNull java.io.FileDescriptor); + } + public class NetworkIdentity { method public int getOemManaged(); method public int getRatType(); @@ -293,6 +291,20 @@ package android.net { field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkStateSnapshot> CREATOR; } + public class NetworkStatsCollection { + method @NonNull public java.util.Map<android.net.NetworkStatsCollection.Key,android.net.NetworkStatsHistory> getEntries(); + } + + public static final class NetworkStatsCollection.Builder { + ctor public NetworkStatsCollection.Builder(long); + method @NonNull public android.net.NetworkStatsCollection.Builder addEntry(@NonNull android.net.NetworkStatsCollection.Key, @NonNull android.net.NetworkStatsHistory); + method @NonNull public android.net.NetworkStatsCollection build(); + } + + public static class NetworkStatsCollection.Key { + ctor public NetworkStatsCollection.Key(@NonNull java.util.Set<android.net.NetworkIdentity>, int, int, int); + } + public final class NetworkStatsHistory implements android.os.Parcelable { method public int describeContents(); method @NonNull public java.util.List<android.net.NetworkStatsHistory.Entry> getEntries(); @@ -327,6 +339,7 @@ package android.net { method public int getRoaming(); method @NonNull public java.util.Set<java.lang.String> getSubscriberIds(); method @NonNull public java.util.Set<java.lang.String> getWifiNetworkKeys(); + method public boolean matches(@NonNull android.net.NetworkIdentity); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkTemplate> CREATOR; field public static final int MATCH_BLUETOOTH = 8; // 0x8 @@ -397,6 +410,17 @@ package android.net { } +package android.net.netstats { + + public class NetworkStatsDataMigrationUtils { + method @NonNull public static android.net.NetworkStatsCollection readPlatformCollection(@NonNull String, long) throws java.io.IOException; + field public static final String PREFIX_UID = "uid"; + field public static final String PREFIX_UID_TAG = "uid_tag"; + field public static final String PREFIX_XT = "xt"; + } + +} + package android.os { public final class BatteryStatsManager { diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 8d5cd3128e95..7d68ee1c1ad6 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -63,6 +63,7 @@ package android { field public static final String BIND_TELEPHONY_NETWORK_SERVICE = "android.permission.BIND_TELEPHONY_NETWORK_SERVICE"; field public static final String BIND_TEXTCLASSIFIER_SERVICE = "android.permission.BIND_TEXTCLASSIFIER_SERVICE"; field public static final String BIND_TIME_ZONE_PROVIDER_SERVICE = "android.permission.BIND_TIME_ZONE_PROVIDER_SERVICE"; + field public static final String BIND_TRACE_REPORT_SERVICE = "android.permission.BIND_TRACE_REPORT_SERVICE"; field public static final String BIND_TRANSLATION_SERVICE = "android.permission.BIND_TRANSLATION_SERVICE"; field public static final String BIND_TRUST_AGENT = "android.permission.BIND_TRUST_AGENT"; field public static final String BIND_TV_REMOTE_SERVICE = "android.permission.BIND_TV_REMOTE_SERVICE"; @@ -144,6 +145,7 @@ package android { field public static final String MANAGE_CONTENT_CAPTURE = "android.permission.MANAGE_CONTENT_CAPTURE"; field public static final String MANAGE_CONTENT_SUGGESTIONS = "android.permission.MANAGE_CONTENT_SUGGESTIONS"; field public static final String MANAGE_DEBUGGING = "android.permission.MANAGE_DEBUGGING"; + field public static final String MANAGE_ETHERNET_NETWORKS = "android.permission.MANAGE_ETHERNET_NETWORKS"; field public static final String MANAGE_FACTORY_RESET_PROTECTION = "android.permission.MANAGE_FACTORY_RESET_PROTECTION"; field public static final String MANAGE_HOTWORD_DETECTION = "android.permission.MANAGE_HOTWORD_DETECTION"; field public static final String MANAGE_IPSEC_TUNNELS = "android.permission.MANAGE_IPSEC_TUNNELS"; @@ -316,6 +318,7 @@ package android { public static final class R.array { field public static final int config_keySystemUuidMapping = 17235973; // 0x1070005 + field public static final int config_optionalIpSecAlgorithms; } public static final class R.attr { @@ -1915,453 +1918,6 @@ package android.apphibernation { } -package android.bluetooth { - - public final class BluetoothA2dp implements android.bluetooth.BluetoothProfile { - method @Nullable @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public android.bluetooth.BufferConstraints getBufferConstraints(); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getDynamicBufferSupport(); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setBufferLengthMillis(int, int); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int); - field public static final int DYNAMIC_BUFFER_SUPPORT_A2DP_OFFLOAD = 1; // 0x1 - field public static final int DYNAMIC_BUFFER_SUPPORT_A2DP_SOFTWARE_ENCODING = 2; // 0x2 - field public static final int DYNAMIC_BUFFER_SUPPORT_NONE = 0; // 0x0 - field public static final int OPTIONAL_CODECS_NOT_SUPPORTED = 0; // 0x0 - field public static final int OPTIONAL_CODECS_PREF_DISABLED = 0; // 0x0 - field public static final int OPTIONAL_CODECS_PREF_ENABLED = 1; // 0x1 - field public static final int OPTIONAL_CODECS_PREF_UNKNOWN = -1; // 0xffffffff - field public static final int OPTIONAL_CODECS_SUPPORTED = 1; // 0x1 - field public static final int OPTIONAL_CODECS_SUPPORT_UNKNOWN = -1; // 0xffffffff - } - - public final class BluetoothA2dpSink implements android.bluetooth.BluetoothProfile { - method public void finalize(); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean isAudioPlaying(@NonNull android.bluetooth.BluetoothDevice); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int); - field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.a2dp-sink.profile.action.CONNECTION_STATE_CHANGED"; - } - - public final class BluetoothActivityEnergyInfo implements android.os.Parcelable { - method public int getBluetoothStackState(); - method public long getControllerEnergyUsed(); - method public long getControllerIdleTimeMillis(); - method public long getControllerRxTimeMillis(); - method public long getControllerTxTimeMillis(); - method public long getTimestampMillis(); - method @NonNull public java.util.List<android.bluetooth.UidTraffic> getUidTraffic(); - method public boolean isValid(); - field public static final int BT_STACK_STATE_INVALID = 0; // 0x0 - field public static final int BT_STACK_STATE_STATE_ACTIVE = 1; // 0x1 - field public static final int BT_STACK_STATE_STATE_IDLE = 3; // 0x3 - field public static final int BT_STACK_STATE_STATE_SCANNING = 2; // 0x2 - field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothActivityEnergyInfo> CREATOR; - } - - public final class BluetoothAdapter { - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean addOnMetadataChangedListener(@NonNull android.bluetooth.BluetoothDevice, @NonNull java.util.concurrent.Executor, @NonNull android.bluetooth.BluetoothAdapter.OnMetadataChangedListener); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean disable(boolean); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean disableBLE(); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean enableBLE(); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean enableNoAutoConnect(); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void generateLocalOobData(int, @NonNull java.util.concurrent.Executor, @NonNull android.bluetooth.BluetoothAdapter.OobDataCallback); - method @NonNull @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public java.util.List<android.bluetooth.BluetoothDevice> getActiveDevices(int); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public long getDiscoveryEndMillis(); - method public boolean isBleScanAlwaysAvailable(); - method public boolean isLeEnabled(); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean removeActiveDevice(int); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean removeOnMetadataChangedListener(@NonNull android.bluetooth.BluetoothDevice, @NonNull android.bluetooth.BluetoothAdapter.OnMetadataChangedListener); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean setActiveDevice(@NonNull android.bluetooth.BluetoothDevice, int); - field public static final String ACTION_BLE_STATE_CHANGED = "android.bluetooth.adapter.action.BLE_STATE_CHANGED"; - field public static final String ACTION_REQUEST_BLE_SCAN_ALWAYS_AVAILABLE = "android.bluetooth.adapter.action.REQUEST_BLE_SCAN_ALWAYS_AVAILABLE"; - field public static final int ACTIVE_DEVICE_ALL = 2; // 0x2 - field public static final int ACTIVE_DEVICE_AUDIO = 0; // 0x0 - field public static final int ACTIVE_DEVICE_PHONE_CALL = 1; // 0x1 - } - - public static interface BluetoothAdapter.OnMetadataChangedListener { - method public void onMetadataChanged(@NonNull android.bluetooth.BluetoothDevice, int, @Nullable byte[]); - } - - public static interface BluetoothAdapter.OobDataCallback { - method public void onError(int); - method public void onOobData(int, @NonNull android.bluetooth.OobData); - } - - public final class BluetoothCsipSetCoordinator implements java.lang.AutoCloseable android.bluetooth.BluetoothProfile { - method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public java.util.List<java.lang.Integer> getAllGroupIds(@Nullable android.os.ParcelUuid); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public int getConnectionPolicy(@Nullable android.bluetooth.BluetoothDevice); - method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public java.util.Map getGroupUuidMapByDevice(@Nullable android.bluetooth.BluetoothDevice); - method @Nullable @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public java.util.UUID groupLock(int, @Nullable java.util.concurrent.Executor, @Nullable android.bluetooth.BluetoothCsipSetCoordinator.ClientLockCallback); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean groupUnlock(@NonNull java.util.UUID); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean setConnectionPolicy(@Nullable android.bluetooth.BluetoothDevice, int); - field @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public static final String ACTION_CSIS_DEVICE_AVAILABLE = "android.bluetooth.action.CSIS_DEVICE_AVAILABLE"; - field @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public static final String ACTION_CSIS_SET_MEMBER_AVAILABLE = "android.bluetooth.action.CSIS_SET_MEMBER_AVAILABLE"; - } - - public static interface BluetoothCsipSetCoordinator.ClientLockCallback { - method public void onGroupLockSet(int, int, boolean); - } - - public final class BluetoothDevice implements android.os.Parcelable { - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean canBondWithoutDialog(); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean cancelBondProcess(); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, android.Manifest.permission.MODIFY_PHONE_STATE}) public int connect(); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean createBond(int); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean createBondOutOfBand(int, @Nullable android.bluetooth.OobData, @Nullable android.bluetooth.OobData); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int disconnect(); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean fetchUuidsWithSdp(int); - method @Nullable @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public byte[] getMetadata(int); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getSimAccessPermission(); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean isConnected(); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean isEncrypted(); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean isInSilenceMode(); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean removeBond(); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setLowLatencyAudioAllowed(boolean); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setMessageAccessPermission(int); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setMetadata(int, @NonNull byte[]); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setPhonebookAccessPermission(int); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setSilenceMode(boolean); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setSimAccessPermission(int); - field public static final int ACCESS_ALLOWED = 1; // 0x1 - field public static final int ACCESS_REJECTED = 2; // 0x2 - field public static final int ACCESS_UNKNOWN = 0; // 0x0 - field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_SILENCE_MODE_CHANGED = "android.bluetooth.device.action.SILENCE_MODE_CHANGED"; - field public static final String DEVICE_TYPE_DEFAULT = "Default"; - field public static final String DEVICE_TYPE_UNTETHERED_HEADSET = "Untethered Headset"; - field public static final String DEVICE_TYPE_WATCH = "Watch"; - field public static final int METADATA_COMPANION_APP = 4; // 0x4 - field public static final int METADATA_DEVICE_TYPE = 17; // 0x11 - field public static final int METADATA_ENHANCED_SETTINGS_UI_URI = 16; // 0x10 - field public static final int METADATA_HARDWARE_VERSION = 3; // 0x3 - field public static final int METADATA_IS_UNTETHERED_HEADSET = 6; // 0x6 - field public static final int METADATA_MAIN_BATTERY = 18; // 0x12 - field public static final int METADATA_MAIN_CHARGING = 19; // 0x13 - field public static final int METADATA_MAIN_ICON = 5; // 0x5 - field public static final int METADATA_MAIN_LOW_BATTERY_THRESHOLD = 20; // 0x14 - field public static final int METADATA_MANUFACTURER_NAME = 0; // 0x0 - field public static final int METADATA_MAX_LENGTH = 2048; // 0x800 - field public static final int METADATA_MODEL_NAME = 1; // 0x1 - field public static final int METADATA_SOFTWARE_VERSION = 2; // 0x2 - field public static final int METADATA_UNTETHERED_CASE_BATTERY = 12; // 0xc - field public static final int METADATA_UNTETHERED_CASE_CHARGING = 15; // 0xf - field public static final int METADATA_UNTETHERED_CASE_ICON = 9; // 0x9 - field public static final int METADATA_UNTETHERED_CASE_LOW_BATTERY_THRESHOLD = 23; // 0x17 - field public static final int METADATA_UNTETHERED_LEFT_BATTERY = 10; // 0xa - field public static final int METADATA_UNTETHERED_LEFT_CHARGING = 13; // 0xd - field public static final int METADATA_UNTETHERED_LEFT_ICON = 7; // 0x7 - field public static final int METADATA_UNTETHERED_LEFT_LOW_BATTERY_THRESHOLD = 21; // 0x15 - field public static final int METADATA_UNTETHERED_RIGHT_BATTERY = 11; // 0xb - field public static final int METADATA_UNTETHERED_RIGHT_CHARGING = 14; // 0xe - field public static final int METADATA_UNTETHERED_RIGHT_ICON = 8; // 0x8 - field public static final int METADATA_UNTETHERED_RIGHT_LOW_BATTERY_THRESHOLD = 22; // 0x16 - } - - public final class BluetoothHeadset implements android.bluetooth.BluetoothProfile { - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean connect(android.bluetooth.BluetoothDevice); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean disconnect(android.bluetooth.BluetoothDevice); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean isInbandRingingEnabled(); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean startScoUsingVirtualVoiceCall(); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean stopScoUsingVirtualVoiceCall(); - } - - public final class BluetoothHeadsetClient implements java.lang.AutoCloseable android.bluetooth.BluetoothProfile { - method @NonNull @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices(); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionState(@NonNull android.bluetooth.BluetoothDevice); - method @NonNull @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(@NonNull int[]); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int); - field @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.headsetprofile.action.CONNECTION_STATE_CHANGED"; - } - - public final class BluetoothHearingAid implements android.bluetooth.BluetoothProfile { - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public long getHiSyncId(@NonNull android.bluetooth.BluetoothDevice); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int); - } - - public final class BluetoothHidDevice implements android.bluetooth.BluetoothProfile { - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int); - } - - public final class BluetoothHidHost implements android.bluetooth.BluetoothProfile { - method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices(); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getConnectionState(@NonNull android.bluetooth.BluetoothDevice); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int); - field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED"; - } - - public final class BluetoothLeAudio implements java.lang.AutoCloseable android.bluetooth.BluetoothProfile { - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getAudioLocation(@NonNull android.bluetooth.BluetoothDevice); - } - - public final class BluetoothMap implements java.lang.AutoCloseable android.bluetooth.BluetoothProfile { - method public void close(); - method protected void finalize(); - method @NonNull @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices(); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int); - field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.map.profile.action.CONNECTION_STATE_CHANGED"; - } - - public final class BluetoothMapClient implements java.lang.AutoCloseable android.bluetooth.BluetoothProfile { - method @NonNull @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices(); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionState(@NonNull android.bluetooth.BluetoothDevice); - method @NonNull @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(@NonNull int[]); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.SEND_SMS}) public boolean sendMessage(@NonNull android.bluetooth.BluetoothDevice, @NonNull java.util.Collection<android.net.Uri>, @NonNull String, @Nullable android.app.PendingIntent, @Nullable android.app.PendingIntent); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int); - field @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.mapmce.profile.action.CONNECTION_STATE_CHANGED"; - } - - public final class BluetoothPan implements android.bluetooth.BluetoothProfile { - method @NonNull @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices(); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionState(@NonNull android.bluetooth.BluetoothDevice); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean isTetheringOn(); - method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, android.Manifest.permission.TETHER_PRIVILEGED}) public void setBluetoothTethering(boolean); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int); - field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.pan.profile.action.CONNECTION_STATE_CHANGED"; - field public static final String ACTION_TETHERING_STATE_CHANGED = "android.bluetooth.action.TETHERING_STATE_CHANGED"; - field public static final String EXTRA_LOCAL_ROLE = "android.bluetooth.pan.extra.LOCAL_ROLE"; - field public static final String EXTRA_TETHERING_STATE = "android.bluetooth.extra.TETHERING_STATE"; - field public static final int LOCAL_NAP_ROLE = 1; // 0x1 - field public static final int LOCAL_PANU_ROLE = 2; // 0x2 - field public static final int PAN_ROLE_NONE = 0; // 0x0 - field public static final int REMOTE_NAP_ROLE = 1; // 0x1 - field public static final int REMOTE_PANU_ROLE = 2; // 0x2 - field public static final int TETHERING_STATE_OFF = 1; // 0x1 - field public static final int TETHERING_STATE_ON = 2; // 0x2 - } - - public class BluetoothPbap implements android.bluetooth.BluetoothProfile { - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionState(@NonNull android.bluetooth.BluetoothDevice); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int); - field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.pbap.profile.action.CONNECTION_STATE_CHANGED"; - } - - public final class BluetoothPbapClient implements java.lang.AutoCloseable android.bluetooth.BluetoothProfile { - method @NonNull @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices(); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionState(@NonNull android.bluetooth.BluetoothDevice); - method @NonNull @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(@NonNull int[]); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int); - field @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.pbapclient.profile.action.CONNECTION_STATE_CHANGED"; - } - - public interface BluetoothProfile { - field public static final int A2DP_SINK = 11; // 0xb - field public static final int AVRCP_CONTROLLER = 12; // 0xc - field public static final int CONNECTION_POLICY_ALLOWED = 100; // 0x64 - field public static final int CONNECTION_POLICY_FORBIDDEN = 0; // 0x0 - field public static final int CONNECTION_POLICY_UNKNOWN = -1; // 0xffffffff - field public static final int HEADSET_CLIENT = 16; // 0x10 - field public static final int MAP_CLIENT = 18; // 0x12 - field public static final int PAN = 5; // 0x5 - field public static final int PBAP_CLIENT = 17; // 0x11 - field @Deprecated public static final int PRIORITY_OFF = 0; // 0x0 - field @Deprecated public static final int PRIORITY_ON = 100; // 0x64 - field public static final int VOLUME_CONTROL = 23; // 0x17 - } - - public final class BluetoothStatusCodes { - field public static final int ERROR_ANOTHER_ACTIVE_OOB_REQUEST = 1000; // 0x3e8 - } - - public final class BluetoothUuid { - method public static boolean containsAnyUuid(@Nullable android.os.ParcelUuid[], @Nullable android.os.ParcelUuid[]); - method @NonNull public static android.os.ParcelUuid parseUuidFrom(@Nullable byte[]); - field @NonNull public static final android.os.ParcelUuid A2DP_SINK; - field @NonNull public static final android.os.ParcelUuid A2DP_SOURCE; - field @NonNull public static final android.os.ParcelUuid ADV_AUDIO_DIST; - field @NonNull public static final android.os.ParcelUuid AVRCP_CONTROLLER; - field @NonNull public static final android.os.ParcelUuid AVRCP_TARGET; - field @NonNull public static final android.os.ParcelUuid BASE_UUID; - field @NonNull public static final android.os.ParcelUuid BNEP; - field @NonNull public static final android.os.ParcelUuid CAP; - field @NonNull public static final android.os.ParcelUuid COORDINATED_SET; - field @NonNull public static final android.os.ParcelUuid DIP; - field @NonNull public static final android.os.ParcelUuid GENERIC_MEDIA_CONTROL; - field @NonNull public static final android.os.ParcelUuid HAS; - field @NonNull public static final android.os.ParcelUuid HEARING_AID; - field @NonNull public static final android.os.ParcelUuid HFP; - field @NonNull public static final android.os.ParcelUuid HFP_AG; - field @NonNull public static final android.os.ParcelUuid HID; - field @NonNull public static final android.os.ParcelUuid HOGP; - field @NonNull public static final android.os.ParcelUuid HSP; - field @NonNull public static final android.os.ParcelUuid HSP_AG; - field @NonNull public static final android.os.ParcelUuid LE_AUDIO; - field @NonNull public static final android.os.ParcelUuid MAP; - field @NonNull public static final android.os.ParcelUuid MAS; - field @NonNull public static final android.os.ParcelUuid MEDIA_CONTROL; - field @NonNull public static final android.os.ParcelUuid MNS; - field @NonNull public static final android.os.ParcelUuid NAP; - field @NonNull public static final android.os.ParcelUuid OBEX_OBJECT_PUSH; - field @NonNull public static final android.os.ParcelUuid PANU; - field @NonNull public static final android.os.ParcelUuid PBAP_PCE; - field @NonNull public static final android.os.ParcelUuid PBAP_PSE; - field @NonNull public static final android.os.ParcelUuid SAP; - field public static final int UUID_BYTES_128_BIT = 16; // 0x10 - field public static final int UUID_BYTES_16_BIT = 2; // 0x2 - field public static final int UUID_BYTES_32_BIT = 4; // 0x4 - field @NonNull public static final android.os.ParcelUuid VOLUME_CONTROL; - } - - public final class BluetoothVolumeControl implements java.lang.AutoCloseable android.bluetooth.BluetoothProfile { - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public void close(); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) protected void finalize(); - method @NonNull @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices(); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void setVolume(@Nullable android.bluetooth.BluetoothDevice, @IntRange(from=0, to=255) int); - field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.volume-control.profile.action.CONNECTION_STATE_CHANGED"; - } - - public final class BufferConstraint implements android.os.Parcelable { - ctor public BufferConstraint(int, int, int); - method public int describeContents(); - method public int getDefaultMillis(); - method public int getMaxMillis(); - method public int getMinMillis(); - method public void writeToParcel(@NonNull android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BufferConstraint> CREATOR; - } - - public final class BufferConstraints implements android.os.Parcelable { - ctor public BufferConstraints(@NonNull java.util.List<android.bluetooth.BufferConstraint>); - method public int describeContents(); - method @Nullable public android.bluetooth.BufferConstraint forCodec(int); - method public void writeToParcel(@NonNull android.os.Parcel, int); - field public static final int BUFFER_CODEC_MAX_NUM = 32; // 0x20 - field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BufferConstraints> CREATOR; - } - - public final class OobData implements android.os.Parcelable { - method @NonNull public byte[] getClassOfDevice(); - method @NonNull public byte[] getClassicLength(); - method @NonNull public byte[] getConfirmationHash(); - method @NonNull public byte[] getDeviceAddressWithType(); - method @Nullable public byte[] getDeviceName(); - method @Nullable public byte[] getLeAppearance(); - method @NonNull public int getLeDeviceRole(); - method @NonNull public int getLeFlags(); - method @Nullable public byte[] getLeTemporaryKey(); - method @NonNull public byte[] getRandomizerHash(); - field public static final int CLASS_OF_DEVICE_OCTETS = 3; // 0x3 - field public static final int CONFIRMATION_OCTETS = 16; // 0x10 - field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.OobData> CREATOR; - field public static final int DEVICE_ADDRESS_OCTETS = 7; // 0x7 - field public static final int LE_APPEARANCE_OCTETS = 2; // 0x2 - field public static final int LE_DEVICE_FLAG_OCTETS = 1; // 0x1 - field public static final int LE_DEVICE_ROLE_BOTH_PREFER_CENTRAL = 3; // 0x3 - field public static final int LE_DEVICE_ROLE_BOTH_PREFER_PERIPHERAL = 2; // 0x2 - field public static final int LE_DEVICE_ROLE_CENTRAL_ONLY = 1; // 0x1 - field public static final int LE_DEVICE_ROLE_OCTETS = 1; // 0x1 - field public static final int LE_DEVICE_ROLE_PERIPHERAL_ONLY = 0; // 0x0 - field public static final int LE_FLAG_BREDR_NOT_SUPPORTED = 2; // 0x2 - field public static final int LE_FLAG_GENERAL_DISCOVERY_MODE = 1; // 0x1 - field public static final int LE_FLAG_LIMITED_DISCOVERY_MODE = 0; // 0x0 - field public static final int LE_FLAG_SIMULTANEOUS_CONTROLLER = 3; // 0x3 - field public static final int LE_FLAG_SIMULTANEOUS_HOST = 4; // 0x4 - field public static final int LE_TK_OCTETS = 16; // 0x10 - field public static final int OOB_LENGTH_OCTETS = 2; // 0x2 - field public static final int RANDOMIZER_OCTETS = 16; // 0x10 - } - - public static final class OobData.ClassicBuilder { - ctor public OobData.ClassicBuilder(@NonNull byte[], @NonNull byte[], @NonNull byte[]); - method @NonNull public android.bluetooth.OobData build(); - method @NonNull public android.bluetooth.OobData.ClassicBuilder setClassOfDevice(@NonNull byte[]); - method @NonNull public android.bluetooth.OobData.ClassicBuilder setDeviceName(@NonNull byte[]); - method @NonNull public android.bluetooth.OobData.ClassicBuilder setRandomizerHash(@NonNull byte[]); - } - - public static final class OobData.LeBuilder { - ctor public OobData.LeBuilder(@NonNull byte[], @NonNull byte[], int); - method @NonNull public android.bluetooth.OobData build(); - method @NonNull public android.bluetooth.OobData.LeBuilder setDeviceName(@NonNull byte[]); - method @NonNull public android.bluetooth.OobData.LeBuilder setLeFlags(int); - method @NonNull public android.bluetooth.OobData.LeBuilder setLeTemporaryKey(@NonNull byte[]); - method @NonNull public android.bluetooth.OobData.LeBuilder setRandomizerHash(@NonNull byte[]); - } - - public final class UidTraffic implements java.lang.Cloneable android.os.Parcelable { - method public long getRxBytes(); - method public long getTxBytes(); - method public int getUid(); - field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.UidTraffic> CREATOR; - } - -} - -package android.bluetooth.le { - - public final class AdvertiseSettings implements android.os.Parcelable { - method public int getOwnAddressType(); - } - - public static final class AdvertiseSettings.Builder { - method @NonNull public android.bluetooth.le.AdvertiseSettings.Builder setOwnAddressType(int); - } - - public final class AdvertisingSetParameters implements android.os.Parcelable { - method public int getOwnAddressType(); - field public static final int ADDRESS_TYPE_DEFAULT = -1; // 0xffffffff - field public static final int ADDRESS_TYPE_PUBLIC = 0; // 0x0 - field public static final int ADDRESS_TYPE_RANDOM = 1; // 0x1 - } - - public static final class AdvertisingSetParameters.Builder { - method @NonNull public android.bluetooth.le.AdvertisingSetParameters.Builder setOwnAddressType(int); - } - - public final class BluetoothLeScanner { - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_SCAN, android.Manifest.permission.UPDATE_DEVICE_STATS}) public void startScanFromSource(android.os.WorkSource, android.bluetooth.le.ScanCallback); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_SCAN, android.Manifest.permission.UPDATE_DEVICE_STATS}) public void startScanFromSource(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.os.WorkSource, android.bluetooth.le.ScanCallback); - method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public void startTruncatedScan(java.util.List<android.bluetooth.le.TruncatedFilter>, android.bluetooth.le.ScanSettings, android.bluetooth.le.ScanCallback); - } - - @Deprecated public final class ResultStorageDescriptor implements android.os.Parcelable { - ctor @Deprecated public ResultStorageDescriptor(int, int, int); - method @Deprecated public int describeContents(); - method @Deprecated public int getLength(); - method @Deprecated public int getOffset(); - method @Deprecated public int getType(); - method @Deprecated public void writeToParcel(android.os.Parcel, int); - field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.ResultStorageDescriptor> CREATOR; - } - - public final class ScanFilter implements android.os.Parcelable { - method public int getAddressType(); - method @Nullable public byte[] getIrk(); - } - - public static final class ScanFilter.Builder { - method @NonNull public android.bluetooth.le.ScanFilter.Builder setDeviceAddress(@NonNull String, int); - method @NonNull public android.bluetooth.le.ScanFilter.Builder setDeviceAddress(@NonNull String, int, @NonNull byte[]); - field public static final int LEN_IRK_OCTETS = 16; // 0x10 - } - - public final class ScanSettings implements android.os.Parcelable { - field public static final int SCAN_MODE_AMBIENT_DISCOVERY = 3; // 0x3 - field public static final int SCAN_RESULT_TYPE_ABBREVIATED = 1; // 0x1 - field public static final int SCAN_RESULT_TYPE_FULL = 0; // 0x0 - } - - public static final class ScanSettings.Builder { - method public android.bluetooth.le.ScanSettings.Builder setScanResultType(int); - } - - @Deprecated public final class TruncatedFilter { - ctor @Deprecated public TruncatedFilter(android.bluetooth.le.ScanFilter, java.util.List<android.bluetooth.le.ResultStorageDescriptor>); - method @Deprecated public android.bluetooth.le.ScanFilter getFilter(); - method @Deprecated public java.util.List<android.bluetooth.le.ResultStorageDescriptor> getStorageDescriptors(); - } - -} - package android.companion { public final class CompanionDeviceManager { @@ -2440,6 +1996,7 @@ package android.content { field public static final String HDMI_CONTROL_SERVICE = "hdmi_control"; field public static final String MEDIA_TRANSCODING_SERVICE = "media_transcoding"; field public static final String MUSIC_RECOGNITION_SERVICE = "music_recognition"; + field public static final String NEARBY_SERVICE = "nearby"; field public static final String NETD_SERVICE = "netd"; field public static final String NETWORK_SCORE_SERVICE = "network_score"; field public static final String OEM_LOCK_SERVICE = "oem_lock"; @@ -3398,6 +2955,7 @@ package android.hardware.hdmi { method public void sendKeyEvent(int, boolean); method public void sendVendorCommand(int, byte[], boolean); method public void setVendorCommandListener(@NonNull android.hardware.hdmi.HdmiControlManager.VendorCommandListener); + method public void setVendorCommandListener(@NonNull android.hardware.hdmi.HdmiControlManager.VendorCommandListener, int); } public final class HdmiControlManager { @@ -7465,7 +7023,10 @@ package android.metrics { package android.net { public class EthernetManager { + method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}) public void connectNetwork(@NonNull String, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.BiConsumer<android.net.Network,android.net.EthernetNetworkManagementException>); + method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}) public void disconnectNetwork(@NonNull String, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.BiConsumer<android.net.Network,android.net.EthernetNetworkManagementException>); method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public android.net.EthernetManager.TetheredInterfaceRequest requestTetheredInterface(@NonNull java.util.concurrent.Executor, @NonNull android.net.EthernetManager.TetheredInterfaceCallback); + method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}) public void updateConfiguration(@NonNull String, @NonNull android.net.EthernetNetworkUpdateRequest, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.BiConsumer<android.net.Network,android.net.EthernetNetworkManagementException>); } public static interface EthernetManager.TetheredInterfaceCallback { @@ -7477,6 +7038,22 @@ package android.net { method public void release(); } + public final class EthernetNetworkManagementException extends java.lang.RuntimeException implements android.os.Parcelable { + ctor public EthernetNetworkManagementException(@NonNull String); + method public int describeContents(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.net.EthernetNetworkManagementException> CREATOR; + } + + public final class EthernetNetworkUpdateRequest implements android.os.Parcelable { + ctor public EthernetNetworkUpdateRequest(@NonNull android.net.StaticIpConfiguration, @NonNull android.net.NetworkCapabilities); + method public int describeContents(); + method @NonNull public android.net.StaticIpConfiguration getIpConfig(); + method @NonNull public android.net.NetworkCapabilities getNetworkCapabilities(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.net.EthernetNetworkUpdateRequest> CREATOR; + } + public final class IpSecManager { method @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void applyTunnelModeTransform(@NonNull android.net.IpSecManager.IpSecTunnelInterface, int, @NonNull android.net.IpSecTransform) throws java.io.IOException; method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public android.net.IpSecManager.IpSecTunnelInterface createIpSecTunnelInterface(@NonNull java.net.InetAddress, @NonNull java.net.InetAddress, @NonNull android.net.Network) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException; @@ -8273,6 +7850,7 @@ package android.os { } public static class Build.VERSION { + field @NonNull public static final java.util.Set<java.lang.String> KNOWN_CODENAMES; field @NonNull public static final String PREVIEW_SDK_FINGERPRINT; } @@ -10566,6 +10144,22 @@ package android.service.timezone { } +package android.service.tracing { + + public class TraceReportService extends android.app.Service { + ctor public TraceReportService(); + method @Nullable public android.os.IBinder onBind(@NonNull android.content.Intent); + method public boolean onMessage(@NonNull android.os.Message); + method public void onReportTrace(@NonNull android.service.tracing.TraceReportService.TraceParams); + } + + public static final class TraceReportService.TraceParams { + method @NonNull public android.os.ParcelFileDescriptor getFd(); + method @NonNull public java.util.UUID getUuid(); + } + +} + package android.service.translation { public abstract class TranslationService extends android.app.Service { @@ -12096,7 +11690,6 @@ package android.telephony { method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<android.service.carrier.CarrierIdentifier> getAllowedCarriers(int); method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getAllowedNetworkTypes(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getAllowedNetworkTypesBitmask(); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getAllowedNetworkTypesForReason(int); method @Nullable @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public android.content.ComponentName getAndUpdateDefaultRespondViaMessageApplication(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getCallForwarding(int, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CallForwardingInfoCallback); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getCallWaitingStatus(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); @@ -12139,7 +11732,6 @@ package android.telephony { method public int getSimCardState(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSimCardState(int); method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Locale getSimLocale(); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getSupportedRadioAccessFamily(); method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<android.telephony.RadioAccessSpecifier> getSystemSelectionChannels(); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public java.util.List<android.telephony.TelephonyHistogram> getTelephonyHistograms(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.UiccSlotInfo[] getUiccSlotsInfo(); @@ -12190,7 +11782,6 @@ package android.telephony { method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int sendThermalMitigationRequest(@NonNull android.telephony.ThermalMitigationRequest); method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>); method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setAllowedNetworkTypes(long); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setAllowedNetworkTypesForReason(int, long); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCallForwarding(@NonNull android.telephony.CallForwardingInfo, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCallWaitingEnabled(boolean, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>); method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCarrierDataEnabled(boolean); @@ -12240,10 +11831,8 @@ package android.telephony { field public static final String ACTION_SIM_APPLICATION_STATE_CHANGED = "android.telephony.action.SIM_APPLICATION_STATE_CHANGED"; field public static final String ACTION_SIM_CARD_STATE_CHANGED = "android.telephony.action.SIM_CARD_STATE_CHANGED"; field public static final String ACTION_SIM_SLOT_STATUS_CHANGED = "android.telephony.action.SIM_SLOT_STATUS_CHANGED"; - field public static final int ALLOWED_NETWORK_TYPES_REASON_CARRIER = 2; // 0x2 field public static final int ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G = 3; // 0x3 field public static final int ALLOWED_NETWORK_TYPES_REASON_POWER = 1; // 0x1 - field public static final int ALLOWED_NETWORK_TYPES_REASON_USER = 0; // 0x0 field public static final int CALL_WAITING_STATUS_DISABLED = 2; // 0x2 field public static final int CALL_WAITING_STATUS_ENABLED = 1; // 0x1 field public static final int CALL_WAITING_STATUS_NOT_SUPPORTED = 4; // 0x4 @@ -12282,26 +11871,6 @@ package android.telephony { field public static final int KEY_TYPE_WLAN = 2; // 0x2 field public static final int MOBILE_DATA_POLICY_DATA_ON_NON_DEFAULT_DURING_VOICE_CALL = 1; // 0x1 field public static final int MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED = 2; // 0x2 - field public static final long NETWORK_TYPE_BITMASK_1xRTT = 64L; // 0x40L - field public static final long NETWORK_TYPE_BITMASK_CDMA = 8L; // 0x8L - field public static final long NETWORK_TYPE_BITMASK_EDGE = 2L; // 0x2L - field public static final long NETWORK_TYPE_BITMASK_EHRPD = 8192L; // 0x2000L - field public static final long NETWORK_TYPE_BITMASK_EVDO_0 = 16L; // 0x10L - field public static final long NETWORK_TYPE_BITMASK_EVDO_A = 32L; // 0x20L - field public static final long NETWORK_TYPE_BITMASK_EVDO_B = 2048L; // 0x800L - field public static final long NETWORK_TYPE_BITMASK_GPRS = 1L; // 0x1L - field public static final long NETWORK_TYPE_BITMASK_GSM = 32768L; // 0x8000L - field public static final long NETWORK_TYPE_BITMASK_HSDPA = 128L; // 0x80L - field public static final long NETWORK_TYPE_BITMASK_HSPA = 512L; // 0x200L - field public static final long NETWORK_TYPE_BITMASK_HSPAP = 16384L; // 0x4000L - field public static final long NETWORK_TYPE_BITMASK_HSUPA = 256L; // 0x100L - field public static final long NETWORK_TYPE_BITMASK_IWLAN = 131072L; // 0x20000L - field public static final long NETWORK_TYPE_BITMASK_LTE = 4096L; // 0x1000L - field public static final long NETWORK_TYPE_BITMASK_LTE_CA = 262144L; // 0x40000L - field public static final long NETWORK_TYPE_BITMASK_NR = 524288L; // 0x80000L - field public static final long NETWORK_TYPE_BITMASK_TD_SCDMA = 65536L; // 0x10000L - field public static final long NETWORK_TYPE_BITMASK_UMTS = 4L; // 0x4L - field public static final long NETWORK_TYPE_BITMASK_UNKNOWN = 0L; // 0x0L field public static final int NR_DUAL_CONNECTIVITY_DISABLE = 2; // 0x2 field public static final int NR_DUAL_CONNECTIVITY_DISABLE_IMMEDIATE = 3; // 0x3 field public static final int NR_DUAL_CONNECTIVITY_ENABLE = 1; // 0x1 @@ -12358,6 +11927,7 @@ package android.telephony { } public static class TelephonyManager.ModemActivityInfoException extends java.lang.Exception { + ctor public TelephonyManager.ModemActivityInfoException(int); method public int getErrorCode(); field public static final int ERROR_INVALID_INFO_RECEIVED = 2; // 0x2 field public static final int ERROR_MODEM_RESPONSE_ERROR = 3; // 0x3 @@ -13326,13 +12896,21 @@ package android.telephony.ims { public class ImsService extends android.app.Service { ctor public ImsService(); - method public android.telephony.ims.feature.MmTelFeature createMmTelFeature(int); - method public android.telephony.ims.feature.RcsFeature createRcsFeature(int); - method public void disableIms(int); - method public void enableIms(int); - method public android.telephony.ims.stub.ImsConfigImplBase getConfig(int); + method @Nullable public android.telephony.ims.feature.MmTelFeature createEmergencyOnlyMmTelFeature(int); + method @Deprecated public android.telephony.ims.feature.MmTelFeature createMmTelFeature(int); + method @Nullable public android.telephony.ims.feature.MmTelFeature createMmTelFeatureForSubscription(int, int); + method @Deprecated public android.telephony.ims.feature.RcsFeature createRcsFeature(int); + method @Nullable public android.telephony.ims.feature.RcsFeature createRcsFeatureForSubscription(int, int); + method @Deprecated public void disableIms(int); + method public void disableImsForSubscription(int, int); + method @Deprecated public void enableIms(int); + method public void enableImsForSubscription(int, int); + method @Deprecated public android.telephony.ims.stub.ImsConfigImplBase getConfig(int); + method @NonNull public android.telephony.ims.stub.ImsConfigImplBase getConfigForSubscription(int, int); + method @NonNull public java.util.concurrent.Executor getExecutor(); method public long getImsServiceCapabilities(); - method public android.telephony.ims.stub.ImsRegistrationImplBase getRegistration(int); + method @Deprecated public android.telephony.ims.stub.ImsRegistrationImplBase getRegistration(int); + method @NonNull public android.telephony.ims.stub.ImsRegistrationImplBase getRegistrationForSubscription(int, int); method @Nullable public android.telephony.ims.stub.SipTransportImplBase getSipTransport(int); method public final void onUpdateSupportedImsFeatures(android.telephony.ims.stub.ImsFeatureConfiguration) throws android.os.RemoteException; method public android.telephony.ims.stub.ImsFeatureConfiguration querySupportedImsFeatures(); @@ -13556,18 +13134,16 @@ package android.telephony.ims { public class ProvisioningManager { method @NonNull public static android.telephony.ims.ProvisioningManager createForSubscriptionId(int); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public int getProvisioningIntValue(int); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean getProvisioningStatusForCapability(int, int); method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public String getProvisioningStringValue(int); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean getRcsProvisioningStatusForCapability(int); + method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean getRcsProvisioningStatusForCapability(int); method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION}) public boolean isRcsVolteSingleRegistrationCapable() throws android.telephony.ims.ImsException; method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void notifyRcsAutoConfigurationReceived(@NonNull byte[], boolean); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerProvisioningChangedCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ProvisioningManager.Callback) throws android.telephony.ims.ImsException; method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION}) public void registerRcsProvisioningCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ProvisioningManager.RcsProvisioningCallback) throws android.telephony.ims.ImsException; method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningIntValue(int, int); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setProvisioningStatusForCapability(int, int, boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningStringValue(int, @NonNull String); method @RequiresPermission(android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION) public void setRcsClientConfiguration(@NonNull android.telephony.ims.RcsClientConfiguration) throws android.telephony.ims.ImsException; - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setRcsProvisioningStatusForCapability(int, boolean); + method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setRcsProvisioningStatusForCapability(int, boolean); method @RequiresPermission(android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION) public void triggerRcsReconfiguration(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterProvisioningChangedCallback(@NonNull android.telephony.ims.ProvisioningManager.Callback); method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION}) public void unregisterRcsProvisioningCallback(@NonNull android.telephony.ims.ProvisioningManager.RcsProvisioningCallback); @@ -13614,6 +13190,7 @@ package android.telephony.ims { field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.RcsClientConfiguration> CREATOR; field public static final String RCS_PROFILE_1_0 = "UP_1.0"; field public static final String RCS_PROFILE_2_3 = "UP_2.3"; + field public static final String RCS_PROFILE_2_4 = "UP_2.4"; } public final class RcsContactPresenceTuple implements android.os.Parcelable { @@ -13724,6 +13301,7 @@ package android.telephony.ims { field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_3G = 6; // 0x6 field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_EHRPD = 4; // 0x4 field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_HSPAPLUS = 5; // 0x5 + field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_INTERNET_PDN = 12; // 0xc field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_IWLAN = 9; // 0x9 field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_DISABLED = 2; // 0x2 field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_ENABLED = 3; // 0x3 @@ -13949,6 +13527,7 @@ package android.telephony.ims.feature { public class MmTelFeature extends android.telephony.ims.feature.ImsFeature { ctor public MmTelFeature(); + ctor public MmTelFeature(@NonNull java.util.concurrent.Executor); method public void changeEnabledCapabilities(@NonNull android.telephony.ims.feature.CapabilityChangeRequest, @NonNull android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy); method public void changeOfferedRtpHeaderExtensionTypes(@NonNull java.util.Set<android.telephony.ims.RtpHeaderExtensionType>); method @Nullable public android.telephony.ims.ImsCallProfile createCallProfile(int, int); @@ -13982,7 +13561,7 @@ package android.telephony.ims.feature { } public class RcsFeature extends android.telephony.ims.feature.ImsFeature { - ctor @Deprecated public RcsFeature(); + ctor public RcsFeature(); ctor public RcsFeature(@NonNull java.util.concurrent.Executor); method public void changeEnabledCapabilities(@NonNull android.telephony.ims.feature.CapabilityChangeRequest, @NonNull android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy); method @NonNull public android.telephony.ims.stub.RcsCapabilityExchangeImplBase createCapabilityExchangeImpl(@NonNull android.telephony.ims.stub.CapabilityExchangeEventListener); @@ -13999,9 +13578,6 @@ package android.telephony.ims.feature { method public void addCapabilities(int); method public boolean isCapable(int); method public void removeCapabilities(int); - field public static final int CAPABILITY_TYPE_NONE = 0; // 0x0 - field public static final int CAPABILITY_TYPE_OPTIONS_UCE = 1; // 0x1 - field public static final int CAPABILITY_TYPE_PRESENCE_UCE = 2; // 0x2 } } @@ -14087,6 +13663,7 @@ package android.telephony.ims.stub { } public class ImsConfigImplBase { + ctor public ImsConfigImplBase(@NonNull java.util.concurrent.Executor); ctor public ImsConfigImplBase(); method public int getConfigInt(int); method public String getConfigString(int); @@ -14139,6 +13716,7 @@ package android.telephony.ims.stub { public class ImsRegistrationImplBase { ctor public ImsRegistrationImplBase(); + ctor public ImsRegistrationImplBase(@NonNull java.util.concurrent.Executor); method public final void onDeregistered(android.telephony.ims.ImsReasonInfo); method public final void onRegistered(int); method public final void onRegistered(@NonNull android.telephony.ims.ImsRegistrationAttributes); @@ -14149,11 +13727,6 @@ package android.telephony.ims.stub { method public void triggerFullNetworkRegistration(@IntRange(from=100, to=699) int, @Nullable String); method public void triggerSipDelegateDeregistration(); method public void updateSipDelegateRegistration(); - field public static final int REGISTRATION_TECH_CROSS_SIM = 2; // 0x2 - field public static final int REGISTRATION_TECH_IWLAN = 1; // 0x1 - field public static final int REGISTRATION_TECH_LTE = 0; // 0x0 - field public static final int REGISTRATION_TECH_NONE = -1; // 0xffffffff - field public static final int REGISTRATION_TECH_NR = 3; // 0x3 } public class ImsSmsImplBase { @@ -14251,6 +13824,7 @@ package android.telephony.ims.stub { } public class SipTransportImplBase { + ctor public SipTransportImplBase(); ctor public SipTransportImplBase(@NonNull java.util.concurrent.Executor); method public void createSipDelegate(int, @NonNull android.telephony.ims.DelegateRequest, @NonNull android.telephony.ims.DelegateStateCallback, @NonNull android.telephony.ims.DelegateMessageCallback); method public void destroySipDelegate(@NonNull android.telephony.ims.stub.SipDelegate, int); diff --git a/core/api/system-removed.txt b/core/api/system-removed.txt index 9a8a49397322..327bfef429ad 100644 --- a/core/api/system-removed.txt +++ b/core/api/system-removed.txt @@ -68,14 +68,6 @@ package android.app.search { } -package android.bluetooth { - - public final class BluetoothHeadset implements android.bluetooth.BluetoothProfile { - method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean setPriority(android.bluetooth.BluetoothDevice, int); - } - -} - package android.content { public class Intent implements java.lang.Cloneable android.os.Parcelable { diff --git a/core/api/test-current.txt b/core/api/test-current.txt index d0e659bf36e9..ae7265726331 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -675,14 +675,6 @@ package android.appwidget { } -package android.bluetooth { - - public final class BluetoothClass implements android.os.Parcelable { - method public int getClassOfDevice(); - } - -} - package android.content { public final class AttributionSource implements android.os.Parcelable { @@ -1715,8 +1707,11 @@ package android.os { public final class Parcel { method public boolean allowSquashing(); + method public int getFlags(); method public int readExceptionCode(); method public void restoreAllowSquashing(boolean); + field public static final int FLAG_IS_REPLY_FROM_BLOCKING_ALLOWED_OBJECT = 1; // 0x1 + field public static final int FLAG_PROPAGATE_ALLOW_BLOCKING = 2; // 0x2 } public class ParcelFileDescriptor implements java.io.Closeable android.os.Parcelable { @@ -2201,8 +2196,8 @@ package android.security { } public class KeyStoreException extends java.lang.Exception { - ctor public KeyStoreException(int, String); method public int getErrorCode(); + method public static boolean hasFailureInfoForError(int); } } @@ -2505,7 +2500,6 @@ package android.telephony { method @NonNull public java.util.List<android.telephony.data.ApnSetting> getDevicePolicyOverrideApns(@NonNull android.content.Context); method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getLine1AlphaTag(); method public android.util.Pair<java.lang.Integer,java.lang.Integer> getRadioHalVersion(); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getSupportedRadioAccessFamily(); method public boolean modifyDevicePolicyOverrideApn(@NonNull android.content.Context, int, @NonNull android.telephony.data.ApnSetting); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void refreshUiccProfile(); method @Deprecated public void setCarrierTestOverride(String, String, String, String, String, String, String); diff --git a/core/java/Android.bp b/core/java/Android.bp index 343830a468dc..27f3fc53101c 100644 --- a/core/java/Android.bp +++ b/core/java/Android.bp @@ -33,6 +33,11 @@ filegroup { srcs: ["android/tracing/ITracingServiceProxy.aidl"], } +filegroup { + name: "TraceReportParams.aidl", + srcs: ["android/tracing/TraceReportParams.aidl"], +} + // These are subset of framework-core-sources that are needed by the // android.test.mock library. The implementation of android.test.mock references // private members of various components to allow mocking of classes that cannot @@ -144,7 +149,6 @@ java_library { filegroup { name: "framework-services-net-module-wifi-shared-srcs", srcs: [ - "android/net/DhcpResults.java", "android/util/LocalLog.java", ], } @@ -160,6 +164,18 @@ filegroup { "com/android/internal/util/IndentingPrintWriter.java", "com/android/internal/util/MessageUtils.java", "com/android/internal/util/WakeupMessage.java", + // TODO: delete as soon as NetworkStatsFactory stops using + "com/android/internal/util/ProcFileReader.java", + ], +} + +// keep these files in sync with the packages/modules/Connectivity jarjar-rules.txt for +// the connectivity module. +filegroup { + name: "framework-connectivity-api-shared-srcs", + srcs: [ + "android/util/IndentingPrintWriter.java", + "com/android/internal/util/FileRotator.java", ], } diff --git a/core/java/android/app/ActivityTransitionState.java b/core/java/android/app/ActivityTransitionState.java index 62619509184a..877e7d3b3bf7 100644 --- a/core/java/android/app/ActivityTransitionState.java +++ b/core/java/android/app/ActivityTransitionState.java @@ -119,7 +119,7 @@ class ActivityTransitionState { for (int i = mExitTransitionCoordinators.size() - 1; i >= 0; i--) { WeakReference<ExitTransitionCoordinator> oldRef = mExitTransitionCoordinators.valueAt(i); - if (oldRef.get() == null) { + if (oldRef.refersTo(null)) { mExitTransitionCoordinators.removeAt(i); } } diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java index 198c33e83707..ab823983235c 100644 --- a/core/java/android/app/ResourcesManager.java +++ b/core/java/android/app/ResourcesManager.java @@ -678,8 +678,7 @@ public class ResourcesManager { int refCount = mResourceImpls.size(); for (int i = 0; i < refCount; i++) { WeakReference<ResourcesImpl> weakImplRef = mResourceImpls.valueAt(i); - ResourcesImpl impl = weakImplRef != null ? weakImplRef.get() : null; - if (resourceImpl == impl) { + if (weakImplRef != null && weakImplRef.refersTo(resourceImpl)) { return mResourceImpls.keyAt(i); } } @@ -1671,7 +1670,7 @@ public class ResourcesManager { for (int i = mResourceImpls.size() - 1; i >= 0; i--) { final ResourcesKey key = mResourceImpls.keyAt(i); final WeakReference<ResourcesImpl> impl = mResourceImpls.valueAt(i); - if (impl == null || impl.get() == null + if (impl == null || impl.refersTo(null) || !ArrayUtils.contains(key.mLoaders, loader)) { continue; } diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java index 6cfa39cd2337..ab645960ee2c 100644 --- a/core/java/android/app/WallpaperManager.java +++ b/core/java/android/app/WallpaperManager.java @@ -1452,18 +1452,27 @@ public class WallpaperManager { mContext.getUserId()); if (fd != null) { FileOutputStream fos = null; - boolean ok = false; + final Bitmap tmp = BitmapFactory.decodeStream(resources.openRawResource(resid)); try { - fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd); - copyStreamToWallpaperFile(resources.openRawResource(resid), fos); - // The 'close()' is the trigger for any server-side image manipulation, - // so we must do that before waiting for completion. - fos.close(); - completion.waitForCompletion(); + // If the stream can't be decoded, treat it as an invalid input. + if (tmp != null) { + fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd); + tmp.compress(Bitmap.CompressFormat.PNG, 100, fos); + // The 'close()' is the trigger for any server-side image manipulation, + // so we must do that before waiting for completion. + fos.close(); + completion.waitForCompletion(); + } else { + throw new IllegalArgumentException( + "Resource 0x" + Integer.toHexString(resid) + " is invalid"); + } } finally { // Might be redundant but completion shouldn't wait unless the write // succeeded; this is a fallback if it threw past the close+wait. IoUtils.closeQuietly(fos); + if (tmp != null) { + tmp.recycle(); + } } } } catch (RemoteException e) { @@ -1705,13 +1714,22 @@ public class WallpaperManager { result, which, completion, mContext.getUserId()); if (fd != null) { FileOutputStream fos = null; + final Bitmap tmp = BitmapFactory.decodeStream(bitmapData); try { - fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd); - copyStreamToWallpaperFile(bitmapData, fos); - fos.close(); - completion.waitForCompletion(); + // If the stream can't be decoded, treat it as an invalid input. + if (tmp != null) { + fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd); + tmp.compress(Bitmap.CompressFormat.PNG, 100, fos); + fos.close(); + completion.waitForCompletion(); + } else { + throw new IllegalArgumentException("InputStream is invalid"); + } } finally { IoUtils.closeQuietly(fos); + if (tmp != null) { + tmp.recycle(); + } } } } catch (RemoteException e) { diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 0fe80c45ad2a..3840f760eda8 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -10177,6 +10177,9 @@ public class DevicePolicyManager { * On fully-managed devices this method is unsupported because all traffic is considered * work traffic. * + * <p> This method enables preferential network service with a default configuration. + * To fine-tune the configuration, use {@link #setPreferentialNetworkServiceConfig) instead. + * * <p>This method can only be called by the profile owner of a managed profile. * @param enabled whether preferential network service should be enabled. * @throws SecurityException if the caller is not the profile owner. @@ -10215,6 +10218,56 @@ public class DevicePolicyManager { } /** + * Sets preferential network configuration on the work profile. + * {@see PreferentialNetworkServiceConfig} + * + * An example of a supported preferential network service is the Enterprise + * slice on 5G networks. + * + * By default, preferential network service is disabled on the work profile on supported + * carriers and devices. Admins can explicitly enable it with this API. + * On fully-managed devices this method is unsupported because all traffic is considered + * work traffic. + * + * <p>This method can only be called by the profile owner of a managed profile. + * @param preferentialNetworkServiceConfig preferential network configuration. + * @throws SecurityException if the caller is not the profile owner. + **/ + public void setPreferentialNetworkServiceConfig( + @NonNull PreferentialNetworkServiceConfig preferentialNetworkServiceConfig) { + throwIfParentInstance("setPreferentialNetworkServiceConfig"); + if (mService == null) { + return; + } + try { + mService.setPreferentialNetworkServiceConfig(preferentialNetworkServiceConfig); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Get preferential network configuration + * {@see PreferentialNetworkServiceConfig} + * + * <p>This method can be called by the profile owner of a managed profile. + * + * @return preferential network configuration. + * @throws SecurityException if the caller is not the profile owner. + */ + public @NonNull PreferentialNetworkServiceConfig getPreferentialNetworkServiceConfig() { + throwIfParentInstance("getPreferentialNetworkServiceConfig"); + if (mService == null) { + return PreferentialNetworkServiceConfig.DEFAULT; + } + try { + return mService.getPreferentialNetworkServiceConfig(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * This method is mostly deprecated. * Most of the settings that still have an effect have dedicated setter methods or user * restrictions. See individual settings for details. diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index d287437b143b..c78a5a00f645 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -21,6 +21,7 @@ import android.app.admin.NetworkEvent; import android.app.IApplicationThread; import android.app.IServiceConnection; import android.app.admin.ParcelableGranteeMap; +import android.app.admin.PreferentialNetworkServiceConfig; import android.app.admin.StartInstallingUpdateCallback; import android.app.admin.SystemUpdateInfo; import android.app.admin.SystemUpdatePolicy; @@ -278,6 +279,10 @@ interface IDevicePolicyManager { void setPreferentialNetworkServiceEnabled(in boolean enabled); boolean isPreferentialNetworkServiceEnabled(int userHandle); + void setPreferentialNetworkServiceConfig( + in PreferentialNetworkServiceConfig preferentialNetworkServiceConfig); + PreferentialNetworkServiceConfig getPreferentialNetworkServiceConfig(); + void setLockTaskPackages(in ComponentName who, in String[] packages); String[] getLockTaskPackages(in ComponentName who); boolean isLockTaskPermitted(in String pkg); diff --git a/core/java/android/app/admin/PreferentialNetworkServiceConfig.aidl b/core/java/android/app/admin/PreferentialNetworkServiceConfig.aidl new file mode 100644 index 000000000000..6b6ee7d8d538 --- /dev/null +++ b/core/java/android/app/admin/PreferentialNetworkServiceConfig.aidl @@ -0,0 +1,20 @@ +/* +** +** Copyright 2022, 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.app.admin; + +parcelable PreferentialNetworkServiceConfig;
\ No newline at end of file diff --git a/core/java/android/app/admin/PreferentialNetworkServiceConfig.java b/core/java/android/app/admin/PreferentialNetworkServiceConfig.java new file mode 100644 index 000000000000..2849139c606b --- /dev/null +++ b/core/java/android/app/admin/PreferentialNetworkServiceConfig.java @@ -0,0 +1,335 @@ +/* + * Copyright (C) 2022 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.app.admin; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.SuppressLint; +import android.os.Parcel; +import android.os.Parcelable; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.Objects; + +/** + * Network configuration to be set for the user profile + * {@see DevicePolicyManager#setPreferentialNetworkServiceConfig}. + */ +public final class PreferentialNetworkServiceConfig implements Parcelable { + final boolean mIsEnabled; + final int mNetworkId; + final boolean mAllowFallbackToDefaultConnection; + final int[] mIncludedUids; + final int[] mExcludedUids; + + /** @hide */ + public static final PreferentialNetworkServiceConfig DEFAULT = + (new PreferentialNetworkServiceConfig.Builder()).build(); + + /** + * Preferential network identifier 1. + */ + public static final int PREFERENTIAL_NETWORK_ID_1 = 1; + + /** + * Preferential network identifier 2. + */ + public static final int PREFERENTIAL_NETWORK_ID_2 = 2; + + /** + * Preferential network identifier 3. + */ + public static final int PREFERENTIAL_NETWORK_ID_3 = 3; + + /** + * Preferential network identifier 4. + */ + public static final int PREFERENTIAL_NETWORK_ID_4 = 4; + + /** + * Preferential network identifier 5. + */ + public static final int PREFERENTIAL_NETWORK_ID_5 = 5; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = { "PREFERENTIAL_NETWORK_ID_" }, value = { + PREFERENTIAL_NETWORK_ID_1, + PREFERENTIAL_NETWORK_ID_2, + PREFERENTIAL_NETWORK_ID_3, + PREFERENTIAL_NETWORK_ID_4, + PREFERENTIAL_NETWORK_ID_5, + }) + + public @interface PreferentialNetworkPreferenceId { + } + + private PreferentialNetworkServiceConfig(boolean isEnabled, + boolean allowFallbackToDefaultConnection, int[] includedUids, + int[] excludedUids, @PreferentialNetworkPreferenceId int networkId) { + mIsEnabled = isEnabled; + mAllowFallbackToDefaultConnection = allowFallbackToDefaultConnection; + mIncludedUids = includedUids; + mExcludedUids = excludedUids; + mNetworkId = networkId; + } + + private PreferentialNetworkServiceConfig(Parcel in) { + mIsEnabled = in.readBoolean(); + mAllowFallbackToDefaultConnection = in.readBoolean(); + mNetworkId = in.readInt(); + mIncludedUids = in.createIntArray(); + mExcludedUids = in.createIntArray(); + } + + /** + * Is the preferential network enabled. + * @return true if enabled else false + */ + public boolean isEnabled() { + return mIsEnabled; + } + + /** + * is fallback to default network allowed. This boolean configures whether default connection + * (default internet or wifi) should be used or not if a preferential network service + * connection is not available. + * @return true if fallback is allowed, else false. + */ + public boolean isFallbackToDefaultConnectionAllowed() { + return mAllowFallbackToDefaultConnection; + } + + /** + * Get the array of uids that are applicable for the profile preference. + * + * {@see #getExcludedUids()} + * Included UIDs and Excluded UIDs can't both be non-empty. + * if both are empty, it means this request applies to all uids in the user profile. + * if included is not empty, then only included UIDs are applied. + * if excluded is not empty, then it is all uids in the user profile except these UIDs. + * @return Array of uids applicable for the profile preference. + * Empty array would mean that this request applies to all uids in the profile. + */ + public @NonNull int[] getIncludedUids() { + return mIncludedUids; + } + + /** + * Get the array of uids that are excluded for the profile preference. + * + * {@see #getIncludedUids()} + * Included UIDs and Excluded UIDs can't both be non-empty. + * if both are empty, it means this request applies to all uids in the user profile. + * if included is not empty, then only included UIDs are applied. + * if excluded is not empty, then it is all uids in the user profile except these UIDs. + * @return Array of uids that are excluded for the profile preference. + * Empty array would mean that this request applies to all uids in the profile. + */ + public @NonNull int[] getExcludedUids() { + return mExcludedUids; + } + + /** + * @return preference enterprise identifier. + * valid values starts from + * {@link #PREFERENTIAL_NETWORK_ID_1} to {@link #PREFERENTIAL_NETWORK_ID_5}. + * preference identifier is applicable only if preference network service is enabled + * + */ + public @PreferentialNetworkPreferenceId int getNetworkId() { + return mNetworkId; + } + + @Override + public String toString() { + return "PreferentialNetworkServiceConfig{" + + "mIsEnabled=" + isEnabled() + + "mAllowFallbackToDefaultConnection=" + isFallbackToDefaultConnectionAllowed() + + "mIncludedUids=" + mIncludedUids.toString() + + "mExcludedUids=" + mExcludedUids.toString() + + "mNetworkId=" + mNetworkId + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + final PreferentialNetworkServiceConfig that = (PreferentialNetworkServiceConfig) o; + return mIsEnabled == that.mIsEnabled + && mAllowFallbackToDefaultConnection == that.mAllowFallbackToDefaultConnection + && mNetworkId == that.mNetworkId + && Objects.equals(mIncludedUids, that.mIncludedUids) + && Objects.equals(mExcludedUids, that.mExcludedUids); + } + + @Override + public int hashCode() { + return ((Objects.hashCode(mIsEnabled) * 17) + + (Objects.hashCode(mAllowFallbackToDefaultConnection) * 19) + + (Objects.hashCode(mIncludedUids) * 23) + + (Objects.hashCode(mExcludedUids) * 29) + + mNetworkId * 31); + } + + /** + * Builder used to create {@link PreferentialNetworkServiceConfig} objects. + * Specify the preferred Network preference + */ + public static final class Builder { + boolean mIsEnabled = false; + int mNetworkId = 0; + boolean mAllowFallbackToDefaultConnection = true; + int[] mIncludedUids = new int[0]; + int[] mExcludedUids = new int[0]; + + /** + * Constructs an empty Builder with preferential network disabled by default. + */ + public Builder() {} + + /** + * Set the preferential network service enabled state. + * Default value is false. + * @param isEnabled the desired network preference to use, true to enable else false + * @return The builder to facilitate chaining. + */ + @NonNull + public PreferentialNetworkServiceConfig.Builder setEnabled(boolean isEnabled) { + mIsEnabled = isEnabled; + return this; + } + + /** + * Set whether the default connection should be used as fallback. + * This boolean configures whether the default connection (default internet or wifi) + * should be used if a preferential network service connection is not available. + * Default value is true + * @param allowFallbackToDefaultConnection true if fallback is allowed else false + * @return The builder to facilitate chaining. + */ + @NonNull + @SuppressLint("MissingGetterMatchingBuilder") + public PreferentialNetworkServiceConfig.Builder setFallbackToDefaultConnectionAllowed( + boolean allowFallbackToDefaultConnection) { + mAllowFallbackToDefaultConnection = allowFallbackToDefaultConnection; + return this; + } + + /** + * Set the array of uids whose network access will go through this preferential + * network service. + * {@see #setExcludedUids(int[])} + * Included UIDs and Excluded UIDs can't both be non-empty. + * if both are empty, it means this request applies to all uids in the user profile. + * if included is not empty, then only included UIDs are applied. + * if excluded is not empty, then it is all uids in the user profile except these UIDs. + * @param uids array of included uids + * @return The builder to facilitate chaining. + */ + @NonNull + public PreferentialNetworkServiceConfig.Builder setIncludedUids( + @NonNull int[] uids) { + Objects.requireNonNull(uids); + mIncludedUids = uids; + return this; + } + + /** + * Set the array of uids who are not allowed through this preferential + * network service. + * {@see #setIncludedUids(int[])} + * Included UIDs and Excluded UIDs can't both be non-empty. + * if both are empty, it means this request applies to all uids in the user profile. + * if included is not empty, then only included UIDs are applied. + * if excluded is not empty, then it is all uids in the user profile except these UIDs. + * @param uids array of excluded uids + * @return The builder to facilitate chaining. + */ + @NonNull + public PreferentialNetworkServiceConfig.Builder setExcludedUids( + @NonNull int[] uids) { + Objects.requireNonNull(uids); + mExcludedUids = uids; + return this; + } + + /** + * Returns an instance of {@link PreferentialNetworkServiceConfig} created from the + * fields set on this builder. + */ + @NonNull + public PreferentialNetworkServiceConfig build() { + if (mIncludedUids.length > 0 && mExcludedUids.length > 0) { + throw new IllegalStateException("Both includedUids and excludedUids " + + "cannot be nonempty"); + } + return new PreferentialNetworkServiceConfig(mIsEnabled, + mAllowFallbackToDefaultConnection, mIncludedUids, mExcludedUids, mNetworkId); + } + + /** + * Set the preferential network identifier. + * Valid values starts from {@link #PREFERENTIAL_NETWORK_ID_1} to + * {@link #PREFERENTIAL_NETWORK_ID_5}. + * preference identifier is applicable only if preferential network service is enabled. + * @param preferenceId preference Id + * @return The builder to facilitate chaining. + */ + @NonNull + public PreferentialNetworkServiceConfig.Builder setNetworkId( + @PreferentialNetworkPreferenceId int preferenceId) { + if ((preferenceId < PREFERENTIAL_NETWORK_ID_1) + || (preferenceId > PREFERENTIAL_NETWORK_ID_5)) { + throw new IllegalArgumentException("Invalid preference identifier"); + } + mNetworkId = preferenceId; + return this; + } + } + + @Override + public void writeToParcel(@NonNull android.os.Parcel dest, int flags) { + dest.writeBoolean(mIsEnabled); + dest.writeBoolean(mAllowFallbackToDefaultConnection); + dest.writeInt(mNetworkId); + dest.writeIntArray(mIncludedUids); + dest.writeIntArray(mExcludedUids); + } + + @Override + public int describeContents() { + return 0; + } + + @NonNull + public static final Creator<PreferentialNetworkServiceConfig> CREATOR = + new Creator<PreferentialNetworkServiceConfig>() { + @Override + public PreferentialNetworkServiceConfig[] newArray(int size) { + return new PreferentialNetworkServiceConfig[size]; + } + + @Override + public PreferentialNetworkServiceConfig createFromParcel( + @NonNull android.os.Parcel in) { + return new PreferentialNetworkServiceConfig(in); + } + }; +} diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 98e124d7e8f4..30850e3ba06c 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -5778,6 +5778,17 @@ public abstract class Context { public static final String DISPLAY_HASH_SERVICE = "display_hash"; /** + * Use with {@link #getSystemService(String)} to retrieve a + * {@link android.nearby.NearbyManager} to discover nearby devices. + * + * @see #getSystemService(String) + * @see android.nearby.NearbyManager + * @hide + */ + @SystemApi + public static final String NEARBY_SERVICE = "nearby"; + + /** * Determine whether the given permission is allowed for a particular * process and user ID running in the system. * diff --git a/core/java/android/content/res/ColorStateList.java b/core/java/android/content/res/ColorStateList.java index 5b727cc47d47..5031faa81afa 100644 --- a/core/java/android/content/res/ColorStateList.java +++ b/core/java/android/content/res/ColorStateList.java @@ -198,7 +198,7 @@ public class ColorStateList extends ComplexColor implements Parcelable { // Prune the cache before adding new items. final int N = sCache.size(); for (int i = N - 1; i >= 0; i--) { - if (sCache.valueAt(i).get() == null) { + if (sCache.valueAt(i).refersTo(null)) { sCache.removeAt(i); } } diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java index 12e41e299e16..932cc8e402e1 100644 --- a/core/java/android/content/res/Resources.java +++ b/core/java/android/content/res/Resources.java @@ -2011,7 +2011,7 @@ public class Resources { // Clean up references to garbage collected themes if (mThemeRefs.size() > mThemeRefsNextFlushSize) { - mThemeRefs.removeIf(ref -> ref.get() == null); + mThemeRefs.removeIf(ref -> ref.refersTo(null)); mThemeRefsNextFlushSize = Math.max(MIN_THEME_REFS_FLUSH_SIZE, 2 * mThemeRefs.size()); } diff --git a/core/java/android/content/res/loader/ResourcesLoader.java b/core/java/android/content/res/loader/ResourcesLoader.java index c3084003c304..cf6e166b82ed 100644 --- a/core/java/android/content/res/loader/ResourcesLoader.java +++ b/core/java/android/content/res/loader/ResourcesLoader.java @@ -257,7 +257,7 @@ public class ResourcesLoader { for (int i = mChangeCallbacks.size() - 1; i >= 0; i--) { final WeakReference<Object> key = mChangeCallbacks.keyAt(i); - if (key.get() == null) { + if (key.refersTo(null)) { mChangeCallbacks.removeAt(i); } else { uniqueCallbacks.add(mChangeCallbacks.valueAt(i)); diff --git a/core/java/android/hardware/OWNERS b/core/java/android/hardware/OWNERS index 4143bfcb9c0a..ce5cf674b5be 100644 --- a/core/java/android/hardware/OWNERS +++ b/core/java/android/hardware/OWNERS @@ -1,3 +1,9 @@ +# Generic +etalvala@google.com +jreck@google.com +michaelwr@google.com +sumir@google.com + # Camera per-file *Camera*=cychen@google.com,epeev@google.com,etalvala@google.com,shuzhenwang@google.com,zhijunhe@google.com,jchowdhary@google.com diff --git a/core/java/android/hardware/hdmi/HdmiClient.java b/core/java/android/hardware/hdmi/HdmiClient.java index 0c21746ea412..066de11d0623 100644 --- a/core/java/android/hardware/hdmi/HdmiClient.java +++ b/core/java/android/hardware/hdmi/HdmiClient.java @@ -17,6 +17,8 @@ import android.util.Log; public abstract class HdmiClient { private static final String TAG = "HdmiClient"; + private static final int UNKNOWN_VENDOR_ID = 0xFFFFFF; + /* package */ final IHdmiControlService mService; private IHdmiVendorCommandListener mIHdmiVendorCommandListener; @@ -94,11 +96,25 @@ public abstract class HdmiClient { } /** - * Sets a listener used to receive incoming vendor-specific command. + * Sets a listener used to receive incoming vendor-specific command. This listener will only + * receive {@code <Vendor Command>} but will not receive any {@code <Vendor Command with ID>} + * messages. * * @param listener listener object */ public void setVendorCommandListener(@NonNull VendorCommandListener listener) { + // Set the vendor ID to INVALID_VENDOR_ID. + setVendorCommandListener(listener, UNKNOWN_VENDOR_ID); + } + + /** + * Sets a listener used to receive incoming vendor-specific command. + * + * @param listener listener object + * @param vendorId The listener is interested in {@code <Vendor Command with ID>} received with + * this vendorId and all {@code <Vendor Command>} messages. + */ + public void setVendorCommandListener(@NonNull VendorCommandListener listener, int vendorId) { if (listener == null) { throw new IllegalArgumentException("listener cannot be null"); } @@ -107,7 +123,7 @@ public abstract class HdmiClient { } try { IHdmiVendorCommandListener wrappedListener = getListenerWrapper(listener); - mService.addVendorCommandListener(wrappedListener, getDeviceType()); + mService.addVendorCommandListener(wrappedListener, vendorId); mIHdmiVendorCommandListener = wrappedListener; } catch (RemoteException e) { Log.e(TAG, "failed to set vendor command listener: ", e); diff --git a/core/java/android/hardware/hdmi/HdmiControlServiceWrapper.java b/core/java/android/hardware/hdmi/HdmiControlServiceWrapper.java index 9a9e945a91cf..45b0689a90d4 100644 --- a/core/java/android/hardware/hdmi/HdmiControlServiceWrapper.java +++ b/core/java/android/hardware/hdmi/HdmiControlServiceWrapper.java @@ -221,8 +221,8 @@ public final class HdmiControlServiceWrapper { } @Override - public void addVendorCommandListener(IHdmiVendorCommandListener listener, int deviceType) { - HdmiControlServiceWrapper.this.addVendorCommandListener(listener, deviceType); + public void addVendorCommandListener(IHdmiVendorCommandListener listener, int vendorId) { + HdmiControlServiceWrapper.this.addVendorCommandListener(listener, vendorId); } @Override @@ -471,7 +471,7 @@ public final class HdmiControlServiceWrapper { boolean hasVendorId) {} /** @hide */ - public void addVendorCommandListener(IHdmiVendorCommandListener listener, int deviceType) {} + public void addVendorCommandListener(IHdmiVendorCommandListener listener, int vendorId) {} /** @hide */ public void sendStandby(int deviceType, int deviceId) {} diff --git a/core/java/android/hardware/hdmi/IHdmiControlService.aidl b/core/java/android/hardware/hdmi/IHdmiControlService.aidl index 7f0e53ea2e68..48177e1726c4 100644 --- a/core/java/android/hardware/hdmi/IHdmiControlService.aidl +++ b/core/java/android/hardware/hdmi/IHdmiControlService.aidl @@ -76,7 +76,7 @@ interface IHdmiControlService { void askRemoteDeviceToBecomeActiveSource(int physicalAddress); void sendVendorCommand(int deviceType, int targetAddress, in byte[] params, boolean hasVendorId); - void addVendorCommandListener(IHdmiVendorCommandListener listener, int deviceType); + void addVendorCommandListener(IHdmiVendorCommandListener listener, int vendorId); void sendStandby(int deviceType, int deviceId); void setHdmiRecordListener(IHdmiRecordListener callback); void startOneTouchRecord(int recorderAddress, in byte[] recordSource); diff --git a/core/java/android/net/DhcpResults.aidl b/core/java/android/net/DhcpResults.aidl deleted file mode 100644 index f4db3c366d1e..000000000000 --- a/core/java/android/net/DhcpResults.aidl +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Copyright (c) 2012, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -parcelable DhcpResults; diff --git a/core/java/android/net/DhcpResults.java b/core/java/android/net/DhcpResults.java deleted file mode 100644 index 82ba156b08d0..000000000000 --- a/core/java/android/net/DhcpResults.java +++ /dev/null @@ -1,330 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.annotation.Nullable; -import android.compat.annotation.UnsupportedAppUsage; -import android.os.Build; -import android.os.Parcel; -import android.os.Parcelable; -import android.text.TextUtils; -import android.util.Log; - -import com.android.net.module.util.InetAddressUtils; - -import java.net.Inet4Address; -import java.net.InetAddress; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; - -/** - * A simple object for retrieving the results of a DHCP request. - * Optimized (attempted) for that jni interface - * TODO: remove this class and replace with other existing constructs - * @hide - */ -public final class DhcpResults implements Parcelable { - private static final String TAG = "DhcpResults"; - - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - public LinkAddress ipAddress; - - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - public InetAddress gateway; - - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - public final ArrayList<InetAddress> dnsServers = new ArrayList<>(); - - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - public String domains; - - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - public Inet4Address serverAddress; - - /** Vendor specific information (from RFC 2132). */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - public String vendorInfo; - - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - public int leaseDuration; - - /** Link MTU option. 0 means unset. */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - public int mtu; - - public String serverHostName; - - @Nullable - public String captivePortalApiUrl; - - public DhcpResults() { - super(); - } - - /** - * Create a {@link StaticIpConfiguration} based on the DhcpResults. - */ - public StaticIpConfiguration toStaticIpConfiguration() { - return new StaticIpConfiguration.Builder() - .setIpAddress(ipAddress) - .setGateway(gateway) - .setDnsServers(dnsServers) - .setDomains(domains) - .build(); - } - - public DhcpResults(StaticIpConfiguration source) { - if (source != null) { - ipAddress = source.getIpAddress(); - gateway = source.getGateway(); - dnsServers.addAll(source.getDnsServers()); - domains = source.getDomains(); - } - } - - /** copy constructor */ - public DhcpResults(DhcpResults source) { - this(source == null ? null : source.toStaticIpConfiguration()); - if (source != null) { - serverAddress = source.serverAddress; - vendorInfo = source.vendorInfo; - leaseDuration = source.leaseDuration; - mtu = source.mtu; - serverHostName = source.serverHostName; - captivePortalApiUrl = source.captivePortalApiUrl; - } - } - - /** - * @see StaticIpConfiguration#getRoutes(String) - * @hide - */ - public List<RouteInfo> getRoutes(String iface) { - return toStaticIpConfiguration().getRoutes(iface); - } - - /** - * Test if this DHCP lease includes vendor hint that network link is - * metered, and sensitive to heavy data transfers. - */ - public boolean hasMeteredHint() { - if (vendorInfo != null) { - return vendorInfo.contains("ANDROID_METERED"); - } else { - return false; - } - } - - public void clear() { - ipAddress = null; - gateway = null; - dnsServers.clear(); - domains = null; - serverAddress = null; - vendorInfo = null; - leaseDuration = 0; - mtu = 0; - serverHostName = null; - captivePortalApiUrl = null; - } - - @Override - public String toString() { - StringBuffer str = new StringBuffer(super.toString()); - - str.append(" DHCP server ").append(serverAddress); - str.append(" Vendor info ").append(vendorInfo); - str.append(" lease ").append(leaseDuration).append(" seconds"); - if (mtu != 0) str.append(" MTU ").append(mtu); - str.append(" Servername ").append(serverHostName); - if (captivePortalApiUrl != null) { - str.append(" CaptivePortalApiUrl ").append(captivePortalApiUrl); - } - - return str.toString(); - } - - @Override - public boolean equals(@Nullable Object obj) { - if (this == obj) return true; - - if (!(obj instanceof DhcpResults)) return false; - - DhcpResults target = (DhcpResults)obj; - - return toStaticIpConfiguration().equals(target.toStaticIpConfiguration()) - && Objects.equals(serverAddress, target.serverAddress) - && Objects.equals(vendorInfo, target.vendorInfo) - && Objects.equals(serverHostName, target.serverHostName) - && leaseDuration == target.leaseDuration - && mtu == target.mtu - && Objects.equals(captivePortalApiUrl, target.captivePortalApiUrl); - } - - /** - * Implement the Parcelable interface - */ - public static final @android.annotation.NonNull Creator<DhcpResults> CREATOR = - new Creator<DhcpResults>() { - public DhcpResults createFromParcel(Parcel in) { - return readFromParcel(in); - } - - public DhcpResults[] newArray(int size) { - return new DhcpResults[size]; - } - }; - - /** Implement the Parcelable interface */ - public void writeToParcel(Parcel dest, int flags) { - toStaticIpConfiguration().writeToParcel(dest, flags); - dest.writeInt(leaseDuration); - dest.writeInt(mtu); - InetAddressUtils.parcelInetAddress(dest, serverAddress, flags); - dest.writeString(vendorInfo); - dest.writeString(serverHostName); - dest.writeString(captivePortalApiUrl); - } - - @Override - public int describeContents() { - return 0; - } - - private static DhcpResults readFromParcel(Parcel in) { - final StaticIpConfiguration s = StaticIpConfiguration.CREATOR.createFromParcel(in); - final DhcpResults dhcpResults = new DhcpResults(s); - dhcpResults.leaseDuration = in.readInt(); - dhcpResults.mtu = in.readInt(); - dhcpResults.serverAddress = (Inet4Address) InetAddressUtils.unparcelInetAddress(in); - dhcpResults.vendorInfo = in.readString(); - dhcpResults.serverHostName = in.readString(); - dhcpResults.captivePortalApiUrl = in.readString(); - return dhcpResults; - } - - // Utils for jni population - false on success - // Not part of the superclass because they're only used by the JNI iterface to the DHCP daemon. - public boolean setIpAddress(String addrString, int prefixLength) { - try { - Inet4Address addr = (Inet4Address) InetAddresses.parseNumericAddress(addrString); - ipAddress = new LinkAddress(addr, prefixLength); - } catch (IllegalArgumentException|ClassCastException e) { - Log.e(TAG, "setIpAddress failed with addrString " + addrString + "/" + prefixLength); - return true; - } - return false; - } - - public boolean setGateway(String addrString) { - try { - gateway = InetAddresses.parseNumericAddress(addrString); - } catch (IllegalArgumentException e) { - Log.e(TAG, "setGateway failed with addrString " + addrString); - return true; - } - return false; - } - - public boolean addDns(String addrString) { - if (TextUtils.isEmpty(addrString) == false) { - try { - dnsServers.add(InetAddresses.parseNumericAddress(addrString)); - } catch (IllegalArgumentException e) { - Log.e(TAG, "addDns failed with addrString " + addrString); - return true; - } - } - return false; - } - - public LinkAddress getIpAddress() { - return ipAddress; - } - - public void setIpAddress(LinkAddress ipAddress) { - this.ipAddress = ipAddress; - } - - public InetAddress getGateway() { - return gateway; - } - - public void setGateway(InetAddress gateway) { - this.gateway = gateway; - } - - public List<InetAddress> getDnsServers() { - return dnsServers; - } - - /** - * Add a DNS server to this configuration. - */ - public void addDnsServer(InetAddress server) { - dnsServers.add(server); - } - - public String getDomains() { - return domains; - } - - public void setDomains(String domains) { - this.domains = domains; - } - - public Inet4Address getServerAddress() { - return serverAddress; - } - - public void setServerAddress(Inet4Address addr) { - serverAddress = addr; - } - - public int getLeaseDuration() { - return leaseDuration; - } - - public void setLeaseDuration(int duration) { - leaseDuration = duration; - } - - public String getVendorInfo() { - return vendorInfo; - } - - public void setVendorInfo(String info) { - vendorInfo = info; - } - - public int getMtu() { - return mtu; - } - - public void setMtu(int mtu) { - this.mtu = mtu; - } - - public String getCaptivePortalApiUrl() { - return captivePortalApiUrl; - } - - public void setCaptivePortalApiUrl(String url) { - captivePortalApiUrl = url; - } -} diff --git a/core/java/android/net/IVpnManager.aidl b/core/java/android/net/IVpnManager.aidl index 271efe41a9ef..070efa363cc0 100644 --- a/core/java/android/net/IVpnManager.aidl +++ b/core/java/android/net/IVpnManager.aidl @@ -38,7 +38,7 @@ interface IVpnManager { /** VpnManager APIs */ boolean provisionVpnProfile(in VpnProfile profile, String packageName); void deleteVpnProfile(String packageName); - void startVpnProfile(String packageName); + String startVpnProfile(String packageName); void stopVpnProfile(String packageName); /** Always-on VPN APIs */ diff --git a/core/java/android/net/Ikev2VpnProfile.java b/core/java/android/net/Ikev2VpnProfile.java index 55541377a0bf..ec752fdbf45f 100644 --- a/core/java/android/net/Ikev2VpnProfile.java +++ b/core/java/android/net/Ikev2VpnProfile.java @@ -25,6 +25,12 @@ import static android.net.IpSecAlgorithm.AUTH_HMAC_SHA384; import static android.net.IpSecAlgorithm.AUTH_HMAC_SHA512; import static android.net.IpSecAlgorithm.CRYPT_AES_CBC; import static android.net.IpSecAlgorithm.CRYPT_AES_CTR; +import static android.net.eap.EapSessionConfig.EapMsChapV2Config; +import static android.net.ipsec.ike.IkeSessionParams.IkeAuthConfig; +import static android.net.ipsec.ike.IkeSessionParams.IkeAuthDigitalSignLocalConfig; +import static android.net.ipsec.ike.IkeSessionParams.IkeAuthDigitalSignRemoteConfig; +import static android.net.ipsec.ike.IkeSessionParams.IkeAuthEapConfig; +import static android.net.ipsec.ike.IkeSessionParams.IkeAuthPskConfig; import static com.android.internal.annotations.VisibleForTesting.Visibility; import static com.android.internal.util.Preconditions.checkStringNotEmpty; @@ -34,6 +40,14 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresFeature; import android.content.pm.PackageManager; +import android.net.ipsec.ike.IkeFqdnIdentification; +import android.net.ipsec.ike.IkeIdentification; +import android.net.ipsec.ike.IkeIpv4AddrIdentification; +import android.net.ipsec.ike.IkeIpv6AddrIdentification; +import android.net.ipsec.ike.IkeKeyIdIdentification; +import android.net.ipsec.ike.IkeRfc822AddrIdentification; +import android.net.ipsec.ike.IkeSessionParams; +import android.net.ipsec.ike.IkeTunnelConnectionParams; import android.security.Credentials; import android.util.Log; @@ -145,8 +159,9 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { boolean isMetered, int maxMtu, boolean restrictToTestNetworks, - boolean excludeLocalRoutes) { - super(type, excludeLocalRoutes); + boolean excludeLocalRoutes, + boolean requiresInternetValidation) { + super(type, excludeLocalRoutes, requiresInternetValidation); checkNotNull(serverAddr, MISSING_PARAM_MSG_TMPL, "Server address"); checkNotNull(userIdentity, MISSING_PARAM_MSG_TMPL, "User Identity"); @@ -167,7 +182,7 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { mAllowedAlgorithms = Collections.unmodifiableList(new ArrayList<>(allowedAlgorithms)); if (excludeLocalRoutes && !isBypassable) { throw new IllegalArgumentException( - "Vpn should be byassable if excludeLocalRoutes is set"); + "Vpn must be bypassable if excludeLocalRoutes is set"); } mIsBypassable = isBypassable; @@ -224,7 +239,7 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { * that provides Authentication, and one that provides Encryption. Authenticated Encryption with * Associated Data (AEAD) algorithms are counted as providing Authentication and Encryption. * - * @param allowedAlgorithms The list to be validated + * @param algorithmNames The list to be validated */ private static void validateAllowedAlgorithms(@NonNull List<String> algorithmNames) { // First, make sure no insecure algorithms were proposed. @@ -386,7 +401,9 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { mIsBypassable, mIsMetered, mMaxMtu, - mIsRestrictedToTestNetworks); + mIsRestrictedToTestNetworks, + mExcludeLocalRoutes, + mRequiresInternetValidation); } @Override @@ -411,7 +428,8 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { && mIsMetered == other.mIsMetered && mMaxMtu == other.mMaxMtu && mIsRestrictedToTestNetworks == other.mIsRestrictedToTestNetworks - && mExcludeLocalRoutes == other.mExcludeLocalRoutes; + && mExcludeLocalRoutes == other.mExcludeLocalRoutes + && mRequiresInternetValidation == other.mRequiresInternetValidation; } /** @@ -425,7 +443,7 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { @NonNull public VpnProfile toVpnProfile() throws IOException, GeneralSecurityException { final VpnProfile profile = new VpnProfile("" /* Key; value unused by IKEv2VpnProfile(s) */, - mIsRestrictedToTestNetworks, mExcludeLocalRoutes); + mIsRestrictedToTestNetworks, mExcludeLocalRoutes, mRequiresInternetValidation); profile.type = mType; profile.server = mServerAddr; profile.ipsecIdentifier = mUserIdentity; @@ -530,6 +548,7 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { Log.w(TAG, "ExcludeLocalRoutes should only be set in the bypassable VPN"); } builder.setExcludeLocalRoutes(profile.excludeLocalRoutes && profile.isBypassable); + builder.setRequiresInternetValidation(profile.requiresInternetValidation); return builder.build(); } @@ -644,6 +663,102 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { return Objects.requireNonNull(reference, String.format(messageTemplate, messageArgs)); } + private static void checkBuilderSetter(boolean constructedFromIkeTunConParams, + @NonNull String message) { + if (constructedFromIkeTunConParams) { + throw new IllegalArgumentException("Constructed using IkeTunnelConnectionParams " + + "should not set " + message); + } + } + + private static int getTypeFromIkeSession(@NonNull IkeSessionParams params) { + final IkeAuthConfig config = params.getLocalAuthConfig(); + if (config instanceof IkeAuthDigitalSignLocalConfig) { + return TYPE_IKEV2_IPSEC_RSA; + } else if (config instanceof IkeAuthEapConfig) { + return TYPE_IKEV2_IPSEC_USER_PASS; + } else if (config instanceof IkeAuthPskConfig) { + return TYPE_IKEV2_IPSEC_PSK; + } else { + throw new IllegalStateException("Invalid local IkeAuthConfig"); + } + } + + @Nullable + private static String getPasswordFromIkeSession(@NonNull IkeSessionParams params) { + if (!(params.getLocalAuthConfig() instanceof IkeAuthEapConfig)) return null; + + final IkeAuthEapConfig ikeAuthEapConfig = (IkeAuthEapConfig) params.getLocalAuthConfig(); + final EapMsChapV2Config eapMsChapV2Config = + ikeAuthEapConfig.getEapConfig().getEapMsChapV2Config(); + return (eapMsChapV2Config != null) ? eapMsChapV2Config.getPassword() : null; + } + + @Nullable + private static String getUsernameFromIkeSession(@NonNull IkeSessionParams params) { + if (!(params.getLocalAuthConfig() instanceof IkeAuthEapConfig)) return null; + + final IkeAuthEapConfig ikeAuthEapConfig = (IkeAuthEapConfig) params.getLocalAuthConfig(); + final EapMsChapV2Config eapMsChapV2Config = + ikeAuthEapConfig.getEapConfig().getEapMsChapV2Config(); + return (eapMsChapV2Config != null) ? eapMsChapV2Config.getUsername() : null; + } + + @Nullable + private static X509Certificate getUserCertFromIkeSession(@NonNull IkeSessionParams params) { + if (!(params.getLocalAuthConfig() instanceof IkeAuthDigitalSignLocalConfig)) return null; + + final IkeAuthDigitalSignLocalConfig config = + (IkeAuthDigitalSignLocalConfig) params.getLocalAuthConfig(); + return config.getClientEndCertificate(); + } + + @Nullable + private static X509Certificate getServerRootCaCertFromIkeSession( + @NonNull IkeSessionParams params) { + if (!(params.getRemoteAuthConfig() instanceof IkeAuthDigitalSignRemoteConfig)) return null; + + final IkeAuthDigitalSignRemoteConfig config = + (IkeAuthDigitalSignRemoteConfig) params.getRemoteAuthConfig(); + return config.getRemoteCaCert(); + } + + @Nullable + private static PrivateKey getRsaPrivateKeyFromIkeSession(@NonNull IkeSessionParams params) { + if (!(params.getLocalAuthConfig() instanceof IkeAuthDigitalSignLocalConfig)) return null; + + final IkeAuthDigitalSignLocalConfig config = + (IkeAuthDigitalSignLocalConfig) params.getLocalAuthConfig(); + return config.getPrivateKey(); + } + + @Nullable + private static byte[] getPresharedKeyFromIkeSession(@NonNull IkeSessionParams params) { + if (!(params.getLocalAuthConfig() instanceof IkeAuthPskConfig)) return null; + + final IkeAuthPskConfig config = (IkeAuthPskConfig) params.getLocalAuthConfig(); + return config.getPsk(); + } + + @NonNull + private static String getUserIdentityFromIkeSession(@NonNull IkeSessionParams params) { + final IkeIdentification ident = params.getLocalIdentification(); + // Refer to VpnIkev2Utils.parseIkeIdentification(). + if (ident instanceof IkeKeyIdIdentification) { + return "@#" + new String(((IkeKeyIdIdentification) ident).keyId); + } else if (ident instanceof IkeRfc822AddrIdentification) { + return "@@" + ((IkeRfc822AddrIdentification) ident).rfc822Name; + } else if (ident instanceof IkeFqdnIdentification) { + return "@" + ((IkeFqdnIdentification) ident).fqdn; + } else if (ident instanceof IkeIpv4AddrIdentification) { + return ((IkeIpv4AddrIdentification) ident).ipv4Address.getHostAddress(); + } else if (ident instanceof IkeIpv6AddrIdentification) { + return ((IkeIpv6AddrIdentification) ident).ipv6Address.getHostAddress(); + } else { + throw new IllegalArgumentException("Unknown IkeIdentification to get user identity"); + } + } + /** A incremental builder for IKEv2 VPN profiles */ public static final class Builder { private int mType = -1; @@ -666,11 +781,13 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { @Nullable private ProxyInfo mProxyInfo; @NonNull private List<String> mAllowedAlgorithms = DEFAULT_ALGORITHMS; + private boolean mRequiresInternetValidation = false; private boolean mIsBypassable = false; private boolean mIsMetered = true; private int mMaxMtu = PlatformVpnProfile.MAX_MTU_DEFAULT; private boolean mIsRestrictedToTestNetworks = false; private boolean mExcludeLocalRoutes = false; + @Nullable private IkeTunnelConnectionParams mIkeTunConnParams; /** * Creates a new builder with the basic parameters of an IKEv2/IPsec VPN. @@ -687,6 +804,32 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { mUserIdentity = identity; } + /** + * Creates a new builder from a {@link IkeTunnelConnectionParams} + * + * @param ikeTunConnParams the {@link IkeTunnelConnectionParams} contains IKEv2 + * configurations + */ + @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) + public Builder(@NonNull IkeTunnelConnectionParams ikeTunConnParams) { + checkNotNull(ikeTunConnParams, MISSING_PARAM_MSG_TMPL, "ikeTunConnParams"); + + mIkeTunConnParams = ikeTunConnParams; + + final IkeSessionParams ikeSessionParams = mIkeTunConnParams.getIkeSessionParams(); + mServerAddr = ikeSessionParams.getServerHostname(); + + mType = getTypeFromIkeSession(ikeSessionParams); + mUserCert = getUserCertFromIkeSession(ikeSessionParams); + mServerRootCaCert = getServerRootCaCertFromIkeSession(ikeSessionParams); + mRsaPrivateKey = getRsaPrivateKeyFromIkeSession(ikeSessionParams); + mServerRootCaCert = getServerRootCaCertFromIkeSession(ikeSessionParams); + mUsername = getUsernameFromIkeSession(ikeSessionParams); + mPassword = getPasswordFromIkeSession(ikeSessionParams); + mPresharedKey = getPresharedKeyFromIkeSession(ikeSessionParams); + mUserIdentity = getUserIdentityFromIkeSession(ikeSessionParams); + } + private void resetAuthParams() { mPresharedKey = null; mServerRootCaCert = null; @@ -719,6 +862,7 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { @Nullable X509Certificate serverRootCa) { checkNotNull(user, MISSING_PARAM_MSG_TMPL, "user"); checkNotNull(pass, MISSING_PARAM_MSG_TMPL, "pass"); + checkBuilderSetter(mIkeTunConnParams != null, "authUsernamePassword"); // Test to make sure all auth params can be encoded safely. if (serverRootCa != null) checkCert(serverRootCa); @@ -755,6 +899,7 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { @Nullable X509Certificate serverRootCa) { checkNotNull(userCert, MISSING_PARAM_MSG_TMPL, "userCert"); checkNotNull(key, MISSING_PARAM_MSG_TMPL, "key"); + checkBuilderSetter(mIkeTunConnParams != null, "authDigitalSignature"); // Test to make sure all auth params can be encoded safely. checkCert(userCert); @@ -782,6 +927,7 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) public Builder setAuthPsk(@NonNull byte[] psk) { checkNotNull(psk, MISSING_PARAM_MSG_TMPL, "psk"); + checkBuilderSetter(mIkeTunConnParams != null, "authPsk"); resetAuthParams(); mPresharedKey = psk; @@ -848,6 +994,30 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { } /** + * Request that this VPN undergoes Internet validation. + * + * If this is true, the platform will perform basic validation checks for Internet + * connectivity over this VPN. If and when they succeed, the VPN network capabilities will + * reflect this by gaining the {@link NetworkCapabilities#NET_CAPABILITY_VALIDATED} + * capability. + * + * If this is false, the platform assumes the VPN either is always capable of reaching the + * Internet or intends not to. In this case, the VPN network capabilities will + * always gain the {@link NetworkCapabilities#NET_CAPABILITY_VALIDATED} capability + * immediately after it connects, whether it can reach public Internet destinations or not. + * + * @param requiresInternetValidation {@code true} if the framework should attempt to + * validate this VPN for Internet connectivity. Defaults + * to {@code false}. + */ + @NonNull + @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) + public Builder setRequiresInternetValidation(boolean requiresInternetValidation) { + mRequiresInternetValidation = requiresInternetValidation; + return this; + } + + /** * Marks the VPN network as metered. * * <p>A VPN network is classified as metered when the user is sensitive to heavy data usage @@ -931,8 +1101,6 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { * * Note that because the local traffic will always bypass the VPN, * it is not possible to set this flag on a non-bypassable VPN. - * - * @hide TODO(184750836): unhide once the implementation is completed */ @NonNull @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) @@ -965,7 +1133,8 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { mIsMetered, mMaxMtu, mIsRestrictedToTestNetworks, - mExcludeLocalRoutes); + mExcludeLocalRoutes, + mRequiresInternetValidation); } } } diff --git a/core/java/android/net/LocalServerSocket.java b/core/java/android/net/LocalServerSocket.java index d1f49d2082f5..506cbcb0623d 100644 --- a/core/java/android/net/LocalServerSocket.java +++ b/core/java/android/net/LocalServerSocket.java @@ -55,7 +55,9 @@ public class LocalServerSocket implements Closeable { * Create a LocalServerSocket from a file descriptor that's already * been created and bound. listen() will be called immediately on it. * Used for cases where file descriptors are passed in via environment - * variables + * variables. The passed-in FileDescriptor is not managed by this class + * and must be closed by the caller. Calling {@link #close()} on a socket + * created by this method has no effect. * * @param fd bound file descriptor * @throws IOException diff --git a/core/java/android/net/LocalSocket.java b/core/java/android/net/LocalSocket.java index 5b38f78782a8..b69410cf7d73 100644 --- a/core/java/android/net/LocalSocket.java +++ b/core/java/android/net/LocalSocket.java @@ -16,7 +16,14 @@ package android.net; +import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; + +import android.annotation.NonNull; +import android.annotation.SuppressLint; +import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; +import android.system.ErrnoException; +import android.system.Os; import java.io.Closeable; import java.io.FileDescriptor; @@ -74,32 +81,39 @@ public class LocalSocket implements Closeable { this.isBound = false; } + private void checkConnected() { + try { + Os.getpeername(impl.getFileDescriptor()); + } catch (ErrnoException e) { + throw new IllegalArgumentException("Not a connected socket", e); + } + isConnected = true; + isBound = true; + implCreated = true; + } + /** - * Creates a LocalSocket instances using the FileDescriptor for an already-connected - * AF_LOCAL/UNIX domain stream socket. Note: the FileDescriptor must be closed by the caller: - * closing the LocalSocket will not close it. + * Creates a LocalSocket instance using the {@link FileDescriptor} for an already-connected + * AF_LOCAL/UNIX domain stream socket. The passed-in FileDescriptor is not managed by this class + * and must be closed by the caller. Calling {@link #close()} on a socket created by this + * method has no effect. + * + * @param fd the filedescriptor to adopt * - * @hide - used by BluetoothSocket. + * @hide */ - public static LocalSocket createConnectedLocalSocket(FileDescriptor fd) { - return createConnectedLocalSocket(new LocalSocketImpl(fd), SOCKET_UNKNOWN); + @SystemApi(client = MODULE_LIBRARIES) + public LocalSocket(@NonNull @SuppressLint("UseParcelFileDescriptor") FileDescriptor fd) { + this(new LocalSocketImpl(fd), SOCKET_UNKNOWN); + checkConnected(); } /** * for use with LocalServerSocket.accept() */ static LocalSocket createLocalSocketForAccept(LocalSocketImpl impl) { - return createConnectedLocalSocket(impl, SOCKET_UNKNOWN); - } - - /** - * Creates a LocalSocket from an existing LocalSocketImpl that is already connected. - */ - private static LocalSocket createConnectedLocalSocket(LocalSocketImpl impl, int sockType) { - LocalSocket socket = new LocalSocket(impl, sockType); - socket.isConnected = true; - socket.isBound = true; - socket.implCreated = true; + LocalSocket socket = new LocalSocket(impl, SOCKET_UNKNOWN); + socket.checkConnected(); return socket; } diff --git a/core/java/android/net/PlatformVpnProfile.java b/core/java/android/net/PlatformVpnProfile.java index 777a90c8985c..8bd1c8d07017 100644 --- a/core/java/android/net/PlatformVpnProfile.java +++ b/core/java/android/net/PlatformVpnProfile.java @@ -16,10 +16,6 @@ package android.net; -import static android.net.PlatformVpnProfile.TYPE_IKEV2_IPSEC_PSK; -import static android.net.PlatformVpnProfile.TYPE_IKEV2_IPSEC_RSA; -import static android.net.PlatformVpnProfile.TYPE_IKEV2_IPSEC_USER_PASS; - import android.annotation.IntDef; import android.annotation.NonNull; @@ -67,11 +63,15 @@ public abstract class PlatformVpnProfile { /** @hide */ protected final boolean mExcludeLocalRoutes; + /** @hide */ + protected final boolean mRequiresInternetValidation; /** @hide */ - PlatformVpnProfile(@PlatformVpnType int type, boolean excludeLocalRoutes) { + PlatformVpnProfile(@PlatformVpnType int type, boolean excludeLocalRoutes, + boolean requiresValidation) { mType = type; mExcludeLocalRoutes = excludeLocalRoutes; + mRequiresInternetValidation = requiresValidation; } /** Returns the profile integer type. */ @@ -80,16 +80,30 @@ public abstract class PlatformVpnProfile { return mType; } - /** - * Returns if the local traffic is exempted from the VPN. - * - * @hide TODO(184750836): unhide once the implementation is completed + * Returns whether the local traffic is exempted from the VPN. */ public final boolean getExcludeLocalRoutes() { return mExcludeLocalRoutes; } + /** + * Returns whether this VPN should undergo Internet validation. + * + * If this is true, the platform will perform basic validation checks for Internet + * connectivity over this VPN. If and when they succeed, the VPN network capabilities will + * reflect this by gaining the {@link NetworkCapabilities#NET_CAPABILITY_VALIDATED} + * capability. + * + * If this is false, the platform assumes the VPN either is always capable of reaching the + * Internet or intends not to. In this case, the VPN network capabilities will + * always gain the {@link NetworkCapabilities#NET_CAPABILITY_VALIDATED} capability + * immediately after it connects, whether it can reach public Internet destinations or not. + */ + public final boolean getRequiresInternetValidation() { + return mRequiresInternetValidation; + } + /** Returns a type string describing the VPN profile type */ @NonNull public final String getTypeString() { diff --git a/core/java/android/net/VpnManager.java b/core/java/android/net/VpnManager.java index 319382691925..5aad997af8c1 100644 --- a/core/java/android/net/VpnManager.java +++ b/core/java/android/net/VpnManager.java @@ -211,25 +211,18 @@ public class VpnManager { public static final int ERROR_CODE_NETWORK_TIMEOUT = 1; /** - * An error code to indicate that the connection is refused. - * - * @hide - */ - public static final int ERROR_CODE_NETWORK_CONNECT = 2; - - /** * An error code to indicate the connection was reset. (e.g. SocketException) * * @hide */ - public static final int ERROR_CODE_NETWORK_CONNECTION_RESET = 3; + public static final int ERROR_CODE_NETWORK_RESET = 2; /** * An error code to indicate that there is an IOException. * * @hide */ - public static final int ERROR_CODE_NETWORK_IO = 4; + public static final int ERROR_CODE_NETWORK_IO = 3; /** @hide */ @IntDef(value = {TYPE_VPN_NONE, TYPE_VPN_SERVICE, TYPE_VPN_PLATFORM, TYPE_VPN_LEGACY, @@ -317,17 +310,32 @@ public class VpnManager { /** * Request the startup of a previously provisioned VPN. * + * @return A unique key corresponding to this session. * @throws SecurityException exception if user or device settings prevent this VPN from being - * setup, or if user consent has not been granted + * setup, or if user consent has not been granted */ - public void startProvisionedVpnProfile() { + @NonNull + public String startProvisionedVpnProfileSession() { try { - mService.startVpnProfile(mContext.getOpPackageName()); + return mService.startVpnProfile(mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } + /** + * Request the startup of a previously provisioned VPN. + * + * @throws SecurityException exception if user or device settings prevent this VPN from being + * setup, or if user consent has not been granted + * @deprecated This method is replaced by startProvisionedVpnProfileSession which returns a + * session key for the caller to diagnose the errors. + */ + @Deprecated + public void startProvisionedVpnProfile() { + startProvisionedVpnProfileSession(); + } + /** Tear down the VPN provided by the calling app (if any) */ public void stopProvisionedVpnProfile() { try { diff --git a/core/java/android/net/netstats/NetworkStatsDataMigrationUtils.java b/core/java/android/net/netstats/NetworkStatsDataMigrationUtils.java new file mode 100644 index 000000000000..9772bde94ac9 --- /dev/null +++ b/core/java/android/net/netstats/NetworkStatsDataMigrationUtils.java @@ -0,0 +1,568 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.netstats; + +import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; +import static android.net.ConnectivityManager.TYPE_MOBILE; +import static android.net.ConnectivityManager.TYPE_MOBILE_DUN; +import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI; +import static android.net.ConnectivityManager.TYPE_MOBILE_MMS; +import static android.net.ConnectivityManager.TYPE_MOBILE_SUPL; +import static android.net.NetworkStats.SET_DEFAULT; +import static android.net.NetworkStats.TAG_NONE; + +import android.annotation.NonNull; +import android.annotation.SystemApi; +import android.net.NetworkIdentity; +import android.net.NetworkStatsCollection; +import android.net.NetworkStatsHistory; +import android.net.NetworkTemplate; +import android.os.Environment; +import android.util.AtomicFile; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.util.FastDataInput; + +import libcore.io.IoUtils; + +import java.io.BufferedInputStream; +import java.io.DataInput; +import java.io.DataInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.net.ProtocolException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; + +/** + * Helper class to read old version of persistent network statistics. + * + * The implementation is intended to be modified by OEM partners to + * accommodate their custom changes. + * + * @hide + */ +@SystemApi(client = MODULE_LIBRARIES) +public class NetworkStatsDataMigrationUtils { + /** + * Prefix of the files which are used to store per network interface statistics. + */ + public static final String PREFIX_XT = "xt"; + /** + * Prefix of the files which are used to store per uid statistics. + */ + public static final String PREFIX_UID = "uid"; + /** + * Prefix of the files which are used to store per uid tagged traffic statistics. + */ + public static final String PREFIX_UID_TAG = "uid_tag"; + + private static final HashMap<String, String> sPrefixLegacyFileNameMap = + new HashMap<String, String>() {{ + put(PREFIX_XT, "netstats_xt.bin"); + put(PREFIX_UID, "netstats_uid.bin"); + put(PREFIX_UID_TAG, "netstats_uid.bin"); + }}; + + // These version constants are copied from NetworkStatsCollection/History, which is okay for + // OEMs to modify to adapt their own logic. + private static class CollectionVersion { + static final int VERSION_NETWORK_INIT = 1; + + static final int VERSION_UID_INIT = 1; + static final int VERSION_UID_WITH_IDENT = 2; + static final int VERSION_UID_WITH_TAG = 3; + static final int VERSION_UID_WITH_SET = 4; + + static final int VERSION_UNIFIED_INIT = 16; + } + + private static class HistoryVersion { + static final int VERSION_INIT = 1; + static final int VERSION_ADD_PACKETS = 2; + static final int VERSION_ADD_ACTIVE = 3; + } + + private static class IdentitySetVersion { + static final int VERSION_INIT = 1; + static final int VERSION_ADD_ROAMING = 2; + static final int VERSION_ADD_NETWORK_ID = 3; + static final int VERSION_ADD_METERED = 4; + static final int VERSION_ADD_DEFAULT_NETWORK = 5; + static final int VERSION_ADD_OEM_MANAGED_NETWORK = 6; + } + + /** + * File header magic number: "ANET". The definition is copied from NetworkStatsCollection, + * but it is fine for OEM to re-define to their own value to adapt the legacy file reading + * logic. + */ + private static final int FILE_MAGIC = 0x414E4554; + /** Default buffer size from BufferedInputStream */ + private static final int BUFFER_SIZE = 8192; + + // Constructing this object is not allowed. + private NetworkStatsDataMigrationUtils() { + } + + // Used to read files at /data/system/netstats_*.bin. + @NonNull + private static File getPlatformSystemDir() { + return new File(Environment.getDataDirectory(), "system"); + } + + // Used to read files at /data/system/netstats/<tag>.<start>-<end>. + @NonNull + private static File getPlatformBaseDir() { + File baseDir = new File(getPlatformSystemDir(), "netstats"); + baseDir.mkdirs(); + return baseDir; + } + + // Get /data/system/netstats_*.bin legacy files. Does not check for existence. + @NonNull + private static File getLegacyBinFileForPrefix(@NonNull String prefix) { + return new File(getPlatformSystemDir(), sPrefixLegacyFileNameMap.get(prefix)); + } + + // List /data/system/netstats/[xt|uid|uid_tag].<start>-<end> legacy files. + @NonNull + private static ArrayList<File> getPlatformFileListForPrefix(@NonNull String prefix) { + final ArrayList<File> list = new ArrayList<>(); + final File platformFiles = new File(getPlatformBaseDir(), "netstats"); + if (platformFiles.exists()) { + for (String name : platformFiles.list()) { + // Skip when prefix doesn't match. + if (!name.startsWith(prefix + ".")) continue; + + list.add(new File(platformFiles, name)); + } + } + return list; + } + + /** + * Read legacy persisted network stats from disk. + * + * This function provides the implementation to read legacy network stats + * from disk. It is used for migration of legacy network stats into the + * stats provided by the Connectivity module. + * This function needs to know about the previous format(s) of the network + * stats data that might be stored on this device so it can be read and + * conserved upon upgrade to Android 13 or above. + * + * This function will be called multiple times sequentially, all on the + * same thread, and will not be called multiple times concurrently. This + * function is expected to do a substantial amount of disk access, and + * doesn't need to return particularly fast, but the first boot after + * an upgrade to Android 13+ will be held until migration is done. As + * migration is only necessary once, after the first boot following the + * upgrade, this delay is not incurred. + * + * If this function fails in any way, it should throw an exception. If this + * happens, the system can't know about the data that was stored in the + * legacy files, but it will still count data usage happening on this + * session. On the next boot, the system will try migration again, and + * merge the returned data with the data used with the previous session. + * The system will only try the migration up to three (3) times. The remaining + * count is stored in the netstats_import_legacy_file_needed device config. The + * legacy data is never deleted by the mainline module to avoid any possible + * data loss. + * + * It is possible to set the netstats_import_legacy_file_needed device config + * to any positive integer to force the module to perform the migration. This + * can be achieved by calling the following command before rebooting : + * adb shell device_config put connectivity netstats_import_legacy_file_needed 1 + * + * The AOSP implementation provides code to read persisted network stats as + * they were written by AOSP prior to Android 13. + * OEMs who have used the AOSP implementation of persisting network stats + * to disk don't need to change anything. + * OEM that had modifications to this format should modify this function + * to read from their custom file format or locations if necessary. + * + * @param prefix Type of data which is being read by the service. + * @param bucketDuration Duration of the buckets of the object, in milliseconds. + * @return {@link NetworkStatsCollection} instance. + */ + @NonNull + public static NetworkStatsCollection readPlatformCollection( + @NonNull String prefix, long bucketDuration) throws IOException { + final NetworkStatsCollection.Builder builder = + new NetworkStatsCollection.Builder(bucketDuration); + + // Import /data/system/netstats_uid.bin legacy files if exists. + switch (prefix) { + case PREFIX_UID: + case PREFIX_UID_TAG: + final File uidFile = getLegacyBinFileForPrefix(prefix); + if (uidFile.exists()) { + readLegacyUid(builder, uidFile, PREFIX_UID_TAG.equals(prefix) ? true : false); + } + break; + default: + // Ignore other types. + } + + // Import /data/system/netstats/[xt|uid|uid_tag].<start>-<end> legacy files if exists. + final ArrayList<File> platformFiles = getPlatformFileListForPrefix(prefix); + for (final File platformFile : platformFiles) { + if (platformFile.exists()) { + readPlatformCollection(builder, platformFile); + } + } + + return builder.build(); + } + + private static void readPlatformCollection(@NonNull NetworkStatsCollection.Builder builder, + @NonNull File file) throws IOException { + final FileInputStream is = new FileInputStream(file); + final FastDataInput dataIn = new FastDataInput(is, BUFFER_SIZE); + try { + readPlatformCollection(builder, dataIn); + } finally { + IoUtils.closeQuietly(dataIn); + } + } + + /** + * Helper function to read old version of NetworkStatsCollections that resided in the platform. + * + * @hide + */ + @VisibleForTesting + public static void readPlatformCollection(@NonNull NetworkStatsCollection.Builder builder, + @NonNull DataInput in) throws IOException { + // verify file magic header intact + final int magic = in.readInt(); + if (magic != FILE_MAGIC) { + throw new ProtocolException("unexpected magic: " + magic); + } + + final int version = in.readInt(); + switch (version) { + case CollectionVersion.VERSION_UNIFIED_INIT: { + // uid := size *(NetworkIdentitySet size *(uid set tag NetworkStatsHistory)) + final int identSize = in.readInt(); + for (int i = 0; i < identSize; i++) { + final Set<NetworkIdentity> ident = readPlatformNetworkIdentitySet(in); + + final int size = in.readInt(); + for (int j = 0; j < size; j++) { + final int uid = in.readInt(); + final int set = in.readInt(); + final int tag = in.readInt(); + + final NetworkStatsCollection.Key key = new NetworkStatsCollection.Key( + ident, uid, set, tag); + final NetworkStatsHistory history = readPlatformHistory(in); + builder.addEntry(key, history); + } + } + break; + } + default: { + throw new ProtocolException("unexpected version: " + version); + } + } + } + + // Copied from NetworkStatsHistory#DataStreamUtils. + private static long[] readFullLongArray(DataInput in) throws IOException { + final int size = in.readInt(); + if (size < 0) throw new ProtocolException("negative array size"); + final long[] values = new long[size]; + for (int i = 0; i < values.length; i++) { + values[i] = in.readLong(); + } + return values; + } + + // Copied from NetworkStatsHistory#DataStreamUtils. + private static long[] readVarLongArray(@NonNull DataInput in) throws IOException { + final int size = in.readInt(); + if (size == -1) return null; + if (size < 0) throw new ProtocolException("negative array size"); + final long[] values = new long[size]; + for (int i = 0; i < values.length; i++) { + values[i] = readVarLong(in); + } + return values; + } + + /** + * Read variable-length {@link Long} using protobuf-style approach. + */ + // Copied from NetworkStatsHistory#DataStreamUtils. + private static long readVarLong(DataInput in) throws IOException { + int shift = 0; + long result = 0; + while (shift < 64) { + byte b = in.readByte(); + result |= (long) (b & 0x7F) << shift; + if ((b & 0x80) == 0) { + return result; + } + shift += 7; + } + throw new ProtocolException("malformed var long"); + } + + // Copied from NetworkIdentitySet. + private static String readOptionalString(DataInput in) throws IOException { + if (in.readByte() != 0) { + return in.readUTF(); + } else { + return null; + } + } + + /** + * This is copied from NetworkStatsHistory#NetworkStatsHistory(DataInput in). But it is fine + * for OEM to re-write the logic to adapt the legacy file reading. + */ + @NonNull + private static NetworkStatsHistory readPlatformHistory(@NonNull DataInput in) + throws IOException { + final long bucketDuration; + final long[] bucketStart; + final long[] rxBytes; + final long[] rxPackets; + final long[] txBytes; + final long[] txPackets; + final long[] operations; + final int bucketCount; + long[] activeTime = new long[0]; + + final int version = in.readInt(); + switch (version) { + case HistoryVersion.VERSION_INIT: { + bucketDuration = in.readLong(); + bucketStart = readFullLongArray(in); + rxBytes = readFullLongArray(in); + rxPackets = new long[bucketStart.length]; + txBytes = readFullLongArray(in); + txPackets = new long[bucketStart.length]; + operations = new long[bucketStart.length]; + bucketCount = bucketStart.length; + break; + } + case HistoryVersion.VERSION_ADD_PACKETS: + case HistoryVersion.VERSION_ADD_ACTIVE: { + bucketDuration = in.readLong(); + bucketStart = readVarLongArray(in); + activeTime = (version >= HistoryVersion.VERSION_ADD_ACTIVE) + ? readVarLongArray(in) + : new long[bucketStart.length]; + rxBytes = readVarLongArray(in); + rxPackets = readVarLongArray(in); + txBytes = readVarLongArray(in); + txPackets = readVarLongArray(in); + operations = readVarLongArray(in); + bucketCount = bucketStart.length; + break; + } + default: { + throw new ProtocolException("unexpected version: " + version); + } + } + + final NetworkStatsHistory.Builder historyBuilder = + new NetworkStatsHistory.Builder(bucketDuration, bucketCount); + for (int i = 0; i < bucketCount; i++) { + final NetworkStatsHistory.Entry entry = new NetworkStatsHistory.Entry( + bucketStart[i], activeTime[i], + rxBytes[i], rxPackets[i], txBytes[i], txPackets[i], operations[i]); + historyBuilder.addEntry(entry); + } + + return historyBuilder.build(); + } + + @NonNull + private static Set<NetworkIdentity> readPlatformNetworkIdentitySet(@NonNull DataInput in) + throws IOException { + final int version = in.readInt(); + final int size = in.readInt(); + final Set<NetworkIdentity> set = new HashSet<>(); + for (int i = 0; i < size; i++) { + if (version <= IdentitySetVersion.VERSION_INIT) { + final int ignored = in.readInt(); + } + final int type = in.readInt(); + final int ratType = in.readInt(); + final String subscriberId = readOptionalString(in); + final String networkId; + if (version >= IdentitySetVersion.VERSION_ADD_NETWORK_ID) { + networkId = readOptionalString(in); + } else { + networkId = null; + } + final boolean roaming; + if (version >= IdentitySetVersion.VERSION_ADD_ROAMING) { + roaming = in.readBoolean(); + } else { + roaming = false; + } + + final boolean metered; + if (version >= IdentitySetVersion.VERSION_ADD_METERED) { + metered = in.readBoolean(); + } else { + // If this is the old data and the type is mobile, treat it as metered. (Note that + // if this is a mobile network, TYPE_MOBILE is the only possible type that could be + // used.) + metered = (type == TYPE_MOBILE); + } + + final boolean defaultNetwork; + if (version >= IdentitySetVersion.VERSION_ADD_DEFAULT_NETWORK) { + defaultNetwork = in.readBoolean(); + } else { + defaultNetwork = true; + } + + final int oemNetCapabilities; + if (version >= IdentitySetVersion.VERSION_ADD_OEM_MANAGED_NETWORK) { + oemNetCapabilities = in.readInt(); + } else { + oemNetCapabilities = NetworkTemplate.OEM_MANAGED_NO; + } + + // Legacy files might contain TYPE_MOBILE_* types which were deprecated in later + // releases. For backward compatibility, record them as TYPE_MOBILE instead. + final int collapsedLegacyType = getCollapsedLegacyType(type); + final NetworkIdentity.Builder builder = new NetworkIdentity.Builder() + .setType(collapsedLegacyType) + .setSubscriberId(subscriberId) + .setWifiNetworkKey(networkId) + .setRoaming(roaming).setMetered(metered) + .setDefaultNetwork(defaultNetwork) + .setOemManaged(oemNetCapabilities); + if (type == TYPE_MOBILE && ratType != NetworkTemplate.NETWORK_TYPE_ALL) { + builder.setRatType(ratType); + } + set.add(builder.build()); + } + return set; + } + + private static int getCollapsedLegacyType(int networkType) { + // The constants are referenced from ConnectivityManager#TYPE_MOBILE_*. + switch (networkType) { + case TYPE_MOBILE: + case TYPE_MOBILE_SUPL: + case TYPE_MOBILE_MMS: + case TYPE_MOBILE_DUN: + case TYPE_MOBILE_HIPRI: + case 10 /* TYPE_MOBILE_FOTA */: + case 11 /* TYPE_MOBILE_IMS */: + case 12 /* TYPE_MOBILE_CBS */: + case 14 /* TYPE_MOBILE_IA */: + case 15 /* TYPE_MOBILE_EMERGENCY */: + return TYPE_MOBILE; + } + return networkType; + } + + private static void readLegacyUid(@NonNull NetworkStatsCollection.Builder builder, + @NonNull File uidFile, boolean onlyTaggedData) throws IOException { + final AtomicFile inputFile = new AtomicFile(uidFile); + DataInputStream in = new DataInputStream(new BufferedInputStream(inputFile.openRead())); + try { + readLegacyUid(builder, in, onlyTaggedData); + } finally { + IoUtils.closeQuietly(in); + } + } + + /** + * Read legacy Uid statistics file format into the collection. + * + * This is copied from {@code NetworkStatsCollection#readLegacyUid}. + * See {@code NetworkStatsService#maybeUpgradeLegacyStatsLocked}. + * + * @param taggedData whether to read tagged data. For legacy uid files, the tagged + * data was stored in the same binary file with non-tagged data. + * But in later releases, these data should be kept in different + * recorders. + * @hide + */ + @VisibleForTesting + public static void readLegacyUid(@NonNull NetworkStatsCollection.Builder builder, + @NonNull DataInput in, boolean taggedData) throws IOException { + try { + // verify file magic header intact + final int magic = in.readInt(); + if (magic != FILE_MAGIC) { + throw new ProtocolException("unexpected magic: " + magic); + } + + final int version = in.readInt(); + switch (version) { + case CollectionVersion.VERSION_UID_INIT: { + // uid := size *(UID NetworkStatsHistory) + // drop this data version, since we don't have a good + // mapping into NetworkIdentitySet. + break; + } + case CollectionVersion.VERSION_UID_WITH_IDENT: { + // uid := size *(NetworkIdentitySet size *(UID NetworkStatsHistory)) + // drop this data version, since this version only existed + // for a short time. + break; + } + case CollectionVersion.VERSION_UID_WITH_TAG: + case CollectionVersion.VERSION_UID_WITH_SET: { + // uid := size *(NetworkIdentitySet size *(uid set tag NetworkStatsHistory)) + final int identSize = in.readInt(); + for (int i = 0; i < identSize; i++) { + final Set<NetworkIdentity> ident = readPlatformNetworkIdentitySet(in); + + final int size = in.readInt(); + for (int j = 0; j < size; j++) { + final int uid = in.readInt(); + final int set = (version >= CollectionVersion.VERSION_UID_WITH_SET) + ? in.readInt() + : SET_DEFAULT; + final int tag = in.readInt(); + + final NetworkStatsCollection.Key key = new NetworkStatsCollection.Key( + ident, uid, set, tag); + final NetworkStatsHistory history = readPlatformHistory(in); + + if ((tag == TAG_NONE) != taggedData) { + builder.addEntry(key, history); + } + } + } + break; + } + default: { + throw new ProtocolException("unknown version: " + version); + } + } + } catch (FileNotFoundException | ProtocolException e) { + // missing stats is okay, probably first boot + } + } +} diff --git a/core/java/android/os/BinderProxy.java b/core/java/android/os/BinderProxy.java index c6466235e5d1..71c63ffd841c 100644 --- a/core/java/android/os/BinderProxy.java +++ b/core/java/android/os/BinderProxy.java @@ -116,7 +116,7 @@ public final class BinderProxy implements IBinder { for (ArrayList<WeakReference<BinderProxy>> a : mMainIndexValues) { if (a != null) { for (WeakReference<BinderProxy> ref : a) { - if (ref.get() != null) { + if (!ref.refersTo(null)) { ++size; } } @@ -187,7 +187,7 @@ public final class BinderProxy implements IBinder { // This ensures that ArrayList size is bounded by the maximum occupancy of // that bucket. for (int i = 0; i < size; ++i) { - if (valueArray.get(i).get() == null) { + if (valueArray.get(i).refersTo(null)) { valueArray.set(i, newWr); Long[] keyArray = mMainIndexKeys[myHash]; keyArray[i] = key; @@ -195,7 +195,7 @@ public final class BinderProxy implements IBinder { // "Randomly" check one of the remaining entries in [i+1, size), so that // needlessly long buckets are eventually pruned. int rnd = Math.floorMod(++mRandom, size - (i + 1)); - if (valueArray.get(i + 1 + rnd).get() == null) { + if (valueArray.get(i + 1 + rnd).refersTo(null)) { remove(myHash, i + 1 + rnd); } } @@ -516,12 +516,15 @@ public final class BinderProxy implements IBinder { public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { Binder.checkParcel(this, code, data, "Unreasonably large binder buffer"); - if (mWarnOnBlocking && ((flags & FLAG_ONEWAY) == 0) + boolean warnOnBlocking = mWarnOnBlocking; // Cache it to reduce volatile access. + + if (warnOnBlocking && ((flags & FLAG_ONEWAY) == 0) && Binder.sWarnOnBlockingOnCurrentThread.get()) { // For now, avoid spamming the log by disabling after we've logged // about this interface at least once mWarnOnBlocking = false; + warnOnBlocking = false; if (Build.IS_USERDEBUG) { // Log this as a WTF on userdebug builds. @@ -568,7 +571,13 @@ public final class BinderProxy implements IBinder { } try { - return transactNative(code, data, reply, flags); + final boolean result = transactNative(code, data, reply, flags); + + if (reply != null && !warnOnBlocking) { + reply.addFlags(Parcel.FLAG_IS_REPLY_FROM_BLOCKING_ALLOWED_OBJECT); + } + + return result; } finally { AppOpsManager.resumeNotedAppOpsCollection(prevCollection); diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index e519ff3a3739..f46f45228f07 100755 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -31,6 +31,7 @@ import android.sysprop.DeviceProperties; import android.sysprop.SocProperties; import android.sysprop.TelephonyProperties; import android.text.TextUtils; +import android.util.ArraySet; import android.util.Slog; import android.view.View; @@ -39,6 +40,7 @@ import dalvik.system.VMRuntime; import java.util.ArrayList; import java.util.List; import java.util.Objects; +import java.util.Set; import java.util.stream.Collectors; /** @@ -396,6 +398,17 @@ public class Build { */ public static final String CODENAME = getString("ro.build.version.codename"); + /** + * All known codenames starting from {@link VERSION_CODES.Q}. + * + * <p>This includes in development codenames as well. + * + * @hide + */ + @SystemApi + @NonNull public static final Set<String> KNOWN_CODENAMES = + new ArraySet<>(new String[]{"Q", "R", "S", "Sv2", "Tiramisu"}); + private static final String[] ALL_CODENAMES = getStringList("ro.build.version.all_codenames", ","); @@ -1024,7 +1037,7 @@ public class Build { * will also enable {@link StrictMode.ThreadPolicy.Builder#detectUnbufferedIo}.</li> * <li>{@link android.provider.DocumentsContract}'s various methods will throw failure * exceptions back to the caller instead of returning null. - * <li>{@link View#hasFocusable View.hasFocusable} now includes auto-focusable views.</li> + * <li>{@link View#hasFocusable() View.hasFocusable} now includes auto-focusable views.</li> * <li>{@link android.view.SurfaceView} will no longer always change the underlying * Surface object when something about it changes; apps need to look at the current * state of the object to determine which things they are interested in have changed.</li> @@ -1132,6 +1145,14 @@ public class Build { public static final int S = 31; /** + * S V2. + * + * Once more unto the breach, dear friends, once more. + * + */ + public static final int S_V2 = 32; + + /** * Tiramisu. */ public static final int TIRAMISU = CUR_DEVELOPMENT; diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java index ffaff9533c8c..13d1d96fadc8 100644 --- a/core/java/android/os/Parcel.java +++ b/core/java/android/os/Parcel.java @@ -18,6 +18,7 @@ package android.os; import static java.util.Objects.requireNonNull; +import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SuppressLint; @@ -53,6 +54,8 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.ObjectStreamClass; import java.io.Serializable; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.lang.reflect.Array; import java.lang.reflect.Field; import java.lang.reflect.Modifier; @@ -229,6 +232,25 @@ public final class Parcel { private RuntimeException mStack; + /** @hide */ + @TestApi + public static final int FLAG_IS_REPLY_FROM_BLOCKING_ALLOWED_OBJECT = 1 << 0; + + /** @hide */ + @TestApi + public static final int FLAG_PROPAGATE_ALLOW_BLOCKING = 1 << 1; + + /** @hide */ + @IntDef(flag = true, prefix = { "FLAG_" }, value = { + FLAG_IS_REPLY_FROM_BLOCKING_ALLOWED_OBJECT, + FLAG_PROPAGATE_ALLOW_BLOCKING, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface ParcelFlags {} + + @ParcelFlags + private int mFlags; + /** * Whether or not to parcel the stack trace of an exception. This has a performance * impact, so should only be included in specific processes and only on debug builds. @@ -585,6 +607,40 @@ public final class Parcel { nativeMarkForBinder(mNativePtr, binder); } + /** @hide */ + @ParcelFlags + @TestApi + public int getFlags() { + return mFlags; + } + + /** @hide */ + public void setFlags(@ParcelFlags int flags) { + mFlags = flags; + } + + /** @hide */ + public void addFlags(@ParcelFlags int flags) { + mFlags |= flags; + } + + /** @hide */ + private boolean hasFlags(@ParcelFlags int flags) { + return (mFlags & flags) == flags; + } + + /** + * This method is used by the AIDL compiler for system components. Not intended to be + * used by non-system apps. + */ + // Note: Ideally this method should be @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES), + // but we need to make this method public due to the way the aidl compiler is compiled. + // We don't really need to protect it; even if 3p / non-system apps, nothing would happen. + // This would only work when used on a reply parcel by a binder object that's allowed-blocking. + public void setPropagateAllowBlocking() { + addFlags(FLAG_PROPAGATE_ALLOW_BLOCKING); + } + /** * Returns the total amount of data contained in the parcel. */ @@ -2079,6 +2135,102 @@ public final class Parcel { } /** + * Flatten a homogeneous multi-dimensional array with fixed-size. This delegates to other + * APIs to write a one-dimensional array. Use {@link #readFixedArray(Object)} or + * {@link #createFixedArray(Class, int[])} with the same dimensions to unmarshal. + * + * @param val The array to be written. + * @param parcelableFlags Contextual flags as per + * {@link Parcelable#writeToParcel(Parcel, int) Parcelable.writeToParcel()}. + * Used only if val is an array of Parcelable objects. + * @param dimensions an array of int representing length of each dimension. The array should be + * sized with the exact size of dimensions. + * + * @see #readFixedArray + * @see #createFixedArray + * @see #writeBooleanArray + * @see #writeByteArray + * @see #writeCharArray + * @see #writeIntArray + * @see #writeLongArray + * @see #writeFloatArray + * @see #writeDoubleArray + * @see #writeBinderArray + * @see #writeInterfaceArray + * @see #writeTypedArray + * @throws BadParcelableException If the array's component type is not supported or if its + * size doesn't match with the given dimensions. + */ + public <T> void writeFixedArray(@Nullable T val, int parcelableFlags, + @NonNull int... dimensions) { + if (val == null) { + writeInt(-1); + return; + } + writeFixedArrayInternal(val, parcelableFlags, /*index=*/0, dimensions); + } + + private <T> void writeFixedArrayInternal(T val, int parcelableFlags, int index, + int[] dimensions) { + if (index >= dimensions.length) { + throw new BadParcelableException("Array has more dimensions than expected: " + + dimensions.length); + } + + int length = dimensions[index]; + + // val should be an array of length N + if (val == null) { + throw new BadParcelableException("Non-null array shouldn't have a null array."); + } + if (!val.getClass().isArray()) { + throw new BadParcelableException("Not an array: " + val); + } + if (Array.getLength(val) != length) { + throw new BadParcelableException("bad length: expected " + length + ", but got " + + Array.getLength(val)); + } + + // Delegates to other writers if this is a one-dimensional array. + // Otherwise, write component arrays with recursive calls. + + final Class<?> componentType = val.getClass().getComponentType(); + if (!componentType.isArray() && index + 1 != dimensions.length) { + throw new BadParcelableException("Array has fewer dimensions than expected: " + + dimensions.length); + } + if (componentType == boolean.class) { + writeBooleanArray((boolean[]) val); + } else if (componentType == byte.class) { + writeByteArray((byte[]) val); + } else if (componentType == char.class) { + writeCharArray((char[]) val); + } else if (componentType == int.class) { + writeIntArray((int[]) val); + } else if (componentType == long.class) { + writeLongArray((long[]) val); + } else if (componentType == float.class) { + writeFloatArray((float[]) val); + } else if (componentType == double.class) { + writeDoubleArray((double[]) val); + } else if (componentType == IBinder.class) { + writeBinderArray((IBinder[]) val); + } else if (IInterface.class.isAssignableFrom(componentType)) { + writeInterfaceArray((IInterface[]) val); + } else if (Parcelable.class.isAssignableFrom(componentType)) { + writeTypedArray((Parcelable[]) val, parcelableFlags); + } else if (componentType.isArray()) { + writeInt(length); + for (int i = 0; i < length; i++) { + writeFixedArrayInternal(Array.get(val, i), parcelableFlags, index + 1, + dimensions); + } + } else { + throw new BadParcelableException("unknown type for fixed-size array: " + componentType); + } + } + + /** * Flatten a generic object in to a parcel. The given Object value may * currently be one of the following types: * @@ -2940,7 +3092,15 @@ public final class Parcel { * Read an object from the parcel at the current dataPosition(). */ public final IBinder readStrongBinder() { - return nativeReadStrongBinder(mNativePtr); + final IBinder result = nativeReadStrongBinder(mNativePtr); + + // If it's a reply from a method with @PropagateAllowBlocking, then inherit allow-blocking + // from the object that returned it. + if (result != null && hasFlags( + FLAG_IS_REPLY_FROM_BLOCKING_ALLOWED_OBJECT | FLAG_PROPAGATE_ALLOW_BLOCKING)) { + Binder.allowBlocking(result); + } + return result; } /** @@ -3704,10 +3864,10 @@ public final class Parcel { final int m = list.size(); int i = 0; for (; i < m && i < n; i++) { - list.set(i, readParcelableInternal(cl, clazz)); + list.set(i, (T) readParcelableInternal(cl, clazz)); } for (; i < n; i++) { - list.add(readParcelableInternal(cl, clazz)); + list.add((T) readParcelableInternal(cl, clazz)); } for (; i < m; i++) { list.remove(n); @@ -3781,6 +3941,317 @@ public final class Parcel { } /** + * Read a new multi-dimensional array from a parcel. If you want to read Parcelable or + * IInterface values, use {@link #readFixedArray(Object, Parcelable.Creator)} or + * {@link #readFixedArray(Object, Function)}. + * @param val the destination array to hold the read values. + * + * @see #writeTypedArray + * @see #readBooleanArray + * @see #readByteArray + * @see #readCharArray + * @see #readIntArray + * @see #readLongArray + * @see #readFloatArray + * @see #readDoubleArray + * @see #readBinderArray + * @see #readInterfaceArray + * @see #readTypedArray + */ + public <T> void readFixedArray(@NonNull T val) { + Class<?> componentType = val.getClass().getComponentType(); + if (componentType == boolean.class) { + readBooleanArray((boolean[]) val); + } else if (componentType == byte.class) { + readByteArray((byte[]) val); + } else if (componentType == char.class) { + readCharArray((char[]) val); + } else if (componentType == int.class) { + readIntArray((int[]) val); + } else if (componentType == long.class) { + readLongArray((long[]) val); + } else if (componentType == float.class) { + readFloatArray((float[]) val); + } else if (componentType == double.class) { + readDoubleArray((double[]) val); + } else if (componentType == IBinder.class) { + readBinderArray((IBinder[]) val); + } else if (componentType.isArray()) { + int length = readInt(); + if (length != Array.getLength(val)) { + throw new BadParcelableException("Bad length: expected " + Array.getLength(val) + + ", but got " + length); + } + for (int i = 0; i < length; i++) { + readFixedArray(Array.get(val, i)); + } + } else { + throw new BadParcelableException("Unknown type for fixed-size array: " + componentType); + } + } + + /** + * Read a new multi-dimensional array of typed interfaces from a parcel. + * If you want to read Parcelable values, use + * {@link #readFixedArray(Object, Parcelable.Creator)}. For values of other types, use + * {@link #readFixedArray(Object)}. + * @param val the destination array to hold the read values. + */ + public <T, S extends IInterface> void readFixedArray(@NonNull T val, + @NonNull Function<IBinder, S> asInterface) { + Class<?> componentType = val.getClass().getComponentType(); + if (IInterface.class.isAssignableFrom(componentType)) { + readInterfaceArray((S[]) val, asInterface); + } else if (componentType.isArray()) { + int length = readInt(); + if (length != Array.getLength(val)) { + throw new BadParcelableException("Bad length: expected " + Array.getLength(val) + + ", but got " + length); + } + for (int i = 0; i < length; i++) { + readFixedArray(Array.get(val, i), asInterface); + } + } else { + throw new BadParcelableException("Unknown type for fixed-size array: " + componentType); + } + } + + /** + * Read a new multi-dimensional array of typed parcelables from a parcel. + * If you want to read IInterface values, use + * {@link #readFixedArray(Object, Function)}. For values of other types, use + * {@link #readFixedArray(Object)}. + * @param val the destination array to hold the read values. + */ + public <T, S extends Parcelable> void readFixedArray(@NonNull T val, + @NonNull Parcelable.Creator<S> c) { + Class<?> componentType = val.getClass().getComponentType(); + if (Parcelable.class.isAssignableFrom(componentType)) { + readTypedArray((S[]) val, c); + } else if (componentType.isArray()) { + int length = readInt(); + if (length != Array.getLength(val)) { + throw new BadParcelableException("Bad length: expected " + Array.getLength(val) + + ", but got " + length); + } + for (int i = 0; i < length; i++) { + readFixedArray(Array.get(val, i), c); + } + } else { + throw new BadParcelableException("Unknown type for fixed-size array: " + componentType); + } + } + + private void ensureClassHasExpectedDimensions(@NonNull Class<?> cls, int numDimension) { + if (numDimension <= 0) { + throw new BadParcelableException("Fixed-size array should have dimensions."); + } + + for (int i = 0; i < numDimension; i++) { + if (!cls.isArray()) { + throw new BadParcelableException("Array has fewer dimensions than expected: " + + numDimension); + } + cls = cls.getComponentType(); + } + if (cls.isArray()) { + throw new BadParcelableException("Array has more dimensions than expected: " + + numDimension); + } + } + + /** + * Read and return a new multi-dimensional array from a parcel. Returns null if the + * previously written array object is null. If you want to read Parcelable or + * IInterface values, use {@link #createFixedArray(Class, Parcelable.Creator, int[])} or + * {@link #createFixedArray(Class, Function, int[])}. + * @param cls the Class object for the target array type. (e.g. int[][].class) + * @param dimensions an array of int representing length of each dimension. + * + * @see #writeTypedArray + * @see #createBooleanArray + * @see #createByteArray + * @see #createCharArray + * @see #createIntArray + * @see #createLongArray + * @see #createFloatArray + * @see #createDoubleArray + * @see #createBinderArray + * @see #createInterfaceArray + * @see #createTypedArray + */ + @Nullable + public <T> T createFixedArray(@NonNull Class<T> cls, @NonNull int... dimensions) { + // Check if type matches with dimensions + // If type is one-dimensional array, delegate to other creators + // Otherwise, create an multi-dimensional array at once and then fill it with readFixedArray + + ensureClassHasExpectedDimensions(cls, dimensions.length); + + T val = null; + final Class<?> componentType = cls.getComponentType(); + if (componentType == boolean.class) { + val = (T) createBooleanArray(); + } else if (componentType == byte.class) { + val = (T) createByteArray(); + } else if (componentType == char.class) { + val = (T) createCharArray(); + } else if (componentType == int.class) { + val = (T) createIntArray(); + } else if (componentType == long.class) { + val = (T) createLongArray(); + } else if (componentType == float.class) { + val = (T) createFloatArray(); + } else if (componentType == double.class) { + val = (T) createDoubleArray(); + } else if (componentType == IBinder.class) { + val = (T) createBinderArray(); + } else if (componentType.isArray()) { + int length = readInt(); + if (length < 0) { + return null; + } + if (length != dimensions[0]) { + throw new BadParcelableException("Bad length: expected " + dimensions[0] + + ", but got " + length); + } + + // Create a multi-dimensional array with an innermost component type and dimensions + Class<?> innermost = componentType.getComponentType(); + while (innermost.isArray()) { + innermost = innermost.getComponentType(); + } + val = (T) Array.newInstance(innermost, dimensions); + for (int i = 0; i < length; i++) { + readFixedArray(Array.get(val, i)); + } + return val; + } else { + throw new BadParcelableException("Unknown type for fixed-size array: " + componentType); + } + + // Check if val is null (which is OK) or has the expected size. + // This check doesn't have to be multi-dimensional because multi-dimensional arrays + // are created with expected dimensions. + if (val != null && Array.getLength(val) != dimensions[0]) { + throw new BadParcelableException("Bad length: expected " + dimensions[0] + ", but got " + + Array.getLength(val)); + } + return val; + } + + /** + * Read and return a new multi-dimensional array of typed interfaces from a parcel. + * Returns null if the previously written array object is null. If you want to read + * Parcelable values, use {@link #createFixedArray(Class, Parcelable.Creator, int[])}. + * For values of other types use {@link #createFixedArray(Class, int[])}. + * @param cls the Class object for the target array type. (e.g. IFoo[][].class) + * @param dimensions an array of int representing length of each dimension. + */ + @Nullable + public <T, S extends IInterface> T createFixedArray(@NonNull Class<T> cls, + @NonNull Function<IBinder, S> asInterface, @NonNull int... dimensions) { + // Check if type matches with dimensions + // If type is one-dimensional array, delegate to other creators + // Otherwise, create an multi-dimensional array at once and then fill it with readFixedArray + + ensureClassHasExpectedDimensions(cls, dimensions.length); + + T val = null; + final Class<?> componentType = cls.getComponentType(); + if (IInterface.class.isAssignableFrom(componentType)) { + val = (T) createInterfaceArray(n -> (S[]) Array.newInstance(componentType, n), + asInterface); + } else if (componentType.isArray()) { + int length = readInt(); + if (length < 0) { + return null; + } + if (length != dimensions[0]) { + throw new BadParcelableException("Bad length: expected " + dimensions[0] + + ", but got " + length); + } + + // Create a multi-dimensional array with an innermost component type and dimensions + Class<?> innermost = componentType.getComponentType(); + while (innermost.isArray()) { + innermost = innermost.getComponentType(); + } + val = (T) Array.newInstance(innermost, dimensions); + for (int i = 0; i < length; i++) { + readFixedArray(Array.get(val, i), asInterface); + } + return val; + } else { + throw new BadParcelableException("Unknown type for fixed-size array: " + componentType); + } + + // Check if val is null (which is OK) or has the expected size. + // This check doesn't have to be multi-dimensional because multi-dimensional arrays + // are created with expected dimensions. + if (val != null && Array.getLength(val) != dimensions[0]) { + throw new BadParcelableException("Bad length: expected " + dimensions[0] + ", but got " + + Array.getLength(val)); + } + return val; + } + + /** + * Read and return a new multi-dimensional array of typed parcelables from a parcel. + * Returns null if the previously written array object is null. If you want to read + * IInterface values, use {@link #createFixedArray(Class, Function, int[])}. + * For values of other types use {@link #createFixedArray(Class, int[])}. + * @param cls the Class object for the target array type. (e.g. Foo[][].class) + * @param dimensions an array of int representing length of each dimension. + */ + @Nullable + public <T, S extends Parcelable> T createFixedArray(@NonNull Class<T> cls, + @NonNull Parcelable.Creator<S> c, @NonNull int... dimensions) { + // Check if type matches with dimensions + // If type is one-dimensional array, delegate to other creators + // Otherwise, create an multi-dimensional array at once and then fill it with readFixedArray + + ensureClassHasExpectedDimensions(cls, dimensions.length); + + T val = null; + final Class<?> componentType = cls.getComponentType(); + if (Parcelable.class.isAssignableFrom(componentType)) { + val = (T) createTypedArray(c); + } else if (componentType.isArray()) { + int length = readInt(); + if (length < 0) { + return null; + } + if (length != dimensions[0]) { + throw new BadParcelableException("Bad length: expected " + dimensions[0] + + ", but got " + length); + } + + // Create a multi-dimensional array with an innermost component type and dimensions + Class<?> innermost = componentType.getComponentType(); + while (innermost.isArray()) { + innermost = innermost.getComponentType(); + } + val = (T) Array.newInstance(innermost, dimensions); + for (int i = 0; i < length; i++) { + readFixedArray(Array.get(val, i), c); + } + return val; + } else { + throw new BadParcelableException("Unknown type for fixed-size array: " + componentType); + } + + // Check if val is null (which is OK) or has the expected size. + // This check doesn't have to be multi-dimensional because multi-dimensional arrays + // are created with expected dimensions. + if (val != null && Array.getLength(val) != dimensions[0]) { + throw new BadParcelableException("Bad length: expected " + dimensions[0] + ", but got " + + Array.getLength(val)); + } + return val; + } + + /** * Write a heterogeneous array of Parcelable objects into the Parcel. * Each object in the array is written along with its class name, so * that the correct class can later be instantiated. As a result, this @@ -4210,8 +4681,7 @@ public final class Parcel { * trying to instantiate an element. */ @Nullable - public <T extends Parcelable> T readParcelable(@Nullable ClassLoader loader, - @NonNull Class<? super T> clazz) { + public <T> T readParcelable(@Nullable ClassLoader loader, @NonNull Class<T> clazz) { Objects.requireNonNull(clazz); return readParcelableInternal(loader, clazz); } @@ -4221,8 +4691,7 @@ public final class Parcel { */ @SuppressWarnings("unchecked") @Nullable - private <T extends Parcelable> T readParcelableInternal(@Nullable ClassLoader loader, - @Nullable Class<? super T> clazz) { + private <T> T readParcelableInternal(@Nullable ClassLoader loader, @Nullable Class<T> clazz) { Parcelable.Creator<?> creator = readParcelableCreatorInternal(loader, clazz); if (creator == null) { return null; @@ -4458,8 +4927,7 @@ public final class Parcel { * deserializing the object. */ @Nullable - public <T extends Serializable> T readSerializable(@Nullable ClassLoader loader, - @NonNull Class<? super T> clazz) { + public <T> T readSerializable(@Nullable ClassLoader loader, @NonNull Class<T> clazz) { Objects.requireNonNull(clazz); return readSerializableInternal( loader == null ? getClass().getClassLoader() : loader, clazz); @@ -4469,8 +4937,8 @@ public final class Parcel { * @param clazz The type of the serializable expected or {@code null} for performing no checks */ @Nullable - private <T extends Serializable> T readSerializableInternal(@Nullable final ClassLoader loader, - @Nullable Class<? super T> clazz) { + private <T> T readSerializableInternal(@Nullable final ClassLoader loader, + @Nullable Class<T> clazz) { String name = readString(); if (name == null) { // For some reason we were unable to read the name of the Serializable (either there @@ -4584,6 +5052,7 @@ public final class Parcel { } private void freeBuffer() { + mFlags = 0; resetSqaushingState(); if (mOwnsNativeParcelObject) { nativeFreeBuffer(mNativePtr); diff --git a/core/java/android/os/image/IDynamicSystemService.aidl b/core/java/android/os/image/IDynamicSystemService.aidl index a5a40ad55853..4e69952fac2f 100644 --- a/core/java/android/os/image/IDynamicSystemService.aidl +++ b/core/java/android/os/image/IDynamicSystemService.aidl @@ -26,6 +26,7 @@ interface IDynamicSystemService * @param dsuSlot Name used to identify this installation * @return true if the call succeeds */ + @EnforcePermission("MANAGE_DYNAMIC_SYSTEM") boolean startInstallation(@utf8InCpp String dsuSlot); /** @@ -36,6 +37,7 @@ interface IDynamicSystemService * @param readOnly True if this partition is readOnly * @return true if the call succeeds */ + @EnforcePermission("MANAGE_DYNAMIC_SYSTEM") boolean createPartition(@utf8InCpp String name, long size, boolean readOnly); /** @@ -43,12 +45,14 @@ interface IDynamicSystemService * * @return true if the partition installation completes without error. */ + @EnforcePermission("MANAGE_DYNAMIC_SYSTEM") boolean closePartition(); /** * Finish a previously started installation. Installations without * a cooresponding finishInstallation() will be cleaned up during device boot. */ + @EnforcePermission("MANAGE_DYNAMIC_SYSTEM") boolean finishInstallation(); /** @@ -57,6 +61,7 @@ interface IDynamicSystemService * * @return GsiProgress */ + @EnforcePermission("MANAGE_DYNAMIC_SYSTEM") GsiProgress getInstallationProgress(); /** @@ -66,21 +71,25 @@ interface IDynamicSystemService * * @return true if the call succeeds */ + @EnforcePermission("MANAGE_DYNAMIC_SYSTEM") boolean abort(); /** * @return true if the device is running an DynamicAnroid image */ + @RequiresNoPermission boolean isInUse(); /** * @return true if the device has an DynamicSystem image installed */ + @RequiresNoPermission boolean isInstalled(); /** * @return true if the device has an DynamicSystem image enabled */ + @EnforcePermission("MANAGE_DYNAMIC_SYSTEM") boolean isEnabled(); /** @@ -88,6 +97,7 @@ interface IDynamicSystemService * * @return true if the call succeeds */ + @EnforcePermission("MANAGE_DYNAMIC_SYSTEM") boolean remove(); /** @@ -97,6 +107,7 @@ interface IDynamicSystemService * * @return true if the call succeeds */ + @EnforcePermission("MANAGE_DYNAMIC_SYSTEM") boolean setEnable(boolean enable, boolean oneShot); /** @@ -106,6 +117,7 @@ interface IDynamicSystemService * @param fd fd that points to a ashmem * @param size size of the ashmem file */ + @EnforcePermission("MANAGE_DYNAMIC_SYSTEM") boolean setAshmem(in ParcelFileDescriptor fd, long size); /** @@ -115,6 +127,7 @@ interface IDynamicSystemService * @param bytes number of bytes that can be read from stream. * @return true on success, false otherwise. */ + @EnforcePermission("MANAGE_DYNAMIC_SYSTEM") boolean submitFromAshmem(long bytes); /** @@ -124,10 +137,12 @@ interface IDynamicSystemService * @return true on success, false if partition doesn't have a * valid VBMeta block to retrieve the AVB key from. */ + @EnforcePermission("MANAGE_DYNAMIC_SYSTEM") boolean getAvbPublicKey(out AvbPublicKey dst); /** * Returns the suggested scratch partition size for overlayFS. */ + @EnforcePermission("MANAGE_DYNAMIC_SYSTEM") long suggestScratchSize(); } diff --git a/core/java/android/security/keymaster/KeymasterDefs.java b/core/java/android/security/keymaster/KeymasterDefs.java index 3b4f7e241852..f90055829b89 100644 --- a/core/java/android/security/keymaster/KeymasterDefs.java +++ b/core/java/android/security/keymaster/KeymasterDefs.java @@ -317,16 +317,35 @@ public final class KeymasterDefs { ErrorCode.MISSING_MIN_MAC_LENGTH; // -58; public static final int KM_ERROR_UNSUPPORTED_MIN_MAC_LENGTH = ErrorCode.UNSUPPORTED_MIN_MAC_LENGTH; // -59; + public static final int KM_ERROR_UNSUPPORTED_KDF = ErrorCode.UNSUPPORTED_KDF; // -60 + public static final int KM_ERROR_UNSUPPORTED_EC_CURVE = ErrorCode.UNSUPPORTED_EC_CURVE; // -61 + // -62 is KEY_REQUIRES_UPGRADE and is handled by Keystore. + public static final int KM_ERROR_ATTESTATION_CHALLENGE_MISSING = + ErrorCode.ATTESTATION_CHALLENGE_MISSING; // -63 + public static final int KM_ERROR_KEYMINT_NOT_CONFIGURED = + ErrorCode.KEYMINT_NOT_CONFIGURED; // -64 + public static final int KM_ERROR_ATTESTATION_APPLICATION_ID_MISSING = + ErrorCode.ATTESTATION_APPLICATION_ID_MISSING; // -65; public static final int KM_ERROR_CANNOT_ATTEST_IDS = ErrorCode.CANNOT_ATTEST_IDS; // -66; + public static final int KM_ERROR_ROLLBACK_RESISTANCE_UNAVAILABLE = + ErrorCode.ROLLBACK_RESISTANCE_UNAVAILABLE; // -67; public static final int KM_ERROR_HARDWARE_TYPE_UNAVAILABLE = ErrorCode.HARDWARE_TYPE_UNAVAILABLE; // -68; public static final int KM_ERROR_DEVICE_LOCKED = ErrorCode.DEVICE_LOCKED; // -72; + public static final int KM_ERROR_STORAGE_KEY_UNSUPPORTED = + ErrorCode.STORAGE_KEY_UNSUPPORTED; // -77, + public static final int KM_ERROR_INCOMPATIBLE_MGF_DIGEST = + ErrorCode.INCOMPATIBLE_MGF_DIGEST; // -78, + public static final int KM_ERROR_UNSUPPORTED_MGF_DIGEST = + ErrorCode.UNSUPPORTED_MGF_DIGEST; // -79, public static final int KM_ERROR_MISSING_NOT_BEFORE = ErrorCode.MISSING_NOT_BEFORE; // -80; public static final int KM_ERROR_MISSING_NOT_AFTER = ErrorCode.MISSING_NOT_AFTER; // -80; + public static final int KM_ERROR_HARDWARE_NOT_YET_AVAILABLE = + ErrorCode.HARDWARE_NOT_YET_AVAILABLE; // -85 public static final int KM_ERROR_UNIMPLEMENTED = ErrorCode.UNIMPLEMENTED; // -100; public static final int KM_ERROR_VERSION_MISMATCH = diff --git a/core/java/android/service/tracing/TraceReportService.java b/core/java/android/service/tracing/TraceReportService.java new file mode 100644 index 000000000000..3d16a3d41ea3 --- /dev/null +++ b/core/java/android/service/tracing/TraceReportService.java @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.service.tracing; + +import static android.annotation.SystemApi.Client.PRIVILEGED_APPS; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.app.Service; +import android.content.Intent; +import android.os.Handler; +import android.os.IBinder; +import android.os.Looper; +import android.os.Message; +import android.os.Messenger; +import android.os.ParcelFileDescriptor; +import android.os.Process; +import android.tracing.TraceReportParams; +import android.util.Log; + +import java.io.IOException; +import java.util.UUID; + +/** + * Service to be sub-classed and exposed by (privileged) apps which want to report + * system traces. + * <p> + * Subclasses should implement the onReportTrace method to handle traces reported + * to them. + * </p> + * <pre> + * public class SampleReportService extends TraceReportService { + * public void onReportTrace(TraceParams args) { + * // --- Implementation goes here --- + * } + * } + * </pre> + * <p> + * The service declaration in the application manifest must specify + * BIND_TRACE_REPORT_SERVICE in the permission attribute. + * </p> + * <pre> + * <application> + * <service android:name=".SampleReportService" + * android:permission="android.permission.BIND_TRACE_REPORT_SERVICE"> + * </service> + * </application> + * </pre> + * + * Moreover, the package containing this service must hold the DUMP and PACKAGE_USAGE_STATS + * permissions. + * + * @hide + */ +@SystemApi(client = PRIVILEGED_APPS) +public class TraceReportService extends Service { + private static final String TAG = "TraceReportService"; + private Messenger mMessenger = null; + + /** + * Public to allow this to be used by TracingServiceProxy in system_server. + * + * @hide + */ + public static final int MSG_REPORT_TRACE = 1; + + /** + * Contains information about the trace which is being reported. + * + * @hide + */ + @SystemApi(client = PRIVILEGED_APPS) + public static final class TraceParams { + private final ParcelFileDescriptor mFd; + private final UUID mUuid; + + private TraceParams(TraceReportParams params) { + mFd = params.fd; + mUuid = new UUID(params.uuidMsb, params.uuidLsb); + } + + /** + * Returns the ParcelFileDescriptor for the collected trace. + */ + @NonNull + public ParcelFileDescriptor getFd() { + return mFd; + } + + /** + * Returns the UUID of the trace; this is exactly the UUID created by the tracing system + * (i.e. Perfetto) and is also present inside the trace file. + */ + @NonNull + public UUID getUuid() { + return mUuid; + } + } + + // Methods to override. + /** + * Called when a trace is reported and sent to this class. + * + * Note: the trace file descriptor should not be persisted beyond the lifetime of this + * function as it is owned by the framework and will be closed immediately after this function + * returns: if future use of the fd is needed, it should be duped. + */ + public void onReportTrace(@NonNull TraceParams args) { + } + + // Optional methods to override. + // Realistically, these methods are internal implementation details but since this class is + // a SystemApi, it's better to err on the side of flexibility just in-case we need to override + // these methods down the line. + + /** + * Handles binder calls from system_server. + */ + public boolean onMessage(@NonNull Message msg) { + if (msg.what == MSG_REPORT_TRACE) { + if (!(msg.obj instanceof TraceReportParams)) { + Log.e(TAG, "Received invalid type for report trace message."); + return false; + } + TraceParams params = new TraceParams((TraceReportParams) msg.obj); + try { + onReportTrace(params); + } finally { + try { + params.getFd().close(); + } catch (IOException ignored) { + } + } + return true; + } + return false; + } + + /** + * Returns an IBinder for handling binder calls from system_server. + */ + @Nullable + @Override + public IBinder onBind(@NonNull Intent intent) { + if (mMessenger == null) { + mMessenger = new Messenger(new Handler(Looper.getMainLooper(), this::onMessage)); + } + return mMessenger.getBinder(); + } +}
\ No newline at end of file diff --git a/core/java/android/text/method/TextKeyListener.java b/core/java/android/text/method/TextKeyListener.java index 9cbda9c07591..2eb917b6fd57 100644 --- a/core/java/android/text/method/TextKeyListener.java +++ b/core/java/android/text/method/TextKeyListener.java @@ -306,7 +306,7 @@ public class TextKeyListener extends BaseKeyListener implements SpanWatcher { /* package */ int getPrefs(Context context) { synchronized (this) { - if (!mPrefsInited || mResolver.get() == null) { + if (!mPrefsInited || mResolver.refersTo(null)) { initPrefs(context); } } diff --git a/core/java/android/tracing/ITracingServiceProxy.aidl b/core/java/android/tracing/ITracingServiceProxy.aidl index 4520db3915a2..8029b88226b0 100644 --- a/core/java/android/tracing/ITracingServiceProxy.aidl +++ b/core/java/android/tracing/ITracingServiceProxy.aidl @@ -16,17 +16,25 @@ package android.tracing; +import android.tracing.TraceReportParams; + /** * Binder interface for the TracingServiceProxy running in system_server. * * {@hide} */ -interface ITracingServiceProxy -{ +interface ITracingServiceProxy { /** * Notifies system tracing app that a tracing session has ended. If a session is repurposed * for use in a bugreport, sessionStolen can be set to indicate that tracing has ended but * there is no buffer available to dump. */ oneway void notifyTraceSessionEnded(boolean sessionStolen); + + /** + * Notifies the specified service that a trace has been captured. The contents of |params| + * contains the intended recipient (package and class) of this trace as well as a file + * descriptor to an unlinked trace |fd| (i.e. an fd opened using O_TMPFILE). + */ + oneway void reportTrace(in TraceReportParams params); } diff --git a/core/java/android/tracing/TraceReportParams.aidl b/core/java/android/tracing/TraceReportParams.aidl new file mode 100644 index 000000000000..f57386c087ea --- /dev/null +++ b/core/java/android/tracing/TraceReportParams.aidl @@ -0,0 +1,59 @@ +/** + * Copyright (c) 2021, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.tracing; + +import android.os.ParcelFileDescriptor; + +/* + * Parameters for a trace report. + * + * See ITracingServiceProxy::reportTrace for more details. + * + * @hide + */ +parcelable TraceReportParams { + // The package name containing the reporter service (see |reporterClassName|). + String reporterPackageName; + + // The class name of the reporter service. The framework will bind to this service and pass the + // trace fd and metadata to this class. + // This class should be "trusted" (in practice this means being a priv_app + having DUMP and + // USAGE_STATS permissions). + String reporterClassName; + + // The file descriptor for the trace file. This will be an unlinked file fd (i.e. created + // with O_TMPFILE); the intention is that reporter classes link this fd into a app-private + // folder for reporting when conditions are right (e.g. charging, on unmetered networks etc). + ParcelFileDescriptor fd; + + // The least-significant-bytes of the UUID of this trace. + long uuidLsb; + + // The most-significant-bytes of the UUID of this trace. + long uuidMsb; + + // Flag indicating whether, instead of passing the fd from the trace collector, to pass a + // pipe fd from system_server and send the file over it. + // + // This flag is necessary because there is no good way to write a CTS test where a helper + // priv_app (in terms of SELinux) is needed (this is because priv_apps are supposed to be + // preinstalled on the system partition). By creating a pipe in system_server we work around + // this restriction. Note that there is a maximum allowed file size if this flag is set + // (see TracingServiceProxy). Further note that, even though SELinux may be worked around, + // manifest (i.e. framework) permissions are still checked even if this flag is set. + boolean usePipeForTesting; +}
\ No newline at end of file diff --git a/core/java/android/util/OWNERS b/core/java/android/util/OWNERS index 5425c214de1f..28c078e45347 100644 --- a/core/java/android/util/OWNERS +++ b/core/java/android/util/OWNERS @@ -1,6 +1,6 @@ +per-file Dump* = file:/core/java/com/android/internal/util/dump/OWNERS per-file FeatureFlagUtils.java = sbasi@google.com per-file FeatureFlagUtils.java = tmfang@google.com -per-file FeatureFlagUtils.java = asapperstein@google.com per-file AttributeSet.java = file:/core/java/android/content/res/OWNERS per-file TypedValue.java = file:/core/java/android/content/res/OWNERS diff --git a/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java b/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java index c7d9b9c4ab3e..c8c1fd4eba21 100644 --- a/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java +++ b/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java @@ -407,20 +407,6 @@ public class ApkSignatureSchemeV2Verifier { } } - static byte[] generateApkVerityRootHash(String apkPath) - throws IOException, SignatureNotFoundException, DigestException, - NoSuchAlgorithmException { - try (RandomAccessFile apk = new RandomAccessFile(apkPath, "r")) { - SignatureInfo signatureInfo = findSignature(apk); - VerifiedSigner vSigner = verify(apk, false); - if (vSigner.verityRootHash == null) { - return null; - } - return VerityBuilder.generateApkVerityRootHash( - apk, ByteBuffer.wrap(vSigner.verityRootHash), signatureInfo); - } - } - /** * Verified APK Signature Scheme v2 signer. * diff --git a/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java b/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java index b07b5223d296..15215c6c85b8 100644 --- a/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java +++ b/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java @@ -444,20 +444,6 @@ public class ApkSignatureSchemeV3Verifier { } } - static byte[] generateApkVerityRootHash(String apkPath) - throws NoSuchAlgorithmException, DigestException, IOException, - SignatureNotFoundException { - try (RandomAccessFile apk = new RandomAccessFile(apkPath, "r")) { - SignatureInfo signatureInfo = findSignature(apk); - VerifiedSigner vSigner = verify(apk, false); - if (vSigner.verityRootHash == null) { - return null; - } - return VerityBuilder.generateApkVerityRootHash( - apk, ByteBuffer.wrap(vSigner.verityRootHash), signatureInfo); - } - } - /** * Verified APK Signature Scheme v3 signer, including the proof of rotation structure. * diff --git a/core/java/android/util/apk/ApkSignatureVerifier.java b/core/java/android/util/apk/ApkSignatureVerifier.java index 73f7543ba819..f6b85fddf441 100644 --- a/core/java/android/util/apk/ApkSignatureVerifier.java +++ b/core/java/android/util/apk/ApkSignatureVerifier.java @@ -551,27 +551,6 @@ public class ApkSignatureVerifier { } /** - * Generates the FSVerity root hash from FSVerity header, extensions and Merkle tree root hash - * in Signing Block. - * - * @return FSverity root hash - */ - public static byte[] generateApkVerityRootHash(String apkPath) - throws NoSuchAlgorithmException, DigestException, IOException { - // first try v3 - try { - return ApkSignatureSchemeV3Verifier.generateApkVerityRootHash(apkPath); - } catch (SignatureNotFoundException e) { - // try older version - } - try { - return ApkSignatureSchemeV2Verifier.generateApkVerityRootHash(apkPath); - } catch (SignatureNotFoundException e) { - return null; - } - } - - /** * Extended signing details. * @hide for internal use only. */ diff --git a/core/java/android/util/apk/VerityBuilder.java b/core/java/android/util/apk/VerityBuilder.java index c7c465d30dad..adf53c213f8c 100644 --- a/core/java/android/util/apk/VerityBuilder.java +++ b/core/java/android/util/apk/VerityBuilder.java @@ -143,25 +143,6 @@ public abstract class VerityBuilder { return generateFsVerityTreeInternal(apk, salt, levelOffset, tree); } } - /** - * Calculates the apk-verity root hash for integrity measurement. This needs to be consistent - * to what kernel returns. - */ - @NonNull - static byte[] generateApkVerityRootHash(@NonNull RandomAccessFile apk, - @NonNull ByteBuffer apkDigest, @NonNull SignatureInfo signatureInfo) - throws NoSuchAlgorithmException, DigestException, IOException { - assertSigningBlockAlignedAndHasFullPages(signatureInfo); - - ByteBuffer footer = ByteBuffer.allocate(CHUNK_SIZE_BYTES).order(ByteOrder.LITTLE_ENDIAN); - generateApkVerityFooter(apk, signatureInfo, footer); - footer.flip(); - - MessageDigest md = MessageDigest.getInstance(JCA_DIGEST_ALGORITHM); - md.update(footer); - md.update(apkDigest); - return md.digest(); - } /** * Generates the apk-verity header and hash tree to be used by kernel for the given apk. This diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index f5c1bcf2de42..452dad3b79db 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -4347,7 +4347,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * pixel" units. This size is adjusted based on the current density and * user font size preference. * - * <p>Note: if this TextView has the auto-size feature enabled than this function is no-op. + * <p>Note: if this TextView has the auto-size feature enabled, then this function is no-op. * * @param size The scaled pixel size. * @@ -4362,7 +4362,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * Set the default text size to a given unit and value. See {@link * TypedValue} for the possible dimension units. * - * <p>Note: if this TextView has the auto-size feature enabled than this function is no-op. + * <p>Note: if this TextView has the auto-size feature enabled, then this function is no-op. * * @param unit The desired dimension unit. * @param size The desired size in the given units. diff --git a/core/java/com/android/internal/net/VpnConfig.java b/core/java/com/android/internal/net/VpnConfig.java index 2ae56f808972..f174498c0d0d 100644 --- a/core/java/com/android/internal/net/VpnConfig.java +++ b/core/java/com/android/internal/net/VpnConfig.java @@ -105,6 +105,7 @@ public class VpnConfig implements Parcelable { public boolean allowIPv4; public boolean allowIPv6; public boolean isMetered = true; + public boolean requiresInternetValidation = false; public Network[] underlyingNetworks; public ProxyInfo proxyInfo; @@ -131,6 +132,7 @@ public class VpnConfig implements Parcelable { allowIPv4 = other.allowIPv4; allowIPv6 = other.allowIPv6; isMetered = other.isMetered; + requiresInternetValidation = other.requiresInternetValidation; underlyingNetworks = other.underlyingNetworks != null ? Arrays.copyOf( other.underlyingNetworks, other.underlyingNetworks.length) : null; proxyInfo = other.proxyInfo; @@ -189,6 +191,7 @@ public class VpnConfig implements Parcelable { out.writeInt(allowIPv4 ? 1 : 0); out.writeInt(allowIPv6 ? 1 : 0); out.writeInt(isMetered ? 1 : 0); + out.writeInt(requiresInternetValidation ? 1 : 0); out.writeTypedArray(underlyingNetworks, flags); out.writeParcelable(proxyInfo, flags); } @@ -216,6 +219,7 @@ public class VpnConfig implements Parcelable { config.allowIPv4 = in.readInt() != 0; config.allowIPv6 = in.readInt() != 0; config.isMetered = in.readInt() != 0; + config.requiresInternetValidation = in.readInt() != 0; config.underlyingNetworks = in.createTypedArray(Network.CREATOR); config.proxyInfo = in.readParcelable(null); return config; @@ -248,6 +252,8 @@ public class VpnConfig implements Parcelable { .append(", allowBypass=").append(allowBypass) .append(", allowIPv4=").append(allowIPv4) .append(", allowIPv6=").append(allowIPv6) + .append(", isMetered=").append(isMetered) + .append(", requiresInternetValidation").append(requiresInternetValidation) .append(", underlyingNetworks=").append(Arrays.toString(underlyingNetworks)) .append(", proxyInfo=").append(proxyInfo) .append("}") diff --git a/core/java/com/android/internal/net/VpnProfile.java b/core/java/com/android/internal/net/VpnProfile.java index d8dc1436128e..bd3e898a631c 100644 --- a/core/java/com/android/internal/net/VpnProfile.java +++ b/core/java/com/android/internal/net/VpnProfile.java @@ -144,23 +144,26 @@ public final class VpnProfile implements Cloneable, Parcelable { public final boolean isRestrictedToTestNetworks; // 24 public final boolean excludeLocalRoutes; // 25 + public final boolean requiresInternetValidation; // 26 // Helper fields. @UnsupportedAppUsage public transient boolean saveLogin = false; public VpnProfile(String key) { - this(key, false, false); + this(key, false, false, false); } public VpnProfile(String key, boolean isRestrictedToTestNetworks) { - this(key, isRestrictedToTestNetworks, false); + this(key, isRestrictedToTestNetworks, false, false); } - public VpnProfile(String key, boolean isRestrictedToTestNetworks, boolean excludeLocalRoutes) { + public VpnProfile(String key, boolean isRestrictedToTestNetworks, boolean excludeLocalRoutes, + boolean requiresInternetValidation) { this.key = key; this.isRestrictedToTestNetworks = isRestrictedToTestNetworks; this.excludeLocalRoutes = excludeLocalRoutes; + this.requiresInternetValidation = requiresInternetValidation; } @UnsupportedAppUsage @@ -191,6 +194,7 @@ public final class VpnProfile implements Cloneable, Parcelable { areAuthParamsInline = in.readBoolean(); isRestrictedToTestNetworks = in.readBoolean(); excludeLocalRoutes = in.readBoolean(); + requiresInternetValidation = in.readBoolean(); } /** @@ -239,6 +243,7 @@ public final class VpnProfile implements Cloneable, Parcelable { out.writeBoolean(areAuthParamsInline); out.writeBoolean(isRestrictedToTestNetworks); out.writeBoolean(excludeLocalRoutes); + out.writeBoolean(requiresInternetValidation); } /** @@ -258,9 +263,11 @@ public final class VpnProfile implements Cloneable, Parcelable { // 14-19: Standard profile, with option for serverCert, proxy // 24: Standard profile with serverCert, proxy and platform-VPN parameters // 25: Standard profile with platform-VPN parameters and isRestrictedToTestNetworks - // 26: Standard profile with platform-VPN parameters and excludeLocalRoutes - if ((values.length < 14 || values.length > 19) - && values.length != 24 && values.length != 25 && values.length != 26) { + // 26: ...and excludeLocalRoutes + // (26 can only be found on dogfood devices) + // 27: ...and requiresInternetValidation + if ((values.length < 14 || (values.length > 19 && values.length < 24) + || values.length > 27)) { return null; } @@ -278,8 +285,15 @@ public final class VpnProfile implements Cloneable, Parcelable { excludeLocalRoutes = false; } + final boolean requiresInternetValidation; + if (values.length >= 27) { + requiresInternetValidation = Boolean.parseBoolean(values[26]); + } else { + requiresInternetValidation = false; + } + VpnProfile profile = new VpnProfile(key, isRestrictedToTestNetworks, - excludeLocalRoutes); + excludeLocalRoutes, requiresInternetValidation); profile.name = values[0]; profile.type = Integer.parseInt(values[1]); if (profile.type < 0 || profile.type > TYPE_MAX) { @@ -390,6 +404,7 @@ public final class VpnProfile implements Cloneable, Parcelable { builder.append(VALUE_DELIMITER).append(isRestrictedToTestNetworks); builder.append(VALUE_DELIMITER).append(excludeLocalRoutes); + builder.append(VALUE_DELIMITER).append(requiresInternetValidation); return builder.toString().getBytes(StandardCharsets.UTF_8); } @@ -471,7 +486,7 @@ public final class VpnProfile implements Cloneable, Parcelable { key, type, server, username, password, dnsServers, searchDomains, routes, mppe, l2tpSecret, ipsecIdentifier, ipsecSecret, ipsecUserCert, ipsecCaCert, ipsecServerCert, proxy, mAllowedAlgorithms, isBypassable, isMetered, maxMtu, areAuthParamsInline, - isRestrictedToTestNetworks, excludeLocalRoutes); + isRestrictedToTestNetworks, excludeLocalRoutes, requiresInternetValidation); } /** Checks VPN profiles for interior equality. */ @@ -505,11 +520,12 @@ public final class VpnProfile implements Cloneable, Parcelable { && maxMtu == other.maxMtu && areAuthParamsInline == other.areAuthParamsInline && isRestrictedToTestNetworks == other.isRestrictedToTestNetworks - && excludeLocalRoutes == other.excludeLocalRoutes; + && excludeLocalRoutes == other.excludeLocalRoutes + && requiresInternetValidation == other.requiresInternetValidation; } @NonNull - public static final Creator<VpnProfile> CREATOR = new Creator<VpnProfile>() { + public static final Creator<VpnProfile> CREATOR = new Creator<>() { @Override public VpnProfile createFromParcel(Parcel in) { return new VpnProfile(in); diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java index 611f644ffc7d..f258f84c5e3e 100644 --- a/core/java/com/android/internal/os/ZygoteInit.java +++ b/core/java/com/android/internal/os/ZygoteInit.java @@ -713,7 +713,7 @@ public class ZygoteInit { "--setuid=1000", "--setgid=1000", "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023," - + "1024,1032,1065,3001,3002,3003,3006,3007,3009,3010,3011,3012", + + "1024,1032,1065,3001,3002,3003,3005,3006,3007,3009,3010,3011,3012", "--capabilities=" + capabilities + "," + capabilities, "--nice-name=system_server", "--runtime-args", diff --git a/core/java/com/android/internal/security/VerityUtils.java b/core/java/com/android/internal/security/VerityUtils.java index 877026777ce3..76f7b2180b34 100644 --- a/core/java/com/android/internal/security/VerityUtils.java +++ b/core/java/com/android/internal/security/VerityUtils.java @@ -18,28 +18,15 @@ package com.android.internal.security; import android.annotation.NonNull; import android.os.Build; -import android.os.SharedMemory; import android.os.SystemProperties; -import android.system.ErrnoException; import android.system.Os; import android.system.OsConstants; -import android.util.Pair; import android.util.Slog; -import android.util.apk.ApkSignatureVerifier; -import android.util.apk.ByteBufferFactory; -import android.util.apk.SignatureNotFoundException; - -import libcore.util.HexEncoding; import java.io.File; -import java.io.FileDescriptor; import java.io.IOException; -import java.nio.ByteBuffer; import java.nio.file.Files; import java.nio.file.Paths; -import java.security.DigestException; -import java.security.NoSuchAlgorithmException; -import java.util.Arrays; /** Provides fsverity related operations. */ public abstract class VerityUtils { @@ -57,8 +44,6 @@ public abstract class VerityUtils { /** SHA256 hash size. */ private static final int HASH_SIZE_BYTES = 32; - private static final boolean DEBUG = false; - public static boolean isFsVeritySupported() { return Build.VERSION.DEVICE_INITIAL_SDK_INT >= Build.VERSION_CODES.R || SystemProperties.getInt("ro.apk_verity.mode", 0) == 2; @@ -123,204 +108,4 @@ public abstract class VerityUtils { private static native int measureFsverityNative(@NonNull String filePath, @NonNull byte[] digest); private static native int statxForFsverityNative(@NonNull String filePath); - - /** - * Generates legacy Merkle tree and fs-verity metadata with Signing Block skipped. - * - * @deprecated This is only used for previous fs-verity implementation, and should never be used - * on new devices. - * @return {@code SetupResult} that contains the result code, and when success, the - * {@code FileDescriptor} to read all the data from. - */ - @Deprecated - public static SetupResult generateApkVeritySetupData(@NonNull String apkPath) { - if (DEBUG) { - Slog.d(TAG, "Trying to install legacy apk verity to " + apkPath); - } - SharedMemory shm = null; - try { - final byte[] signedVerityHash = ApkSignatureVerifier.getVerityRootHash(apkPath); - if (signedVerityHash == null) { - if (DEBUG) { - Slog.d(TAG, "Skip verity tree generation since there is no signed root hash"); - } - return SetupResult.skipped(); - } - - Pair<SharedMemory, Integer> result = - generateFsVerityIntoSharedMemory(apkPath, signedVerityHash); - shm = result.first; - int contentSize = result.second; - FileDescriptor rfd = shm.getFileDescriptor(); - if (rfd == null || !rfd.valid()) { - return SetupResult.failed(); - } - return SetupResult.ok(Os.dup(rfd), contentSize); - } catch (IOException | SecurityException | DigestException | NoSuchAlgorithmException - | SignatureNotFoundException | ErrnoException e) { - Slog.e(TAG, "Failed to set up apk verity: ", e); - return SetupResult.failed(); - } finally { - if (shm != null) { - shm.close(); - } - } - } - - /** - * {@see ApkSignatureVerifier#generateApkVerityRootHash(String)}. - * @deprecated This is only used for previous fs-verity implementation, and should never be used - * on new devices. - */ - @Deprecated - public static byte[] generateApkVerityRootHash(@NonNull String apkPath) - throws NoSuchAlgorithmException, DigestException, IOException { - return ApkSignatureVerifier.generateApkVerityRootHash(apkPath); - } - - /** - * {@see ApkSignatureVerifier#getVerityRootHash(String)}. - * @deprecated This is only used for previous fs-verity implementation, and should never be used - * on new devices. - */ - @Deprecated - public static byte[] getVerityRootHash(@NonNull String apkPath) - throws IOException, SignatureNotFoundException { - return ApkSignatureVerifier.getVerityRootHash(apkPath); - } - - /** - * Returns a pair of {@code SharedMemory} and {@code Integer}. The {@code SharedMemory} contains - * Merkle tree and fsverity headers for the given apk, in the form that can immediately be used - * for fsverity setup. The data is aligned to the beginning of {@code SharedMemory}, and has - * length equals to the returned {@code Integer}. - */ - private static Pair<SharedMemory, Integer> generateFsVerityIntoSharedMemory(String apkPath, - @NonNull byte[] expectedRootHash) - throws IOException, DigestException, NoSuchAlgorithmException, - SignatureNotFoundException { - TrackedShmBufferFactory shmBufferFactory = new TrackedShmBufferFactory(); - byte[] generatedRootHash = - ApkSignatureVerifier.generateApkVerity(apkPath, shmBufferFactory); - // We only generate Merkle tree once here, so it's important to make sure the root hash - // matches the signed one in the apk. - if (!Arrays.equals(expectedRootHash, generatedRootHash)) { - throw new SecurityException("verity hash mismatch: " - + bytesToString(generatedRootHash) + " != " + bytesToString(expectedRootHash)); - } - - int contentSize = shmBufferFactory.getBufferLimit(); - SharedMemory shm = shmBufferFactory.releaseSharedMemory(); - if (shm == null) { - throw new IllegalStateException("Failed to generate verity tree into shared memory"); - } - if (!shm.setProtect(OsConstants.PROT_READ)) { - throw new SecurityException("Failed to set up shared memory correctly"); - } - return Pair.create(shm, contentSize); - } - - private static String bytesToString(byte[] bytes) { - return HexEncoding.encodeToString(bytes); - } - - /** - * @deprecated This is only used for previous fs-verity implementation, and should never be used - * on new devices. - */ - @Deprecated - public static class SetupResult { - /** Result code if verity is set up correctly. */ - private static final int RESULT_OK = 1; - - /** Result code if signature is not provided. */ - private static final int RESULT_SKIPPED = 2; - - /** Result code if the setup failed. */ - private static final int RESULT_FAILED = 3; - - private final int mCode; - private final FileDescriptor mFileDescriptor; - private final int mContentSize; - - /** @deprecated */ - @Deprecated - public static SetupResult ok(@NonNull FileDescriptor fileDescriptor, int contentSize) { - return new SetupResult(RESULT_OK, fileDescriptor, contentSize); - } - - /** @deprecated */ - @Deprecated - public static SetupResult skipped() { - return new SetupResult(RESULT_SKIPPED, null, -1); - } - - /** @deprecated */ - @Deprecated - public static SetupResult failed() { - return new SetupResult(RESULT_FAILED, null, -1); - } - - private SetupResult(int code, FileDescriptor fileDescriptor, int contentSize) { - this.mCode = code; - this.mFileDescriptor = fileDescriptor; - this.mContentSize = contentSize; - } - - public boolean isFailed() { - return mCode == RESULT_FAILED; - } - - public boolean isOk() { - return mCode == RESULT_OK; - } - - public @NonNull FileDescriptor getUnownedFileDescriptor() { - return mFileDescriptor; - } - - public int getContentSize() { - return mContentSize; - } - } - - /** A {@code ByteBufferFactory} that creates a shared memory backed {@code ByteBuffer}. */ - private static class TrackedShmBufferFactory implements ByteBufferFactory { - private SharedMemory mShm; - private ByteBuffer mBuffer; - - @Override - public ByteBuffer create(int capacity) { - try { - if (DEBUG) Slog.d(TAG, "Creating shared memory for apk verity"); - // NB: This method is supposed to be called once according to the contract with - // ApkSignatureSchemeV2Verifier. - if (mBuffer != null) { - throw new IllegalStateException("Multiple instantiation from this factory"); - } - mShm = SharedMemory.create("apkverity", capacity); - if (!mShm.setProtect(OsConstants.PROT_READ | OsConstants.PROT_WRITE)) { - throw new SecurityException("Failed to set protection"); - } - mBuffer = mShm.mapReadWrite(); - return mBuffer; - } catch (ErrnoException e) { - throw new SecurityException("Failed to set protection", e); - } - } - - public SharedMemory releaseSharedMemory() { - if (mBuffer != null) { - SharedMemory.unmap(mBuffer); - mBuffer = null; - } - SharedMemory tmp = mShm; - mShm = null; - return tmp; - } - - public int getBufferLimit() { - return mBuffer == null ? -1 : mBuffer.limit(); - } - } } diff --git a/core/java/com/android/internal/util/OWNERS b/core/java/com/android/internal/util/OWNERS index 2b7f8b2749fd..354dd9a41586 100644 --- a/core/java/com/android/internal/util/OWNERS +++ b/core/java/com/android/internal/util/OWNERS @@ -4,3 +4,4 @@ per-file *Notification* = file:/services/core/java/com/android/server/notificati per-file *ContrastColor* = file:/services/core/java/com/android/server/notification/OWNERS per-file Protocol* = etancohen@google.com, lorenzo@google.com per-file State* = jchalard@google.com, lorenzo@google.com, satk@google.com +per-file *Dump* = file:/core/java/com/android/internal/util/dump/OWNERS diff --git a/core/java/com/android/internal/util/dump/OWNERS b/core/java/com/android/internal/util/dump/OWNERS new file mode 100644 index 000000000000..ce9302aed42e --- /dev/null +++ b/core/java/com/android/internal/util/dump/OWNERS @@ -0,0 +1,2 @@ +omakoto@google.com +felipeal@google.com diff --git a/core/jni/Android.bp b/core/jni/Android.bp index adcbb425d1cf..dd2015dd7c6d 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -195,7 +195,6 @@ cc_library_shared { "android_util_FileObserver.cpp", "android/opengl/poly_clip.cpp", // TODO: .arm "android/opengl/util.cpp", - "android_server_NetworkManagementSocketTagger.cpp", "android_ddm_DdmHandleNativeHeap.cpp", "android_backup_BackupDataInput.cpp", "android_backup_BackupDataOutput.cpp", @@ -299,6 +298,8 @@ cc_library_shared { "libdl_android", "libtimeinstate", "server_configurable_flags", + // TODO: delete when ConnectivityT moves to APEX. + "libframework-connectivity-tiramisu-jni", ], export_shared_lib_headers: [ // our headers include libnativewindow's public headers diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index 0f98b74441a7..1c4107a12b74 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -164,7 +164,6 @@ extern int register_android_text_AndroidCharacter(JNIEnv *env); extern int register_android_text_Hyphenator(JNIEnv *env); extern int register_android_opengl_classes(JNIEnv *env); extern int register_android_ddm_DdmHandleNativeHeap(JNIEnv *env); -extern int register_android_server_NetworkManagementSocketTagger(JNIEnv* env); extern int register_android_backup_BackupDataInput(JNIEnv *env); extern int register_android_backup_BackupDataOutput(JNIEnv *env); extern int register_android_backup_FileBackupHelperBase(JNIEnv *env); @@ -1618,7 +1617,6 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_media_midi), REG_JNI(register_android_opengl_classes), - REG_JNI(register_android_server_NetworkManagementSocketTagger), REG_JNI(register_android_ddm_DdmHandleNativeHeap), REG_JNI(register_android_backup_BackupDataInput), REG_JNI(register_android_backup_BackupDataOutput), diff --git a/core/jni/OWNERS b/core/jni/OWNERS index 80e83ad9865c..a17d807f946b 100644 --- a/core/jni/OWNERS +++ b/core/jni/OWNERS @@ -62,6 +62,7 @@ per-file com_android_internal_net_* = file:/services/core/java/com/android/serve ### Graphics ### per-file android_graphics_* = file:/graphics/java/android/graphics/OWNERS +per-file android_hardware_HardwareBuffer.cpp = file:/graphics/java/android/graphics/OWNERS ### Text ### per-file android_text_* = file:/core/java/android/text/OWNERS diff --git a/core/jni/android/opengl/OWNERS b/core/jni/android/opengl/OWNERS new file mode 100644 index 000000000000..ce4b9075d59c --- /dev/null +++ b/core/jni/android/opengl/OWNERS @@ -0,0 +1 @@ +file:/graphics/java/android/graphics/OWNERS diff --git a/core/jni/android_hardware_UsbDeviceConnection.cpp b/core/jni/android_hardware_UsbDeviceConnection.cpp index 845d65c67719..a0228428e90e 100644 --- a/core/jni/android_hardware_UsbDeviceConnection.cpp +++ b/core/jni/android_hardware_UsbDeviceConnection.cpp @@ -16,20 +16,19 @@ #define LOG_TAG "UsbDeviceConnectionJNI" -#include "utils/Log.h" - -#include "jni.h" +#include <fcntl.h> #include <nativehelper/JNIPlatformHelp.h> -#include "core_jni_helpers.h" - +#include <stdio.h> +#include <sys/stat.h> +#include <sys/types.h> #include <usbhost/usbhost.h> +#include <usbhost/usbhost_jni.h> #include <chrono> -#include <stdio.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> +#include "core_jni_helpers.h" +#include "jni.h" +#include "utils/Log.h" using namespace android; using namespace std::chrono; @@ -91,22 +90,8 @@ android_hardware_UsbDeviceConnection_get_fd(JNIEnv *env, jobject thiz) static jbyteArray android_hardware_UsbDeviceConnection_get_desc(JNIEnv *env, jobject thiz) { - char buffer[16384]; int fd = android_hardware_UsbDeviceConnection_get_fd(env, thiz); - if (fd < 0) return NULL; - lseek(fd, 0, SEEK_SET); - int length = read(fd, buffer, sizeof(buffer)); - if (length < 0) return NULL; - - jbyteArray ret = env->NewByteArray(length); - if (ret) { - jbyte* bytes = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0); - if (bytes) { - memcpy(bytes, buffer, length); - env->ReleasePrimitiveArrayCritical(ret, bytes, 0); - } - } - return ret; + return usb_jni_read_descriptors(env, fd); } static jboolean diff --git a/core/jni/android_os_HwRemoteBinder.cpp b/core/jni/android_os_HwRemoteBinder.cpp index 3af55fe810fc..d2d7213e5761 100644 --- a/core/jni/android_os_HwRemoteBinder.cpp +++ b/core/jni/android_os_HwRemoteBinder.cpp @@ -81,27 +81,37 @@ public: void binderDied(const wp<hardware::IBinder>& who) { - if (mObject != NULL) { - JNIEnv* env = javavm_to_jnienv(mVM); + JNIEnv* env = javavm_to_jnienv(mVM); + + // Serialize with our containing HwBinderDeathRecipientList so that we can't + // delete the global ref on object while the list is being iterated. + sp<HwBinderDeathRecipientList> list = mList.promote(); + if (list == nullptr) return; - env->CallStaticVoidMethod(gProxyOffsets.proxy_class, gProxyOffsets.sendDeathNotice, mObject, mCookie); + jobject object; + { + AutoMutex _l(list->lock()); + + // this function now owns the global ref - to the rest of the code, it looks like + // this binder already died, but we won't actually delete the reference until + // the Java code has processed the death + object = mObject; + + // Demote from strong ref to weak for after binderDied() has been delivered, + // to allow the DeathRecipient and BinderProxy to be GC'd if no longer needed. + mObjectWeak = env->NewWeakGlobalRef(mObject); + mObject = nullptr; + } + + if (object != nullptr) { + env->CallStaticVoidMethod(gProxyOffsets.proxy_class, gProxyOffsets.sendDeathNotice, + object, mCookie); if (env->ExceptionCheck()) { ALOGE("Uncaught exception returned from death notification."); env->ExceptionClear(); } - // Serialize with our containing HwBinderDeathRecipientList so that we can't - // delete the global ref on mObject while the list is being iterated. - sp<HwBinderDeathRecipientList> list = mList.promote(); - if (list != NULL) { - AutoMutex _l(list->lock()); - - // Demote from strong ref to weak after binderDied() has been delivered, - // to allow the DeathRecipient and BinderProxy to be GC'd if no longer needed. - mObjectWeak = env->NewWeakGlobalRef(mObject); - env->DeleteGlobalRef(mObject); - mObject = NULL; - } + env->DeleteGlobalRef(object); } } @@ -115,7 +125,7 @@ public: } } - bool matches(jobject obj) { + bool matchesLocked(jobject obj) { bool result; JNIEnv* env = javavm_to_jnienv(mVM); @@ -129,7 +139,7 @@ public: return result; } - void warnIfStillLive() { + void warnIfStillLiveLocked() { if (mObject != NULL) { // Okay, something is wrong -- we have a hard reference to a live death // recipient on the VM side, but the list is being torn down. @@ -176,7 +186,7 @@ HwBinderDeathRecipientList::~HwBinderDeathRecipientList() { AutoMutex _l(mLock); for (const sp<HwBinderDeathRecipient>& deathRecipient : mList) { - deathRecipient->warnIfStillLive(); + deathRecipient->warnIfStillLiveLocked(); } } @@ -201,7 +211,7 @@ sp<HwBinderDeathRecipient> HwBinderDeathRecipientList::find(jobject recipient) { AutoMutex _l(mLock); for(auto iter = mList.rbegin(); iter != mList.rend(); iter++) { - if ((*iter)->matches(recipient)) { + if ((*iter)->matchesLocked(recipient)) { return (*iter); } } diff --git a/core/jni/android_server_NetworkManagementSocketTagger.cpp b/core/jni/android_server_NetworkManagementSocketTagger.cpp deleted file mode 100644 index 1be18733e97d..000000000000 --- a/core/jni/android_server_NetworkManagementSocketTagger.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2011, 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. - */ - -#define LOG_TAG "NMST_QTagUidNative" - -#include <android/multinetwork.h> -#include <cutils/qtaguid.h> -#include <errno.h> -#include <fcntl.h> -#include <nativehelper/JNIPlatformHelp.h> -#include <sys/socket.h> -#include <sys/types.h> -#include <utils/Log.h> -#include <utils/misc.h> - -#include "jni.h" - -namespace android { - -static jint tagSocketFd(JNIEnv* env, jclass, jobject fileDescriptor, - jint tagNum, jint uid) { - int userFd = jniGetFDFromFileDescriptor(env, fileDescriptor); - - if (env->ExceptionCheck()) { - ALOGE("Can't get FileDescriptor num"); - return (jint)-1; - } - - int res = android_tag_socket_with_uid(userFd, tagNum, uid); - if (res < 0) { - return (jint)-errno; - } - return (jint)res; -} - -static jint untagSocketFd(JNIEnv* env, jclass, jobject fileDescriptor) { - int userFd = jniGetFDFromFileDescriptor(env, fileDescriptor); - - if (env->ExceptionCheck()) { - ALOGE("Can't get FileDescriptor num"); - return (jint)-1; - } - - int res = android_untag_socket(userFd); - if (res < 0) { - return (jint)-errno; - } - return (jint)res; -} - -static jint setCounterSet(JNIEnv* env, jclass, jint setNum, jint uid) { - int res = qtaguid_setCounterSet(setNum, uid); - if (res < 0) { - return (jint)-errno; - } - return (jint)res; -} - -static jint deleteTagData(JNIEnv* env, jclass, jint tagNum, jint uid) { - int res = qtaguid_deleteTagData(tagNum, uid); - if (res < 0) { - return (jint)-errno; - } - return (jint)res; -} - -static const JNINativeMethod gQTagUidMethods[] = { - { "native_tagSocketFd", "(Ljava/io/FileDescriptor;II)I", (void*)tagSocketFd}, - { "native_untagSocketFd", "(Ljava/io/FileDescriptor;)I", (void*)untagSocketFd}, - { "native_setCounterSet", "(II)I", (void*)setCounterSet}, - { "native_deleteTagData", "(II)I", (void*)deleteTagData}, -}; - -int register_android_server_NetworkManagementSocketTagger(JNIEnv* env) { - return jniRegisterNativeMethods(env, "com/android/server/NetworkManagementSocketTagger", gQTagUidMethods, NELEM(gQTagUidMethods)); -} - -}; diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp index 61b91ddaa2e7..13ca13322cc7 100644 --- a/core/jni/android_util_Binder.cpp +++ b/core/jni/android_util_Binder.cpp @@ -873,7 +873,7 @@ void signalExceptionForError(JNIEnv* env, jobject obj, status_t err, const char* exceptionToThrow; char msg[128]; // TransactionTooLargeException is a checked exception, only throw from certain methods. - // FIXME: Transaction too large is the most common reason for FAILED_TRANSACTION + // TODO(b/28321379): Transaction size is the most common cause for FAILED_TRANSACTION // but it is not the only one. The Binder driver can return BR_FAILED_REPLY // for other reasons also, such as if the transaction is malformed or // refers to an FD that has been closed. We should change the driver @@ -890,8 +890,9 @@ void signalExceptionForError(JNIEnv* env, jobject obj, status_t err, exceptionToThrow = (canThrowRemoteException) ? "android/os/DeadObjectException" : "java/lang/RuntimeException"; - snprintf(msg, sizeof(msg)-1, - "Transaction failed on small parcel; remote process probably died"); + snprintf(msg, sizeof(msg) - 1, + "Transaction failed on small parcel; remote process probably died, but " + "this could also be caused by running out of binder buffer space"); } jniThrowException(env, exceptionToThrow, msg); } break; diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp index aacf700b1168..5efc4db52623 100644 --- a/core/jni/com_android_internal_os_Zygote.cpp +++ b/core/jni/com_android_internal_os_Zygote.cpp @@ -202,6 +202,8 @@ static constexpr unsigned int STORAGE_DIR_CHECK_MAX_INTERVAL_US = 1000; */ static constexpr int STORAGE_DIR_CHECK_TIMEOUT_US = 1000 * 1000 * 60 * 5; +static void WaitUntilDirReady(const std::string& target, fail_fn_t fail_fn); + /** * A helper class containing accounting information for USAPs. */ @@ -1249,7 +1251,11 @@ static void isolateAppData(JNIEnv* env, const std::vector<std::string>& merged_d auto volPath = StringPrintf("%s/%s", externalPrivateMountPath, ent->d_name); auto cePath = StringPrintf("%s/user", volPath.c_str()); auto dePath = StringPrintf("%s/user_de", volPath.c_str()); + // Wait until dir user is created. + WaitUntilDirReady(cePath.c_str(), fail_fn); MountAppDataTmpFs(cePath.c_str(), fail_fn); + // Wait until dir user_de is created. + WaitUntilDirReady(dePath.c_str(), fail_fn); MountAppDataTmpFs(dePath.c_str(), fail_fn); } closedir(dir); diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto index 998ec96f6f23..51e150e28437 100644 --- a/core/proto/android/os/incident.proto +++ b/core/proto/android/os/incident.proto @@ -249,7 +249,8 @@ message IncidentProto { optional android.service.NetworkStatsServiceDumpProto netstats = 3001 [ (section).type = SECTION_DUMPSYS, - (section).args = "netstats --proto" + (section).args = "netstats --proto", + (section).userdebug_and_eng_only = true ]; optional android.providers.settings.SettingsServiceDumpProto settings = 3002 [ diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 6bcaace96cbe..111b694d65f3 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -1945,6 +1945,11 @@ <permission android:name="android.permission.CONTROL_OEM_PAID_NETWORK_PREFERENCE" android:protectionLevel="signature" /> + <!-- @SystemApi @hide Allows an application to manage ethernet networks. + <p>Not for use by third-party or privileged applications. --> + <permission android:name="android.permission.MANAGE_ETHERNET_NETWORKS" + android:protectionLevel="signature" /> + <!-- ======================================= --> <!-- Permissions for short range, peripheral networks --> <!-- ======================================= --> @@ -3453,6 +3458,13 @@ <permission android:name="android.permission.SIGNAL_PERSISTENT_PROCESSES" android:protectionLevel="signature|privileged|development" /> + <!-- @hide @SystemApi Must be required by a + {@link com.android.service.tracing.TraceReportService}, to ensure that only the system + can bind to it. + <p>Not for use by third-party applications. --> + <permission android:name="android.permission.BIND_TRACE_REPORT_SERVICE" + android:protectionLevel="signature" /> + <!-- @hide @SystemApi @TestApi Allow an application to approve incident and bug reports to be shared off-device. There can be only one application installed on the diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 2f334989b53a..ba647d7daa28 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -134,9 +134,6 @@ be sent during a change to the audio output device. --> <bool name="config_sendAudioBecomingNoisy">true</bool> - <!-- Whether Hearing Aid profile is supported --> - <bool name="config_hearing_aid_profile_supported">false</bool> - <!-- Flag to disable all transition animations --> <bool name="config_disableTransitionAnimation">false</bool> @@ -404,10 +401,6 @@ <string-array translatable="false" name="config_tether_bluetooth_regexs"> </string-array> - <!-- Max number of Bluetooth tethering connections allowed. If this is - updated config_tether_dhcp_range has to be updated appropriately. --> - <integer translatable="false" name="config_max_pan_devices">5</integer> - <!-- This setting is deprecated, please use com.android.networkstack.tethering.R.array.config_dhcp_range instead. --> <string-array translatable="false" name="config_tether_dhcp_range"> @@ -1820,53 +1813,38 @@ <!-- Integer to set a max latency the accelerometer will batch sensor requests with. --> <integer name="config_flipToScreenOffMaxLatencyMicros">2000000</integer> - <!-- Boolean indicating if current platform supports bluetooth SCO for off call - use cases --> + <!-- Note: This config is deprecated + Boolean indicating if current platform supports bluetooth SCO for off call + use cases + --> <bool name="config_bluetooth_sco_off_call">true</bool> - <!-- Boolean indicating if current platform supports bluetooth wide band - speech --> - <bool name="config_bluetooth_wide_band_speech">true</bool> - - <!-- Boolean indicating if current platform need do one-time bluetooth address - re-validation --> + <!-- Note: This config is deprecated + Boolean indicating if current platform need do one-time bluetooth address + re-validation + --> <bool name="config_bluetooth_address_validation">false</bool> - <!-- Boolean indicating if current platform supports BLE peripheral mode --> - <bool name="config_bluetooth_le_peripheral_mode_supported">false</bool> - - <!-- Boolean indicating if current platform supports HFP inband ringing --> - <bool name="config_bluetooth_hfp_inband_ringing_support">false</bool> - - <!-- Max number of scan filters supported by blutooth controller. 0 if the - device does not support hardware scan filters--> - <integer translatable="false" name="config_bluetooth_max_scan_filters">0</integer> - - <!-- Max number of advertisers supported by bluetooth controller. 0 if the - device does not support multiple advertisement--> - <integer translatable="false" name="config_bluetooth_max_advertisers">0</integer> - - <!-- Idle current for bluetooth controller. 0 by default--> + <!-- Note: This config is deprecated, use BluetoothProperties instead. + Idle current for bluetooth controller. 0 by default + --> <integer translatable="false" name="config_bluetooth_idle_cur_ma">0</integer> - <!-- Rx current for bluetooth controller. 0 by default--> + <!-- Note: This config is deprecated, use BluetoothProperties instead. + Rx current for bluetooth controller. 0 by default + --> <integer translatable="false" name="config_bluetooth_rx_cur_ma">0</integer> - <!-- Tx current for bluetooth controller. 0 by default--> + <!-- Note: This config is deprecated, use BluetoothProperties instead. + Tx current for bluetooth controller. 0 by default + --> <integer translatable="false" name="config_bluetooth_tx_cur_ma">0</integer> - <!-- Operating volatage for bluetooth controller. 0 by default--> + <!-- Note: This config is deprecated, use BluetoothProperties instead. + Operating volatage for bluetooth controller. 0 by default + --> <integer translatable="false" name="config_bluetooth_operating_voltage_mv">0</integer> - <!-- Max number of connected audio devices supported by Bluetooth stack --> - <integer name="config_bluetooth_max_connected_audio_devices">5</integer> - - <!-- Whether supported profiles should be reloaded upon enabling bluetooth --> - <bool name="config_bluetooth_reload_supported_profiles_when_enabled">false</bool> - - <!-- Enabling autoconnect over pan --> - <bool name="config_bluetooth_pan_enable_autoconnect">false</bool> - <!-- The default data-use polling period. --> <integer name="config_datause_polling_period_sec">600</integer> @@ -2007,10 +1985,6 @@ <!-- The name of the package that will be allowed to change its components' label/icon. --> <string name="config_overrideComponentUiPackage" translatable="false">com.android.stk</string> - <!-- Enable/disable default bluetooth profiles: - HSP_AG, ObexObjectPush, Audio, NAP --> - <bool name="config_bluetooth_default_profiles">true</bool> - <!-- IP address of the dns server to use if nobody else suggests one --> <string name="config_default_dns_server" translatable="false">8.8.8.8</string> @@ -4141,8 +4115,6 @@ <!-- Component name that should be granted Notification Assistant access --> <string name="config_defaultAssistantAccessComponent" translatable="false">android.ext.services/android.ext.services.notification.Assistant</string> - <bool name="config_supportBluetoothPersistedState">true</bool> - <bool name="config_keepRestrictedProfilesInBackground">true</bool> <!-- Cellular network service package name to bind to by default. --> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 5f89588bdc7d..6ef5bd46dce7 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -3239,6 +3239,8 @@ </staging-public-group> <staging-public-group type="array" first-id="0x01d90000"> + <!-- @hide @SystemApi --> + <public name="config_optionalIpSecAlgorithms" /> </staging-public-group> <staging-public-group type="drawable" first-id="0x01d80000"> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 4db6499569b3..590fcf46f373 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -278,8 +278,6 @@ <java-symbol type="bool" name="config_flipToScreenOffEnabled" /> <java-symbol type="integer" name="config_flipToScreenOffMaxLatencyMicros" /> <java-symbol type="bool" name="config_bluetooth_sco_off_call" /> - <java-symbol type="bool" name="config_bluetooth_le_peripheral_mode_supported" /> - <java-symbol type="bool" name="config_bluetooth_hfp_inband_ringing_support" /> <java-symbol type="bool" name="config_cellBroadcastAppLinks" /> <java-symbol type="bool" name="config_duplicate_port_omadm_wappush" /> <java-symbol type="bool" name="config_disableTransitionAnimation" /> @@ -343,7 +341,6 @@ <java-symbol type="integer" name="config_timeZoneRulesCheckRetryCount" /> <java-symbol type="bool" name="config_sendAudioBecomingNoisy" /> <java-symbol type="bool" name="config_enableScreenshotChord" /> - <java-symbol type="bool" name="config_bluetooth_default_profiles" /> <java-symbol type="bool" name="config_enableWifiDisplay" /> <java-symbol type="bool" name="config_allowAnimationsInLowPowerMode" /> <java-symbol type="bool" name="config_useDevInputEventForAudioJack" /> @@ -417,9 +414,6 @@ <java-symbol type="dimen" name="config_pictureInPictureMaxAspectRatio" /> <java-symbol type="integer" name="config_pictureInPictureMaxNumberOfActions" /> <java-symbol type="dimen" name="config_closeToSquareDisplayMaxAspectRatio" /> - <java-symbol type="integer" name="config_bluetooth_max_advertisers" /> - <java-symbol type="integer" name="config_bluetooth_max_scan_filters" /> - <java-symbol type="integer" name="config_bluetooth_max_connected_audio_devices" /> <java-symbol type="integer" name="config_burnInProtectionMinHorizontalOffset" /> <java-symbol type="integer" name="config_burnInProtectionMaxHorizontalOffset" /> <java-symbol type="integer" name="config_burnInProtectionMinVerticalOffset" /> @@ -429,9 +423,6 @@ <java-symbol type="integer" name="config_bluetooth_rx_cur_ma" /> <java-symbol type="integer" name="config_bluetooth_tx_cur_ma" /> <java-symbol type="integer" name="config_bluetooth_operating_voltage_mv" /> - <java-symbol type="bool" name="config_bluetooth_pan_enable_autoconnect" /> - <java-symbol type="bool" name="config_bluetooth_reload_supported_profiles_when_enabled" /> - <java-symbol type="bool" name="config_hearing_aid_profile_supported" /> <java-symbol type="integer" name="config_cursorWindowSize" /> <java-symbol type="integer" name="config_drawLockTimeoutMillis" /> <java-symbol type="integer" name="config_doublePressOnPowerBehavior" /> @@ -450,7 +441,6 @@ <java-symbol type="integer" name="config_wakeUpToLastStateTimeoutMillis" /> <java-symbol type="integer" name="config_lowMemoryKillerMinFreeKbytesAdjust" /> <java-symbol type="integer" name="config_lowMemoryKillerMinFreeKbytesAbsolute" /> - <java-symbol type="integer" name="config_max_pan_devices" /> <java-symbol type="integer" name="config_ntpPollingInterval" /> <java-symbol type="integer" name="config_ntpPollingIntervalShorter" /> <java-symbol type="integer" name="config_ntpRetry" /> @@ -3782,8 +3772,6 @@ <java-symbol type="string" name="config_defaultAssistantAccessComponent" /> - <java-symbol type="bool" name="config_supportBluetoothPersistedState" /> - <java-symbol type="string" name="slices_permission_request" /> <java-symbol type="string" name="screenshot_edit" /> diff --git a/core/res/res/xml/sms_short_codes.xml b/core/res/res/xml/sms_short_codes.xml index 4c20ae1b099c..d1d86a782016 100644 --- a/core/res/res/xml/sms_short_codes.xml +++ b/core/res/res/xml/sms_short_codes.xml @@ -154,9 +154,9 @@ <!-- Israel: 4 digits, known premium codes listed --> <shortcode country="il" pattern="\\d{4}" premium="4422|4545" /> - <!-- Italy: 5 digits (premium=4xxxx), plus EU: - http://clients.txtnation.com/attachments/token/di5kfblvubttvlw/?name=Italy_CASP_EN.pdf --> - <shortcode country="it" pattern="\\d{5}" premium="4\\d{4}" free="116\\d{3}|4112503" standard="43\\d{3}" /> + <!-- Italy: 5 digits (premium=41xxx,42xxx), plus EU: + https://www.itu.int/dms_pub/itu-t/oth/02/02/T020200006B0001PDFE.pdf --> + <shortcode country="it" pattern="\\d{5}" premium="4\\d{4}" free="116\\d{3}|4112503|40\\d{0,12}" standard="430\\d{2}|431\\d{2}|434\\d{4}|435\\d{4}|439\\d{7}" /> <!-- Japan: 8083 used by SOFTBANK_DCB_2 --> <shortcode country="jp" pattern="\\d{1,5}" free="8083" /> diff --git a/core/tests/coretests/src/android/view/OWNERS b/core/tests/coretests/src/android/view/OWNERS index 74cdd2146937..10f6f1fd22f1 100644 --- a/core/tests/coretests/src/android/view/OWNERS +++ b/core/tests/coretests/src/android/view/OWNERS @@ -16,3 +16,6 @@ per-file *Window* = file:/services/core/java/com/android/server/wm/OWNERS # Scroll Capture per-file *ScrollCapture*.java = file:/packages/SystemUI/src/com/android/systemui/screenshot/OWNERS + +# Stylus +per-file stylus/* = file:/core/java/android/text/OWNERS
\ No newline at end of file diff --git a/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java index 597ea14df56d..12e52c62b7c7 100644 --- a/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java +++ b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java @@ -288,9 +288,8 @@ public class HdmiAudioSystemClientTest { } @Override - public void addVendorCommandListener(final IHdmiVendorCommandListener listener, - final int deviceType) { - } + public void addVendorCommandListener( + final IHdmiVendorCommandListener listener, final int vendorId) {} @Override public void sendVendorCommand(final int deviceType, final int targetAddress, diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml index be85fcc15ffa..fcd179912800 100644 --- a/data/etc/privapp-permissions-platform.xml +++ b/data/etc/privapp-permissions-platform.xml @@ -393,6 +393,7 @@ applications that come with the platform <!-- Permission required for CTS test - TrustTestCases --> <permission name="android.permission.PROVIDE_TRUST_AGENT" /> <permission name="android.permission.ACCESS_KEYGUARD_SECURE_STORAGE" /> + <permission name="android.permission.TRUST_LISTENER" /> <!-- Permissions required for Incremental CTS tests --> <permission name="com.android.permission.USE_INSTALLER_V2"/> <permission name="android.permission.LOADER_USAGE_STATS"/> @@ -461,6 +462,8 @@ applications that come with the platform <!-- Permission needed for CTS test - WifiManagerTest --> <permission name="android.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS" /> <permission name="android.permission.WIFI_UPDATE_COEX_UNSAFE_CHANNELS" /> + <permission name="android.permission.NEARBY_WIFI_DEVICES" /> + <permission name="android.permission.OVERRIDE_WIFI_CONFIG" /> <!-- Permission required for CTS test CarrierMessagingServiceWrapperTest --> <permission name="android.permission.BIND_CARRIER_SERVICES"/> <!-- Permission required for CTS test - MusicRecognitionManagerTest --> diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java index 42e470b7f660..5bfc32177ec0 100644 --- a/graphics/java/android/graphics/Paint.java +++ b/graphics/java/android/graphics/Paint.java @@ -1611,7 +1611,7 @@ public class Paint { * Return the paint's Align value for drawing text. This controls how the * text is positioned relative to its origin. LEFT align means that all of * the text will be drawn to the right of its origin (i.e. the origin - * specifieds the LEFT edge of the text) and so on. + * specifies the LEFT edge of the text) and so on. * * @return the paint's Align value for drawing text. */ @@ -1623,7 +1623,7 @@ public class Paint { * Set the paint's text alignment. This controls how the * text is positioned relative to its origin. LEFT align means that all of * the text will be drawn to the right of its origin (i.e. the origin - * specifieds the LEFT edge of the text) and so on. + * specifies the LEFT edge of the text) and so on. * * @param align set the paint's Align value for drawing text. */ diff --git a/graphics/java/android/graphics/SurfaceTexture.java b/graphics/java/android/graphics/SurfaceTexture.java index 9b2effcde1d3..0fadae23556d 100644 --- a/graphics/java/android/graphics/SurfaceTexture.java +++ b/graphics/java/android/graphics/SurfaceTexture.java @@ -288,7 +288,7 @@ public class SurfaceTexture { * context at a time. * * @param texName The name of the OpenGL ES texture that will be created. This texture name - * must be unusued in the OpenGL ES context that is current on the calling thread. + * must be unused in the OpenGL ES context that is current on the calling thread. */ public void attachToGLContext(int texName) { int err = nativeAttachToGLContext(texName); diff --git a/identity/java/android/security/identity/IdentityCredential.java b/identity/java/android/security/identity/IdentityCredential.java index cdf746fc9900..f440b693a5b3 100644 --- a/identity/java/android/security/identity/IdentityCredential.java +++ b/identity/java/android/security/identity/IdentityCredential.java @@ -454,7 +454,8 @@ public abstract class IdentityCredential { * @param challenge is a non-empty byte array whose contents should be unique, fresh and * provided by the issuing authority. The value provided is embedded in the * generated CBOR and enables the issuing authority to verify that the - * returned proof is fresh. + * returned proof is fresh. Implementations are required to support + * challenges at least 32 bytes of length. * @return the COSE_Sign1 data structure above */ public @NonNull byte[] proveOwnership(@NonNull byte[] challenge) { @@ -485,7 +486,8 @@ public abstract class IdentityCredential { * @param challenge is a non-empty byte array whose contents should be unique, fresh and * provided by the issuing authority. The value provided is embedded in the * generated CBOR and enables the issuing authority to verify that the - * returned proof is fresh. + * returned proof is fresh. Implementations are required to support + * challenges at least 32 bytes of length. * @return the COSE_Sign1 data structure above */ public @NonNull byte[] delete(@NonNull byte[] challenge) { diff --git a/identity/java/android/security/identity/WritableIdentityCredential.java b/identity/java/android/security/identity/WritableIdentityCredential.java index 305d0ead0652..6d569648f2c6 100644 --- a/identity/java/android/security/identity/WritableIdentityCredential.java +++ b/identity/java/android/security/identity/WritableIdentityCredential.java @@ -59,7 +59,8 @@ public abstract class WritableIdentityCredential { * @param challenge is a non-empty byte array whose contents should be unique, fresh and * provided by the issuing authority. The value provided is embedded in the * attestation extension and enables the issuing authority to verify that the - * attestation certificate is fresh. + * attestation certificate is fresh. Implementations are required to support + * challenges at least 32 bytes of length. * @return the X.509 certificate for this credential's CredentialKey. */ public abstract @NonNull Collection<X509Certificate> getCredentialKeyCertificateChain( diff --git a/keystore/OWNERS b/keystore/OWNERS index a63ca46df2a6..7ab9d761e236 100644 --- a/keystore/OWNERS +++ b/keystore/OWNERS @@ -1,4 +1,4 @@ +eranm@google.com jbires@google.com jdanis@google.com -robbarnes@google.com swillden@google.com diff --git a/keystore/java/android/security/KeyStore2.java b/keystore/java/android/security/KeyStore2.java index 1034847b761b..3d53cfb388e1 100644 --- a/keystore/java/android/security/KeyStore2.java +++ b/keystore/java/android/security/KeyStore2.java @@ -108,7 +108,7 @@ public class KeyStore2 { try { return request.execute(service); } catch (ServiceSpecificException e) { - throw getKeyStoreException(e.errorCode); + throw getKeyStoreException(e.errorCode, e.getMessage()); } catch (RemoteException e) { if (firstTry) { Log.w(TAG, "Looks like we may have lost connection to the Keystore " @@ -120,7 +120,7 @@ public class KeyStore2 { firstTry = false; } else { Log.e(TAG, "Cannot connect to Keystore daemon.", e); - throw new KeyStoreException(ResponseCode.SYSTEM_ERROR, ""); + throw new KeyStoreException(ResponseCode.SYSTEM_ERROR, "", e.getMessage()); } } } @@ -322,26 +322,32 @@ public class KeyStore2 { } } - static KeyStoreException getKeyStoreException(int errorCode) { + static KeyStoreException getKeyStoreException(int errorCode, String serviceErrorMessage) { if (errorCode > 0) { // KeyStore layer error switch (errorCode) { case ResponseCode.LOCKED: - return new KeyStoreException(errorCode, "User authentication required"); + return new KeyStoreException(errorCode, "User authentication required", + serviceErrorMessage); case ResponseCode.UNINITIALIZED: - return new KeyStoreException(errorCode, "Keystore not initialized"); + return new KeyStoreException(errorCode, "Keystore not initialized", + serviceErrorMessage); case ResponseCode.SYSTEM_ERROR: - return new KeyStoreException(errorCode, "System error"); + return new KeyStoreException(errorCode, "System error", serviceErrorMessage); case ResponseCode.PERMISSION_DENIED: - return new KeyStoreException(errorCode, "Permission denied"); + return new KeyStoreException(errorCode, "Permission denied", + serviceErrorMessage); case ResponseCode.KEY_NOT_FOUND: - return new KeyStoreException(errorCode, "Key not found"); + return new KeyStoreException(errorCode, "Key not found", serviceErrorMessage); case ResponseCode.VALUE_CORRUPTED: - return new KeyStoreException(errorCode, "Key blob corrupted"); + return new KeyStoreException(errorCode, "Key blob corrupted", + serviceErrorMessage); case ResponseCode.KEY_PERMANENTLY_INVALIDATED: - return new KeyStoreException(errorCode, "Key permanently invalidated"); + return new KeyStoreException(errorCode, "Key permanently invalidated", + serviceErrorMessage); default: - return new KeyStoreException(errorCode, String.valueOf(errorCode)); + return new KeyStoreException(errorCode, String.valueOf(errorCode), + serviceErrorMessage); } } else { // Keymaster layer error @@ -350,10 +356,12 @@ public class KeyStore2 { // The name of this parameter significantly differs between Keymaster and // framework APIs. Use the framework wording to make life easier for developers. return new KeyStoreException(errorCode, - "Invalid user authentication validity duration"); + "Invalid user authentication validity duration", + serviceErrorMessage); default: return new KeyStoreException(errorCode, - KeymasterDefs.getErrorMessage(errorCode)); + KeymasterDefs.getErrorMessage(errorCode), + serviceErrorMessage); } } } diff --git a/keystore/java/android/security/KeyStoreException.java b/keystore/java/android/security/KeyStoreException.java index 30389a29d342..54184dbf6e08 100644 --- a/keystore/java/android/security/KeyStoreException.java +++ b/keystore/java/android/security/KeyStoreException.java @@ -16,25 +16,458 @@ package android.security; +import android.annotation.IntDef; +import android.annotation.Nullable; import android.annotation.TestApi; +import android.security.keymaster.KeymasterDefs; +import android.system.keystore2.ResponseCode; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.HashMap; +import java.util.Map; /** - * KeyStore/keymaster exception with positive error codes coming from the KeyStore and negative - * ones from keymaster. + * Exception containing information about the failure at the Keystore / KeyMint layer while + * generating or using a key. * - * @hide + * The public error codes indicate the cause of the error and the methods indicate whether + * it's a system/key issue and whether re-trying the operation (with the same key or a new key) + * is likely to succeed. */ -@TestApi public class KeyStoreException extends Exception { + /** + * This error code is for mapping errors that the caller will not know about. If the caller is + * targeting an API level earlier than the one the error was introduced in, then the error will + * be mapped to this one. + * In API level 33 no errors map to this error. + */ + public static final int ERROR_OTHER = 1; + /** + * Indicating the key could not be used because the user needs to authenticate first. + * See + * {@link android.security.keystore.KeyGenParameterSpec.Builder#setUserAuthenticationRequired(boolean)}. + */ + public static final int ERROR_USER_AUTHENTICATION_REQUIRED = 2; + /** + * Indicating that {@code load()} has not been called on the Keystore instance, or an attempt + * has been made to generate an authorization bound key while the user has not set a lock + * screen knowledge factor (LSKF). Instruct the user to set an LSKF and retry. + */ + public static final int ERROR_KEYSTORE_UNINITIALIZED = 3; + /** + * An internal system error - refer to {@link #isTransientFailure()} to determine whether + * re-trying the operation is likely to yield different results. + */ + public static final int ERROR_INTERNAL_SYSTEM_ERROR = 4; + /** + * The caller has requested key parameters or operation which are only available to system + * or privileged apps. + */ + public static final int ERROR_PERMISSION_DENIED = 5; + /** + * The key the operation refers to doesn't exist. + */ + public static final int ERROR_KEY_DOES_NOT_EXIST = 6; + /** + * The key is corrupted and could not be recovered. + */ + public static final int ERROR_KEY_CORRUPTED = 7; + /** + * The error related to inclusion of device identifiers in the attestation record. + */ + public static final int ERROR_ID_ATTESTATION_FAILURE = 8; + /** + * The attestation challenge specified is too large. + */ + public static final int ERROR_ATTESTATION_CHALLENGE_TOO_LARGE = 9; + /** + * General error in the KeyMint layer. + */ + public static final int ERROR_KEYMINT_FAILURE = 10; + /** + * Failure in the Keystore layer. + */ + public static final int ERROR_KEYSTORE_FAILURE = 11; + /** + * The feature the caller is trying to use is not implemented by the underlying + * KeyMint implementation. + * This could happen when an unsupported algorithm is requested, or when trying to import + * a key in a format other than raw or PKCS#8. + */ + public static final int ERROR_UNIMPLEMENTED = 12; + /** + * The feature the caller is trying to use is not compatible with the parameters used to + * generate the key. For example, trying to use a key generated for a different signature + * algorithm, or a digest not specified during key creation. + * Another case is the attempt to generate a symmetric AES key and requesting key attestation. + */ + public static final int ERROR_INCORRECT_USAGE = 13; + /** + * The key is not currently valid: Either at has expired or it will be valid for use in the + * future. + */ + public static final int ERROR_KEY_NOT_TEMPORALLY_VALID = 14; + /** + * The crypto object the caller has been using held a reference to a KeyMint operation that + * has been evacuated (likely due to other concurrent operations taking place). + * The caller should re-create the crypto object and try again. + */ + public static final int ERROR_KEY_OPERATION_EXPIRED = 15; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(flag = true, prefix = {"ERROR_"}, value = { + ERROR_OTHER, + ERROR_USER_AUTHENTICATION_REQUIRED, + ERROR_KEYSTORE_UNINITIALIZED, + ERROR_INTERNAL_SYSTEM_ERROR, + ERROR_PERMISSION_DENIED, + ERROR_KEY_DOES_NOT_EXIST, + ERROR_KEY_CORRUPTED, + ERROR_ID_ATTESTATION_FAILURE, + ERROR_ATTESTATION_CHALLENGE_TOO_LARGE, + ERROR_KEYMINT_FAILURE, + ERROR_KEYSTORE_FAILURE, + ERROR_UNIMPLEMENTED, + ERROR_INCORRECT_USAGE, + ERROR_KEY_NOT_TEMPORALLY_VALID, + ERROR_KEY_OPERATION_EXPIRED + }) + public @interface PublicErrorCode { + } + // Constants for encoding information about the error encountered: + // Whether the error relates to the system state/implementation as a whole, or a specific key. + private static final int IS_SYSTEM_ERROR = 1 << 1; + // Whether the error is permanent. + private static final int IS_TRANSIENT_ERROR = 1 << 2; + // Whether the cause of the error is the user not having authenticated recently. + private static final int REQUIRES_USER_AUTHENTICATION = 1 << 3; + + // The internal error code. NOT to be returned directly to callers or made part of the + // public API. private final int mErrorCode; - public KeyStoreException(int errorCode, String message) { + /** + * @hide + */ + public KeyStoreException(int errorCode, @Nullable String message) { super(message); mErrorCode = errorCode; } + /** + * @hide + */ + public KeyStoreException(int errorCode, @Nullable String message, + @Nullable String keystoreErrorMessage) { + super(message + " (internal Keystore code: " + errorCode + " message: " + + keystoreErrorMessage + ")"); + mErrorCode = errorCode; + } + + /** + * Returns the internal error code. Only for use by the platform. + * + * @hide + */ + @TestApi public int getErrorCode() { return mErrorCode; } + + /** + * Returns one of the error codes exported by the class. + * + * @return a public error code, one of the values in {@link PublicErrorCode}. + */ + @PublicErrorCode + public int getNumericErrorCode() { + PublicErrorInformation failureInfo = getErrorInformation(mErrorCode); + return failureInfo.errorCode; + } + + /** + * Returns true if the failure is a transient failure - that is, performing the same operation + * again at a late time is likely to succeed. + * + * If {@link #isSystemError()} returns true, the transient nature of the failure relates to the + * device, otherwise relates to the key (so a permanent failure with an existing key likely + * requires creating another key to repeat the operation with). + */ + public boolean isTransientFailure() { + PublicErrorInformation failureInfo = getErrorInformation(mErrorCode); + return (failureInfo.indicators & IS_TRANSIENT_ERROR) != 0; + } + + /** + * Indicates whether the failure is due to the device being locked. + * + * @return true if the key operation failed because the user has to authenticate + * (e.g. by unlocking the device). + */ + public boolean requiresUserAuthentication() { + PublicErrorInformation failureInfo = getErrorInformation(mErrorCode); + return (failureInfo.indicators & REQUIRES_USER_AUTHENTICATION) != 0; + } + + /** + * Indicates whether the error related to the Keystore/KeyMint implementation and not + * a specific key. + * + * @return true if the error is related to the system, not the key in use. System + * errors indicate a feature isn't working, whereas key-related errors are likely + * to succeed with a new key. + */ + public boolean isSystemError() { + PublicErrorInformation failureInfo = getErrorInformation(mErrorCode); + return (failureInfo.indicators & IS_SYSTEM_ERROR) != 0; + } + + @Override + public String toString() { + String errorCodes = String.format(" (public error code: %d internal Keystore code: %d)", + getNumericErrorCode(), mErrorCode); + return super.toString() + errorCodes; + } + + private static PublicErrorInformation getErrorInformation(int internalErrorCode) { + PublicErrorInformation errorInfo = sErrorCodeToFailureInfo.get(internalErrorCode); + if (errorInfo != null) { + return errorInfo; + } + + /** + * KeyStore/keymaster exception with positive error codes coming from the KeyStore and + * negative ones from keymaster. + * This is a safety fall-back: All error codes should be present in the map. + */ + if (internalErrorCode > 0) { + return GENERAL_KEYSTORE_ERROR; + } else { + return GENERAL_KEYMINT_ERROR; + } + } + + private static final class PublicErrorInformation { + public final int indicators; + public final int errorCode; + + PublicErrorInformation(int indicators, @PublicErrorCode int errorCode) { + this.indicators = indicators; + this.errorCode = errorCode; + } + } + + private static final PublicErrorInformation GENERAL_KEYMINT_ERROR = + new PublicErrorInformation(0, ERROR_KEYMINT_FAILURE); + + private static final PublicErrorInformation GENERAL_KEYSTORE_ERROR = + new PublicErrorInformation(0, ERROR_KEYSTORE_FAILURE); + + private static final PublicErrorInformation KEYMINT_UNIMPLEMENTED_ERROR = + new PublicErrorInformation(IS_SYSTEM_ERROR, ERROR_UNIMPLEMENTED); + + private static final PublicErrorInformation KEYMINT_RETRYABLE_ERROR = + new PublicErrorInformation(IS_SYSTEM_ERROR | IS_TRANSIENT_ERROR, + ERROR_KEYMINT_FAILURE); + + private static final PublicErrorInformation KEYMINT_INCORRECT_USAGE_ERROR = + new PublicErrorInformation(0, ERROR_INCORRECT_USAGE); + + private static final PublicErrorInformation KEYMINT_TEMPORAL_VALIDITY_ERROR = + new PublicErrorInformation(0, ERROR_KEY_NOT_TEMPORALLY_VALID); + + + private static final Map<Integer, PublicErrorInformation> sErrorCodeToFailureInfo = + new HashMap(); + + /** + * @hide + */ + @TestApi + public static boolean hasFailureInfoForError(int internalErrorCode) { + return sErrorCodeToFailureInfo.containsKey(internalErrorCode); + } + + static { + // KeyMint error codes + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_OK, GENERAL_KEYMINT_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_ROOT_OF_TRUST_ALREADY_SET, + GENERAL_KEYMINT_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNSUPPORTED_PURPOSE, + KEYMINT_INCORRECT_USAGE_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INCOMPATIBLE_PURPOSE, + KEYMINT_INCORRECT_USAGE_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNSUPPORTED_ALGORITHM, + KEYMINT_UNIMPLEMENTED_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INCOMPATIBLE_ALGORITHM, + KEYMINT_INCORRECT_USAGE_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNSUPPORTED_KEY_SIZE, + KEYMINT_UNIMPLEMENTED_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNSUPPORTED_BLOCK_MODE, + KEYMINT_UNIMPLEMENTED_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INCOMPATIBLE_BLOCK_MODE, + KEYMINT_INCORRECT_USAGE_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNSUPPORTED_MAC_LENGTH, + KEYMINT_UNIMPLEMENTED_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNSUPPORTED_PADDING_MODE, + KEYMINT_INCORRECT_USAGE_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INCOMPATIBLE_PADDING_MODE, + KEYMINT_INCORRECT_USAGE_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNSUPPORTED_DIGEST, + KEYMINT_UNIMPLEMENTED_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INCOMPATIBLE_DIGEST, + KEYMINT_INCORRECT_USAGE_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INVALID_EXPIRATION_TIME, + KEYMINT_INCORRECT_USAGE_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INVALID_USER_ID, + GENERAL_KEYMINT_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INVALID_AUTHORIZATION_TIMEOUT, + KEYMINT_INCORRECT_USAGE_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNSUPPORTED_KEY_FORMAT, + KEYMINT_INCORRECT_USAGE_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INCOMPATIBLE_KEY_FORMAT, + KEYMINT_INCORRECT_USAGE_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM, + KEYMINT_UNIMPLEMENTED_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNSUPPORTED_KEY_VERIFICATION_ALGORITHM, + KEYMINT_UNIMPLEMENTED_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INVALID_INPUT_LENGTH, + KEYMINT_INCORRECT_USAGE_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_KEY_EXPORT_OPTIONS_INVALID, + KEYMINT_INCORRECT_USAGE_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_DELEGATION_NOT_ALLOWED, + GENERAL_KEYMINT_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_KEY_NOT_YET_VALID, + KEYMINT_TEMPORAL_VALIDITY_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_KEY_EXPIRED, + KEYMINT_TEMPORAL_VALIDITY_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_KEY_USER_NOT_AUTHENTICATED, + new PublicErrorInformation(REQUIRES_USER_AUTHENTICATION, + ERROR_USER_AUTHENTICATION_REQUIRED)); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_OUTPUT_PARAMETER_NULL, + GENERAL_KEYMINT_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INVALID_OPERATION_HANDLE, + new PublicErrorInformation(IS_SYSTEM_ERROR | IS_TRANSIENT_ERROR, + ERROR_KEY_OPERATION_EXPIRED)); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INSUFFICIENT_BUFFER_SPACE, + GENERAL_KEYMINT_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_VERIFICATION_FAILED, + GENERAL_KEYMINT_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_TOO_MANY_OPERATIONS, + GENERAL_KEYMINT_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNEXPECTED_NULL_POINTER, + GENERAL_KEYMINT_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INVALID_KEY_BLOB, + GENERAL_KEYMINT_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_IMPORTED_KEY_NOT_ENCRYPTED, + KEYMINT_INCORRECT_USAGE_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_IMPORTED_KEY_DECRYPTION_FAILED, + KEYMINT_INCORRECT_USAGE_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_IMPORTED_KEY_NOT_SIGNED, + KEYMINT_INCORRECT_USAGE_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_IMPORTED_KEY_VERIFICATION_FAILED, + KEYMINT_INCORRECT_USAGE_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INVALID_ARGUMENT, + GENERAL_KEYMINT_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNSUPPORTED_TAG, + KEYMINT_UNIMPLEMENTED_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INVALID_TAG, + KEYMINT_INCORRECT_USAGE_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_MEMORY_ALLOCATION_FAILED, + GENERAL_KEYMINT_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_IMPORT_PARAMETER_MISMATCH, + GENERAL_KEYMINT_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_SECURE_HW_ACCESS_DENIED, + GENERAL_KEYMINT_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_OPERATION_CANCELLED, + GENERAL_KEYMINT_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_CONCURRENT_ACCESS_CONFLICT, + GENERAL_KEYMINT_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_SECURE_HW_BUSY, + KEYMINT_RETRYABLE_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_SECURE_HW_COMMUNICATION_FAILED, + KEYMINT_RETRYABLE_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNSUPPORTED_EC_FIELD, + KEYMINT_UNIMPLEMENTED_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_MISSING_NONCE, + KEYMINT_INCORRECT_USAGE_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INVALID_NONCE, + KEYMINT_INCORRECT_USAGE_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_MISSING_MAC_LENGTH, + KEYMINT_INCORRECT_USAGE_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_KEY_RATE_LIMIT_EXCEEDED, + KEYMINT_RETRYABLE_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_CALLER_NONCE_PROHIBITED, + GENERAL_KEYMINT_ERROR); + // Error related to MAX_USES_PER_BOOT, restricting the number of uses per boot. + // It is not re-tryable. + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_KEY_MAX_OPS_EXCEEDED, + GENERAL_KEYMINT_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INVALID_MAC_LENGTH, + KEYMINT_INCORRECT_USAGE_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_MISSING_MIN_MAC_LENGTH, + KEYMINT_INCORRECT_USAGE_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNSUPPORTED_MIN_MAC_LENGTH, + KEYMINT_INCORRECT_USAGE_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNSUPPORTED_KDF, + KEYMINT_UNIMPLEMENTED_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNSUPPORTED_EC_CURVE, + KEYMINT_UNIMPLEMENTED_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_ATTESTATION_CHALLENGE_MISSING, + KEYMINT_INCORRECT_USAGE_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_KEYMINT_NOT_CONFIGURED, + new PublicErrorInformation(IS_SYSTEM_ERROR, ERROR_KEYMINT_FAILURE)); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_ATTESTATION_APPLICATION_ID_MISSING, + KEYMINT_RETRYABLE_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_CANNOT_ATTEST_IDS, + new PublicErrorInformation(IS_SYSTEM_ERROR, + ERROR_ID_ATTESTATION_FAILURE)); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_ROLLBACK_RESISTANCE_UNAVAILABLE, + KEYMINT_UNIMPLEMENTED_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_HARDWARE_TYPE_UNAVAILABLE, + KEYMINT_UNIMPLEMENTED_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_DEVICE_LOCKED, + new PublicErrorInformation(IS_SYSTEM_ERROR | REQUIRES_USER_AUTHENTICATION, + ERROR_USER_AUTHENTICATION_REQUIRED)); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_STORAGE_KEY_UNSUPPORTED, + KEYMINT_UNIMPLEMENTED_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INCOMPATIBLE_MGF_DIGEST, + KEYMINT_INCORRECT_USAGE_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNSUPPORTED_MGF_DIGEST, + KEYMINT_UNIMPLEMENTED_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_MISSING_NOT_BEFORE, + KEYMINT_INCORRECT_USAGE_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_MISSING_NOT_AFTER, + KEYMINT_INCORRECT_USAGE_ERROR); + // This should not be exposed to apps as it's handled by Keystore. + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_HARDWARE_NOT_YET_AVAILABLE, + GENERAL_KEYMINT_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNIMPLEMENTED, + KEYMINT_UNIMPLEMENTED_ERROR); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNKNOWN_ERROR, + new PublicErrorInformation(IS_SYSTEM_ERROR, + ERROR_KEYMINT_FAILURE)); + sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_VERSION_MISMATCH, GENERAL_KEYMINT_ERROR); + + // Keystore error codes + sErrorCodeToFailureInfo.put(ResponseCode.LOCKED, + new PublicErrorInformation(REQUIRES_USER_AUTHENTICATION, + ERROR_USER_AUTHENTICATION_REQUIRED)); + sErrorCodeToFailureInfo.put(ResponseCode.UNINITIALIZED, + new PublicErrorInformation(IS_SYSTEM_ERROR, ERROR_KEYSTORE_UNINITIALIZED)); + sErrorCodeToFailureInfo.put(ResponseCode.SYSTEM_ERROR, + new PublicErrorInformation(IS_SYSTEM_ERROR, + ERROR_INTERNAL_SYSTEM_ERROR)); + sErrorCodeToFailureInfo.put(ResponseCode.PERMISSION_DENIED, + new PublicErrorInformation(0, ERROR_PERMISSION_DENIED)); + sErrorCodeToFailureInfo.put(ResponseCode.KEY_NOT_FOUND, + new PublicErrorInformation(0, ERROR_KEY_DOES_NOT_EXIST)); + sErrorCodeToFailureInfo.put(ResponseCode.VALUE_CORRUPTED, + new PublicErrorInformation(0, ERROR_KEY_CORRUPTED)); + sErrorCodeToFailureInfo.put(ResponseCode.KEY_PERMANENTLY_INVALIDATED, + new PublicErrorInformation(0, ERROR_KEY_DOES_NOT_EXIST)); + } } diff --git a/keystore/java/android/security/KeyStoreOperation.java b/keystore/java/android/security/KeyStoreOperation.java index e6c1ea827118..737ff2b4822f 100644 --- a/keystore/java/android/security/KeyStoreOperation.java +++ b/keystore/java/android/security/KeyStoreOperation.java @@ -75,7 +75,7 @@ public class KeyStoreOperation { ); } default: - throw KeyStore2.getKeyStoreException(e.errorCode); + throw KeyStore2.getKeyStoreException(e.errorCode, e.getMessage()); } } catch (RemoteException e) { // Log exception and report invalid operation handle. @@ -85,7 +85,8 @@ public class KeyStoreOperation { "Remote exception while advancing a KeyStoreOperation.", e ); - throw new KeyStoreException(KeymasterDefs.KM_ERROR_INVALID_OPERATION_HANDLE, ""); + throw new KeyStoreException(KeymasterDefs.KM_ERROR_INVALID_OPERATION_HANDLE, "", + e.getMessage()); } } diff --git a/keystore/java/android/security/KeyStoreSecurityLevel.java b/keystore/java/android/security/KeyStoreSecurityLevel.java index b85dd742cc49..9c0b46c8e87b 100644 --- a/keystore/java/android/security/KeyStoreSecurityLevel.java +++ b/keystore/java/android/security/KeyStoreSecurityLevel.java @@ -54,12 +54,12 @@ public class KeyStoreSecurityLevel { try { return request.execute(); } catch (ServiceSpecificException e) { - throw KeyStore2.getKeyStoreException(e.errorCode); + throw KeyStore2.getKeyStoreException(e.errorCode, e.getMessage()); } catch (RemoteException e) { // Log exception and report invalid operation handle. // This should prompt the caller drop the reference to this operation and retry. Log.e(TAG, "Could not connect to Keystore.", e); - throw new KeyStoreException(ResponseCode.SYSTEM_ERROR, ""); + throw new KeyStoreException(ResponseCode.SYSTEM_ERROR, "", e.getMessage()); } } @@ -117,7 +117,7 @@ public class KeyStoreSecurityLevel { break; } default: - throw KeyStore2.getKeyStoreException(e.errorCode); + throw KeyStore2.getKeyStoreException(e.errorCode, e.getMessage()); } } catch (RemoteException e) { Log.w(TAG, "Cannot connect to keystore", e); diff --git a/keystore/tests/src/android/security/keystore/KeyStoreExceptionTest.java b/keystore/tests/src/android/security/keystore/KeyStoreExceptionTest.java new file mode 100644 index 000000000000..31c742289a61 --- /dev/null +++ b/keystore/tests/src/android/security/keystore/KeyStoreExceptionTest.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2022 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.security.keystore; + +import static org.junit.Assert.assertTrue; + +import android.security.KeyStoreException; + +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +public class KeyStoreExceptionTest { + @Test + public void testKeystoreMessageIsIncluded() { + final String primaryMessage = "some_message"; + final String keystoreMessage = "ks_message"; + KeyStoreException exception = new KeyStoreException(-1, primaryMessage, keystoreMessage); + + String exceptionMessage = exception.getMessage(); + assertTrue(exceptionMessage.contains(primaryMessage)); + assertTrue(exceptionMessage.contains(keystoreMessage)); + + String exceptionString = exception.toString(); + assertTrue(exceptionString.contains(primaryMessage)); + assertTrue(exceptionString.contains(keystoreMessage)); + } +} diff --git a/libs/androidfw/LoadedArsc.cpp b/libs/androidfw/LoadedArsc.cpp index d17c32817994..8150e78fdddc 100644 --- a/libs/androidfw/LoadedArsc.cpp +++ b/libs/androidfw/LoadedArsc.cpp @@ -686,6 +686,12 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk, std::unordered_set<uint32_t> finalized_ids; const auto lib_alias = child_chunk.header<ResTable_staged_alias_header>(); if (!lib_alias) { + LOG(ERROR) << "RES_TABLE_STAGED_ALIAS_TYPE is too small."; + return {}; + } + if ((child_chunk.data_size() / sizeof(ResTable_staged_alias_entry)) + < dtohl(lib_alias->count)) { + LOG(ERROR) << "RES_TABLE_STAGED_ALIAS_TYPE is too small to hold entries."; return {}; } const auto entry_begin = child_chunk.data_ptr().convert<ResTable_staged_alias_entry>(); diff --git a/libs/hwui/Readback.cpp b/libs/hwui/Readback.cpp index f8d6c07b980d..a743d30939d0 100644 --- a/libs/hwui/Readback.cpp +++ b/libs/hwui/Readback.cpp @@ -32,8 +32,6 @@ using namespace android::uirenderer::renderthread; -static constexpr bool sEnableExtraCropInset = true; - namespace android { namespace uirenderer { @@ -66,20 +64,6 @@ CopyResult Readback::copySurfaceInto(ANativeWindow* window, const Rect& inSrcRec ALOGW("Surface doesn't have any previously queued frames, nothing to readback from"); return CopyResult::SourceEmpty; } - - if (sEnableExtraCropInset && - (cropRect.right - cropRect.left != bitmap->width() || - cropRect.bottom - cropRect.top != bitmap->height())) { - /* - * When we need use filtering, we should also make border shrink here like gui. - * But we could not check format for YUV or RGB here... Just use 1 pix. - */ - cropRect.left += 0.5f; - cropRect.top += 0.5f; - cropRect.right -= 0.5f; - cropRect.bottom -= 0.5f; - } - UniqueAHardwareBuffer sourceBuffer{rawSourceBuffer}; AHardwareBuffer_Desc description; AHardwareBuffer_describe(sourceBuffer.get(), &description); diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h index 2fed4686f16e..00561be3c1c4 100644 --- a/libs/hwui/renderthread/CanvasContext.h +++ b/libs/hwui/renderthread/CanvasContext.h @@ -287,7 +287,7 @@ private: }; // Need at least 4 because we do quad buffer. Add a 5th for good measure. - RingBuffer<SwapHistory, 5> mSwapHistory; + RingBuffer<SwapHistory, 7> mSwapHistory; int64_t mFrameNumber = -1; int64_t mDamageId = 0; diff --git a/libs/tracingproxy/Android.bp b/libs/tracingproxy/Android.bp index 7126bfac773d..23d107b56340 100644 --- a/libs/tracingproxy/Android.bp +++ b/libs/tracingproxy/Android.bp @@ -37,6 +37,7 @@ cc_library_shared { srcs: [ ":ITracingServiceProxy.aidl", + ":TraceReportParams.aidl", ], shared_libs: [ diff --git a/media/Android.bp b/media/Android.bp index 1b7bef53dba4..b7c3a9c112d1 100644 --- a/media/Android.bp +++ b/media/Android.bp @@ -100,6 +100,11 @@ aidl_interface { vndk: { enabled: true, }, + min_sdk_version: "29", + apex_available: [ + "//apex_available:platform", + "com.android.bluetooth", + ], }, }, } diff --git a/media/java/android/media/AudioDeviceInfo.java b/media/java/android/media/AudioDeviceInfo.java index a186566aec0b..3edb10108497 100644 --- a/media/java/android/media/AudioDeviceInfo.java +++ b/media/java/android/media/AudioDeviceInfo.java @@ -177,6 +177,11 @@ public final class AudioDeviceInfo { */ public static final int TYPE_HDMI_EARC = 29; + /** + * A device type describing a Bluetooth Low Energy (BLE) broadcast group. + */ + public static final int TYPE_BLE_BROADCAST = 30; + /** @hide */ @IntDef(flag = false, prefix = "TYPE", value = { TYPE_BUILTIN_EARPIECE, @@ -207,7 +212,8 @@ public final class AudioDeviceInfo { TYPE_REMOTE_SUBMIX, TYPE_BLE_HEADSET, TYPE_BLE_SPEAKER, - TYPE_ECHO_REFERENCE} + TYPE_ECHO_REFERENCE, + TYPE_BLE_BROADCAST} ) @Retention(RetentionPolicy.SOURCE) public @interface AudioDeviceType {} @@ -264,7 +270,8 @@ public final class AudioDeviceInfo { TYPE_HEARING_AID, TYPE_BUILTIN_SPEAKER_SAFE, TYPE_BLE_HEADSET, - TYPE_BLE_SPEAKER} + TYPE_BLE_SPEAKER, + TYPE_BLE_BROADCAST} ) @Retention(RetentionPolicy.SOURCE) public @interface AudioDeviceTypeOut {} @@ -296,6 +303,7 @@ public final class AudioDeviceInfo { case TYPE_BUILTIN_SPEAKER_SAFE: case TYPE_BLE_HEADSET: case TYPE_BLE_SPEAKER: + case TYPE_BLE_BROADCAST: return true; default: return false; @@ -627,6 +635,7 @@ public final class AudioDeviceInfo { INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_REMOTE_SUBMIX, TYPE_REMOTE_SUBMIX); INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLE_HEADSET, TYPE_BLE_HEADSET); INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLE_SPEAKER, TYPE_BLE_SPEAKER); + INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLE_BROADCAST, TYPE_BLE_BROADCAST); INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BUILTIN_MIC, TYPE_BUILTIN_MIC); INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET, TYPE_BLUETOOTH_SCO); @@ -684,6 +693,7 @@ public final class AudioDeviceInfo { EXT_TO_INT_DEVICE_MAPPING.put(TYPE_REMOTE_SUBMIX, AudioSystem.DEVICE_OUT_REMOTE_SUBMIX); EXT_TO_INT_DEVICE_MAPPING.put(TYPE_BLE_HEADSET, AudioSystem.DEVICE_OUT_BLE_HEADSET); EXT_TO_INT_DEVICE_MAPPING.put(TYPE_BLE_SPEAKER, AudioSystem.DEVICE_OUT_BLE_SPEAKER); + EXT_TO_INT_DEVICE_MAPPING.put(TYPE_BLE_BROADCAST, AudioSystem.DEVICE_OUT_BLE_BROADCAST); // privileges mapping to input device EXT_TO_INT_INPUT_DEVICE_MAPPING = new SparseIntArray(); diff --git a/media/java/android/media/AudioDevicePort.java b/media/java/android/media/AudioDevicePort.java index ebe08822a0c9..9211c53a17bc 100644 --- a/media/java/android/media/AudioDevicePort.java +++ b/media/java/android/media/AudioDevicePort.java @@ -90,7 +90,8 @@ public class AudioDevicePort extends AudioPort { * {@link AudioManager#DEVICE_OUT_BLE_HEADSET}, {@link AudioManager#DEVICE_OUT_BLE_SPEAKER}) * use the MAC address of the bluetooth device in the form "00:11:22:AA:BB:CC" as reported by * {@link BluetoothDevice#getAddress()}. - * - Deivces that do not have an address will indicate an empty string "". + * - Bluetooth LE broadcast group ({@link AudioManager#DEVICE_OUT_BLE_BROADCAST} use the group number. + * - Devices that do not have an address will indicate an empty string "". */ public String address() { return mAddress; diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index b7e8c8cb0a7e..ce2bccfb1059 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -5404,6 +5404,10 @@ public class AudioManager { */ public static final int DEVICE_OUT_BLE_SPEAKER = AudioSystem.DEVICE_OUT_BLE_SPEAKER; /** @hide + * The audio output device code for a BLE audio brodcast group. + */ + public static final int DEVICE_OUT_BLE_BROADCAST = AudioSystem.DEVICE_OUT_BLE_BROADCAST; + /** @hide * This is not used as a returned value from {@link #getDevicesForStream}, but could be * used in the future in a set method to select whatever default device is chosen by the * platform-specific implementation. @@ -5806,13 +5810,14 @@ public class AudioManager { * @param newDevice Bluetooth device connected or null if there is no new devices * @param previousDevice Bluetooth device disconnected or null if there is no disconnected * devices - * @param info contain all info related to the device. {@link BtProfileConnectionInfo} + * @param info contain all info related to the device. {@link BluetoothProfileConnectionInfo} * {@hide} */ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) @RequiresPermission(android.Manifest.permission.BLUETOOTH_STACK) public void handleBluetoothActiveDeviceChanged(@Nullable BluetoothDevice newDevice, - @Nullable BluetoothDevice previousDevice, @NonNull BtProfileConnectionInfo info) { + @Nullable BluetoothDevice previousDevice, + @NonNull BluetoothProfileConnectionInfo info) { final IAudioService service = getService(); try { service.handleBluetoothActiveDeviceChanged(newDevice, previousDevice, info); diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java index 143b11f76f23..33b877c6a958 100644 --- a/media/java/android/media/AudioSystem.java +++ b/media/java/android/media/AudioSystem.java @@ -982,6 +982,8 @@ public class AudioSystem public static final int DEVICE_OUT_BLE_HEADSET = 0x20000000; /** @hide */ public static final int DEVICE_OUT_BLE_SPEAKER = 0x20000001; + /** @hide */ + public static final int DEVICE_OUT_BLE_BROADCAST = 0x20000002; /** @hide */ public static final int DEVICE_OUT_DEFAULT = DEVICE_BIT_DEFAULT; @@ -1042,6 +1044,7 @@ public class AudioSystem DEVICE_OUT_ALL_SET.add(DEVICE_OUT_ECHO_CANCELLER); DEVICE_OUT_ALL_SET.add(DEVICE_OUT_BLE_HEADSET); DEVICE_OUT_ALL_SET.add(DEVICE_OUT_BLE_SPEAKER); + DEVICE_OUT_ALL_SET.add(DEVICE_OUT_BLE_BROADCAST); DEVICE_OUT_ALL_SET.add(DEVICE_OUT_DEFAULT); DEVICE_OUT_ALL_A2DP_SET = new HashSet<>(); @@ -1072,6 +1075,7 @@ public class AudioSystem DEVICE_OUT_ALL_BLE_SET = new HashSet<>(); DEVICE_OUT_ALL_BLE_SET.add(DEVICE_OUT_BLE_HEADSET); DEVICE_OUT_ALL_BLE_SET.add(DEVICE_OUT_BLE_SPEAKER); + DEVICE_OUT_ALL_BLE_SET.add(DEVICE_OUT_BLE_BROADCAST); } // input devices @@ -1255,6 +1259,7 @@ public class AudioSystem /** @hide */ public static final String DEVICE_OUT_ECHO_CANCELLER_NAME = "echo_canceller"; /** @hide */ public static final String DEVICE_OUT_BLE_HEADSET_NAME = "ble_headset"; /** @hide */ public static final String DEVICE_OUT_BLE_SPEAKER_NAME = "ble_speaker"; + /** @hide */ public static final String DEVICE_OUT_BLE_BROADCAST_NAME = "ble_broadcast"; /** @hide */ public static final String DEVICE_IN_COMMUNICATION_NAME = "communication"; /** @hide */ public static final String DEVICE_IN_AMBIENT_NAME = "ambient"; @@ -1354,6 +1359,8 @@ public class AudioSystem return DEVICE_OUT_BLE_HEADSET_NAME; case DEVICE_OUT_BLE_SPEAKER: return DEVICE_OUT_BLE_SPEAKER_NAME; + case DEVICE_OUT_BLE_BROADCAST: + return DEVICE_OUT_BLE_BROADCAST_NAME; case DEVICE_OUT_DEFAULT: default: return Integer.toString(device); diff --git a/media/java/android/media/BtProfileConnectionInfo.aidl b/media/java/android/media/BluetoothProfileConnectionInfo.aidl index 047f06be0964..0617084fd826 100644 --- a/media/java/android/media/BtProfileConnectionInfo.aidl +++ b/media/java/android/media/BluetoothProfileConnectionInfo.aidl @@ -16,5 +16,5 @@ package android.media; -parcelable BtProfileConnectionInfo; +parcelable BluetoothProfileConnectionInfo; diff --git a/media/java/android/media/BtProfileConnectionInfo.java b/media/java/android/media/BluetoothProfileConnectionInfo.java index d1bb41e70b54..c14884657ddd 100644 --- a/media/java/android/media/BtProfileConnectionInfo.java +++ b/media/java/android/media/BluetoothProfileConnectionInfo.java @@ -15,40 +15,25 @@ */ package android.media; -import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.SystemApi; import android.bluetooth.BluetoothProfile; import android.os.Parcel; import android.os.Parcelable; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - /** * Contains information about Bluetooth profile connection state changed * {@hide} */ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) -public final class BtProfileConnectionInfo implements Parcelable { - /** @hide */ - @IntDef({ - BluetoothProfile.A2DP, - BluetoothProfile.A2DP_SINK, - BluetoothProfile.HEADSET, // Can only be set by BtHelper - BluetoothProfile.HEARING_AID, - BluetoothProfile.LE_AUDIO, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface BtProfile {} - - private final @BtProfile int mProfile; +public final class BluetoothProfileConnectionInfo implements Parcelable { + private final int mProfile; private final boolean mSupprNoisy; private final int mVolume; private final boolean mIsLeOutput; - private BtProfileConnectionInfo(@BtProfile int profile, boolean suppressNoisyIntent, int volume, - boolean isLeOutput) { + private BluetoothProfileConnectionInfo(int profile, boolean suppressNoisyIntent, + int volume, boolean isLeOutput) { mProfile = profile; mSupprNoisy = suppressNoisyIntent; mVolume = volume; @@ -59,21 +44,21 @@ public final class BtProfileConnectionInfo implements Parcelable { * Constructor used by BtHelper when a profile is connected * {@hide} */ - public BtProfileConnectionInfo(@BtProfile int profile) { + public BluetoothProfileConnectionInfo(int profile) { this(profile, false, -1, false); } - public static final @NonNull Parcelable.Creator<BtProfileConnectionInfo> CREATOR = - new Parcelable.Creator<BtProfileConnectionInfo>() { + public static final @NonNull Parcelable.Creator<BluetoothProfileConnectionInfo> CREATOR = + new Parcelable.Creator<BluetoothProfileConnectionInfo>() { @Override - public BtProfileConnectionInfo createFromParcel(Parcel source) { - return new BtProfileConnectionInfo(source.readInt(), source.readBoolean(), - source.readInt(), source.readBoolean()); + public BluetoothProfileConnectionInfo createFromParcel(Parcel source) { + return new BluetoothProfileConnectionInfo(source.readInt(), + source.readBoolean(), source.readInt(), source.readBoolean()); } @Override - public BtProfileConnectionInfo[] newArray(int size) { - return new BtProfileConnectionInfo[size]; + public BluetoothProfileConnectionInfo[] newArray(int size) { + return new BluetoothProfileConnectionInfo[size]; } }; @@ -98,10 +83,10 @@ public final class BtProfileConnectionInfo implements Parcelable { * * @param volume of device -1 to ignore value */ - public static @NonNull BtProfileConnectionInfo a2dpInfo(boolean suppressNoisyIntent, - int volume) { - return new BtProfileConnectionInfo(BluetoothProfile.A2DP, suppressNoisyIntent, volume, - false); + public static @NonNull BluetoothProfileConnectionInfo createA2dpInfo( + boolean suppressNoisyIntent, int volume) { + return new BluetoothProfileConnectionInfo(BluetoothProfile.A2DP, suppressNoisyIntent, + volume, false); } /** @@ -110,8 +95,8 @@ public final class BtProfileConnectionInfo implements Parcelable { * * @param volume of device -1 to ignore value */ - public static @NonNull BtProfileConnectionInfo a2dpSinkInfo(int volume) { - return new BtProfileConnectionInfo(BluetoothProfile.A2DP_SINK, true, volume, false); + public static @NonNull BluetoothProfileConnectionInfo createA2dpSinkInfo(int volume) { + return new BluetoothProfileConnectionInfo(BluetoothProfile.A2DP_SINK, true, volume, false); } /** @@ -120,9 +105,10 @@ public final class BtProfileConnectionInfo implements Parcelable { * @param suppressNoisyIntent if true the {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY} * intent will not be sent. */ - public static @NonNull BtProfileConnectionInfo hearingAidInfo(boolean suppressNoisyIntent) { - return new BtProfileConnectionInfo(BluetoothProfile.HEARING_AID, suppressNoisyIntent, -1, - false); + public static @NonNull BluetoothProfileConnectionInfo createHearingAidInfo( + boolean suppressNoisyIntent) { + return new BluetoothProfileConnectionInfo(BluetoothProfile.HEARING_AID, suppressNoisyIntent, + -1, false); } /** @@ -133,16 +119,16 @@ public final class BtProfileConnectionInfo implements Parcelable { * * @param isLeOutput if true mean the device is an output device, if false it's an input device */ - public static @NonNull BtProfileConnectionInfo leAudio(boolean suppressNoisyIntent, - boolean isLeOutput) { - return new BtProfileConnectionInfo(BluetoothProfile.LE_AUDIO, suppressNoisyIntent, -1, - isLeOutput); + public static @NonNull BluetoothProfileConnectionInfo createLeAudioInfo( + boolean suppressNoisyIntent, boolean isLeOutput) { + return new BluetoothProfileConnectionInfo(BluetoothProfile.LE_AUDIO, suppressNoisyIntent, + -1, isLeOutput); } /** * @return The profile connection */ - public @BtProfile int getProfile() { + public int getProfile() { return mProfile; } @@ -150,7 +136,7 @@ public final class BtProfileConnectionInfo implements Parcelable { * @return {@code true} if {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY} intent will not be * sent */ - public boolean getSuppressNoisyIntent() { + public boolean isSuppressNoisyIntent() { return mSupprNoisy; } @@ -167,7 +153,7 @@ public final class BtProfileConnectionInfo implements Parcelable { * @return {@code true} is the LE device is an output device, {@code false} if it's an input * device */ - public boolean getIsLeOutput() { + public boolean isLeOutput() { return mIsLeOutput; } } diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl index 5ff56f9c680d..d5a2d07d4bb7 100755 --- a/media/java/android/media/IAudioService.aidl +++ b/media/java/android/media/IAudioService.aidl @@ -24,7 +24,7 @@ import android.media.AudioFocusInfo; import android.media.AudioPlaybackConfiguration; import android.media.AudioRecordingConfiguration; import android.media.AudioRoutesInfo; -import android.media.BtProfileConnectionInfo; +import android.media.BluetoothProfileConnectionInfo; import android.media.IAudioFocusDispatcher; import android.media.IAudioModeDispatcher; import android.media.IAudioRoutesObserver; @@ -268,7 +268,7 @@ interface IAudioService { oneway void playerHasOpPlayAudio(in int piid, in boolean hasOpPlayAudio); void handleBluetoothActiveDeviceChanged(in BluetoothDevice newDevice, - in BluetoothDevice previousDevice, in BtProfileConnectionInfo info); + in BluetoothDevice previousDevice, in BluetoothProfileConnectionInfo info); oneway void setFocusRequestResultFromExtPolicy(in AudioFocusInfo afi, int requestResult, in IAudioPolicyCallback pcb); diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java index e75df1d9b691..77709d7d3823 100644 --- a/media/java/android/media/MediaCodecInfo.java +++ b/media/java/android/media/MediaCodecInfo.java @@ -426,10 +426,30 @@ public final class MediaCodecInfo { /** @deprecated Use {@link #COLOR_Format32bitABGR8888}. */ public static final int COLOR_Format24BitABGR6666 = 43; - /** @hide - * P010 is a 4:2:0 YCbCr semiplanar format comprised of a WxH Y plane - * followed by a Wx(H/2) CbCr plane. Each sample is represented by a 16-bit - * little-endian value, with the lower 6 bits set to zero. */ + /** + * P010 is 10-bit-per component 4:2:0 YCbCr semiplanar format. + * <p> + * This format uses 24 allocated bits per pixel with 15 bits of + * data per pixel. Chroma planes are subsampled by 2 both + * horizontally and vertically. Each chroma and luma component + * has 16 allocated bits in little-endian configuration with 10 + * MSB of actual data. + * + * <pre> + * byte byte + * <--------- i --------> | <------ i + 1 ------> + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * | UNUSED | Y/Cb/Cr | + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * 0 5 6 7 0 7 + * bit + * </pre> + * + * Use this format with {@link Image}. This format corresponds + * to {@link android.graphics.ImageFormat#YCBCR_P010}. + * <p> + */ + @SuppressLint("AllUpper") public static final int COLOR_FormatYUVP010 = 54; /** @deprecated Use {@link #COLOR_FormatYUV420Flexible}. */ @@ -439,6 +459,25 @@ public final class MediaCodecInfo { public static final int COLOR_FormatSurface = 0x7F000789; /** + * 64 bits per pixel RGBA color format, with 16-bit signed + * floating point red, green, blue, and alpha components. + * <p> + * + * <pre> + * byte byte byte byte + * <-- i -->|<- i+1 ->|<- i+2 ->|<- i+3 ->|<- i+4 ->|<- i+5 ->|<- i+6 ->|<- i+7 -> + * +---------+---------+-------------------+---------+---------+---------+---------+ + * | RED | GREEN | BLUE | ALPHA | + * +---------+---------+-------------------+---------+---------+---------+---------+ + * 0 7 0 7 0 7 0 7 0 7 0 7 0 7 0 7 + * </pre> + * + * This corresponds to {@link android.graphics.PixelFormat#RGBA_F16}. + */ + @SuppressLint("AllUpper") + public static final int COLOR_Format64bitABGRFloat = 0x7F000F16; + + /** * 32 bits per pixel RGBA color format, with 8-bit red, green, blue, and alpha components. * <p> * Using 32-bit little-endian representation, colors stored as Red 7:0, Green 15:8, @@ -456,6 +495,26 @@ public final class MediaCodecInfo { public static final int COLOR_Format32bitABGR8888 = 0x7F00A000; /** + * 32 bits per pixel RGBA color format, with 10-bit red, green, + * blue, and 2-bit alpha components. + * <p> + * Using 32-bit little-endian representation, colors stored as + * Red 9:0, Green 19:10, Blue 29:20, and Alpha 31:30. + * <pre> + * byte byte byte byte + * <------ i -----> | <---- i+1 ----> | <---- i+2 ----> | <---- i+3 -----> + * +-----------------+---+-------------+-------+---------+-----------+-----+ + * | RED | GREEN | BLUE |ALPHA| + * +-----------------+---+-------------+-------+---------+-----------+-----+ + * 0 7 0 1 2 7 0 3 4 7 0 5 6 7 + * </pre> + * + * This corresponds to {@link android.graphics.PixelFormat#RGBA_1010102}. + */ + @SuppressLint("AllUpper") + public static final int COLOR_Format32bitABGR2101010 = 0x7F00AAA2; + + /** * Flexible 12 bits per pixel, subsampled YUV color format with 8-bit chroma and luma * components. * <p> @@ -3966,6 +4025,12 @@ public final class MediaCodecInfo { public static final int DolbyVisionLevelUhd30 = 0x40; public static final int DolbyVisionLevelUhd48 = 0x80; public static final int DolbyVisionLevelUhd60 = 0x100; + @SuppressLint("AllUpper") + public static final int DolbyVisionLevelUhd120 = 0x200; + @SuppressLint("AllUpper") + public static final int DolbyVisionLevel8k30 = 0x400; + @SuppressLint("AllUpper") + public static final int DolbyVisionLevel8k60 = 0x800; // Profiles and levels for AV1 Codec, corresponding to the definitions in // "AV1 Bitstream & Decoding Process Specification", Annex A diff --git a/media/java/android/mtp/MtpDatabase.java b/media/java/android/mtp/MtpDatabase.java index d8f48c2cf0c6..20d711cf4c54 100755 --- a/media/java/android/mtp/MtpDatabase.java +++ b/media/java/android/mtp/MtpDatabase.java @@ -103,6 +103,7 @@ public class MtpDatabase implements AutoCloseable { private int mDeviceType; private String mHostType; private boolean mSkipThumbForHost = false; + private volatile boolean mHostIsWindows = false; private MtpServer mServer; private MtpStorageManager mManager; @@ -358,7 +359,7 @@ public class MtpDatabase implements AutoCloseable { } public void addStorage(StorageVolume storage) { - MtpStorage mtpStorage = mManager.addMtpStorage(storage); + MtpStorage mtpStorage = mManager.addMtpStorage(storage, () -> mHostIsWindows); mStorageMap.put(storage.getPath(), mtpStorage); if (mServer != null) { mServer.addStorage(mtpStorage); @@ -413,6 +414,7 @@ public class MtpDatabase implements AutoCloseable { } mHostType = ""; mSkipThumbForHost = false; + mHostIsWindows = false; } @VisibleForNative @@ -736,10 +738,12 @@ public class MtpDatabase implements AutoCloseable { : MtpConstants.RESPONSE_GENERAL_ERROR); case MtpConstants.DEVICE_PROPERTY_SESSION_INITIATOR_VERSION_INFO: mHostType = stringValue; + Log.d(TAG, "setDeviceProperty." + Integer.toHexString(property) + + "=" + stringValue); if (stringValue.startsWith("Android/")) { - Log.d(TAG, "setDeviceProperty." + Integer.toHexString(property) - + "=" + stringValue); mSkipThumbForHost = true; + } else if (stringValue.startsWith("Windows/")) { + mHostIsWindows = true; } return MtpConstants.RESPONSE_OK; } diff --git a/media/java/android/mtp/MtpStorage.java b/media/java/android/mtp/MtpStorage.java index 88c32a3ea72b..a3754e90a875 100644 --- a/media/java/android/mtp/MtpStorage.java +++ b/media/java/android/mtp/MtpStorage.java @@ -19,6 +19,8 @@ package android.mtp; import android.compat.annotation.UnsupportedAppUsage; import android.os.storage.StorageVolume; +import java.util.function.Supplier; + /** * This class represents a storage unit on an MTP device. * Used only for MTP support in USB responder mode. @@ -33,14 +35,16 @@ public class MtpStorage { private final boolean mRemovable; private final long mMaxFileSize; private final String mVolumeName; + private final Supplier<Boolean> mIsHostWindows; - public MtpStorage(StorageVolume volume, int storageId) { + public MtpStorage(StorageVolume volume, int storageId, Supplier<Boolean> isHostWindows) { mStorageId = storageId; mPath = volume.getPath(); mDescription = volume.getDescription(null); mRemovable = volume.isRemovable(); mMaxFileSize = volume.getMaxFileSize(); mVolumeName = volume.getMediaStoreVolumeName(); + mIsHostWindows = isHostWindows; } /** @@ -93,4 +97,13 @@ public class MtpStorage { public String getVolumeName() { return mVolumeName; } + + /** + * Returns true if the mtp host of this storage is Windows. + * + * @return is host Windows + */ + public boolean isHostWindows() { + return mIsHostWindows.get(); + } } diff --git a/media/java/android/mtp/MtpStorageManager.java b/media/java/android/mtp/MtpStorageManager.java index 0bede0dccbed..e9426cf2ce31 100644 --- a/media/java/android/mtp/MtpStorageManager.java +++ b/media/java/android/mtp/MtpStorageManager.java @@ -18,7 +18,11 @@ package android.mtp; import android.media.MediaFile; import android.os.FileObserver; +import android.os.SystemProperties; import android.os.storage.StorageVolume; +import android.system.ErrnoException; +import android.system.Os; +import android.system.StructStat; import android.util.Log; import com.android.internal.util.Preconditions; @@ -35,6 +39,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.function.Supplier; /** * MtpStorageManager provides functionality for listing, tracking, and notifying MtpServer of @@ -199,7 +204,38 @@ public class MtpStorageManager { } public long getSize() { - return mIsDir ? 0 : getPath().toFile().length(); + return mIsDir ? 0 : maybeApplyTranscodeLengthWorkaround(getPath().toFile().length()); + } + + private long maybeApplyTranscodeLengthWorkaround(long length) { + // Windows truncates transferred files to the size advertised in the object property. + if (mStorage.isHostWindows() && isTranscodeMtpEnabled() && isFileTranscodeSupported()) { + // If the file supports transcoding, we double the returned size to accommodate + // the increase in size from transcoding to AVC. This is the same heuristic + // applied in the FUSE daemon (MediaProvider). + return length * 2; + } + return length; + } + + private boolean isTranscodeMtpEnabled() { + return SystemProperties.getBoolean("sys.fuse.transcode_mtp", false); + } + + private boolean isFileTranscodeSupported() { + // Check if the file supports transcoding by reading the |st_nlinks| struct stat + // field. This will be > 1 if the file supports transcoding. The FUSE daemon + // sets the field accordingly to enable the MTP stack workaround some Windows OS + // MTP client bug where they ignore the size returned as part of getting the MTP + // object, see MtpServer#doGetObject. + final Path path = getPath(); + try { + StructStat stat = Os.stat(path.toString()); + return stat.st_nlink > 1; + } catch (ErrnoException e) { + Log.w(TAG, "Failed to stat path: " + getPath() + ". Ignoring transcoding."); + return false; + } } public Path getPath() { @@ -420,10 +456,12 @@ public class MtpStorageManager { * @param volume Storage to add. * @return the associated MtpStorage */ - public synchronized MtpStorage addMtpStorage(StorageVolume volume) { + public synchronized MtpStorage addMtpStorage(StorageVolume volume, + Supplier<Boolean> isHostWindows) { int storageId = ((getNextStorageId() & 0x0000FFFF) << 16) + 1; - MtpStorage storage = new MtpStorage(volume, storageId); - MtpObject root = new MtpObject(storage.getPath(), storageId, storage, null, true); + MtpStorage storage = new MtpStorage(volume, storageId, isHostWindows); + MtpObject root = new MtpObject(storage.getPath(), storageId, storage, /* parent= */ null, + /* isDir= */ true); mRoots.put(storageId, root); return storage; } diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/BtProfileConnectionInfoTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/BluetoothProfileConnectionInfoTest.java index fd66d3b9904e..f23794b50543 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/BtProfileConnectionInfoTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/BluetoothProfileConnectionInfoTest.java @@ -19,7 +19,7 @@ package com.android.mediaframeworktest.unit; import static org.junit.Assert.assertEquals; import android.bluetooth.BluetoothProfile; -import android.media.BtProfileConnectionInfo; +import android.media.BluetoothProfileConnectionInfo; import androidx.test.runner.AndroidJUnit4; @@ -27,22 +27,24 @@ import org.junit.Test; import org.junit.runner.RunWith; @RunWith(AndroidJUnit4.class) -public class BtProfileConnectionInfoTest { +public class BluetoothProfileConnectionInfoTest { @Test public void testCoverageA2dp() { final boolean supprNoisy = false; final int volume = 42; - final BtProfileConnectionInfo info = BtProfileConnectionInfo.a2dpInfo(supprNoisy, volume); + final BluetoothProfileConnectionInfo info = BluetoothProfileConnectionInfo + .createA2dpInfo(supprNoisy, volume); assertEquals(info.getProfile(), BluetoothProfile.A2DP); - assertEquals(info.getSuppressNoisyIntent(), supprNoisy); + assertEquals(info.isSuppressNoisyIntent(), supprNoisy); assertEquals(info.getVolume(), volume); } @Test public void testCoverageA2dpSink() { final int volume = 42; - final BtProfileConnectionInfo info = BtProfileConnectionInfo.a2dpSinkInfo(volume); + final BluetoothProfileConnectionInfo info = BluetoothProfileConnectionInfo + .createA2dpSinkInfo(volume); assertEquals(info.getProfile(), BluetoothProfile.A2DP_SINK); assertEquals(info.getVolume(), volume); } @@ -50,20 +52,21 @@ public class BtProfileConnectionInfoTest { @Test public void testCoveragehearingAid() { final boolean supprNoisy = true; - final BtProfileConnectionInfo info = BtProfileConnectionInfo.hearingAidInfo(supprNoisy); + final BluetoothProfileConnectionInfo info = BluetoothProfileConnectionInfo + .createHearingAidInfo(supprNoisy); assertEquals(info.getProfile(), BluetoothProfile.HEARING_AID); - assertEquals(info.getSuppressNoisyIntent(), supprNoisy); + assertEquals(info.isSuppressNoisyIntent(), supprNoisy); } @Test public void testCoverageLeAudio() { final boolean supprNoisy = false; final boolean isLeOutput = true; - final BtProfileConnectionInfo info = BtProfileConnectionInfo.leAudio(supprNoisy, - isLeOutput); + final BluetoothProfileConnectionInfo info = BluetoothProfileConnectionInfo + .createLeAudioInfo(supprNoisy, isLeOutput); assertEquals(info.getProfile(), BluetoothProfile.LE_AUDIO); - assertEquals(info.getSuppressNoisyIntent(), supprNoisy); - assertEquals(info.getIsLeOutput(), isLeOutput); + assertEquals(info.isSuppressNoisyIntent(), supprNoisy); + assertEquals(info.isLeOutput(), isLeOutput); } } diff --git a/media/tests/MtpTests/src/android/mtp/MtpStorageManagerTest.java b/media/tests/MtpTests/src/android/mtp/MtpStorageManagerTest.java index fdf65823b1f3..eb357f67caea 100644 --- a/media/tests/MtpTests/src/android/mtp/MtpStorageManagerTest.java +++ b/media/tests/MtpTests/src/android/mtp/MtpStorageManagerTest.java @@ -159,10 +159,11 @@ public class MtpStorageManagerTest { Log.d(TAG, "sendObjectInfoChanged: " + id); objectsInfoChanged.add(id); } - }, null); + }, /* subdirectories= */ null); - mainMtpStorage = manager.addMtpStorage(mainStorage); - secondaryMtpStorage = manager.addMtpStorage(secondaryStorage); + mainMtpStorage = manager.addMtpStorage(mainStorage, /* isHostWindows= */ () -> false); + secondaryMtpStorage = manager.addMtpStorage(secondaryStorage, + /* isHostWindows= */ () -> false); } @After diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt index f33e11817730..220175398eba 100644 --- a/native/android/libandroid.map.txt +++ b/native/android/libandroid.map.txt @@ -300,6 +300,9 @@ LIBANDROID { android_res_nquery; # introduced=29 android_res_nresult; # introduced=29 android_res_nsend; # introduced=29 + android_tag_socket_with_uid; # introduced=Tiramisu + android_tag_socket; # introduced=Tiramisu + android_untag_socket; # introduced=Tiramisu AThermal_acquireManager; # introduced=30 AThermal_releaseManager; # introduced=30 AThermal_getCurrentThermalStatus; # introduced=30 diff --git a/omapi/OWNERS b/omapi/OWNERS new file mode 100644 index 000000000000..5682fd3281f4 --- /dev/null +++ b/omapi/OWNERS @@ -0,0 +1,5 @@ +# Bug component: 456592 + +zachoverflow@google.com +alisher@google.com +jackcwyu@google.com diff --git a/packages/ConnectivityT/framework-t/Android.bp b/packages/ConnectivityT/framework-t/Android.bp index 223bdcdd9c95..54538d91a5cf 100644 --- a/packages/ConnectivityT/framework-t/Android.bp +++ b/packages/ConnectivityT/framework-t/Android.bp @@ -39,7 +39,6 @@ filegroup { "src/android/net/TrafficStats.java", "src/android/net/UnderlyingNetworkInfo.*", "src/android/net/netstats/**/*.*", - "src/com/android/server/NetworkManagementSocketTagger.java", ], path: "src", visibility: [ @@ -126,14 +125,14 @@ filegroup { name: "framework-connectivity-ethernet-sources", srcs: [ "src/android/net/EthernetManager.java", + "src/android/net/EthernetNetworkManagementException.java", + "src/android/net/EthernetNetworkManagementException.aidl", "src/android/net/EthernetNetworkSpecifier.java", + "src/android/net/EthernetNetworkUpdateRequest.java", + "src/android/net/EthernetNetworkUpdateRequest.aidl", "src/android/net/IEthernetManager.aidl", + "src/android/net/IEthernetNetworkManagementListener.aidl", "src/android/net/IEthernetServiceListener.aidl", - "src/android/net/IInternalNetworkManagementListener.aidl", - "src/android/net/InternalNetworkUpdateRequest.java", - "src/android/net/InternalNetworkUpdateRequest.aidl", - "src/android/net/InternalNetworkManagementException.java", - "src/android/net/InternalNetworkManagementException.aidl", "src/android/net/ITetheredInterfaceCallback.aidl", ], path: "src", @@ -176,3 +175,34 @@ filegroup { "//packages/modules/Connectivity:__subpackages__", ], } + +cc_library_shared { + name: "libframework-connectivity-tiramisu-jni", + min_sdk_version: "30", + cflags: [ + "-Wall", + "-Werror", + "-Wno-unused-parameter", + // Don't warn about S API usage even with + // min_sdk 30: the library is only loaded + // on S+ devices + "-Wno-unguarded-availability", + "-Wthread-safety", + ], + srcs: [ + "jni/android_net_TrafficStats.cpp", + "jni/onload.cpp", + ], + shared_libs: [ + "liblog", + ], + static_libs: [ + "libnativehelper_compat_libc++", + ], + stl: "none", + apex_available: [ + "com.android.tethering", + // TODO: remove when ConnectivityT moves to APEX. + "//apex_available:platform", + ], +} diff --git a/packages/ConnectivityT/framework-t/jni/android_net_TrafficStats.cpp b/packages/ConnectivityT/framework-t/jni/android_net_TrafficStats.cpp new file mode 100644 index 000000000000..f3c58b112f0d --- /dev/null +++ b/packages/ConnectivityT/framework-t/jni/android_net_TrafficStats.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2022 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. + */ + +#include <android/file_descriptor_jni.h> +#include <android/multinetwork.h> +#include <nativehelper/JNIHelp.h> + +namespace android { + +static jint tagSocketFd(JNIEnv* env, jclass, jobject fileDescriptor, jint tag, jint uid) { + int fd = AFileDescriptor_getFd(env, fileDescriptor); + if (fd == -1) return -EBADF; + return android_tag_socket_with_uid(fd, tag, uid); +} + +static jint untagSocketFd(JNIEnv* env, jclass, jobject fileDescriptor) { + int fd = AFileDescriptor_getFd(env, fileDescriptor); + if (fd == -1) return -EBADF; + return android_untag_socket(fd); +} + +static const JNINativeMethod gMethods[] = { + /* name, signature, funcPtr */ + { "native_tagSocketFd", "(Ljava/io/FileDescriptor;II)I", (void*) tagSocketFd }, + { "native_untagSocketFd", "(Ljava/io/FileDescriptor;)I", (void*) untagSocketFd }, +}; + +int register_android_net_TrafficStats(JNIEnv* env) { + return jniRegisterNativeMethods(env, "android/net/TrafficStats", gMethods, NELEM(gMethods)); +} + +}; // namespace android + diff --git a/packages/ConnectivityT/framework-t/jni/onload.cpp b/packages/ConnectivityT/framework-t/jni/onload.cpp new file mode 100644 index 000000000000..1fb42c63477e --- /dev/null +++ b/packages/ConnectivityT/framework-t/jni/onload.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2022 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. + */ + +#define LOG_TAG "FrameworkConnectivityJNI" + +#include <log/log.h> +#include <nativehelper/JNIHelp.h> + +namespace android { + +int register_android_net_TrafficStats(JNIEnv* env); + +extern "C" jint JNI_OnLoad(JavaVM* vm, void*) { + JNIEnv *env; + if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) { + __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "ERROR: GetEnv failed"); + return JNI_ERR; + } + + if (register_android_net_TrafficStats(env) < 0) return JNI_ERR; + + return JNI_VERSION_1_6; +} + +}; // namespace android + diff --git a/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java b/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java index 453e8e61bf33..5ce7e59b38ff 100644 --- a/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java +++ b/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java @@ -41,6 +41,7 @@ import android.net.NetworkStateSnapshot; import android.net.NetworkTemplate; import android.net.UnderlyingNetworkInfo; import android.net.netstats.IUsageCallback; +import android.net.netstats.NetworkStatsDataMigrationUtils; import android.net.netstats.provider.INetworkStatsProviderCallback; import android.net.netstats.provider.NetworkStatsProvider; import android.os.Build; @@ -126,17 +127,12 @@ public class NetworkStatsManager { private final INetworkStatsService mService; /** - * Type constants for reading different types of Data Usage. + * @deprecated Use {@link NetworkStatsDataMigrationUtils#PREFIX_XT} + * instead. * @hide */ - // @SystemApi(client = MODULE_LIBRARIES) + @Deprecated public static final String PREFIX_DEV = "dev"; - /** @hide */ - public static final String PREFIX_XT = "xt"; - /** @hide */ - public static final String PREFIX_UID = "uid"; - /** @hide */ - public static final String PREFIX_UID_TAG = "uid_tag"; /** @hide */ public static final int FLAG_POLL_ON_OPEN = 1 << 0; @@ -145,6 +141,18 @@ public class NetworkStatsManager { /** @hide */ public static final int FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN = 1 << 2; + /** + * Virtual RAT type to represent 5G NSA (Non Stand Alone) mode, where the primary cell is + * still LTE and network allocates a secondary 5G cell so telephony reports RAT = LTE along + * with NR state as connected. This is a concept added by NetworkStats on top of the telephony + * constants for backward compatibility of metrics so this should not be overlapped with any of + * the {@code TelephonyManager.NETWORK_TYPE_*} constants. + * + * @hide + */ + @SystemApi(client = MODULE_LIBRARIES) + public static final int NETWORK_TYPE_5G_NSA = -2; + private int mFlags; /** @hide */ @@ -729,7 +737,8 @@ public class NetworkStatsManager { * {@link #unregisterUsageCallback} is called. * * @param template Template used to match networks. See {@link NetworkTemplate}. - * @param thresholdBytes Threshold in bytes to be notified on. + * @param thresholdBytes Threshold in bytes to be notified on. The provided value that lower + * than 2MiB will be clamped for non-privileged callers. * @param executor The executor on which callback will be invoked. The provided {@link Executor} * must run callback sequentially, otherwise the order of callbacks cannot be * guaranteed. @@ -1110,4 +1119,52 @@ public class NetworkStatsManager { throw e.rethrowFromSystemServer(); } } + + /** + * Get a RAT type representative of a group of RAT types for network statistics. + * + * Collapse the given Radio Access Technology (RAT) type into a bucket that + * is representative of the original RAT type for network statistics. The + * mapping mostly corresponds to {@code TelephonyManager#NETWORK_CLASS_BIT_MASK_*} + * but with adaptations specific to the virtual types introduced by + * networks stats. + * + * @param ratType An integer defined in {@code TelephonyManager#NETWORK_TYPE_*}. + * + * @hide + */ + @SystemApi(client = MODULE_LIBRARIES) + public static int getCollapsedRatType(int ratType) { + switch (ratType) { + case TelephonyManager.NETWORK_TYPE_GPRS: + case TelephonyManager.NETWORK_TYPE_GSM: + case TelephonyManager.NETWORK_TYPE_EDGE: + case TelephonyManager.NETWORK_TYPE_IDEN: + case TelephonyManager.NETWORK_TYPE_CDMA: + case TelephonyManager.NETWORK_TYPE_1xRTT: + return TelephonyManager.NETWORK_TYPE_GSM; + case TelephonyManager.NETWORK_TYPE_EVDO_0: + case TelephonyManager.NETWORK_TYPE_EVDO_A: + case TelephonyManager.NETWORK_TYPE_EVDO_B: + case TelephonyManager.NETWORK_TYPE_EHRPD: + case TelephonyManager.NETWORK_TYPE_UMTS: + case TelephonyManager.NETWORK_TYPE_HSDPA: + case TelephonyManager.NETWORK_TYPE_HSUPA: + case TelephonyManager.NETWORK_TYPE_HSPA: + case TelephonyManager.NETWORK_TYPE_HSPAP: + case TelephonyManager.NETWORK_TYPE_TD_SCDMA: + return TelephonyManager.NETWORK_TYPE_UMTS; + case TelephonyManager.NETWORK_TYPE_LTE: + case TelephonyManager.NETWORK_TYPE_IWLAN: + return TelephonyManager.NETWORK_TYPE_LTE; + case TelephonyManager.NETWORK_TYPE_NR: + return TelephonyManager.NETWORK_TYPE_NR; + // Virtual RAT type for 5G NSA mode, see + // {@link NetworkStatsManager#NETWORK_TYPE_5G_NSA}. + case NetworkStatsManager.NETWORK_TYPE_5G_NSA: + return NetworkStatsManager.NETWORK_TYPE_5G_NSA; + default: + return TelephonyManager.NETWORK_TYPE_UNKNOWN; + } + } } diff --git a/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java b/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java index ece54df96665..1f67f6d654e1 100644 --- a/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java +++ b/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java @@ -19,12 +19,14 @@ package android.net; import android.annotation.CallbackExecutor; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.RequiresFeature; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.SystemService; import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; +import android.content.pm.PackageManager; import android.os.Build; import android.os.RemoteException; @@ -320,15 +322,15 @@ public class EthernetManager { } private static final class InternalNetworkManagementListener - extends IInternalNetworkManagementListener.Stub { + extends IEthernetNetworkManagementListener.Stub { @NonNull private final Executor mExecutor; @NonNull - private final BiConsumer<Network, InternalNetworkManagementException> mListener; + private final BiConsumer<Network, EthernetNetworkManagementException> mListener; InternalNetworkManagementListener( @NonNull final Executor executor, - @NonNull final BiConsumer<Network, InternalNetworkManagementException> listener) { + @NonNull final BiConsumer<Network, EthernetNetworkManagementException> listener) { Objects.requireNonNull(executor, "Pass a non-null executor"); Objects.requireNonNull(listener, "Pass a non-null listener"); mExecutor = executor; @@ -338,14 +340,14 @@ public class EthernetManager { @Override public void onComplete( @Nullable final Network network, - @Nullable final InternalNetworkManagementException e) { + @Nullable final EthernetNetworkManagementException e) { mExecutor.execute(() -> mListener.accept(network, e)); } } private InternalNetworkManagementListener getInternalNetworkManagementListener( @Nullable final Executor executor, - @Nullable final BiConsumer<Network, InternalNetworkManagementException> listener) { + @Nullable final BiConsumer<Network, EthernetNetworkManagementException> listener) { if (null != listener) { Objects.requireNonNull(executor, "Pass a non-null executor, or a null listener"); } @@ -358,11 +360,43 @@ public class EthernetManager { return proxy; } - private void updateConfiguration( + /** + * Updates the configuration of an automotive device's ethernet network. + * + * The {@link EthernetNetworkUpdateRequest} {@code request} argument describes how to update the + * configuration for this network. + * Use {@link StaticIpConfiguration.Builder} to build a {@code StaticIpConfiguration} object for + * this network to put inside the {@code request}. + * Similarly, use {@link NetworkCapabilities.Builder} to build a {@code NetworkCapabilities} + * object for this network to put inside the {@code request}. + * + * If non-null, the listener will be called exactly once after this is called, unless + * a synchronous exception was thrown. + * + * @param iface the name of the interface to act upon. + * @param request the {@link EthernetNetworkUpdateRequest} used to set an ethernet network's + * {@link StaticIpConfiguration} and {@link NetworkCapabilities} values. + * @param executor an {@link Executor} to execute the listener on. Optional if listener is null. + * @param listener an optional {@link BiConsumer} to listen for completion of the operation. + * @throws SecurityException if the process doesn't hold + * {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}. + * @throws UnsupportedOperationException if called on a non-automotive device or on an + * unsupported interface. + * @hide + */ + @SystemApi + @RequiresPermission(anyOf = { + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, + android.Manifest.permission.NETWORK_STACK, + android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}) + @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE) + public void updateConfiguration( @NonNull String iface, - @NonNull InternalNetworkUpdateRequest request, + @NonNull EthernetNetworkUpdateRequest request, @Nullable @CallbackExecutor Executor executor, - @Nullable BiConsumer<Network, InternalNetworkManagementException> listener) { + @Nullable BiConsumer<Network, EthernetNetworkManagementException> listener) { + Objects.requireNonNull(iface, "iface must be non-null"); + Objects.requireNonNull(request, "request must be non-null"); final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener( executor, listener); try { @@ -372,10 +406,34 @@ public class EthernetManager { } } - private void connectNetwork( + /** + * Set an ethernet network's link state up. + * + * When the link is successfully turned up, the listener will be called with the resulting + * network. If any error or unexpected condition happens while the system tries to turn the + * interface up, the listener will be called with an appropriate exception. + * The listener is guaranteed to be called exactly once for each call to this method, but this + * may take an unbounded amount of time depending on the actual network conditions. + * + * @param iface the name of the interface to act upon. + * @param executor an {@link Executor} to execute the listener on. Optional if listener is null. + * @param listener an optional {@link BiConsumer} to listen for completion of the operation. + * @throws SecurityException if the process doesn't hold + * {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}. + * @throws UnsupportedOperationException if called on a non-automotive device. + * @hide + */ + @SystemApi + @RequiresPermission(anyOf = { + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, + android.Manifest.permission.NETWORK_STACK, + android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}) + @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE) + public void connectNetwork( @NonNull String iface, @Nullable @CallbackExecutor Executor executor, - @Nullable BiConsumer<Network, InternalNetworkManagementException> listener) { + @Nullable BiConsumer<Network, EthernetNetworkManagementException> listener) { + Objects.requireNonNull(iface, "iface must be non-null"); final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener( executor, listener); try { @@ -385,10 +443,33 @@ public class EthernetManager { } } - private void disconnectNetwork( + /** + * Set an ethernet network's link state down. + * + * When the link is successfully turned down, the listener will be called with the network that + * was torn down, if any. If any error or unexpected condition happens while the system tries to + * turn the interface down, the listener will be called with an appropriate exception. + * The listener is guaranteed to be called exactly once for each call to this method. + * + * @param iface the name of the interface to act upon. + * @param executor an {@link Executor} to execute the listener on. Optional if listener is null. + * @param listener an optional {@link BiConsumer} to listen for completion of the operation. + * @throws SecurityException if the process doesn't hold + * {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}. + * @throws UnsupportedOperationException if called on a non-automotive device. + * @hide + */ + @SystemApi + @RequiresPermission(anyOf = { + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, + android.Manifest.permission.NETWORK_STACK, + android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}) + @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE) + public void disconnectNetwork( @NonNull String iface, @Nullable @CallbackExecutor Executor executor, - @Nullable BiConsumer<Network, InternalNetworkManagementException> listener) { + @Nullable BiConsumer<Network, EthernetNetworkManagementException> listener) { + Objects.requireNonNull(iface, "iface must be non-null"); final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener( executor, listener); try { diff --git a/packages/ConnectivityT/framework-t/src/android/net/InternalNetworkManagementException.aidl b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkManagementException.aidl index dcce706989f6..adf9e5a4db9d 100644 --- a/packages/ConnectivityT/framework-t/src/android/net/InternalNetworkManagementException.aidl +++ b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkManagementException.aidl @@ -16,4 +16,4 @@ package android.net; - parcelable InternalNetworkManagementException;
\ No newline at end of file + parcelable EthernetNetworkManagementException;
\ No newline at end of file diff --git a/packages/ConnectivityT/framework-t/src/android/net/InternalNetworkManagementException.java b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkManagementException.java index 7f4e403f2259..a69cc55363b2 100644 --- a/packages/ConnectivityT/framework-t/src/android/net/InternalNetworkManagementException.java +++ b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkManagementException.java @@ -17,25 +17,39 @@ package android.net; import android.annotation.NonNull; +import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; +import java.util.Objects; + /** @hide */ -public final class InternalNetworkManagementException +@SystemApi +public final class EthernetNetworkManagementException extends RuntimeException implements Parcelable { /* @hide */ - public InternalNetworkManagementException(@NonNull final Throwable t) { - super(t); + public EthernetNetworkManagementException(@NonNull final String errorMessage) { + super(errorMessage); + } + + @Override + public int hashCode() { + return Objects.hash(getMessage()); } - private InternalNetworkManagementException(@NonNull final Parcel source) { - super(source.readString()); + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + final EthernetNetworkManagementException that = (EthernetNetworkManagementException) obj; + + return Objects.equals(getMessage(), that.getMessage()); } @Override public void writeToParcel(@NonNull Parcel dest, int flags) { - dest.writeString(getCause().getMessage()); + dest.writeString(getMessage()); } @Override @@ -44,16 +58,16 @@ public final class InternalNetworkManagementException } @NonNull - public static final Parcelable.Creator<InternalNetworkManagementException> CREATOR = - new Parcelable.Creator<InternalNetworkManagementException>() { + public static final Parcelable.Creator<EthernetNetworkManagementException> CREATOR = + new Parcelable.Creator<EthernetNetworkManagementException>() { @Override - public InternalNetworkManagementException[] newArray(int size) { - return new InternalNetworkManagementException[size]; + public EthernetNetworkManagementException[] newArray(int size) { + return new EthernetNetworkManagementException[size]; } @Override - public InternalNetworkManagementException createFromParcel(@NonNull Parcel source) { - return new InternalNetworkManagementException(source); + public EthernetNetworkManagementException createFromParcel(@NonNull Parcel source) { + return new EthernetNetworkManagementException(source.readString()); } }; } diff --git a/packages/ConnectivityT/framework-t/src/android/net/InternalNetworkUpdateRequest.aidl b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkUpdateRequest.aidl index da00cb97afb4..debc348ea363 100644 --- a/packages/ConnectivityT/framework-t/src/android/net/InternalNetworkUpdateRequest.aidl +++ b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkUpdateRequest.aidl @@ -16,4 +16,4 @@ package android.net; - parcelable InternalNetworkUpdateRequest;
\ No newline at end of file + parcelable EthernetNetworkUpdateRequest;
\ No newline at end of file diff --git a/packages/ConnectivityT/framework-t/src/android/net/InternalNetworkUpdateRequest.java b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkUpdateRequest.java index f42c4b7c420d..e879e40247cf 100644 --- a/packages/ConnectivityT/framework-t/src/android/net/InternalNetworkUpdateRequest.java +++ b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkUpdateRequest.java @@ -17,13 +17,15 @@ package android.net; import android.annotation.NonNull; +import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; import java.util.Objects; /** @hide */ -public final class InternalNetworkUpdateRequest implements Parcelable { +@SystemApi +public final class EthernetNetworkUpdateRequest implements Parcelable { @NonNull private final StaticIpConfiguration mIpConfig; @NonNull @@ -39,8 +41,7 @@ public final class InternalNetworkUpdateRequest implements Parcelable { return new NetworkCapabilities(mNetworkCapabilities); } - /** @hide */ - public InternalNetworkUpdateRequest(@NonNull final StaticIpConfiguration ipConfig, + public EthernetNetworkUpdateRequest(@NonNull final StaticIpConfiguration ipConfig, @NonNull final NetworkCapabilities networkCapabilities) { Objects.requireNonNull(ipConfig); Objects.requireNonNull(networkCapabilities); @@ -48,7 +49,7 @@ public final class InternalNetworkUpdateRequest implements Parcelable { mNetworkCapabilities = new NetworkCapabilities(networkCapabilities); } - private InternalNetworkUpdateRequest(@NonNull final Parcel source) { + private EthernetNetworkUpdateRequest(@NonNull final Parcel source) { Objects.requireNonNull(source); mIpConfig = StaticIpConfiguration.CREATOR.createFromParcel(source); mNetworkCapabilities = NetworkCapabilities.CREATOR.createFromParcel(source); @@ -56,7 +57,7 @@ public final class InternalNetworkUpdateRequest implements Parcelable { @Override public String toString() { - return "InternalNetworkUpdateRequest{" + return "EthernetNetworkUpdateRequest{" + "mIpConfig=" + mIpConfig + ", mNetworkCapabilities=" + mNetworkCapabilities + '}'; } @@ -65,7 +66,7 @@ public final class InternalNetworkUpdateRequest implements Parcelable { public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - InternalNetworkUpdateRequest that = (InternalNetworkUpdateRequest) o; + EthernetNetworkUpdateRequest that = (EthernetNetworkUpdateRequest) o; return Objects.equals(that.getIpConfig(), mIpConfig) && Objects.equals(that.getNetworkCapabilities(), mNetworkCapabilities); @@ -88,16 +89,16 @@ public final class InternalNetworkUpdateRequest implements Parcelable { } @NonNull - public static final Parcelable.Creator<InternalNetworkUpdateRequest> CREATOR = - new Parcelable.Creator<InternalNetworkUpdateRequest>() { + public static final Parcelable.Creator<EthernetNetworkUpdateRequest> CREATOR = + new Parcelable.Creator<EthernetNetworkUpdateRequest>() { @Override - public InternalNetworkUpdateRequest[] newArray(int size) { - return new InternalNetworkUpdateRequest[size]; + public EthernetNetworkUpdateRequest[] newArray(int size) { + return new EthernetNetworkUpdateRequest[size]; } @Override - public InternalNetworkUpdateRequest createFromParcel(@NonNull Parcel source) { - return new InternalNetworkUpdateRequest(source); + public EthernetNetworkUpdateRequest createFromParcel(@NonNull Parcel source) { + return new EthernetNetworkUpdateRequest(source); } }; } diff --git a/packages/ConnectivityT/framework-t/src/android/net/IEthernetManager.aidl b/packages/ConnectivityT/framework-t/src/android/net/IEthernetManager.aidl index e688bea1cfac..544d02ba76ff 100644 --- a/packages/ConnectivityT/framework-t/src/android/net/IEthernetManager.aidl +++ b/packages/ConnectivityT/framework-t/src/android/net/IEthernetManager.aidl @@ -18,8 +18,8 @@ package android.net; import android.net.IpConfiguration; import android.net.IEthernetServiceListener; -import android.net.IInternalNetworkManagementListener; -import android.net.InternalNetworkUpdateRequest; +import android.net.IEthernetNetworkManagementListener; +import android.net.EthernetNetworkUpdateRequest; import android.net.ITetheredInterfaceCallback; /** @@ -38,8 +38,8 @@ interface IEthernetManager void setIncludeTestInterfaces(boolean include); void requestTetheredInterface(in ITetheredInterfaceCallback callback); void releaseTetheredInterface(in ITetheredInterfaceCallback callback); - void updateConfiguration(String iface, in InternalNetworkUpdateRequest request, - in IInternalNetworkManagementListener listener); - void connectNetwork(String iface, in IInternalNetworkManagementListener listener); - void disconnectNetwork(String iface, in IInternalNetworkManagementListener listener); + void updateConfiguration(String iface, in EthernetNetworkUpdateRequest request, + in IEthernetNetworkManagementListener listener); + void connectNetwork(String iface, in IEthernetNetworkManagementListener listener); + void disconnectNetwork(String iface, in IEthernetNetworkManagementListener listener); } diff --git a/packages/ConnectivityT/framework-t/src/android/net/IInternalNetworkManagementListener.aidl b/packages/ConnectivityT/framework-t/src/android/net/IEthernetNetworkManagementListener.aidl index 69cde3bd14e8..93edccfdafd9 100644 --- a/packages/ConnectivityT/framework-t/src/android/net/IInternalNetworkManagementListener.aidl +++ b/packages/ConnectivityT/framework-t/src/android/net/IEthernetNetworkManagementListener.aidl @@ -16,10 +16,10 @@ package android.net; -import android.net.InternalNetworkManagementException; +import android.net.EthernetNetworkManagementException; import android.net.Network; /** @hide */ -oneway interface IInternalNetworkManagementListener { - void onComplete(in Network network, in InternalNetworkManagementException exception); +oneway interface IEthernetNetworkManagementListener { + void onComplete(in Network network, in EthernetNetworkManagementException exception); }
\ No newline at end of file diff --git a/packages/ConnectivityT/framework-t/src/android/net/IpSecAlgorithm.java b/packages/ConnectivityT/framework-t/src/android/net/IpSecAlgorithm.java index a84e7a9c6344..10a22ac360b1 100644 --- a/packages/ConnectivityT/framework-t/src/android/net/IpSecAlgorithm.java +++ b/packages/ConnectivityT/framework-t/src/android/net/IpSecAlgorithm.java @@ -343,7 +343,7 @@ public final class IpSecAlgorithm implements Parcelable { // Load and validate the optional algorithm resource. Undefined or duplicate algorithms in // the resource are not allowed. final String[] resourceAlgos = systemResources.getStringArray( - com.android.internal.R.array.config_optionalIpSecAlgorithms); + android.R.array.config_optionalIpSecAlgorithms); for (String str : resourceAlgos) { if (!ALGO_TO_REQUIRED_FIRST_SDK.containsKey(str) || !enabledAlgos.add(str)) { // This error should be caught by CTS and never be thrown to API callers diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentity.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentity.java index d3d5a087ccac..56faa52e82df 100644 --- a/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentity.java +++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentity.java @@ -26,10 +26,10 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SuppressLint; import android.annotation.SystemApi; +import android.app.usage.NetworkStatsManager; import android.content.Context; import android.net.wifi.WifiInfo; import android.service.NetworkIdentityProto; -import android.telephony.Annotation; import android.telephony.TelephonyManager; import android.util.proto.ProtoOutputStream; @@ -274,8 +274,7 @@ public class NetworkIdentity { @Deprecated @NonNull public static NetworkIdentity buildNetworkIdentity(Context context, - @NonNull NetworkStateSnapshot snapshot, - boolean defaultNetwork, @Annotation.NetworkType int ratType) { + @NonNull NetworkStateSnapshot snapshot, boolean defaultNetwork, int ratType) { final NetworkIdentity.Builder builder = new NetworkIdentity.Builder() .setNetworkStateSnapshot(snapshot).setDefaultNetwork(defaultNetwork); if (snapshot.getLegacyType() == TYPE_MOBILE && ratType != NETWORK_TYPE_ALL) { @@ -432,9 +431,10 @@ public class NetworkIdentity { * @return this builder. */ @NonNull - public Builder setRatType(@Annotation.NetworkType int ratType) { + public Builder setRatType(int ratType) { if (!CollectionUtils.contains(TelephonyManager.getAllNetworkTypes(), ratType) - && ratType != TelephonyManager.NETWORK_TYPE_UNKNOWN) { + && ratType != TelephonyManager.NETWORK_TYPE_UNKNOWN + && ratType != NetworkStatsManager.NETWORK_TYPE_5G_NSA) { throw new IllegalArgumentException("Invalid ratType " + ratType); } mRatType = ratType; diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsCollection.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsCollection.java index 58ca21fdfad0..735c44d5c87e 100644 --- a/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsCollection.java +++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsCollection.java @@ -16,6 +16,7 @@ package android.net; +import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; import static android.net.NetworkStats.DEFAULT_NETWORK_NO; import static android.net.NetworkStats.DEFAULT_NETWORK_YES; import static android.net.NetworkStats.IFACE_ALL; @@ -34,6 +35,8 @@ import static com.android.net.module.util.NetworkStatsUtils.multiplySafeByRation import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.net.NetworkStatsHistory.Entry; import android.os.Binder; import android.service.NetworkStatsCollectionKeyProto; import android.service.NetworkStatsCollectionProto; @@ -71,6 +74,8 @@ import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; +import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Set; @@ -80,7 +85,7 @@ import java.util.Set; * * @hide */ -// @SystemApi(client = MODULE_LIBRARIES) +@SystemApi(client = MODULE_LIBRARIES) public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.Writer { private static final String TAG = NetworkStatsCollection.class.getSimpleName(); /** File header magic number: "ANET" */ @@ -810,6 +815,71 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W } /** + * Get the all historical stats of the collection {@link NetworkStatsCollection}. + * + * @return All {@link NetworkStatsHistory} in this collection. + */ + @NonNull + public Map<Key, NetworkStatsHistory> getEntries() { + return new ArrayMap(mStats); + } + + /** + * Builder class for {@link NetworkStatsCollection}. + */ + public static final class Builder { + private final long mBucketDuration; + private final ArrayMap<Key, NetworkStatsHistory> mEntries = new ArrayMap<>(); + + /** + * Creates a new Builder with given bucket duration. + * + * @param bucketDuration Duration of the buckets of the object, in milliseconds. + */ + public Builder(long bucketDuration) { + mBucketDuration = bucketDuration; + } + + /** + * Add association of the history with the specified key in this map. + * + * @param key The object used to identify a network, see {@link Key}. + * @param history {@link NetworkStatsHistory} instance associated to the given {@link Key}. + * @return The builder object. + */ + @NonNull + public NetworkStatsCollection.Builder addEntry(@NonNull Key key, + @NonNull NetworkStatsHistory history) { + Objects.requireNonNull(key); + Objects.requireNonNull(history); + final List<Entry> historyEntries = history.getEntries(); + + final NetworkStatsHistory.Builder historyBuilder = + new NetworkStatsHistory.Builder(mBucketDuration, historyEntries.size()); + for (Entry entry : historyEntries) { + historyBuilder.addEntry(entry); + } + + mEntries.put(key, historyBuilder.build()); + return this; + } + + /** + * Builds the instance of the {@link NetworkStatsCollection}. + * + * @return the built instance of {@link NetworkStatsCollection}. + */ + @NonNull + public NetworkStatsCollection build() { + final NetworkStatsCollection collection = new NetworkStatsCollection(mBucketDuration); + for (int i = 0; i < mEntries.size(); i++) { + collection.recordHistory(mEntries.keyAt(i), mEntries.valueAt(i)); + } + return collection; + } + } + + /** * the identifier that associate with the {@link NetworkStatsHistory} object to identify * a certain record in the {@link NetworkStatsCollection} object. */ diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkTemplate.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkTemplate.java index cad80752b8e7..9b58b016bbf3 100644 --- a/packages/ConnectivityT/framework-t/src/android/net/NetworkTemplate.java +++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkTemplate.java @@ -41,13 +41,12 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; +import android.app.usage.NetworkStatsManager; import android.compat.annotation.UnsupportedAppUsage; import android.net.wifi.WifiInfo; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; -import android.telephony.Annotation.NetworkType; -import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.ArraySet; @@ -58,9 +57,7 @@ import com.android.net.module.util.NetworkStatsUtils; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Arrays; -import java.util.Collection; import java.util.Comparator; -import java.util.HashSet; import java.util.List; import java.util.Objects; import java.util.Set; @@ -136,15 +133,6 @@ public final class NetworkTemplate implements Parcelable { * {@code TelephonyManager.NETWORK_TYPE_*} constants, and thus needs to stay in sync. */ public static final int NETWORK_TYPE_ALL = -1; - /** - * Virtual RAT type to represent 5G NSA (Non Stand Alone) mode, where the primary cell is - * still LTE and network allocates a secondary 5G cell so telephony reports RAT = LTE along - * with NR state as connected. This should not be overlapped with any of the - * {@code TelephonyManager.NETWORK_TYPE_*} constants. - * - * @hide - */ - public static final int NETWORK_TYPE_5G_NSA = -2; /** @hide */ @Retention(RetentionPolicy.SOURCE) @@ -214,7 +202,7 @@ public final class NetworkTemplate implements Parcelable { * @hide */ public static NetworkTemplate buildTemplateMobileWithRatType(@Nullable String subscriberId, - @NetworkType int ratType, int metered) { + int ratType, int metered) { if (TextUtils.isEmpty(subscriberId)) { return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null /* subscriberId */, null /* matchSubscriberIds */, @@ -652,7 +640,9 @@ public final class NetworkTemplate implements Parcelable { * * @hide */ - public boolean matches(NetworkIdentity ident) { + @SystemApi(client = MODULE_LIBRARIES) + public boolean matches(@NonNull NetworkIdentity ident) { + Objects.requireNonNull(ident); if (!matchesMetered(ident)) return false; if (!matchesRoaming(ident)) return false; if (!matchesDefaultNetwork(ident)) return false; @@ -709,7 +699,8 @@ public final class NetworkTemplate implements Parcelable { private boolean matchesCollapsedRatType(NetworkIdentity ident) { return mRatType == NETWORK_TYPE_ALL - || getCollapsedRatType(mRatType) == getCollapsedRatType(ident.mRatType); + || NetworkStatsManager.getCollapsedRatType(mRatType) + == NetworkStatsManager.getCollapsedRatType(ident.mRatType); } /** @@ -753,84 +744,6 @@ public final class NetworkTemplate implements Parcelable { } /** - * Get a Radio Access Technology(RAT) type that is representative of a group of RAT types. - * The mapping is corresponding to {@code TelephonyManager#NETWORK_CLASS_BIT_MASK_*}. - * - * @param ratType An integer defined in {@code TelephonyManager#NETWORK_TYPE_*}. - * - * @hide - */ - // TODO: 1. Consider move this to TelephonyManager if used by other modules. - // 2. Consider make this configurable. - // 3. Use TelephonyManager APIs when available. - // TODO: @SystemApi when ready. - public static int getCollapsedRatType(int ratType) { - switch (ratType) { - case TelephonyManager.NETWORK_TYPE_GPRS: - case TelephonyManager.NETWORK_TYPE_GSM: - case TelephonyManager.NETWORK_TYPE_EDGE: - case TelephonyManager.NETWORK_TYPE_IDEN: - case TelephonyManager.NETWORK_TYPE_CDMA: - case TelephonyManager.NETWORK_TYPE_1xRTT: - return TelephonyManager.NETWORK_TYPE_GSM; - case TelephonyManager.NETWORK_TYPE_EVDO_0: - case TelephonyManager.NETWORK_TYPE_EVDO_A: - case TelephonyManager.NETWORK_TYPE_EVDO_B: - case TelephonyManager.NETWORK_TYPE_EHRPD: - case TelephonyManager.NETWORK_TYPE_UMTS: - case TelephonyManager.NETWORK_TYPE_HSDPA: - case TelephonyManager.NETWORK_TYPE_HSUPA: - case TelephonyManager.NETWORK_TYPE_HSPA: - case TelephonyManager.NETWORK_TYPE_HSPAP: - case TelephonyManager.NETWORK_TYPE_TD_SCDMA: - return TelephonyManager.NETWORK_TYPE_UMTS; - case TelephonyManager.NETWORK_TYPE_LTE: - case TelephonyManager.NETWORK_TYPE_IWLAN: - return TelephonyManager.NETWORK_TYPE_LTE; - case TelephonyManager.NETWORK_TYPE_NR: - return TelephonyManager.NETWORK_TYPE_NR; - // Virtual RAT type for 5G NSA mode, see {@link NetworkTemplate#NETWORK_TYPE_5G_NSA}. - case NetworkTemplate.NETWORK_TYPE_5G_NSA: - return NetworkTemplate.NETWORK_TYPE_5G_NSA; - default: - return TelephonyManager.NETWORK_TYPE_UNKNOWN; - } - } - - /** - * Return all supported collapsed RAT types that could be returned by - * {@link #getCollapsedRatType(int)}. - * - * @hide - */ - // TODO: @SystemApi when ready. - @NonNull - public static final int[] getAllCollapsedRatTypes() { - final int[] ratTypes = TelephonyManager.getAllNetworkTypes(); - final HashSet<Integer> collapsedRatTypes = new HashSet<>(); - for (final int ratType : ratTypes) { - collapsedRatTypes.add(NetworkTemplate.getCollapsedRatType(ratType)); - } - // Add NETWORK_TYPE_5G_NSA to the returned list since 5G NSA is a virtual RAT type and - // it is not in TelephonyManager#NETWORK_TYPE_* constants. - // See {@link NetworkTemplate#NETWORK_TYPE_5G_NSA}. - collapsedRatTypes.add(NetworkTemplate.getCollapsedRatType(NETWORK_TYPE_5G_NSA)); - // Ensure that unknown type is returned. - collapsedRatTypes.add(TelephonyManager.NETWORK_TYPE_UNKNOWN); - return toIntArray(collapsedRatTypes); - } - - @NonNull - private static int[] toIntArray(@NonNull Collection<Integer> list) { - final int[] array = new int[list.size()]; - int i = 0; - for (final Integer item : list) { - array[i++] = item; - } - return array; - } - - /** * Check if matches Wi-Fi network template. */ private boolean matchesWifi(NetworkIdentity ident) { @@ -1125,7 +1038,7 @@ public final class NetworkTemplate implements Parcelable { * @return this builder. */ @NonNull - public Builder setRatType(@NetworkType int ratType) { + public Builder setRatType(int ratType) { // Input will be validated with the match rule when building the template. mRatType = ratType; return this; diff --git a/packages/ConnectivityT/framework-t/src/android/net/TrafficStats.java b/packages/ConnectivityT/framework-t/src/android/net/TrafficStats.java index 77b7f16671a0..bc836d857e3e 100644 --- a/packages/ConnectivityT/framework-t/src/android/net/TrafficStats.java +++ b/packages/ConnectivityT/framework-t/src/android/net/TrafficStats.java @@ -31,10 +31,8 @@ import android.media.MediaPlayer; import android.os.Binder; import android.os.Build; import android.os.RemoteException; - -import com.android.server.NetworkManagementSocketTagger; - -import dalvik.system.SocketTagger; +import android.os.StrictMode; +import android.util.Log; import java.io.FileDescriptor; import java.io.IOException; @@ -55,6 +53,10 @@ import java.net.SocketException; * use {@link NetworkStatsManager} instead. */ public class TrafficStats { + static { + System.loadLibrary("framework-connectivity-tiramisu-jni"); + } + private static final String TAG = TrafficStats.class.getSimpleName(); /** * The return value to indicate that the device does not support the statistic. @@ -212,6 +214,13 @@ public class TrafficStats { } final NetworkStatsManager statsManager = context.getSystemService(NetworkStatsManager.class); + if (statsManager == null) { + // TODO: Currently Process.isSupplemental is not working yet, because it depends on + // process to run in a certain UID range, which is not true for now. Change this + // to Log.wtf once Process.isSupplemental is ready. + Log.e(TAG, "TrafficStats not initialized, uid=" + Binder.getCallingUid()); + return; + } sStatsService = statsManager.getBinder(); } @@ -224,9 +233,68 @@ public class TrafficStats { */ @SystemApi(client = MODULE_LIBRARIES) public static void attachSocketTagger() { - NetworkManagementSocketTagger.install(); + dalvik.system.SocketTagger.set(new SocketTagger()); } + private static class SocketTagger extends dalvik.system.SocketTagger { + + // TODO: set to false + private static final boolean LOGD = true; + + SocketTagger() { + } + + @Override + public void tag(FileDescriptor fd) throws SocketException { + final UidTag tagInfo = sThreadUidTag.get(); + if (LOGD) { + Log.d(TAG, "tagSocket(" + fd.getInt$() + ") with statsTag=0x" + + Integer.toHexString(tagInfo.tag) + ", statsUid=" + tagInfo.uid); + } + if (tagInfo.tag == -1) { + StrictMode.noteUntaggedSocket(); + } + + if (tagInfo.tag == -1 && tagInfo.uid == -1) return; + final int errno = native_tagSocketFd(fd, tagInfo.tag, tagInfo.uid); + if (errno < 0) { + Log.i(TAG, "tagSocketFd(" + fd.getInt$() + ", " + + tagInfo.tag + ", " + + tagInfo.uid + ") failed with errno" + errno); + } + } + + @Override + public void untag(FileDescriptor fd) throws SocketException { + if (LOGD) { + Log.i(TAG, "untagSocket(" + fd.getInt$() + ")"); + } + + final UidTag tagInfo = sThreadUidTag.get(); + if (tagInfo.tag == -1 && tagInfo.uid == -1) return; + + final int errno = native_untagSocketFd(fd); + if (errno < 0) { + Log.w(TAG, "untagSocket(" + fd.getInt$() + ") failed with errno " + errno); + } + } + } + + private static native int native_tagSocketFd(FileDescriptor fd, int tag, int uid); + private static native int native_untagSocketFd(FileDescriptor fd); + + private static class UidTag { + public int tag = -1; + public int uid = -1; + } + + private static ThreadLocal<UidTag> sThreadUidTag = new ThreadLocal<UidTag>() { + @Override + protected UidTag initialValue() { + return new UidTag(); + } + }; + /** * Set active tag to use when accounting {@link Socket} traffic originating * from the current thread. Only one active tag per thread is supported. @@ -241,7 +309,7 @@ public class TrafficStats { * @see #clearThreadStatsTag() */ public static void setThreadStatsTag(int tag) { - NetworkManagementSocketTagger.setThreadSocketStatsTag(tag); + getAndSetThreadStatsTag(tag); } /** @@ -259,7 +327,9 @@ public class TrafficStats { * restore any existing values after a nested operation is finished */ public static int getAndSetThreadStatsTag(int tag) { - return NetworkManagementSocketTagger.setThreadSocketStatsTag(tag); + final int old = sThreadUidTag.get().tag; + sThreadUidTag.get().tag = tag; + return old; } /** @@ -319,7 +389,7 @@ public class TrafficStats { * @see #setThreadStatsTag(int) */ public static int getThreadStatsTag() { - return NetworkManagementSocketTagger.getThreadSocketStatsTag(); + return sThreadUidTag.get().tag; } /** @@ -329,7 +399,7 @@ public class TrafficStats { * @see #setThreadStatsTag(int) */ public static void clearThreadStatsTag() { - NetworkManagementSocketTagger.setThreadSocketStatsTag(-1); + sThreadUidTag.get().tag = -1; } /** @@ -349,7 +419,7 @@ public class TrafficStats { */ @SuppressLint("RequiresPermission") public static void setThreadStatsUid(int uid) { - NetworkManagementSocketTagger.setThreadSocketStatsUid(uid); + sThreadUidTag.get().uid = uid; } /** @@ -360,7 +430,7 @@ public class TrafficStats { * @see #setThreadStatsUid(int) */ public static int getThreadStatsUid() { - return NetworkManagementSocketTagger.getThreadSocketStatsUid(); + return sThreadUidTag.get().uid; } /** @@ -387,7 +457,7 @@ public class TrafficStats { */ @SuppressLint("RequiresPermission") public static void clearThreadStatsUid() { - NetworkManagementSocketTagger.setThreadSocketStatsUid(-1); + setThreadStatsUid(-1); } /** diff --git a/packages/ConnectivityT/framework-t/src/android/net/nsd/NsdManager.java b/packages/ConnectivityT/framework-t/src/android/net/nsd/NsdManager.java index 0f21e55b9f27..512fbcee9330 100644 --- a/packages/ConnectivityT/framework-t/src/android/net/nsd/NsdManager.java +++ b/packages/ConnectivityT/framework-t/src/android/net/nsd/NsdManager.java @@ -16,6 +16,9 @@ package android.net.nsd; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.RequiresPermission; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SystemService; @@ -23,15 +26,22 @@ import android.app.compat.CompatChanges; import android.compat.annotation.ChangeId; import android.compat.annotation.EnabledSince; import android.content.Context; +import android.net.ConnectivityManager; +import android.net.ConnectivityManager.NetworkCallback; +import android.net.Network; +import android.net.NetworkRequest; import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; import android.os.Message; import android.os.RemoteException; import android.text.TextUtils; +import android.util.ArrayMap; +import android.util.ArraySet; import android.util.Log; import android.util.SparseArray; +import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import java.util.Objects; @@ -278,9 +288,180 @@ public final class NsdManager { private final SparseArray mListenerMap = new SparseArray(); private final SparseArray<NsdServiceInfo> mServiceMap = new SparseArray<>(); private final Object mMapLock = new Object(); + // Map of listener key sent by client -> per-network discovery tracker + @GuardedBy("mPerNetworkDiscoveryMap") + private final ArrayMap<Integer, PerNetworkDiscoveryTracker> + mPerNetworkDiscoveryMap = new ArrayMap<>(); private final ServiceHandler mHandler; + private class PerNetworkDiscoveryTracker { + final String mServiceType; + final int mProtocolType; + final DiscoveryListener mBaseListener; + final ArrayMap<Network, DelegatingDiscoveryListener> mPerNetworkListeners = + new ArrayMap<>(); + + final NetworkCallback mNetworkCb = new NetworkCallback() { + @Override + public void onAvailable(@NonNull Network network) { + final DelegatingDiscoveryListener wrappedListener = new DelegatingDiscoveryListener( + network, mBaseListener); + mPerNetworkListeners.put(network, wrappedListener); + discoverServices(mServiceType, mProtocolType, network, wrappedListener); + } + + @Override + public void onLost(@NonNull Network network) { + final DelegatingDiscoveryListener listener = mPerNetworkListeners.get(network); + if (listener == null) return; + listener.notifyAllServicesLost(); + // Listener will be removed from map in discovery stopped callback + stopServiceDiscovery(listener); + } + }; + + // Accessed from mHandler + private boolean mStopRequested; + + public void start(@NonNull NetworkRequest request) { + final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class); + cm.registerNetworkCallback(request, mNetworkCb, mHandler); + mHandler.post(() -> mBaseListener.onDiscoveryStarted(mServiceType)); + } + + /** + * Stop discovery on all networks tracked by this class. + * + * This will request all underlying listeners to stop, and the last one to stop will call + * onDiscoveryStopped or onStopDiscoveryFailed. + * + * Must be called on the handler thread. + */ + public void requestStop() { + mHandler.post(() -> { + mStopRequested = true; + final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class); + cm.unregisterNetworkCallback(mNetworkCb); + if (mPerNetworkListeners.size() == 0) { + mBaseListener.onDiscoveryStopped(mServiceType); + return; + } + for (int i = 0; i < mPerNetworkListeners.size(); i++) { + final DelegatingDiscoveryListener listener = mPerNetworkListeners.valueAt(i); + stopServiceDiscovery(listener); + } + }); + } + + private PerNetworkDiscoveryTracker(String serviceType, int protocolType, + DiscoveryListener baseListener) { + mServiceType = serviceType; + mProtocolType = protocolType; + mBaseListener = baseListener; + } + + /** + * Subset of NsdServiceInfo that is tracked to generate service lost notifications when a + * network is lost. + * + * Service lost notifications only contain service name, type and network, so only track + * that information (Network is known from the listener). This also implements + * equals/hashCode for usage in maps. + */ + private class TrackedNsdInfo { + private final String mServiceName; + private final String mServiceType; + TrackedNsdInfo(NsdServiceInfo info) { + mServiceName = info.getServiceName(); + mServiceType = info.getServiceType(); + } + + @Override + public int hashCode() { + return Objects.hash(mServiceName, mServiceType); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof TrackedNsdInfo)) return false; + final TrackedNsdInfo other = (TrackedNsdInfo) obj; + return Objects.equals(mServiceName, other.mServiceName) + && Objects.equals(mServiceType, other.mServiceType); + } + } + + private class DelegatingDiscoveryListener implements DiscoveryListener { + private final Network mNetwork; + private final DiscoveryListener mWrapped; + private final ArraySet<TrackedNsdInfo> mFoundInfo = new ArraySet<>(); + + private DelegatingDiscoveryListener(Network network, DiscoveryListener listener) { + mNetwork = network; + mWrapped = listener; + } + + void notifyAllServicesLost() { + for (int i = 0; i < mFoundInfo.size(); i++) { + final TrackedNsdInfo trackedInfo = mFoundInfo.valueAt(i); + final NsdServiceInfo serviceInfo = new NsdServiceInfo( + trackedInfo.mServiceName, trackedInfo.mServiceType); + serviceInfo.setNetwork(mNetwork); + mWrapped.onServiceLost(serviceInfo); + } + } + + @Override + public void onStartDiscoveryFailed(String serviceType, int errorCode) { + // The delegated listener is used when NsdManager takes care of starting/stopping + // discovery on multiple networks. Failure to start on one network is not a global + // failure to be reported up, as other networks may succeed: just log. + Log.e(TAG, "Failed to start discovery for " + serviceType + " on " + mNetwork + + " with code " + errorCode); + mPerNetworkListeners.remove(mNetwork); + } + + @Override + public void onDiscoveryStarted(String serviceType) { + // Wrapped listener was called upon registration, it is not called for discovery + // on each network + } + + @Override + public void onStopDiscoveryFailed(String serviceType, int errorCode) { + Log.e(TAG, "Failed to stop discovery for " + serviceType + " on " + mNetwork + + " with code " + errorCode); + mPerNetworkListeners.remove(mNetwork); + if (mStopRequested && mPerNetworkListeners.size() == 0) { + // Do not report onStopDiscoveryFailed when some underlying listeners failed: + // this does not mean that all listeners did, and onStopDiscoveryFailed is not + // actionable anyway. Just report that discovery stopped. + mWrapped.onDiscoveryStopped(serviceType); + } + } + + @Override + public void onDiscoveryStopped(String serviceType) { + mPerNetworkListeners.remove(mNetwork); + if (mStopRequested && mPerNetworkListeners.size() == 0) { + mWrapped.onDiscoveryStopped(serviceType); + } + } + + @Override + public void onServiceFound(NsdServiceInfo serviceInfo) { + mFoundInfo.add(new TrackedNsdInfo(serviceInfo)); + mWrapped.onServiceFound(serviceInfo); + } + + @Override + public void onServiceLost(NsdServiceInfo serviceInfo) { + mFoundInfo.remove(new TrackedNsdInfo(serviceInfo)); + mWrapped.onServiceLost(serviceInfo); + } + } + } + /** * Create a new Nsd instance. Applications use * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve @@ -634,6 +815,14 @@ public final class NsdManager { } /** + * Same as {@link #discoverServices(String, int, Network, DiscoveryListener)} with a null + * {@link Network}. + */ + public void discoverServices(String serviceType, int protocolType, DiscoveryListener listener) { + discoverServices(serviceType, protocolType, (Network) null, listener); + } + + /** * Initiate service discovery to browse for instances of a service type. Service discovery * consumes network bandwidth and will continue until the application calls * {@link #stopServiceDiscovery}. @@ -657,11 +846,13 @@ public final class NsdManager { * @param serviceType The service type being discovered. Examples include "_http._tcp" for * http services or "_ipp._tcp" for printers * @param protocolType The service discovery protocol + * @param network Network to discover services on, or null to discover on all available networks * @param listener The listener notifies of a successful discovery and is used * to stop discovery on this serviceType through a call on {@link #stopServiceDiscovery}. * Cannot be null. Cannot be in use for an active service discovery. */ - public void discoverServices(String serviceType, int protocolType, DiscoveryListener listener) { + public void discoverServices(@NonNull String serviceType, int protocolType, + @Nullable Network network, @NonNull DiscoveryListener listener) { if (TextUtils.isEmpty(serviceType)) { throw new IllegalArgumentException("Service type cannot be empty"); } @@ -669,6 +860,7 @@ public final class NsdManager { NsdServiceInfo s = new NsdServiceInfo(); s.setServiceType(serviceType); + s.setNetwork(network); int key = putListener(listener, s); try { @@ -679,6 +871,67 @@ public final class NsdManager { } /** + * Initiate service discovery to browse for instances of a service type. Service discovery + * consumes network bandwidth and will continue until the application calls + * {@link #stopServiceDiscovery}. + * + * <p> The function call immediately returns after sending a request to start service + * discovery to the framework. The application is notified of a success to initiate + * discovery through the callback {@link DiscoveryListener#onDiscoveryStarted} or a failure + * through {@link DiscoveryListener#onStartDiscoveryFailed}. + * + * <p> Upon successful start, application is notified when a service is found with + * {@link DiscoveryListener#onServiceFound} or when a service is lost with + * {@link DiscoveryListener#onServiceLost}. + * + * <p> Upon failure to start, service discovery is not active and application does + * not need to invoke {@link #stopServiceDiscovery} + * + * <p> The application should call {@link #stopServiceDiscovery} when discovery of this + * service type is no longer required, and/or whenever the application is paused or + * stopped. + * + * <p> During discovery, new networks may connect or existing networks may disconnect - for + * example if wifi is reconnected. When a service was found on a network that disconnects, + * {@link DiscoveryListener#onServiceLost} will be called. If a new network connects that + * matches the {@link NetworkRequest}, {@link DiscoveryListener#onServiceFound} will be called + * for services found on that network. Applications that do not want to track networks + * themselves are encouraged to use this method instead of other overloads of + * {@code discoverServices}, as they will receive proper notifications when a service becomes + * available or unavailable due to network changes. + * + * @param serviceType The service type being discovered. Examples include "_http._tcp" for + * http services or "_ipp._tcp" for printers + * @param protocolType The service discovery protocol + * @param networkRequest Request specifying networks that should be considered when discovering + * @param listener The listener notifies of a successful discovery and is used + * to stop discovery on this serviceType through a call on {@link #stopServiceDiscovery}. + * Cannot be null. Cannot be in use for an active service discovery. + */ + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) + public void discoverServices(@NonNull String serviceType, int protocolType, + @NonNull NetworkRequest networkRequest, @NonNull DiscoveryListener listener) { + if (TextUtils.isEmpty(serviceType)) { + throw new IllegalArgumentException("Service type cannot be empty"); + } + Objects.requireNonNull(networkRequest, "NetworkRequest cannot be null"); + checkProtocol(protocolType); + + NsdServiceInfo s = new NsdServiceInfo(); + s.setServiceType(serviceType); + + final int baseListenerKey = putListener(listener, s); + + final PerNetworkDiscoveryTracker discoveryInfo = new PerNetworkDiscoveryTracker( + serviceType, protocolType, listener); + + synchronized (mPerNetworkDiscoveryMap) { + mPerNetworkDiscoveryMap.put(baseListenerKey, discoveryInfo); + discoveryInfo.start(networkRequest); + } + } + + /** * Stop service discovery initiated with {@link #discoverServices}. An active service * discovery is notified to the application with {@link DiscoveryListener#onDiscoveryStarted} * and it stays active until the application invokes a stop service discovery. A successful @@ -696,6 +949,14 @@ public final class NsdManager { */ public void stopServiceDiscovery(DiscoveryListener listener) { int id = getListenerKey(listener); + // If this is a PerNetworkDiscovery request, handle it as such + synchronized (mPerNetworkDiscoveryMap) { + final PerNetworkDiscoveryTracker info = mPerNetworkDiscoveryMap.get(id); + if (info != null) { + info.requestStop(); + return; + } + } try { mService.stopDiscovery(id); } catch (RemoteException e) { diff --git a/packages/ConnectivityT/framework-t/src/android/net/nsd/NsdServiceInfo.java b/packages/ConnectivityT/framework-t/src/android/net/nsd/NsdServiceInfo.java index 0946499f164f..8506db1fbe01 100644 --- a/packages/ConnectivityT/framework-t/src/android/net/nsd/NsdServiceInfo.java +++ b/packages/ConnectivityT/framework-t/src/android/net/nsd/NsdServiceInfo.java @@ -17,7 +17,9 @@ package android.net.nsd; import android.annotation.NonNull; +import android.annotation.Nullable; import android.compat.annotation.UnsupportedAppUsage; +import android.net.Network; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; @@ -49,6 +51,9 @@ public final class NsdServiceInfo implements Parcelable { private int mPort; + @Nullable + private Network mNetwork; + public NsdServiceInfo() { } @@ -307,18 +312,37 @@ public final class NsdServiceInfo implements Parcelable { return txtRecord; } - public String toString() { - StringBuffer sb = new StringBuffer(); + /** + * Get the network where the service can be found. + * + * This is never null if this {@link NsdServiceInfo} was obtained from + * {@link NsdManager#discoverServices} or {@link NsdManager#resolveService}. + */ + @Nullable + public Network getNetwork() { + return mNetwork; + } + /** + * Set the network where the service can be found. + * @param network The network, or null to search for, or to announce, the service on all + * connected networks. + */ + public void setNetwork(@Nullable Network network) { + mNetwork = network; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); sb.append("name: ").append(mServiceName) .append(", type: ").append(mServiceType) .append(", host: ").append(mHost) - .append(", port: ").append(mPort); + .append(", port: ").append(mPort) + .append(", network: ").append(mNetwork); byte[] txtRecord = getTxtRecord(); - if (txtRecord != null) { - sb.append(", txtRecord: ").append(new String(txtRecord, StandardCharsets.UTF_8)); - } + sb.append(", txtRecord: ").append(new String(txtRecord, StandardCharsets.UTF_8)); return sb.toString(); } @@ -352,6 +376,8 @@ public final class NsdServiceInfo implements Parcelable { } dest.writeString(key); } + + dest.writeParcelable(mNetwork, 0); } /** Implement the Parcelable interface */ @@ -381,6 +407,7 @@ public final class NsdServiceInfo implements Parcelable { } info.mTxtRecord.put(in.readString(), valueArray); } + info.mNetwork = in.readParcelable(null, Network.class); return info; } diff --git a/packages/ConnectivityT/framework-t/src/com/android/server/NetworkManagementSocketTagger.java b/packages/ConnectivityT/framework-t/src/com/android/server/NetworkManagementSocketTagger.java deleted file mode 100644 index 1eb52fb44629..000000000000 --- a/packages/ConnectivityT/framework-t/src/com/android/server/NetworkManagementSocketTagger.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server; - -import android.os.StrictMode; -import android.util.Log; - -import dalvik.system.SocketTagger; - -import java.io.FileDescriptor; -import java.net.SocketException; - -/** - * Assigns tags to sockets for traffic stats. - * @hide - */ -public final class NetworkManagementSocketTagger extends SocketTagger { - private static final String TAG = "NetworkManagementSocketTagger"; - private static final boolean LOGD = false; - - private static ThreadLocal<SocketTags> threadSocketTags = new ThreadLocal<SocketTags>() { - @Override - protected SocketTags initialValue() { - return new SocketTags(); - } - }; - - public static void install() { - SocketTagger.set(new NetworkManagementSocketTagger()); - } - - public static int setThreadSocketStatsTag(int tag) { - final int old = threadSocketTags.get().statsTag; - threadSocketTags.get().statsTag = tag; - return old; - } - - public static int getThreadSocketStatsTag() { - return threadSocketTags.get().statsTag; - } - - public static int setThreadSocketStatsUid(int uid) { - final int old = threadSocketTags.get().statsUid; - threadSocketTags.get().statsUid = uid; - return old; - } - - public static int getThreadSocketStatsUid() { - return threadSocketTags.get().statsUid; - } - - @Override - public void tag(FileDescriptor fd) throws SocketException { - final SocketTags options = threadSocketTags.get(); - if (LOGD) { - Log.d(TAG, "tagSocket(" + fd.getInt$() + ") with statsTag=0x" - + Integer.toHexString(options.statsTag) + ", statsUid=" + options.statsUid); - } - if (options.statsTag == -1) { - StrictMode.noteUntaggedSocket(); - } - // TODO: skip tagging when options would be no-op - tagSocketFd(fd, options.statsTag, options.statsUid); - } - - private void tagSocketFd(FileDescriptor fd, int tag, int uid) { - if (tag == -1 && uid == -1) return; - - final int errno = native_tagSocketFd(fd, tag, uid); - if (errno < 0) { - Log.i(TAG, "tagSocketFd(" + fd.getInt$() + ", " - + tag + ", " - + uid + ") failed with errno" + errno); - } - } - - @Override - public void untag(FileDescriptor fd) throws SocketException { - if (LOGD) { - Log.i(TAG, "untagSocket(" + fd.getInt$() + ")"); - } - unTagSocketFd(fd); - } - - private void unTagSocketFd(FileDescriptor fd) { - final SocketTags options = threadSocketTags.get(); - if (options.statsTag == -1 && options.statsUid == -1) return; - - final int errno = native_untagSocketFd(fd); - if (errno < 0) { - Log.w(TAG, "untagSocket(" + fd.getInt$() + ") failed with errno " + errno); - } - } - - public static class SocketTags { - public int statsTag = -1; - public int statsUid = -1; - } - - public static void setKernelCounterSet(int uid, int counterSet) { - final int errno = native_setCounterSet(counterSet, uid); - if (errno < 0) { - Log.w(TAG, "setKernelCountSet(" + uid + ", " + counterSet + ") failed with errno " - + errno); - } - } - - public static void resetKernelUidStats(int uid) { - int errno = native_deleteTagData(0, uid); - if (errno < 0) { - Log.w(TAG, "problem clearing counters for uid " + uid + " : errno " + errno); - } - } - - /** - * Convert {@code /proc/} tag format to {@link Integer}. Assumes incoming - * format like {@code 0x7fffffff00000000}. - */ - public static int kernelToTag(String string) { - int length = string.length(); - if (length > 10) { - return Long.decode(string.substring(0, length - 8)).intValue(); - } else { - return 0; - } - } - - private static native int native_tagSocketFd(FileDescriptor fd, int tag, int uid); - private static native int native_untagSocketFd(FileDescriptor fd); - private static native int native_setCounterSet(int uid, int counterSetNum); - private static native int native_deleteTagData(int tag, int uid); -} diff --git a/packages/ConnectivityT/service/Android.bp b/packages/ConnectivityT/service/Android.bp index 24bc91d91ef7..d05370f9ba60 100644 --- a/packages/ConnectivityT/service/Android.bp +++ b/packages/ConnectivityT/service/Android.bp @@ -28,6 +28,11 @@ filegroup { "src/com/android/server/net/NetworkStats*.java", "src/com/android/server/net/BpfInterfaceMapUpdater.java", "src/com/android/server/net/InterfaceMapValue.java", + "src/com/android/server/net/CookieTagMapKey.java", + "src/com/android/server/net/CookieTagMapValue.java", + "src/com/android/server/net/StatsMapKey.java", + "src/com/android/server/net/StatsMapValue.java", + "src/com/android/server/net/UidStatsMapKey.java", ], path: "src", visibility: [ diff --git a/packages/ConnectivityT/service/src/com/android/server/NsdService.java b/packages/ConnectivityT/service/src/com/android/server/NsdService.java index 497107dbf989..ddf6d2c4ab15 100644 --- a/packages/ConnectivityT/service/src/com/android/server/NsdService.java +++ b/packages/ConnectivityT/service/src/com/android/server/NsdService.java @@ -19,6 +19,9 @@ package com.android.server; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; +import android.net.ConnectivityManager; +import android.net.LinkProperties; +import android.net.Network; import android.net.nsd.INsdManager; import android.net.nsd.INsdManagerCallback; import android.net.nsd.INsdServiceConnector; @@ -44,6 +47,9 @@ import com.android.net.module.util.DnsSdTxtRecord; import java.io.FileDescriptor; import java.io.PrintWriter; import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.net.UnknownHostException; import java.util.Arrays; import java.util.HashMap; import java.util.concurrent.CountDownLatch; @@ -60,6 +66,7 @@ public class NsdService extends INsdManager.Stub { private static final boolean DBG = true; private static final long CLEANUP_DELAY_MS = 10000; + private static final int IFACE_IDX_ANY = 0; private final Context mContext; private final NsdStateMachine mNsdStateMachine; @@ -297,7 +304,7 @@ public class NsdService extends INsdManager.Stub { maybeStartDaemon(); id = getUniqueId(); - if (discoverServices(id, args.serviceInfo.getServiceType())) { + if (discoverServices(id, args.serviceInfo)) { if (DBG) { Log.d(TAG, "Discover " + msg.arg2 + " " + id + args.serviceInfo.getServiceType()); @@ -430,13 +437,38 @@ public class NsdService extends INsdManager.Stub { } switch (code) { case NativeResponseCode.SERVICE_FOUND: - /* NNN uniqueId serviceName regType domain */ + /* NNN uniqueId serviceName regType domain interfaceIdx netId */ servInfo = new NsdServiceInfo(cooked[2], cooked[3]); + final int foundNetId; + try { + foundNetId = Integer.parseInt(cooked[6]); + } catch (NumberFormatException e) { + Log.wtf(TAG, "Invalid network received from mdnsd: " + cooked[6]); + break; + } + if (foundNetId == 0L) { + // Ignore services that do not have a Network: they are not usable + // by apps, as they would need privileged permissions to use + // interfaces that do not have an associated Network. + break; + } + servInfo.setNetwork(new Network(foundNetId)); clientInfo.onServiceFound(clientId, servInfo); break; case NativeResponseCode.SERVICE_LOST: - /* NNN uniqueId serviceName regType domain */ + /* NNN uniqueId serviceName regType domain interfaceIdx netId */ + final int lostNetId; + try { + lostNetId = Integer.parseInt(cooked[6]); + } catch (NumberFormatException e) { + Log.wtf(TAG, "Invalid network received from mdnsd: " + cooked[6]); + break; + } servInfo = new NsdServiceInfo(cooked[2], cooked[3]); + // The network could be null if it was torn down when the service is lost + // TODO: avoid returning null in that case, possibly by remembering found + // services on the same interface index and their network at the time + servInfo.setNetwork(lostNetId == 0 ? null : new Network(lostNetId)); clientInfo.onServiceLost(clientId, servInfo); break; case NativeResponseCode.SERVICE_DISCOVERY_FAILED: @@ -461,7 +493,7 @@ public class NsdService extends INsdManager.Stub { /* NNN regId errorCode */ break; case NativeResponseCode.SERVICE_RESOLVED: - /* NNN resolveId fullName hostName port txtlen txtdata */ + /* NNN resolveId fullName hostName port txtlen txtdata interfaceIdx */ int index = 0; while (index < cooked[2].length() && cooked[2].charAt(index) != '.') { if (cooked[2].charAt(index) == '\\') { @@ -473,6 +505,7 @@ public class NsdService extends INsdManager.Stub { Log.e(TAG, "Invalid service found " + raw); break; } + String name = cooked[2].substring(0, index); String rest = cooked[2].substring(index); String type = rest.replace(".local.", ""); @@ -483,12 +516,13 @@ public class NsdService extends INsdManager.Stub { clientInfo.mResolvedService.setServiceType(type); clientInfo.mResolvedService.setPort(Integer.parseInt(cooked[4])); clientInfo.mResolvedService.setTxtRecords(cooked[6]); + // Network will be added after SERVICE_GET_ADDR_SUCCESS stopResolveService(id); removeRequestMap(clientId, id, clientInfo); int id2 = getUniqueId(); - if (getAddrInfo(id2, cooked[3])) { + if (getAddrInfo(id2, cooked[3], cooked[7] /* interfaceIdx */)) { storeRequestMap(clientId, id2, clientInfo, NsdManager.RESOLVE_SERVICE); } else { clientInfo.onResolveServiceFailed( @@ -513,12 +547,31 @@ public class NsdService extends INsdManager.Stub { clientId, NsdManager.FAILURE_INTERNAL_ERROR); break; case NativeResponseCode.SERVICE_GET_ADDR_SUCCESS: - /* NNN resolveId hostname ttl addr */ + /* NNN resolveId hostname ttl addr interfaceIdx netId */ + Network network = null; + try { + final int netId = Integer.parseInt(cooked[6]); + network = netId == 0L ? null : new Network(netId); + } catch (NumberFormatException e) { + Log.wtf(TAG, "Invalid network in GET_ADDR_SUCCESS: " + cooked[6], e); + } + + InetAddress serviceHost = null; try { - clientInfo.mResolvedService.setHost(InetAddress.getByName(cooked[4])); + serviceHost = InetAddress.getByName(cooked[4]); + } catch (UnknownHostException e) { + Log.wtf(TAG, "Invalid host in GET_ADDR_SUCCESS", e); + } + + // If the resolved service is on an interface without a network, consider it + // as a failure: it would not be usable by apps as they would need + // privileged permissions. + if (network != null && serviceHost != null) { + clientInfo.mResolvedService.setHost(serviceHost); + clientInfo.mResolvedService.setNetwork(network); clientInfo.onResolveServiceSucceeded( clientId, clientInfo.mResolvedService); - } catch (java.net.UnknownHostException e) { + } else { clientInfo.onResolveServiceFailed( clientId, NsdManager.FAILURE_INTERNAL_ERROR); } @@ -815,8 +868,15 @@ public class NsdService extends INsdManager.Stub { return mDaemon.execute("update", regId, t.size(), t.getRawData()); } - private boolean discoverServices(int discoveryId, String serviceType) { - return mDaemon.execute("discover", discoveryId, serviceType); + private boolean discoverServices(int discoveryId, NsdServiceInfo serviceInfo) { + final Network network = serviceInfo.getNetwork(); + final int discoverInterface = getNetworkInterfaceIndex(network); + if (network != null && discoverInterface == IFACE_IDX_ANY) { + Log.e(TAG, "Interface to discover service on not found"); + return false; + } + return mDaemon.execute("discover", discoveryId, serviceInfo.getServiceType(), + discoverInterface); } private boolean stopServiceDiscovery(int discoveryId) { @@ -824,17 +884,61 @@ public class NsdService extends INsdManager.Stub { } private boolean resolveService(int resolveId, NsdServiceInfo service) { - String name = service.getServiceName(); - String type = service.getServiceType(); - return mDaemon.execute("resolve", resolveId, name, type, "local."); + final String name = service.getServiceName(); + final String type = service.getServiceType(); + final Network network = service.getNetwork(); + final int resolveInterface = getNetworkInterfaceIndex(network); + if (network != null && resolveInterface == IFACE_IDX_ANY) { + Log.e(TAG, "Interface to resolve service on not found"); + return false; + } + return mDaemon.execute("resolve", resolveId, name, type, "local.", resolveInterface); + } + + /** + * Guess the interface to use to resolve or discover a service on a specific network. + * + * This is an imperfect guess, as for example the network may be gone or not yet fully + * registered. This is fine as failing is correct if the network is gone, and a client + * attempting to resolve/discover on a network not yet setup would have a bad time anyway; also + * this is to support the legacy mdnsresponder implementation, which historically resolved + * services on an unspecified network. + */ + private int getNetworkInterfaceIndex(Network network) { + if (network == null) return IFACE_IDX_ANY; + + final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class); + if (cm == null) { + Log.wtf(TAG, "No ConnectivityManager for resolveService"); + return IFACE_IDX_ANY; + } + final LinkProperties lp = cm.getLinkProperties(network); + if (lp == null) return IFACE_IDX_ANY; + + // Only resolve on non-stacked interfaces + final NetworkInterface iface; + try { + iface = NetworkInterface.getByName(lp.getInterfaceName()); + } catch (SocketException e) { + Log.e(TAG, "Error querying interface", e); + return IFACE_IDX_ANY; + } + + if (iface == null) { + Log.e(TAG, "Interface not found: " + lp.getInterfaceName()); + return IFACE_IDX_ANY; + } + + return iface.getIndex(); } private boolean stopResolveService(int resolveId) { return mDaemon.execute("stop-resolve", resolveId); } - private boolean getAddrInfo(int resolveId, String hostname) { - return mDaemon.execute("getaddrinfo", resolveId, hostname); + private boolean getAddrInfo(int resolveId, String hostname, String interfaceIdx) { + // interfaceIdx is always obtained (as string) from the service resolved callback + return mDaemon.execute("getaddrinfo", resolveId, hostname, interfaceIdx); } private boolean stopGetAddrInfo(int resolveId) { diff --git a/packages/ConnectivityT/service/src/com/android/server/net/CookieTagMapKey.java b/packages/ConnectivityT/service/src/com/android/server/net/CookieTagMapKey.java new file mode 100644 index 000000000000..443e5b38475e --- /dev/null +++ b/packages/ConnectivityT/service/src/com/android/server/net/CookieTagMapKey.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.net; + +import com.android.net.module.util.Struct; +import com.android.net.module.util.Struct.Field; +import com.android.net.module.util.Struct.Type; + +/** + * Key for cookie tag map. + */ +public class CookieTagMapKey extends Struct { + @Field(order = 0, type = Type.S64) + public final long socketCookie; + + public CookieTagMapKey(final long socketCookie) { + this.socketCookie = socketCookie; + } +} diff --git a/packages/ConnectivityT/service/src/com/android/server/net/CookieTagMapValue.java b/packages/ConnectivityT/service/src/com/android/server/net/CookieTagMapValue.java new file mode 100644 index 000000000000..93b9195f92da --- /dev/null +++ b/packages/ConnectivityT/service/src/com/android/server/net/CookieTagMapValue.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.net; + +import com.android.net.module.util.Struct; +import com.android.net.module.util.Struct.Field; +import com.android.net.module.util.Struct.Type; + +/** + * Value for cookie tag map. + */ +public class CookieTagMapValue extends Struct { + @Field(order = 0, type = Type.U32) + public final long uid; + + @Field(order = 1, type = Type.U32) + public final long tag; + + public CookieTagMapValue(final long uid, final long tag) { + this.uid = uid; + this.tag = tag; + } +} diff --git a/packages/ConnectivityT/service/src/com/android/server/net/InterfaceMapValue.java b/packages/ConnectivityT/service/src/com/android/server/net/InterfaceMapValue.java index 061f323447b0..42c0044e666f 100644 --- a/packages/ConnectivityT/service/src/com/android/server/net/InterfaceMapValue.java +++ b/packages/ConnectivityT/service/src/com/android/server/net/InterfaceMapValue.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsFactory.java b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsFactory.java index 17f3455d20a2..668d1cba921b 100644 --- a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsFactory.java +++ b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsFactory.java @@ -22,8 +22,6 @@ import static android.net.NetworkStats.TAG_ALL; import static android.net.NetworkStats.TAG_NONE; import static android.net.NetworkStats.UID_ALL; -import static com.android.server.NetworkManagementSocketTagger.kernelToTag; - import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; @@ -470,6 +468,19 @@ public class NetworkStatsFactory { } /** + * Convert {@code /proc/} tag format to {@link Integer}. Assumes incoming + * format like {@code 0x7fffffff00000000}. + */ + public static int kernelToTag(String string) { + int length = string.length(); + if (length > 10) { + return Long.decode(string.substring(0, length - 8)).intValue(); + } else { + return 0; + } + } + + /** * Parse statistics from file into given {@link NetworkStats} object. Values * are expected to monotonically increase since device boot. */ diff --git a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsObservers.java b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsObservers.java index e85a59e8bed0..19536247b23b 100644 --- a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsObservers.java +++ b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsObservers.java @@ -76,7 +76,7 @@ class NetworkStatsObservers { */ public DataUsageRequest register(DataUsageRequest inputRequest, IUsageCallback callback, int callingUid, @NetworkStatsAccess.Level int accessLevel) { - DataUsageRequest request = buildRequest(inputRequest); + DataUsageRequest request = buildRequest(inputRequest, callingUid); RequestInfo requestInfo = buildRequestInfo(request, callback, callingUid, accessLevel); @@ -194,10 +194,12 @@ class NetworkStatsObservers { } } - private DataUsageRequest buildRequest(DataUsageRequest request) { - // Cap the minimum threshold to a safe default to avoid too many callbacks - long thresholdInBytes = Math.max(MIN_THRESHOLD_BYTES, request.thresholdInBytes); - if (thresholdInBytes < request.thresholdInBytes) { + private DataUsageRequest buildRequest(DataUsageRequest request, int callingUid) { + // For non-system uid, cap the minimum threshold to a safe default to avoid too + // many callbacks. + long thresholdInBytes = (callingUid == Process.SYSTEM_UID ? request.thresholdInBytes + : Math.max(MIN_THRESHOLD_BYTES, request.thresholdInBytes)); + if (thresholdInBytes > request.thresholdInBytes) { Log.w(TAG, "Threshold was too low for " + request + ". Overriding to a safer default of " + thresholdInBytes + " bytes"); } diff --git a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java index 243d62164705..9f3371b724cf 100644 --- a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java +++ b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java @@ -20,9 +20,6 @@ import static android.Manifest.permission.NETWORK_STATS_PROVIDER; import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY; import static android.Manifest.permission.UPDATE_DEVICE_STATS; import static android.app.usage.NetworkStatsManager.PREFIX_DEV; -import static android.app.usage.NetworkStatsManager.PREFIX_UID; -import static android.app.usage.NetworkStatsManager.PREFIX_UID_TAG; -import static android.app.usage.NetworkStatsManager.PREFIX_XT; import static android.content.Intent.ACTION_SHUTDOWN; import static android.content.Intent.ACTION_UID_REMOVED; import static android.content.Intent.ACTION_USER_REMOVED; @@ -50,6 +47,9 @@ import static android.net.TrafficStats.KB_IN_BYTES; import static android.net.TrafficStats.MB_IN_BYTES; import static android.net.TrafficStats.UID_TETHERING; import static android.net.TrafficStats.UNSUPPORTED; +import static android.net.netstats.NetworkStatsDataMigrationUtils.PREFIX_UID; +import static android.net.netstats.NetworkStatsDataMigrationUtils.PREFIX_UID_TAG; +import static android.net.netstats.NetworkStatsDataMigrationUtils.PREFIX_XT; import static android.os.Trace.TRACE_TAG_NETWORK; import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; import static android.text.format.DateUtils.DAY_IN_MILLIS; @@ -59,8 +59,6 @@ import static android.text.format.DateUtils.SECOND_IN_MILLIS; import static com.android.net.module.util.NetworkCapabilitiesUtils.getDisplayTransport; import static com.android.net.module.util.NetworkStatsUtils.LIMIT_GLOBAL_ALERT; -import static com.android.server.NetworkManagementSocketTagger.resetKernelUidStats; -import static com.android.server.NetworkManagementSocketTagger.setKernelCounterSet; import android.annotation.NonNull; import android.annotation.Nullable; @@ -121,6 +119,8 @@ import android.provider.Settings; import android.provider.Settings.Global; import android.service.NetworkInterfaceProto; import android.service.NetworkStatsServiceDumpProto; +import android.system.ErrnoException; +import android.system.Os; import android.telephony.PhoneStateListener; import android.telephony.SubscriptionPlan; import android.text.TextUtils; @@ -139,10 +139,14 @@ import com.android.internal.util.FileRotator; import com.android.net.module.util.BaseNetdUnsolicitedEventListener; import com.android.net.module.util.BestClock; import com.android.net.module.util.BinderUtils; +import com.android.net.module.util.BpfMap; import com.android.net.module.util.CollectionUtils; +import com.android.net.module.util.IBpfMap; import com.android.net.module.util.LocationPermissionChecker; import com.android.net.module.util.NetworkStatsUtils; import com.android.net.module.util.PermissionUtils; +import com.android.net.module.util.Struct.U32; +import com.android.net.module.util.Struct.U8; import java.io.File; import java.io.FileDescriptor; @@ -207,6 +211,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private static final String NETSTATS_COMBINE_SUBTYPE_ENABLED = "netstats_combine_subtype_enabled"; + // This is current path but may be changed soon. + private static final String UID_COUNTERSET_MAP_PATH = + "/sys/fs/bpf/map_netd_uid_counterset_map"; + private final Context mContext; private final NetworkStatsFactory mStatsFactory; private final AlarmManager mAlarmManager; @@ -244,7 +252,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { /** * When enabled, all mobile data is reported under {@link NetworkTemplate#NETWORK_TYPE_ALL}. * When disabled, mobile data is broken down by a granular ratType representative of the - * actual ratType. {@see NetworkTemplate#getCollapsedRatType}. + * actual ratType. {@see android.app.usage.NetworkStatsManager#getCollapsedRatType}. * Enabling this decreases the level of detail but saves performance, disk space and * amount of data logged. */ @@ -325,8 +333,14 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @GuardedBy("mStatsLock") private NetworkStatsCollection mXtStatsCached; - /** Current counter sets for each UID. */ + /** + * Current counter sets for each UID. + * TODO: maybe remove mActiveUidCounterSet and read UidCouneterSet value from mUidCounterSetMap + * directly ? But if mActiveUidCounterSet would be accessed very frequently, maybe keep + * mActiveUidCounterSet to avoid accessing kernel too frequently. + */ private SparseIntArray mActiveUidCounterSet = new SparseIntArray(); + private final IBpfMap<U32, U8> mUidCounterSetMap; /** Data layer operation counters for splicing into other structures. */ private NetworkStats mUidOperations = new NetworkStats(0L, 10); @@ -459,6 +473,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mLocationPermissionChecker = mDeps.makeLocationPermissionChecker(mContext); mInterfaceMapUpdater = mDeps.makeBpfInterfaceMapUpdater(mContext, mHandler); mInterfaceMapUpdater.start(); + mUidCounterSetMap = mDeps.getUidCounterSetMap(); } /** @@ -520,6 +535,21 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @NonNull Context ctx, @NonNull Handler handler) { return new BpfInterfaceMapUpdater(ctx, handler); } + + /** Get counter sets map for each UID. */ + public IBpfMap<U32, U8> getUidCounterSetMap() { + try { + return new BpfMap<U32, U8>(UID_COUNTERSET_MAP_PATH, BpfMap.BPF_F_RDWR, + U32.class, U8.class); + } catch (ErrnoException e) { + Log.wtf(TAG, "Cannot create uid counter set map: " + e); + return null; + } + } + + public TagStatsDeleter getTagStatsDeleter() { + return NetworkStatsService::nativeDeleteTagData; + } } /** @@ -1077,6 +1107,29 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } } + private void setKernelCounterSet(int uid, int set) { + if (mUidCounterSetMap == null) { + Log.wtf(TAG, "Fail to set UidCounterSet: Null bpf map"); + return; + } + + if (set == SET_DEFAULT) { + try { + mUidCounterSetMap.deleteEntry(new U32(uid)); + } catch (ErrnoException e) { + Log.w(TAG, "UidCounterSetMap.deleteEntry(" + uid + ") failed with errno: " + e); + } + return; + } + + try { + mUidCounterSetMap.updateEntry(new U32(uid), new U8((short) set)); + } catch (ErrnoException e) { + Log.w(TAG, "UidCounterSetMap.updateEntry(" + uid + ", " + set + + ") failed with errno: " + e); + } + } + @VisibleForTesting public void setUidForeground(int uid, boolean uidForeground) { PermissionUtils.enforceNetworkStackPermission(mContext); @@ -1752,7 +1805,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // Clear kernel stats associated with UID for (int uid : uids) { - resetKernelUidStats(uid); + final int ret = mDeps.getTagStatsDeleter().deleteTagData(uid); + if (ret < 0) { + Log.w(TAG, "problem clearing counters for uid " + uid + ": " + Os.strerror(-ret)); + } } } @@ -2331,4 +2387,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private static native long nativeGetTotalStat(int type); private static native long nativeGetIfaceStat(String iface, int type); private static native long nativeGetUidStat(int uid, int type); + + // TODO: use BpfNetMaps to delete tag data and remove this. + @VisibleForTesting + interface TagStatsDeleter { + int deleteTagData(int uid); + } + + private static native int nativeDeleteTagData(int uid); } diff --git a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java index 4875f1cf5aaa..5bba0b17aa42 100644 --- a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java +++ b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java @@ -16,15 +16,14 @@ package com.android.server.net; -import static android.net.NetworkTemplate.NETWORK_TYPE_5G_NSA; -import static android.net.NetworkTemplate.getCollapsedRatType; +import static android.app.usage.NetworkStatsManager.NETWORK_TYPE_5G_NSA; +import static android.app.usage.NetworkStatsManager.getCollapsedRatType; import static android.telephony.TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED; import static android.telephony.TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA; import static android.telephony.TelephonyManager.NETWORK_TYPE_LTE; import android.annotation.NonNull; import android.content.Context; -import android.telephony.Annotation; import android.telephony.SubscriptionManager; import android.telephony.TelephonyCallback; import android.telephony.TelephonyDisplayInfo; @@ -57,10 +56,9 @@ public class NetworkStatsSubscriptionsMonitor extends * * @param subscriberId IMSI of the subscription. * @param collapsedRatType collapsed RAT type. - * @see android.net.NetworkTemplate#getCollapsedRatType(int). + * @see android.app.usage.NetworkStatsManager#getCollapsedRatType(int). */ - void onCollapsedRatTypeChanged(@NonNull String subscriberId, - @Annotation.NetworkType int collapsedRatType); + void onCollapsedRatTypeChanged(@NonNull String subscriberId, int collapsedRatType); } private final Delegate mDelegate; diff --git a/packages/ConnectivityT/service/src/com/android/server/net/StatsMapKey.java b/packages/ConnectivityT/service/src/com/android/server/net/StatsMapKey.java new file mode 100644 index 000000000000..ea8d83638347 --- /dev/null +++ b/packages/ConnectivityT/service/src/com/android/server/net/StatsMapKey.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.net; + +import com.android.net.module.util.Struct; +import com.android.net.module.util.Struct.Field; +import com.android.net.module.util.Struct.Type; + +/** + * Key for both stats maps. + */ +public class StatsMapKey extends Struct { + @Field(order = 0, type = Type.U32) + public final long uid; + + @Field(order = 1, type = Type.U32) + public final long tag; + + @Field(order = 2, type = Type.U32) + public final long counterSet; + + @Field(order = 3, type = Type.U32) + public final long ifaceIndex; + + public StatsMapKey(final long uid, final long tag, final long counterSet, + final long ifaceIndex) { + this.uid = uid; + this.tag = tag; + this.counterSet = counterSet; + this.ifaceIndex = ifaceIndex; + } +} diff --git a/packages/ConnectivityT/service/src/com/android/server/net/StatsMapValue.java b/packages/ConnectivityT/service/src/com/android/server/net/StatsMapValue.java new file mode 100644 index 000000000000..48f26ce686e2 --- /dev/null +++ b/packages/ConnectivityT/service/src/com/android/server/net/StatsMapValue.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.net; + +import com.android.net.module.util.Struct; +import com.android.net.module.util.Struct.Field; +import com.android.net.module.util.Struct.Type; + +/** + * Value used for both stats maps and uid stats map. + */ +public class StatsMapValue extends Struct { + @Field(order = 0, type = Type.U63) + public final long rxPackets; + + @Field(order = 1, type = Type.U63) + public final long rxBytes; + + @Field(order = 2, type = Type.U63) + public final long txPackets; + + @Field(order = 3, type = Type.U63) + public final long txBytes; + + public StatsMapValue(final long rxPackets, final long rxBytes, final long txPackets, + final long txBytes) { + this.rxPackets = rxPackets; + this.rxBytes = rxBytes; + this.txPackets = txPackets; + this.txBytes = txBytes; + } +} diff --git a/packages/ConnectivityT/service/src/com/android/server/net/UidStatsMapKey.java b/packages/ConnectivityT/service/src/com/android/server/net/UidStatsMapKey.java new file mode 100644 index 000000000000..2849f94c9383 --- /dev/null +++ b/packages/ConnectivityT/service/src/com/android/server/net/UidStatsMapKey.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.net; + +import com.android.net.module.util.Struct; +import com.android.net.module.util.Struct.Field; +import com.android.net.module.util.Struct.Type; + +/** + * Key for uid stats map. + */ +public class UidStatsMapKey extends Struct { + @Field(order = 0, type = Type.U32) + public final long uid; + + public UidStatsMapKey(final long uid) { + this.uid = uid; + } +} diff --git a/packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java b/packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java index f5aa652f3194..b4e84dd54654 100644 --- a/packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java +++ b/packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java @@ -27,9 +27,7 @@ import static com.android.internal.util.Preconditions.checkNotNull; import android.net.NetworkPolicy; import android.net.NetworkPolicyManager; import android.net.NetworkTemplate; -import android.net.wifi.WifiInfo; import android.os.AsyncTask; -import android.text.TextUtils; import android.util.RecurrenceRule; import com.google.android.collect.Lists; @@ -124,7 +122,7 @@ public class NetworkPolicyEditor { if (policy != null) { return policy; } else { - return getPolicy(buildUnquotedNetworkTemplate(template)); + return getPolicy(template); } } @@ -207,21 +205,4 @@ public class NetworkPolicyEditor { policy.clearSnooze(); writeAsync(); } - - /** - * Build a revised {@link NetworkTemplate} that matches the same rule, but - * with an unquoted {@link NetworkTemplate#getNetworkId()}. Used to work - * around legacy bugs. - */ - private static NetworkTemplate buildUnquotedNetworkTemplate(NetworkTemplate template) { - if (template == null) return null; - final String networkId = template.getNetworkId(); - final String strippedNetworkId = WifiInfo.sanitizeSsid(networkId); - if (!TextUtils.equals(strippedNetworkId, networkId)) { - return new NetworkTemplate( - template.getMatchRule(), template.getSubscriberId(), strippedNetworkId); - } else { - return null; - } - } } diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java index 99e3160fcbe3..df19c67f00e5 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java @@ -173,8 +173,10 @@ public class A2dpProfile implements LocalBluetoothProfile { } public BluetoothDevice getActiveDevice() { - if (mService == null) return null; - return mService.getActiveDevice(); + if (mBluetoothAdapter == null) return null; + final List<BluetoothDevice> activeDevices = mBluetoothAdapter + .getActiveDevices(BluetoothProfile.A2DP); + return (activeDevices.size() > 0) ? activeDevices.get(0) : null; } @Override @@ -221,7 +223,7 @@ public class A2dpProfile implements LocalBluetoothProfile { } public boolean supportsHighQualityAudio(BluetoothDevice device) { - BluetoothDevice bluetoothDevice = (device != null) ? device : mService.getActiveDevice(); + BluetoothDevice bluetoothDevice = (device != null) ? device : getActiveDevice(); if (bluetoothDevice == null) { return false; } @@ -234,7 +236,7 @@ public class A2dpProfile implements LocalBluetoothProfile { */ @RequiresApi(Build.VERSION_CODES.TIRAMISU) public boolean isHighQualityAudioEnabled(BluetoothDevice device) { - BluetoothDevice bluetoothDevice = (device != null) ? device : mService.getActiveDevice(); + BluetoothDevice bluetoothDevice = (device != null) ? device : getActiveDevice(); if (bluetoothDevice == null) { return false; } @@ -260,7 +262,7 @@ public class A2dpProfile implements LocalBluetoothProfile { } public void setHighQualityAudioEnabled(BluetoothDevice device, boolean enabled) { - BluetoothDevice bluetoothDevice = (device != null) ? device : mService.getActiveDevice(); + BluetoothDevice bluetoothDevice = (device != null) ? device : getActiveDevice(); if (bluetoothDevice == null) { return; } @@ -286,7 +288,7 @@ public class A2dpProfile implements LocalBluetoothProfile { */ @RequiresApi(Build.VERSION_CODES.TIRAMISU) public String getHighQualityAudioOptionLabel(BluetoothDevice device) { - BluetoothDevice bluetoothDevice = (device != null) ? device : mService.getActiveDevice(); + BluetoothDevice bluetoothDevice = (device != null) ? device : getActiveDevice(); int unknownCodecId = R.string.bluetooth_profile_a2dp_high_quality_unknown_codec; if (bluetoothDevice == null || !supportsHighQualityAudio(device) || getConnectionStatus(device) != BluetoothProfile.STATE_CONNECTED) { diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java index ddee433d3997..233e798c8578 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java @@ -500,6 +500,17 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> } /** + * Get identity address from remote device + * @return {@link BluetoothDevice#getIdentityAddress()} if + * {@link BluetoothDevice#getIdentityAddress()} is not null otherwise return + * {@link BluetoothDevice#getAddress()} + */ + public String getIdentityAddress() { + final String identityAddress = mDevice.getIdentityAddress(); + return TextUtils.isEmpty(identityAddress) ? getAddress() : identityAddress; + } + + /** * Get name from remote device * @return {@link BluetoothDevice#getAlias()} if * {@link BluetoothDevice#getAlias()} is not null otherwise return diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java index 9dd329ed7cd7..b44d9147c2b0 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java @@ -132,10 +132,12 @@ public class HeadsetProfile implements LocalBluetoothProfile { } public BluetoothDevice getActiveDevice() { - if (mService == null) { + if (mBluetoothAdapter == null) { return null; } - return mService.getActiveDevice(); + final List<BluetoothDevice> activeDevices = mBluetoothAdapter + .getActiveDevices(BluetoothProfile.HEADSET); + return (activeDevices.size() > 0) ? activeDevices.get(0) : null; } public boolean isAudioOn() { diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java index a1fba4a018e2..ff1368adad82 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java @@ -168,8 +168,10 @@ public class HearingAidProfile implements LocalBluetoothProfile { } public List<BluetoothDevice> getActiveDevices() { - if (mService == null) return new ArrayList<>(); - return mService.getActiveDevices(); + if (mBluetoothAdapter == null) { + return new ArrayList<>(); + } + return mBluetoothAdapter.getActiveDevices(BluetoothProfile.HEARING_AID); } @Override diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LeAudioProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LeAudioProfile.java index 209507ac7088..db6d41ef692d 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LeAudioProfile.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LeAudioProfile.java @@ -21,12 +21,12 @@ import static android.bluetooth.BluetoothAdapter.ACTIVE_DEVICE_ALL; import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_ALLOWED; import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; -import android.bluetooth.BluetoothLeAudio; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothClass; import android.bluetooth.BluetoothCodecConfig; import android.bluetooth.BluetoothCodecStatus; import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothLeAudio; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothUuid; import android.content.Context; @@ -177,10 +177,10 @@ public class LeAudioProfile implements LocalBluetoothProfile { } public List<BluetoothDevice> getActiveDevices() { - if (mService == null) { + if (mBluetoothAdapter == null) { return new ArrayList<>(); } - return mService.getActiveDevices(); + return mBluetoothAdapter.getActiveDevices(BluetoothProfile.LE_AUDIO); } @Override diff --git a/packages/SettingsLib/src/com/android/settingslib/mobile/OWNERS b/packages/SettingsLib/src/com/android/settingslib/mobile/OWNERS new file mode 100644 index 000000000000..ab9b5dc3ff7a --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/mobile/OWNERS @@ -0,0 +1,4 @@ +# Default reviewers for this and subdirectories. +bonianchen@google.com + +# Emergency approvers in case the above are not available diff --git a/packages/SettingsLib/src/com/android/settingslib/net/ChartData.java b/packages/SettingsLib/src/com/android/settingslib/net/ChartData.java index e30aac575c67..a69c59c6da6d 100644 --- a/packages/SettingsLib/src/com/android/settingslib/net/ChartData.java +++ b/packages/SettingsLib/src/com/android/settingslib/net/ChartData.java @@ -16,12 +16,18 @@ package com.android.settingslib.net; -import android.net.NetworkStatsHistory; +import android.app.usage.NetworkStats; + +import java.util.List; public class ChartData { - public NetworkStatsHistory network; + // Collect the data usage history of the network from the given {@link NetworkTemplate}. + public List<NetworkStats.Bucket> network; - public NetworkStatsHistory detail; - public NetworkStatsHistory detailDefault; - public NetworkStatsHistory detailForeground; + // Collect the detail datausage history (foreground + Background). + public List<NetworkStats.Bucket> detail; + // Collect background datausage history. + public List<NetworkStats.Bucket> detailDefault; + // Collect foreground datausage history. + public List<NetworkStats.Bucket> detailForeground; } diff --git a/packages/SettingsLib/src/com/android/settingslib/net/ChartDataLoader.java b/packages/SettingsLib/src/com/android/settingslib/net/ChartDataLoader.java index 60d22a0d5803..573922f9013c 100644 --- a/packages/SettingsLib/src/com/android/settingslib/net/ChartDataLoader.java +++ b/packages/SettingsLib/src/com/android/settingslib/net/ChartDataLoader.java @@ -19,20 +19,21 @@ package com.android.settingslib.net; import static android.net.NetworkStats.SET_DEFAULT; import static android.net.NetworkStats.SET_FOREGROUND; import static android.net.NetworkStats.TAG_NONE; -import static android.net.NetworkStatsHistory.FIELD_RX_BYTES; -import static android.net.NetworkStatsHistory.FIELD_TX_BYTES; -import static android.text.format.DateUtils.HOUR_IN_MILLIS; +import android.annotation.NonNull; +import android.app.usage.NetworkStats; +import android.app.usage.NetworkStatsManager; import android.content.AsyncTaskLoader; import android.content.Context; -import android.net.INetworkStatsSession; -import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; import android.os.Bundle; import android.os.RemoteException; import com.android.settingslib.AppItem; +import java.util.ArrayList; +import java.util.List; + /** * Framework loader is deprecated, use the compat version instead. * @@ -42,26 +43,20 @@ import com.android.settingslib.AppItem; public class ChartDataLoader extends AsyncTaskLoader<ChartData> { private static final String KEY_TEMPLATE = "template"; private static final String KEY_APP = "app"; - private static final String KEY_FIELDS = "fields"; - private final INetworkStatsSession mSession; + private final NetworkStatsManager mNetworkStatsManager; private final Bundle mArgs; public static Bundle buildArgs(NetworkTemplate template, AppItem app) { - return buildArgs(template, app, FIELD_RX_BYTES | FIELD_TX_BYTES); - } - - public static Bundle buildArgs(NetworkTemplate template, AppItem app, int fields) { final Bundle args = new Bundle(); args.putParcelable(KEY_TEMPLATE, template); args.putParcelable(KEY_APP, app); - args.putInt(KEY_FIELDS, fields); return args; } - public ChartDataLoader(Context context, INetworkStatsSession session, Bundle args) { + public ChartDataLoader(Context context, NetworkStatsManager statsManager, Bundle args) { super(context); - mSession = session; + mNetworkStatsManager = statsManager; mArgs = args; } @@ -75,10 +70,9 @@ public class ChartDataLoader extends AsyncTaskLoader<ChartData> { public ChartData loadInBackground() { final NetworkTemplate template = mArgs.getParcelable(KEY_TEMPLATE); final AppItem app = mArgs.getParcelable(KEY_APP); - final int fields = mArgs.getInt(KEY_FIELDS); try { - return loadInBackground(template, app, fields); + return loadInBackground(template, app); } catch (RemoteException e) { // since we can't do much without history, and we don't want to // leave with half-baked UI, we bail hard. @@ -86,10 +80,22 @@ public class ChartDataLoader extends AsyncTaskLoader<ChartData> { } } - private ChartData loadInBackground(NetworkTemplate template, AppItem app, int fields) + @NonNull + private List<NetworkStats.Bucket> convertToBuckets(@NonNull NetworkStats stats) { + final List<NetworkStats.Bucket> ret = new ArrayList<>(); + while (stats.hasNextBucket()) { + final NetworkStats.Bucket bucket = new NetworkStats.Bucket(); + stats.getNextBucket(bucket); + ret.add(bucket); + } + return ret; + } + + private ChartData loadInBackground(NetworkTemplate template, AppItem app) throws RemoteException { final ChartData data = new ChartData(); - data.network = mSession.getHistoryForNetwork(template, fields); + data.network = convertToBuckets(mNetworkStatsManager.queryDetailsForDevice( + template, Long.MIN_VALUE, Long.MAX_VALUE)); if (app != null) { // load stats for current uid and template @@ -103,13 +109,13 @@ public class ChartDataLoader extends AsyncTaskLoader<ChartData> { } if (size > 0) { - data.detail = new NetworkStatsHistory(data.detailForeground.getBucketDuration()); - data.detail.recordEntireHistory(data.detailDefault); - data.detail.recordEntireHistory(data.detailForeground); + data.detail = new ArrayList<>(); + data.detail.addAll(data.detailDefault); + data.detail.addAll(data.detailForeground); } else { - data.detailDefault = new NetworkStatsHistory(HOUR_IN_MILLIS); - data.detailForeground = new NetworkStatsHistory(HOUR_IN_MILLIS); - data.detail = new NetworkStatsHistory(HOUR_IN_MILLIS); + data.detailDefault = new ArrayList<>(); + data.detailForeground = new ArrayList<>(); + data.detail = new ArrayList<>(); } } @@ -129,17 +135,17 @@ public class ChartDataLoader extends AsyncTaskLoader<ChartData> { } /** - * Collect {@link NetworkStatsHistory} for the requested UID, combining with - * an existing {@link NetworkStatsHistory} if provided. + * Collect {@link List<NetworkStats.Bucket>} for the requested UID, combining with + * an existing {@link List<NetworkStats.Bucket>} if provided. */ - private NetworkStatsHistory collectHistoryForUid( - NetworkTemplate template, int uid, int set, NetworkStatsHistory existing) - throws RemoteException { - final NetworkStatsHistory history = mSession.getHistoryForUid( - template, uid, set, TAG_NONE, FIELD_RX_BYTES | FIELD_TX_BYTES); + private List<NetworkStats.Bucket> collectHistoryForUid( + NetworkTemplate template, int uid, int set, List<NetworkStats.Bucket> existing) { + final List<NetworkStats.Bucket> history = convertToBuckets( + mNetworkStatsManager.queryDetailsForUidTagState(template, + Long.MIN_VALUE, Long.MAX_VALUE, uid, TAG_NONE, set)); if (existing != null) { - existing.recordEntireHistory(history); + existing.addAll(history); return existing; } else { return history; diff --git a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java index cff45c6be0e0..30c6645193c0 100644 --- a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java +++ b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java @@ -16,7 +16,6 @@ package com.android.settingslib.net; -import static android.net.TrafficStats.MB_IN_BYTES; import static android.telephony.TelephonyManager.SIM_STATE_READY; import static android.text.format.DateUtils.FORMAT_ABBREV_MONTH; import static android.text.format.DateUtils.FORMAT_SHOW_DATE; @@ -49,6 +48,7 @@ public class DataUsageController { private static final StringBuilder PERIOD_BUILDER = new StringBuilder(50); private static final java.util.Formatter PERIOD_FORMATTER = new java.util.Formatter( PERIOD_BUILDER, Locale.getDefault()); + private static final long MB_IN_BYTES = 1024 * 1024; private final Context mContext; private final NetworkPolicyManager mPolicyManager; @@ -237,10 +237,8 @@ public class DataUsageController { final int matchRule = networkTemplate.getMatchRule(); switch (matchRule) { case NetworkTemplate.MATCH_MOBILE: - case NetworkTemplate.MATCH_MOBILE_WILDCARD: return ConnectivityManager.TYPE_MOBILE; case NetworkTemplate.MATCH_WIFI: - case NetworkTemplate.MATCH_WIFI_WILDCARD: return ConnectivityManager.TYPE_WIFI; case NetworkTemplate.MATCH_ETHERNET: return ConnectivityManager.TYPE_ETHERNET; diff --git a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java index afd44d5bbc90..386a47ae29b0 100644 --- a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java +++ b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java @@ -63,14 +63,32 @@ public class DataUsageUtils { private static NetworkTemplate getNormalizedMobileTemplate( TelephonyManager telephonyManager, int subId) { final NetworkTemplate mobileTemplate = getMobileTemplateForSubId(telephonyManager, subId); - final String[] mergedSubscriberIds = telephonyManager - .createForSubscriptionId(subId).getMergedImsisFromGroup(); + final Set<String> mergedSubscriberIds = Set.of(telephonyManager + .createForSubscriptionId(subId).getMergedImsisFromGroup()); if (ArrayUtils.isEmpty(mergedSubscriberIds)) { Log.i(TAG, "mergedSubscriberIds is null."); return mobileTemplate; } - return NetworkTemplate.normalize(mobileTemplate, mergedSubscriberIds); + return normalizeMobileTemplate(mobileTemplate, mergedSubscriberIds); + } + + private static NetworkTemplate normalizeMobileTemplate( + NetworkTemplate template, Set<String> mergedSet) { + if (template.getSubscriberIds().isEmpty()) return template; + // The input template should have at most 1 subscriberId. + final String subscriberId = template.getSubscriberIds().iterator().next(); + + if (mergedSet.contains(subscriberId)) { + // Requested template subscriber is part of the merge group; return + // a template that matches all merged subscribers. + return new NetworkTemplate.Builder(template.getMatchRule()) + .setSubscriberIds(mergedSet) + .setWifiNetworkKeys(template.getWifiNetworkKeys()) + .setMeteredness(NetworkStats.METERED_YES).build(); + } + + return template; } private static NetworkTemplate getMobileTemplateForSubId( diff --git a/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataForUidLoader.java b/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataForUidLoader.java index 43c05b8b64d6..504390cd0b63 100644 --- a/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataForUidLoader.java +++ b/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataForUidLoader.java @@ -53,8 +53,9 @@ public class NetworkCycleDataForUidLoader extends long totalUsage = 0L; long totalForeground = 0L; for (int uid : mUids) { - final NetworkStats stats = mNetworkStatsManager.queryDetailsForUid( - mNetworkTemplate, start, end, uid); + final NetworkStats stats = mNetworkStatsManager.queryDetailsForUidTagState( + mNetworkTemplate, start, end, uid, NetworkStats.Bucket.TAG_NONE, + NetworkStats.Bucket.STATE_ALL); final long usage = getTotalUsage(stats); if (usage > 0L) { totalUsage += usage; diff --git a/packages/SettingsLib/src/com/android/settingslib/net/OWNERS b/packages/SettingsLib/src/com/android/settingslib/net/OWNERS new file mode 100644 index 000000000000..ab9b5dc3ff7a --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/net/OWNERS @@ -0,0 +1,4 @@ +# Default reviewers for this and subdirectories. +bonianchen@google.com + +# Emergency approvers in case the above are not available diff --git a/packages/SettingsLib/src/com/android/settingslib/net/SummaryForAllUidLoader.java b/packages/SettingsLib/src/com/android/settingslib/net/SummaryForAllUidLoader.java index 649aeffd0d5f..8da6032a6649 100644 --- a/packages/SettingsLib/src/com/android/settingslib/net/SummaryForAllUidLoader.java +++ b/packages/SettingsLib/src/com/android/settingslib/net/SummaryForAllUidLoader.java @@ -16,13 +16,12 @@ package com.android.settingslib.net; +import android.app.usage.NetworkStats; +import android.app.usage.NetworkStatsManager; import android.content.AsyncTaskLoader; import android.content.Context; -import android.net.INetworkStatsSession; -import android.net.NetworkStats; import android.net.NetworkTemplate; import android.os.Bundle; -import android.os.RemoteException; /** * Framework loader is deprecated, use the compat version instead. @@ -35,7 +34,7 @@ public class SummaryForAllUidLoader extends AsyncTaskLoader<NetworkStats> { private static final String KEY_START = "start"; private static final String KEY_END = "end"; - private final INetworkStatsSession mSession; + private final NetworkStatsManager mNetworkStatsManager; private final Bundle mArgs; public static Bundle buildArgs(NetworkTemplate template, long start, long end) { @@ -46,9 +45,9 @@ public class SummaryForAllUidLoader extends AsyncTaskLoader<NetworkStats> { return args; } - public SummaryForAllUidLoader(Context context, INetworkStatsSession session, Bundle args) { + public SummaryForAllUidLoader(Context context, Bundle args) { super(context); - mSession = session; + mNetworkStatsManager = context.getSystemService(NetworkStatsManager.class); mArgs = args; } @@ -63,12 +62,7 @@ public class SummaryForAllUidLoader extends AsyncTaskLoader<NetworkStats> { final NetworkTemplate template = mArgs.getParcelable(KEY_TEMPLATE); final long start = mArgs.getLong(KEY_START); final long end = mArgs.getLong(KEY_END); - - try { - return mSession.getSummaryForAllUid(template, start, end, false); - } catch (RemoteException e) { - return null; - } + return mNetworkStatsManager.querySummary(template, start, end); } @Override diff --git a/packages/SettingsLib/src/com/android/settingslib/net/UidDetailProvider.java b/packages/SettingsLib/src/com/android/settingslib/net/UidDetailProvider.java index 02326ea85ff6..623eb33f9c0d 100644 --- a/packages/SettingsLib/src/com/android/settingslib/net/UidDetailProvider.java +++ b/packages/SettingsLib/src/com/android/settingslib/net/UidDetailProvider.java @@ -17,6 +17,7 @@ package com.android.settingslib.net; import android.app.AppGlobals; +import android.app.usage.NetworkStats; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; @@ -116,13 +117,13 @@ public class UidDetailProvider { detail.label = res.getString(R.string.process_kernel_label); detail.icon = pm.getDefaultActivityIcon(); return detail; - case TrafficStats.UID_REMOVED: + case NetworkStats.Bucket.UID_REMOVED: detail.label = res.getString(UserManager.supportsMultipleUsers() ? R.string.data_usage_uninstalled_apps_users : R.string.data_usage_uninstalled_apps); detail.icon = pm.getDefaultActivityIcon(); return detail; - case TrafficStats.UID_TETHERING: + case NetworkStats.Bucket.UID_TETHERING: final TetheringManager tm = mContext.getSystemService(TetheringManager.class); detail.label = res.getString(Utils.getTetheringLabel(tm)); detail.icon = pm.getDefaultActivityIcon(); diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java index f167721f94bf..d7b366e60a1d 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java @@ -60,6 +60,8 @@ public class A2dpProfileTest { private BluetoothDevice mDevice; @Mock private BluetoothA2dp mBluetoothA2dp; + @Mock + private BluetoothAdapter mBluetoothAdapter; private BluetoothProfile.ServiceListener mServiceListener; private A2dpProfile mProfile; @@ -72,7 +74,8 @@ public class A2dpProfileTest { mProfile = new A2dpProfile(mContext, mDeviceManager, mProfileManager); mServiceListener = mShadowBluetoothAdapter.getServiceListener(); mServiceListener.onServiceConnected(BluetoothProfile.A2DP, mBluetoothA2dp); - when(mBluetoothA2dp.getActiveDevice()).thenReturn(mDevice); + when(mBluetoothAdapter.getActiveDevices(eq(BluetoothProfile.A2DP))) + .thenReturn(Arrays.asList(mDevice)); } @Test diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageUtilsTest.java index b0a647e0dd2f..95f7ef41b10b 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageUtilsTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageUtilsTest.java @@ -81,8 +81,8 @@ public class DataUsageUtilsTest { when(mSubscriptionManager.isActiveSubscriptionId(SUB_ID)).thenReturn(false); final NetworkTemplate networkTemplate = DataUsageUtils.getMobileTemplate(mContext, SUB_ID); - assertThat(networkTemplate.matchesSubscriberId(SUBSCRIBER_ID)).isTrue(); - assertThat(networkTemplate.matchesSubscriberId(SUBSCRIBER_ID_2)).isFalse(); + assertThat(networkTemplate.getSubscriberIds().contains(SUBSCRIBER_ID)).isTrue(); + assertThat(networkTemplate.getSubscriberIds().contains(SUBSCRIBER_ID_2)).isFalse(); } @Test @@ -94,8 +94,8 @@ public class DataUsageUtilsTest { .thenReturn(new String[] {SUBSCRIBER_ID}); final NetworkTemplate networkTemplate = DataUsageUtils.getMobileTemplate(mContext, SUB_ID); - assertThat(networkTemplate.matchesSubscriberId(SUBSCRIBER_ID)).isTrue(); - assertThat(networkTemplate.matchesSubscriberId(SUBSCRIBER_ID_2)).isFalse(); + assertThat(networkTemplate.getSubscriberIds().contains(SUBSCRIBER_ID)).isTrue(); + assertThat(networkTemplate.getSubscriberIds().contains(SUBSCRIBER_ID_2)).isFalse(); } @Test @@ -107,7 +107,7 @@ public class DataUsageUtilsTest { .thenReturn(new String[] {SUBSCRIBER_ID, SUBSCRIBER_ID_2}); final NetworkTemplate networkTemplate = DataUsageUtils.getMobileTemplate(mContext, SUB_ID); - assertThat(networkTemplate.matchesSubscriberId(SUBSCRIBER_ID)).isTrue(); - assertThat(networkTemplate.matchesSubscriberId(SUBSCRIBER_ID_2)).isTrue(); + assertThat(networkTemplate.getSubscriberIds().contains(SUBSCRIBER_ID)).isTrue(); + assertThat(networkTemplate.getSubscriberIds().contains(SUBSCRIBER_ID_2)).isTrue(); } } diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataForUidLoaderTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataForUidLoaderTest.java index 5b0f659e9c7a..2f3da831a08f 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataForUidLoaderTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataForUidLoaderTest.java @@ -16,6 +16,7 @@ package com.android.settingslib.net; +import static android.app.usage.NetworkStats.Bucket.STATE_ALL; import static android.app.usage.NetworkStats.Bucket.STATE_FOREGROUND; import static android.net.NetworkStats.TAG_NONE; @@ -83,7 +84,6 @@ public class NetworkCycleDataForUidLoaderTest { mLoader.recordUsage(start, end); - verify(mNetworkStatsManager).queryDetailsForUid(mNetworkTemplate, start, end, uid); verify(mNetworkStatsManager).queryDetailsForUidTagState( mNetworkTemplate, start, end, uid, TAG_NONE, STATE_FOREGROUND); } @@ -116,9 +116,12 @@ public class NetworkCycleDataForUidLoaderTest { mLoader.recordUsage(start, end); - verify(mNetworkStatsManager).queryDetailsForUid(mNetworkTemplate, start, end, 1); - verify(mNetworkStatsManager).queryDetailsForUid(mNetworkTemplate, start, end, 2); - verify(mNetworkStatsManager).queryDetailsForUid(mNetworkTemplate, start, end, 3); + verify(mNetworkStatsManager).queryDetailsForUidTagState(mNetworkTemplate, start, end, 1, + TAG_NONE, STATE_ALL); + verify(mNetworkStatsManager).queryDetailsForUidTagState(mNetworkTemplate, start, end, 2, + TAG_NONE, STATE_ALL); + verify(mNetworkStatsManager).queryDetailsForUidTagState(mNetworkTemplate, start, end, 3, + TAG_NONE, STATE_ALL); } } diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index 96310b8597d2..074d85c1007e 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -190,6 +190,9 @@ <uses-permission android:name="android.permission.REVOKE_RUNTIME_PERMISSIONS" /> <uses-permission android:name="android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS" /> <uses-permission android:name="android.permission.WHITELIST_RESTRICTED_PERMISSIONS" /> + <!-- Permission required for processes that don't own the focused window to switch + touch mode state --> + <uses-permission android:name="android.permission.MODIFY_TOUCH_MODE_STATE" /> <!-- Permission required to test onPermissionsChangedListener --> <uses-permission android:name="android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS" /> <uses-permission android:name="android.permission.SET_KEYBOARD_LAYOUT" /> @@ -504,6 +507,8 @@ <!-- Permission needed for CTS test - WifiManagerTest --> <uses-permission android:name="android.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS" /> <uses-permission android:name="android.permission.WIFI_UPDATE_COEX_UNSAFE_CHANNELS" /> + <uses-permission android:name="android.permission.NEARBY_WIFI_DEVICES" /> + <uses-permission android:name="android.permission.OVERRIDE_WIFI_CONFIG" /> <!-- Permission required for CTS tests to enable/disable rate limiting toasts. --> <uses-permission android:name="android.permission.MANAGE_TOAST_RATE_LIMITING" /> @@ -531,6 +536,7 @@ <!-- Permissions required for CTS test - TrustTestCases --> <uses-permission android:name="android.permission.PROVIDE_TRUST_AGENT" /> <uses-permission android:name="android.permission.ACCESS_KEYGUARD_SECURE_STORAGE" /> + <uses-permission android:name="android.permission.TRUST_LISTENER" /> <!-- Permission required for CTS test - CtsGameManagerTestCases --> <uses-permission android:name="android.permission.MANAGE_GAME_MODE" /> diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt index d3d6e03c9bc7..6f30ac3901e1 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt @@ -18,6 +18,7 @@ package com.android.systemui.controls.ui import android.annotation.MainThread import android.app.Dialog +import android.app.PendingIntent import android.content.Context import android.content.Intent import android.content.pm.PackageManager @@ -88,7 +89,7 @@ class ControlActionCoordinatorImpl @Inject constructor( bouncerOrRun(createAction(cvh.cws.ci.controlId, { cvh.layout.performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK) if (cvh.usePanel()) { - showDetail(cvh, control.getAppIntent().getIntent()) + showDetail(cvh, control.getAppIntent()) } else { cvh.action(CommandAction(templateId)) } @@ -116,7 +117,7 @@ class ControlActionCoordinatorImpl @Inject constructor( // Long press snould only be called when there is valid control state, otherwise ignore cvh.cws.control?.let { cvh.layout.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS) - showDetail(cvh, it.getAppIntent().getIntent()) + showDetail(cvh, it.getAppIntent()) } }, false /* blockable */)) } @@ -167,10 +168,10 @@ class ControlActionCoordinatorImpl @Inject constructor( bgExecutor.execute { vibrator.vibrate(effect) } } - private fun showDetail(cvh: ControlViewHolder, intent: Intent) { + private fun showDetail(cvh: ControlViewHolder, pendingIntent: PendingIntent) { bgExecutor.execute { val activities: List<ResolveInfo> = context.packageManager.queryIntentActivities( - intent, + pendingIntent.getIntent(), PackageManager.MATCH_DEFAULT_ONLY ) @@ -178,7 +179,7 @@ class ControlActionCoordinatorImpl @Inject constructor( // make sure the intent is valid before attempting to open the dialog if (activities.isNotEmpty() && taskViewFactory.isPresent) { taskViewFactory.get().create(context, uiExecutor, { - dialog = DetailDialog(activityContext, it, intent, cvh).also { + dialog = DetailDialog(activityContext, it, pendingIntent, cvh).also { it.setOnDismissListener { _ -> dialog = null } it.show() } diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt index 8a47a36de8c4..4758ab04e2e5 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt @@ -43,7 +43,7 @@ import com.android.wm.shell.TaskView class DetailDialog( val activityContext: Context?, val taskView: TaskView, - val intent: Intent, + val pendingIntent: PendingIntent, val cvh: ControlViewHolder ) : Dialog( activityContext ?: cvh.context, @@ -59,6 +59,14 @@ class DetailDialog( var detailTaskId = INVALID_TASK_ID + private val fillInIntent = Intent().apply { + putExtra(EXTRA_USE_PANEL, true) + + // Apply flags to make behaviour match documentLaunchMode=always. + addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT) + addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK) + } + fun removeDetailTask() { if (detailTaskId == INVALID_TASK_ID) return ActivityTaskManager.getInstance().removeTask(detailTaskId) @@ -67,13 +75,6 @@ class DetailDialog( val stateCallback = object : TaskView.Listener { override fun onInitialized() { - val launchIntent = Intent(intent) - launchIntent.putExtra(EXTRA_USE_PANEL, true) - - // Apply flags to make behaviour match documentLaunchMode=always. - launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT) - launchIntent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK) - val options = activityContext?.let { ActivityOptions.makeCustomAnimation( it, @@ -82,9 +83,8 @@ class DetailDialog( ) } ?: ActivityOptions.makeBasic() taskView.startActivity( - PendingIntent.getActivity(context, 0, launchIntent, - PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE), - null /* fillInIntent */, + pendingIntent, + fillInIntent, options, getTaskViewBounds() ) @@ -97,6 +97,9 @@ class DetailDialog( override fun onTaskCreated(taskId: Int, name: ComponentName?) { detailTaskId = taskId + requireViewById<ViewGroup>(R.id.controls_activity_view).apply { + setAlpha(1f) + } } override fun onReleased() { @@ -121,6 +124,7 @@ class DetailDialog( requireViewById<ViewGroup>(R.id.controls_activity_view).apply { addView(taskView) + setAlpha(0f) } requireViewById<ImageView>(R.id.control_detail_close).apply { @@ -134,7 +138,7 @@ class DetailDialog( removeDetailTask() dismiss() context.sendBroadcast(Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) - v.context.startActivity(intent) + pendingIntent.send() } } diff --git a/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseDialog.kt b/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseDialog.kt index c50365f1bf38..71c5fad5322e 100644 --- a/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseDialog.kt +++ b/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseDialog.kt @@ -15,7 +15,8 @@ import com.android.systemui.statusbar.phone.SystemUIDialog class SensorUseDialog( context: Context, val sensor: Int, - val clickListener: DialogInterface.OnClickListener + val clickListener: DialogInterface.OnClickListener, + val dismissListener: DialogInterface.OnDismissListener ) : SystemUIDialog(context) { // TODO move to onCreate (b/200815309) @@ -69,6 +70,8 @@ class SensorUseDialog( context.getString(com.android.internal.R.string .cancel), clickListener) + setOnDismissListener(dismissListener) + setCancelable(false) } } diff --git a/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt b/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt index b0071d92481d..dae375ad7cc7 100644 --- a/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt +++ b/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt @@ -50,7 +50,7 @@ class SensorUseStartedActivity @Inject constructor( private val keyguardStateController: KeyguardStateController, private val keyguardDismissUtil: KeyguardDismissUtil, @Background private val bgHandler: Handler -) : Activity(), DialogInterface.OnClickListener { +) : Activity(), DialogInterface.OnClickListener, DialogInterface.OnDismissListener { companion object { private val LOG_TAG = SensorUseStartedActivity::class.java.simpleName @@ -120,7 +120,7 @@ class SensorUseStartedActivity @Inject constructor( } } - mDialog = SensorUseDialog(this, sensor, this) + mDialog = SensorUseDialog(this, sensor, this, this) mDialog!!.show() } @@ -212,4 +212,8 @@ class SensorUseStartedActivity @Inject constructor( .suppressSensorPrivacyReminders(sensor, suppressed) } } + + override fun onDismiss(dialog: DialogInterface?) { + finish() + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt new file mode 100644 index 000000000000..87b9172dcefc --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.controls.ui + +import android.app.PendingIntent +import android.testing.AndroidTestingRunner +import android.testing.TestableLooper +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.wm.shell.TaskView +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.ArgumentMatchers.eq +import org.mockito.Mock +import org.mockito.Mockito.any +import org.mockito.Mockito.verify +import org.mockito.MockitoAnnotations + +@SmallTest +@RunWith(AndroidTestingRunner::class) +@TestableLooper.RunWithLooper +class DetailDialogTest : SysuiTestCase() { + + @Mock + private lateinit var taskView: TaskView + @Mock + private lateinit var controlViewHolder: ControlViewHolder + @Mock + private lateinit var pendingIntent: PendingIntent + + @Before + fun setUp() { + MockitoAnnotations.initMocks(this) + } + + @Test + fun testPendingIntentIsUnModified() { + // GIVEN the dialog is created with a PendingIntent + val dialog = createDialog(pendingIntent) + + // WHEN the TaskView is initialized + dialog.stateCallback.onInitialized() + + // THEN the PendingIntent used to call startActivity is unmodified by systemui + verify(taskView).startActivity(eq(pendingIntent), any(), any(), any()) + } + + private fun createDialog(pendingIntent: PendingIntent): DetailDialog { + return DetailDialog( + mContext, + taskView, + pendingIntent, + controlViewHolder + ) + } +} diff --git a/services/core/java/com/android/server/BootReceiver.java b/services/core/java/com/android/server/BootReceiver.java index 48f5b51a8404..a0575cf6bab9 100644 --- a/services/core/java/com/android/server/BootReceiver.java +++ b/services/core/java/com/android/server/BootReceiver.java @@ -484,7 +484,9 @@ public class BootReceiver extends BroadcastReceiver { HashMap<String, Long> timestamps = readTimestamps(); try { if (proto) { - db.addFile(TAG_TOMBSTONE_PROTO, tombstone, 0); + if (recordFileTimestamp(tombstone, timestamps)) { + db.addFile(TAG_TOMBSTONE_PROTO, tombstone, 0); + } } else { final String headers = getBootHeadersToLogAndUpdate(); addFileToDropBox(db, timestamps, headers, tombstone.getPath(), LOG_SIZE, @@ -526,16 +528,10 @@ public class BootReceiver extends BroadcastReceiver { if (db == null || !db.isTagEnabled(tag)) return; // Logging disabled File file = new File(filename); - long fileTime = file.lastModified(); - if (fileTime <= 0) return; // File does not exist - - if (timestamps.containsKey(filename) && timestamps.get(filename) == fileTime) { - return; // Already logged this particular file + if (!recordFileTimestamp(file, timestamps)) { + return; } - timestamps.put(filename, fileTime); - - String fileContents = FileUtils.readTextFile(file, maxSize, TAG_TRUNCATED); String text = headers + fileContents + footers; // Create an additional report for system server native crashes, with a special tag. @@ -548,6 +544,19 @@ public class BootReceiver extends BroadcastReceiver { addTextToDropBox(db, tag, text, filename, maxSize); } + private static boolean recordFileTimestamp(File file, HashMap<String, Long> timestamps) { + final long fileTime = file.lastModified(); + if (fileTime <= 0) return false; // File does not exist + + final String filename = file.getPath(); + if (timestamps.containsKey(filename) && timestamps.get(filename) == fileTime) { + return false; // Already logged this particular file + } + + timestamps.put(filename, fileTime); + return true; + } + private static void addTextToDropBox(DropBoxManager db, String tag, String text, String filename, int maxSize) { Slog.i(TAG, "Copying " + filename + " to DropBox (" + tag + ")"); diff --git a/services/core/java/com/android/server/DynamicSystemService.java b/services/core/java/com/android/server/DynamicSystemService.java index e29e894a5cc0..e924012c8892 100644 --- a/services/core/java/com/android/server/DynamicSystemService.java +++ b/services/core/java/com/android/server/DynamicSystemService.java @@ -16,8 +16,9 @@ package com.android.server; +import android.annotation.EnforcePermission; +import android.annotation.RequiresNoPermission; import android.content.Context; -import android.content.pm.PackageManager; import android.gsi.AvbPublicKey; import android.gsi.GsiProgress; import android.gsi.IGsiService; @@ -53,20 +54,12 @@ public class DynamicSystemService extends IDynamicSystemService.Stub { } private IGsiService getGsiService() { - checkPermission(); if (mGsiService != null) { return mGsiService; } return IGsiService.Stub.asInterface(ServiceManager.waitForService("gsiservice")); } - private void checkPermission() { - if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM) - != PackageManager.PERMISSION_GRANTED) { - throw new SecurityException("Requires MANAGE_DYNAMIC_SYSTEM permission"); - } - } - class GsiServiceCallback extends IGsiServiceCallback.Stub { // 0 for success private int mResult = -1; @@ -82,6 +75,7 @@ public class DynamicSystemService extends IDynamicSystemService.Stub { } @Override + @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM) public boolean startInstallation(String dsuSlot) throws RemoteException { IGsiService service = getGsiService(); mGsiService = service; @@ -124,6 +118,7 @@ public class DynamicSystemService extends IDynamicSystemService.Stub { } @Override + @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM) public boolean createPartition(String name, long size, boolean readOnly) throws RemoteException { IGsiService service = getGsiService(); @@ -135,6 +130,7 @@ public class DynamicSystemService extends IDynamicSystemService.Stub { } @Override + @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM) public boolean closePartition() throws RemoteException { IGsiService service = getGsiService(); if (service.closePartition() != 0) { @@ -145,6 +141,7 @@ public class DynamicSystemService extends IDynamicSystemService.Stub { } @Override + @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM) public boolean finishInstallation() throws RemoteException { IGsiService service = getGsiService(); if (service.closeInstall() != 0) { @@ -155,21 +152,25 @@ public class DynamicSystemService extends IDynamicSystemService.Stub { } @Override + @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM) public GsiProgress getInstallationProgress() throws RemoteException { return getGsiService().getInstallProgress(); } @Override + @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM) public boolean abort() throws RemoteException { return getGsiService().cancelGsiInstall(); } @Override + @RequiresNoPermission public boolean isInUse() { return SystemProperties.getBoolean("ro.gsid.image_running", false); } @Override + @RequiresNoPermission public boolean isInstalled() { boolean installed = SystemProperties.getBoolean("gsid.image_installed", false); Slog.i(TAG, "isInstalled(): " + installed); @@ -177,11 +178,13 @@ public class DynamicSystemService extends IDynamicSystemService.Stub { } @Override + @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM) public boolean isEnabled() throws RemoteException { return getGsiService().isGsiEnabled(); } @Override + @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM) public boolean remove() throws RemoteException { try { GsiServiceCallback callback = new GsiServiceCallback(); @@ -197,6 +200,7 @@ public class DynamicSystemService extends IDynamicSystemService.Stub { } @Override + @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM) public boolean setEnable(boolean enable, boolean oneShot) throws RemoteException { IGsiService gsiService = getGsiService(); if (enable) { @@ -220,6 +224,7 @@ public class DynamicSystemService extends IDynamicSystemService.Stub { } @Override + @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM) public boolean setAshmem(ParcelFileDescriptor ashmem, long size) { try { return getGsiService().setGsiAshmem(ashmem, size); @@ -229,6 +234,7 @@ public class DynamicSystemService extends IDynamicSystemService.Stub { } @Override + @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM) public boolean submitFromAshmem(long size) { try { return getGsiService().commitGsiChunkFromAshmem(size); @@ -238,6 +244,7 @@ public class DynamicSystemService extends IDynamicSystemService.Stub { } @Override + @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM) public boolean getAvbPublicKey(AvbPublicKey dst) { try { return getGsiService().getAvbPublicKey(dst) == 0; @@ -247,6 +254,7 @@ public class DynamicSystemService extends IDynamicSystemService.Stub { } @Override + @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM) public long suggestScratchSize() throws RemoteException { return getGsiService().suggestScratchSize(); } diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java index 8551d887e80c..39ac5effe6fa 100644 --- a/services/core/java/com/android/server/NetworkManagementService.java +++ b/services/core/java/com/android/server/NetworkManagementService.java @@ -34,10 +34,6 @@ import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_POWERSAVE; import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_RESTRICTED; import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_STANDBY; import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT; -import static android.net.NetworkStats.SET_DEFAULT; -import static android.net.NetworkStats.STATS_PER_UID; -import static android.net.NetworkStats.TAG_NONE; -import static android.net.TrafficStats.UID_TETHERING; import static com.android.net.module.util.NetworkStatsUtils.LIMIT_GLOBAL_ALERT; @@ -58,7 +54,6 @@ import android.net.NetworkPolicyManager; import android.net.NetworkStack; import android.net.NetworkStats; import android.net.RouteInfo; -import android.net.TetherStatsParcel; import android.net.UidRangeParcel; import android.net.util.NetdService; import android.os.BatteryStats; @@ -1286,40 +1281,9 @@ public class NetworkManagementService extends INetworkManagementService.Stub { private class NetdTetheringStatsProvider extends ITetheringStatsProvider.Stub { @Override public NetworkStats getTetherStats(int how) { - // We only need to return per-UID stats. Per-device stats are already counted by - // interface counters. - if (how != STATS_PER_UID) { - return new NetworkStats(SystemClock.elapsedRealtime(), 0); - } - - final TetherStatsParcel[] tetherStatsVec; - try { - tetherStatsVec = mNetdService.tetherGetStats(); - } catch (RemoteException | ServiceSpecificException e) { - throw new IllegalStateException("problem parsing tethering stats: ", e); - } - - final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), - tetherStatsVec.length); - final NetworkStats.Entry entry = new NetworkStats.Entry(); - - for (TetherStatsParcel tetherStats : tetherStatsVec) { - try { - entry.iface = tetherStats.iface; - entry.uid = UID_TETHERING; - entry.set = SET_DEFAULT; - entry.tag = TAG_NONE; - entry.rxBytes = tetherStats.rxBytes; - entry.rxPackets = tetherStats.rxPackets; - entry.txBytes = tetherStats.txBytes; - entry.txPackets = tetherStats.txPackets; - stats.combineValues(entry); - } catch (ArrayIndexOutOfBoundsException e) { - throw new IllegalStateException("invalid tethering stats " + e); - } - } - - return stats; + // Remove the implementation of NetdTetheringStatsProvider#getTetherStats + // since all callers are migrated to use INetd#tetherGetStats directly. + throw new UnsupportedOperationException(); } @Override @@ -1330,20 +1294,9 @@ public class NetworkManagementService extends INetworkManagementService.Stub { @Override public NetworkStats getNetworkStatsTethering(int how) { - NetworkStack.checkNetworkStackPermission(mContext); - - final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1); - synchronized (mTetheringStatsProviders) { - for (ITetheringStatsProvider provider: mTetheringStatsProviders.keySet()) { - try { - stats.combineAllValues(provider.getTetherStats(how)); - } catch (RemoteException e) { - Log.e(TAG, "Problem reading tethering stats from " + - mTetheringStatsProviders.get(provider) + ": " + e); - } - } - } - return stats; + // Remove the implementation of getNetworkStatsTethering since all callers are migrated + // to use INetd#tetherGetStats directly. + throw new UnsupportedOperationException(); } @Override diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java index 53c8635c4e0a..9546496fd8e8 100644 --- a/services/core/java/com/android/server/StorageManagerService.java +++ b/services/core/java/com/android/server/StorageManagerService.java @@ -3620,8 +3620,12 @@ class StorageManagerService extends IStorageManager.Stub mInstaller.tryMountDataMirror(volumeUuid); } } - } catch (Exception e) { + } catch (RemoteException | Installer.InstallerException e) { Slog.wtf(TAG, e); + // Make sure to re-throw this exception; we must not ignore failure + // to prepare the user storage as it could indicate that encryption + // wasn't successfully set up. + throw new RuntimeException(e); } } diff --git a/services/core/java/com/android/server/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java index 6a7afd90dc96..2d328d8b0949 100644 --- a/services/core/java/com/android/server/VcnManagementService.java +++ b/services/core/java/com/android/server/VcnManagementService.java @@ -539,7 +539,13 @@ public class VcnManagementService extends IVcnManagementService.Stub { @GuardedBy("mLock") private void notifyAllPolicyListenersLocked() { for (final PolicyListenerBinderDeath policyListener : mRegisteredPolicyListeners.values()) { - Binder.withCleanCallingIdentity(() -> policyListener.mListener.onPolicyChanged()); + Binder.withCleanCallingIdentity(() -> { + try { + policyListener.mListener.onPolicyChanged(); + } catch (RemoteException e) { + logDbg("VcnStatusCallback threw on VCN status change", e); + } + }); } } @@ -548,8 +554,13 @@ public class VcnManagementService extends IVcnManagementService.Stub { @NonNull ParcelUuid subGroup, @VcnStatusCode int statusCode) { for (final VcnStatusCallbackInfo cbInfo : mRegisteredStatusCallbacks.values()) { if (isCallbackPermissioned(cbInfo, subGroup)) { - Binder.withCleanCallingIdentity( - () -> cbInfo.mCallback.onVcnStatusChanged(statusCode)); + Binder.withCleanCallingIdentity(() -> { + try { + cbInfo.mCallback.onVcnStatusChanged(statusCode); + } catch (RemoteException e) { + logDbg("VcnStatusCallback threw on VCN status change", e); + } + }); } } } @@ -1222,13 +1233,17 @@ public class VcnManagementService extends IVcnManagementService.Stub { // Notify all registered StatusCallbacks for this subGroup for (VcnStatusCallbackInfo cbInfo : mRegisteredStatusCallbacks.values()) { if (isCallbackPermissioned(cbInfo, mSubGroup)) { - Binder.withCleanCallingIdentity( - () -> - cbInfo.mCallback.onGatewayConnectionError( - gatewayConnectionName, - errorCode, - exceptionClass, - exceptionMessage)); + Binder.withCleanCallingIdentity(() -> { + try { + cbInfo.mCallback.onGatewayConnectionError( + gatewayConnectionName, + errorCode, + exceptionClass, + exceptionMessage); + } catch (RemoteException e) { + logDbg("VcnStatusCallback threw on VCN status change", e); + } + }); } } } diff --git a/services/core/java/com/android/server/VpnManagerService.java b/services/core/java/com/android/server/VpnManagerService.java index b48e21e4e2c6..7b8cce54c8a7 100644 --- a/services/core/java/com/android/server/VpnManagerService.java +++ b/services/core/java/com/android/server/VpnManagerService.java @@ -340,17 +340,18 @@ public class VpnManagerService extends IVpnManager.Stub { * <p>This is designed to serve the VpnManager only; settings-based VPN profiles are managed * exclusively by the Settings app, and passed into the platform at startup time. * + * @return A unique key corresponding to this session. * @throws IllegalArgumentException if no profile was found for the given package name. * @hide */ @Override - public void startVpnProfile(@NonNull String packageName) { + public String startVpnProfile(@NonNull String packageName) { final int callingUid = Binder.getCallingUid(); verifyCallingUidAndPackage(packageName, callingUid); final int user = UserHandle.getUserId(callingUid); synchronized (mVpns) { throwIfLockdownEnabled(); - mVpns.get(user).startVpnProfile(packageName); + return mVpns.get(user).startVpnProfile(packageName); } } diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java index 2eb59b28c3e9..54987cf04a50 100644 --- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java +++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java @@ -29,7 +29,7 @@ import android.media.AudioDeviceInfo; import android.media.AudioManager; import android.media.AudioRoutesInfo; import android.media.AudioSystem; -import android.media.BtProfileConnectionInfo; +import android.media.BluetoothProfileConnectionInfo; import android.media.IAudioRoutesObserver; import android.media.ICapturePresetDevicesRoleDispatcher; import android.media.ICommunicationDeviceDispatcher; @@ -517,12 +517,12 @@ import java.util.concurrent.atomic.AtomicBoolean; /*package*/ static final class BtDeviceChangedData { final @Nullable BluetoothDevice mNewDevice; final @Nullable BluetoothDevice mPreviousDevice; - final @NonNull BtProfileConnectionInfo mInfo; + final @NonNull BluetoothProfileConnectionInfo mInfo; final @NonNull String mEventSource; BtDeviceChangedData(@Nullable BluetoothDevice newDevice, @Nullable BluetoothDevice previousDevice, - @NonNull BtProfileConnectionInfo info, @NonNull String eventSource) { + @NonNull BluetoothProfileConnectionInfo info, @NonNull String eventSource) { mNewDevice = newDevice; mPreviousDevice = previousDevice; mInfo = info; @@ -554,9 +554,9 @@ import java.util.concurrent.atomic.AtomicBoolean; mDevice = device; mState = state; mProfile = d.mInfo.getProfile(); - mSupprNoisy = d.mInfo.getSuppressNoisyIntent(); + mSupprNoisy = d.mInfo.isSuppressNoisyIntent(); mVolume = d.mInfo.getVolume(); - mIsLeOutput = d.mInfo.getIsLeOutput(); + mIsLeOutput = d.mInfo.isLeOutput(); mEventSource = d.mEventSource; mAudioSystemDevice = audioDevice; mMusicDevice = AudioSystem.DEVICE_NONE; @@ -627,7 +627,7 @@ import java.util.concurrent.atomic.AtomicBoolean; audioDevice = AudioSystem.DEVICE_OUT_HEARING_AID; break; case BluetoothProfile.LE_AUDIO: - if (d.mInfo.getIsLeOutput()) { + if (d.mInfo.isLeOutput()) { audioDevice = AudioSystem.DEVICE_OUT_BLE_HEADSET; } else { audioDevice = AudioSystem.DEVICE_IN_BLE_HEADSET; diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index e00c8a39074a..070725ed0603 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -83,7 +83,7 @@ import android.media.AudioPlaybackConfiguration; import android.media.AudioRecordingConfiguration; import android.media.AudioRoutesInfo; import android.media.AudioSystem; -import android.media.BtProfileConnectionInfo; +import android.media.BluetoothProfileConnectionInfo; import android.media.IAudioFocusDispatcher; import android.media.IAudioModeDispatcher; import android.media.IAudioRoutesObserver; @@ -6301,14 +6301,14 @@ public class AudioService extends IAudioService.Stub * See AudioManager.handleBluetoothActiveDeviceChanged(...) */ public void handleBluetoothActiveDeviceChanged(BluetoothDevice newDevice, - BluetoothDevice previousDevice, @NonNull BtProfileConnectionInfo info) { + BluetoothDevice previousDevice, @NonNull BluetoothProfileConnectionInfo info) { if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.BLUETOOTH_STACK) != PackageManager.PERMISSION_GRANTED) { throw new SecurityException("Bluetooth is the only caller allowed"); } if (info == null) { - throw new IllegalArgumentException("Illegal null BtProfileConnectionInfo for device " - + previousDevice + " -> " + newDevice); + throw new IllegalArgumentException("Illegal null BluetoothProfileConnectionInfo for" + + " device " + previousDevice + " -> " + newDevice); } final int profile = info.getProfile(); if (profile != BluetoothProfile.A2DP && profile != BluetoothProfile.A2DP_SINK diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java index 9273a5d5cf9c..1c299356a48c 100644 --- a/services/core/java/com/android/server/audio/BtHelper.java +++ b/services/core/java/com/android/server/audio/BtHelper.java @@ -31,7 +31,7 @@ import android.content.Intent; import android.media.AudioDeviceAttributes; import android.media.AudioManager; import android.media.AudioSystem; -import android.media.BtProfileConnectionInfo; +import android.media.BluetoothProfileConnectionInfo; import android.os.Binder; import android.os.UserHandle; import android.provider.Settings; @@ -495,11 +495,13 @@ public class BtHelper { if (state == BluetoothProfile.STATE_CONNECTED) { mDeviceBroker.queueOnBluetoothActiveDeviceChanged( new AudioDeviceBroker.BtDeviceChangedData(btDevice, null, - new BtProfileConnectionInfo(profile), "mBluetoothProfileServiceListener")); + new BluetoothProfileConnectionInfo(profile), + "mBluetoothProfileServiceListener")); } else { mDeviceBroker.queueOnBluetoothActiveDeviceChanged( new AudioDeviceBroker.BtDeviceChangedData(null, btDevice, - new BtProfileConnectionInfo(profile), "mBluetoothProfileServiceListener")); + new BluetoothProfileConnectionInfo(profile), + "mBluetoothProfileServiceListener")); } } diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java index 3d5abfe83394..a0c5aa364f0d 100644 --- a/services/core/java/com/android/server/clipboard/ClipboardService.java +++ b/services/core/java/com/android/server/clipboard/ClipboardService.java @@ -571,7 +571,7 @@ public class ClipboardService extends SystemService { final boolean canCopyIntoProfile = !hasRestriction( UserManager.DISALLOW_SHARE_INTO_MANAGED_PROFILE, id); if (canCopyIntoProfile) { - setPrimaryClipInternalLocked( + setPrimaryClipInternalNoClassifyLocked( getClipboardLocked(id), clip, uid, sourcePackage); } } @@ -639,7 +639,7 @@ public class ClipboardService extends SystemService { clipboard.primaryClipListeners.getBroadcastItem(i) .dispatchPrimaryClipChanged(); } - } catch (RemoteException e) { + } catch (RemoteException | SecurityException e) { // The RemoteCallbackList will take care of removing // the dead object for us. } diff --git a/services/core/java/com/android/server/clipboard/OWNERS b/services/core/java/com/android/server/clipboard/OWNERS index 5449df908051..0d5dbf9acac3 100644 --- a/services/core/java/com/android/server/clipboard/OWNERS +++ b/services/core/java/com/android/server/clipboard/OWNERS @@ -1 +1,3 @@ per-file EmulatorClipboardMonitor.java = bohu@google.com,lfy@google.com,rkir@google.com + +olilan@google.com diff --git a/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java b/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java index a5024ffd761f..603f20633cfb 100644 --- a/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java +++ b/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java @@ -24,7 +24,6 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkPolicy.LIMIT_DISABLED; import static android.net.NetworkPolicy.WARNING_DISABLED; -import static android.net.NetworkTemplate.OEM_MANAGED_ALL; import static android.provider.Settings.Global.NETWORK_DEFAULT_DAILY_MULTIPATH_QUOTA_BYTES; import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; @@ -94,6 +93,7 @@ public class MultipathPolicyTracker { private static String TAG = MultipathPolicyTracker.class.getSimpleName(); private static final boolean DBG = false; + private static final long MIN_THRESHOLD_BYTES = 2 * 1_048_576L; // 2MiB // This context is for the current user. private final Context mContext; @@ -278,15 +278,11 @@ public class MultipathPolicyTracker { } private NetworkIdentity getTemplateMatchingNetworkIdentity(NetworkCapabilities nc) { - return new NetworkIdentity( - ConnectivityManager.TYPE_MOBILE, - 0 /* subType, unused for template matching */, - subscriberId, - null /* networkId, unused for matching mobile networks */, - !nc.hasCapability(NET_CAPABILITY_NOT_ROAMING), - !nc.hasCapability(NET_CAPABILITY_NOT_METERED), - false /* defaultNetwork, templates should have DEFAULT_NETWORK_ALL */, - OEM_MANAGED_ALL); + return new NetworkIdentity.Builder().setType(ConnectivityManager.TYPE_MOBILE) + .setSubscriberId(subscriberId) + .setRoaming(!nc.hasCapability(NET_CAPABILITY_NOT_ROAMING)) + .setMetered(!nc.hasCapability(NET_CAPABILITY_NOT_METERED)) + .build(); } private long getRemainingDailyBudget(long limitBytes, @@ -375,7 +371,7 @@ public class MultipathPolicyTracker { // This will only be called if the total quota for the day changed, not if usage changed // since last time, so even if this is called very often the budget will not snap to 0 // as soon as there are less than 2MB left for today. - if (budget > NetworkStatsManager.MIN_THRESHOLD_BYTES) { + if (budget > MIN_THRESHOLD_BYTES) { if (DBG) { Log.d(TAG, "Setting callback for " + budget + " bytes on network " + network); } diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java index 9a9c3ea05d19..3fb49e412ed2 100644 --- a/services/core/java/com/android/server/connectivity/Vpn.java +++ b/services/core/java/com/android/server/connectivity/Vpn.java @@ -151,6 +151,7 @@ import java.util.Objects; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; +import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; @@ -203,6 +204,7 @@ public class Vpn { private final NetworkInfo mNetworkInfo; private int mLegacyState; @VisibleForTesting protected String mPackage; + private String mSessionKey; private int mOwnerUID; private boolean mIsPackageTargetingAtLeastQ; @VisibleForTesting @@ -1302,6 +1304,7 @@ public class Vpn { .setLegacyType(ConnectivityManager.TYPE_VPN) .setLegacyTypeName("VPN") .setBypassableVpn(mConfig.allowBypass && !mLockdown) + .setVpnRequiresValidation(mConfig.requiresInternetValidation) .build(); capsBuilder.setOwnerUid(mOwnerUID); @@ -2503,6 +2506,7 @@ public class Vpn { mProfile = profile; mIpSecManager = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE); mNetworkCallback = new VpnIkev2Utils.Ikev2VpnNetworkCallback(TAG, this); + mSessionKey = UUID.randomUUID().toString(); } @Override @@ -2824,6 +2828,7 @@ public class Vpn { */ private void disconnectVpnRunner() { mActiveNetwork = null; + mSessionKey = null; mIsRunning = false; resetIkeState(); @@ -3314,7 +3319,7 @@ public class Vpn { * * @param packageName the package name of the app provisioning this profile */ - public synchronized void startVpnProfile(@NonNull String packageName) { + public synchronized String startVpnProfile(@NonNull String packageName) { requireNonNull(packageName, "No package name provided"); enforceNotRestrictedUser(); @@ -3332,6 +3337,7 @@ public class Vpn { } startVpnProfilePrivileged(profile, packageName); + return mSessionKey; } finally { Binder.restoreCallingIdentity(token); } @@ -3363,6 +3369,7 @@ public class Vpn { } mConfig.startTime = SystemClock.elapsedRealtime(); mConfig.proxyInfo = profile.proxy; + mConfig.requiresInternetValidation = profile.requiresInternetValidation; switch (profile.type) { case VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS: diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java index c27293c3cc09..c12522b43f2a 100755 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java @@ -75,6 +75,8 @@ abstract class HdmiCecLocalDevice { protected int mLastKeycode = HdmiCecKeycode.UNSUPPORTED_KEYCODE; protected int mLastKeyRepeatCount = 0; + HdmiCecStandbyModeHandler mStandbyHandler; + // Stores recent changes to the active source in the CEC network. private final ArrayBlockingQueue<HdmiCecController.Dumpable> mActiveSourceHistory = new ArrayBlockingQueue<>(MAX_HDMI_ACTIVE_SOURCE_HISTORY); @@ -263,6 +265,11 @@ abstract class HdmiCecLocalDevice { if (dest != mAddress && dest != Constants.ADDR_BROADCAST) { return Constants.NOT_HANDLED; } + if (mService.isPowerStandby() + && !mService.isWakeUpMessageReceived() + && mStandbyHandler.handleCommand(message)) { + return Constants.HANDLED; + } // Cache incoming message if it is included in the list of cacheable opcodes. mCecMessageCache.cacheMessage(message); return onMessage(message); @@ -829,17 +836,12 @@ abstract class HdmiCecLocalDevice { protected int handleVendorCommandWithId(HdmiCecMessage message) { byte[] params = message.getParams(); int vendorId = HdmiUtils.threeBytesToInt(params); - if (vendorId == mService.getVendorId()) { - if (!mService.invokeVendorCommandListenersOnReceived( - mDeviceType, message.getSource(), message.getDestination(), params, true)) { - return Constants.ABORT_REFUSED; - } - } else if (message.getDestination() != Constants.ADDR_BROADCAST - && message.getSource() != Constants.ADDR_UNREGISTERED) { - Slog.v(TAG, "Wrong direct vendor command. Replying with <Feature Abort>"); - return Constants.ABORT_UNRECOGNIZED_OPCODE; - } else { + if (message.getDestination() == Constants.ADDR_BROADCAST + || message.getSource() == Constants.ADDR_UNREGISTERED) { Slog.v(TAG, "Wrong broadcast vendor command. Ignoring"); + } else if (!mService.invokeVendorCommandListenersOnReceived( + mDeviceType, message.getSource(), message.getDestination(), params, true)) { + return Constants.ABORT_REFUSED; } return Constants.HANDLED; } diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java index 0bb128536b42..c549b5598b67 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java @@ -112,6 +112,7 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { mService.readBooleanSetting(Global.HDMI_CEC_SWITCH_ENABLED, false); mSystemAudioControlFeatureEnabled = mService.readBooleanSetting(Global.HDMI_SYSTEM_AUDIO_CONTROL_ENABLED, true); + mStandbyHandler = new HdmiCecStandbyModeHandler(service, this); } private static final String SHORT_AUDIO_DESCRIPTOR_CONFIG_PATH = "/vendor/etc/sadConfig.xml"; diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java index 37ee76b7c615..40718585c484 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java @@ -64,6 +64,7 @@ public class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource { HdmiCecLocalDevicePlayback(HdmiControlService service) { super(service, HdmiDeviceInfo.DEVICE_PLAYBACK); + mStandbyHandler = new HdmiCecStandbyModeHandler(service, this); } @Override diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java index 6e7a2a0eb229..3d218cffc5df 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java @@ -91,8 +91,6 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { @GuardedBy("mLock") private boolean mSystemAudioMute = false; - private final HdmiCecStandbyModeHandler mStandbyHandler; - // If true, do not do routing control/send active source for internal source. // Set to true when the device was woken up by <Text/Image View On>. private boolean mSkipRoutingControl; diff --git a/services/core/java/com/android/server/hdmi/HdmiCecStandbyModeHandler.java b/services/core/java/com/android/server/hdmi/HdmiCecStandbyModeHandler.java index 6f7473d60121..1c296e5b5640 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecStandbyModeHandler.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecStandbyModeHandler.java @@ -16,6 +16,7 @@ package com.android.server.hdmi; +import android.hardware.hdmi.HdmiDeviceInfo; import android.util.SparseArray; /** @@ -56,7 +57,8 @@ public final class HdmiCecStandbyModeHandler { private final class AutoOnHandler implements CecMessageHandler { @Override public boolean handle(HdmiCecMessage message) { - if (!mTv.getAutoWakeup()) { + HdmiCecLocalDeviceTv tv = (HdmiCecLocalDeviceTv) mDevice; + if (!tv.getAutoWakeup()) { mAborterRefused.handle(message); return true; } @@ -78,7 +80,7 @@ public final class HdmiCecStandbyModeHandler { } private final HdmiControlService mService; - private final HdmiCecLocalDeviceTv mTv; + private final HdmiCecLocalDevice mDevice; private final SparseArray<CecMessageHandler> mCecMessageHandlers = new SparseArray<>(); private final CecMessageHandler mDefaultHandler = new Aborter( @@ -92,13 +94,7 @@ public final class HdmiCecStandbyModeHandler { private final UserControlProcessedHandler mUserControlProcessedHandler = new UserControlProcessedHandler(); - public HdmiCecStandbyModeHandler(HdmiControlService service, HdmiCecLocalDeviceTv tv) { - mService = service; - mTv = tv; - - addHandler(Constants.MESSAGE_IMAGE_VIEW_ON, mAutoOnHandler); - addHandler(Constants.MESSAGE_TEXT_VIEW_ON, mAutoOnHandler); - + private void addCommonHandlers() { addHandler(Constants.MESSAGE_ACTIVE_SOURCE, mBystander); addHandler(Constants.MESSAGE_REQUEST_ACTIVE_SOURCE, mBystander); addHandler(Constants.MESSAGE_ROUTING_CHANGE, mBystander); @@ -112,19 +108,6 @@ public final class HdmiCecStandbyModeHandler { addHandler(Constants.MESSAGE_SYSTEM_AUDIO_MODE_STATUS, mBystander); addHandler(Constants.MESSAGE_REPORT_AUDIO_STATUS, mBystander); - // If TV supports the following messages during power-on, ignore them and do nothing, - // else reply with <Feature Abort>["Unrecognized Opcode"] - // <Deck Status>, <Tuner Device Status>, <Tuner Cleared Status>, <Timer Status> - addHandler(Constants.MESSAGE_RECORD_STATUS, mBystander); - - // If TV supports the following messages during power-on, reply with <Feature Abort>["Not - // in correct mode to respond"], else reply with <Feature Abort>["Unrecognized Opcode"] - // <Give Tuner Device Status>, <Select Digital Service>, <Tuner Step Decrement>, - // <Tuner Stem Increment>, <Menu Status>. - addHandler(Constants.MESSAGE_RECORD_TV_SCREEN, mAborterIncorrectMode); - addHandler(Constants.MESSAGE_INITIATE_ARC, mAborterIncorrectMode); - addHandler(Constants.MESSAGE_TERMINATE_ARC, mAborterIncorrectMode); - addHandler(Constants.MESSAGE_GIVE_PHYSICAL_ADDRESS, mBypasser); addHandler(Constants.MESSAGE_GET_MENU_LANGUAGE, mBypasser); addHandler(Constants.MESSAGE_REPORT_PHYSICAL_ADDRESS, mBypasser); @@ -133,6 +116,7 @@ public final class HdmiCecStandbyModeHandler { addHandler(Constants.MESSAGE_SET_OSD_NAME, mBypasser); addHandler(Constants.MESSAGE_DEVICE_VENDOR_ID, mBypasser); addHandler(Constants.MESSAGE_REPORT_POWER_STATUS, mBypasser); + addHandler(Constants.MESSAGE_GIVE_FEATURES, mBypasser); addHandler(Constants.MESSAGE_USER_CONTROL_PRESSED, mUserControlProcessedHandler); @@ -144,6 +128,34 @@ public final class HdmiCecStandbyModeHandler { addHandler(Constants.MESSAGE_SET_SYSTEM_AUDIO_MODE, mAborterIncorrectMode); } + private void addTvHandlers() { + addHandler(Constants.MESSAGE_IMAGE_VIEW_ON, mAutoOnHandler); + addHandler(Constants.MESSAGE_TEXT_VIEW_ON, mAutoOnHandler); + + // If TV supports the following messages during power-on, ignore them and do nothing, + // else reply with <Feature Abort>["Unrecognized Opcode"] + // <Deck Status>, <Tuner Device Status>, <Tuner Cleared Status>, <Timer Status> + addHandler(Constants.MESSAGE_RECORD_STATUS, mBystander); + + // If TV supports the following messages during power-on, reply with <Feature Abort>["Not + // in correct mode to respond"], else reply with <Feature Abort>["Unrecognized Opcode"] + // <Give Tuner Device Status>, <Select Digital Service>, <Tuner Step Decrement>, + // <Tuner Stem Increment>, <Menu Status>. + addHandler(Constants.MESSAGE_RECORD_TV_SCREEN, mAborterIncorrectMode); + addHandler(Constants.MESSAGE_INITIATE_ARC, mAborterIncorrectMode); + addHandler(Constants.MESSAGE_TERMINATE_ARC, mAborterIncorrectMode); + } + + public HdmiCecStandbyModeHandler(HdmiControlService service, HdmiCecLocalDevice device) { + mService = service; + mDevice = device; + + addCommonHandlers(); + if (mDevice.getType() == HdmiDeviceInfo.DEVICE_TV) { + addTvHandlers(); + } + } + private void addHandler(int opcode, CecMessageHandler handler) { mCecMessageHandlers.put(opcode, handler); } diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java index a571dc06db97..8dadf5a8d20d 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -1582,11 +1582,11 @@ public class HdmiControlService extends SystemService { class VendorCommandListenerRecord implements IBinder.DeathRecipient { private final IHdmiVendorCommandListener mListener; - private final int mDeviceType; + private final int mVendorId; - public VendorCommandListenerRecord(IHdmiVendorCommandListener listener, int deviceType) { + VendorCommandListenerRecord(IHdmiVendorCommandListener listener, int vendorId) { mListener = listener; - mDeviceType = deviceType; + mVendorId = vendorId; } @Override @@ -2077,10 +2077,10 @@ public class HdmiControlService extends SystemService { } @Override - public void addVendorCommandListener(final IHdmiVendorCommandListener listener, - final int deviceType) { + public void addVendorCommandListener( + final IHdmiVendorCommandListener listener, final int vendorId) { initBinderCall(); - HdmiControlService.this.addVendorCommandListener(listener, deviceType); + HdmiControlService.this.addVendorCommandListener(listener, vendorId); } @Override @@ -3219,8 +3219,9 @@ public class HdmiControlService extends SystemService { } } - private void addVendorCommandListener(IHdmiVendorCommandListener listener, int deviceType) { - VendorCommandListenerRecord record = new VendorCommandListenerRecord(listener, deviceType); + @VisibleForTesting + void addVendorCommandListener(IHdmiVendorCommandListener listener, int vendorId) { + VendorCommandListenerRecord record = new VendorCommandListenerRecord(listener, vendorId); try { listener.asBinder().linkToDeath(record, 0); } catch (RemoteException e) { @@ -3239,8 +3240,14 @@ public class HdmiControlService extends SystemService { return false; } for (VendorCommandListenerRecord record : mVendorCommandListenerRecords) { - if (record.mDeviceType != deviceType) { - continue; + if (hasVendorId) { + int vendorId = + ((params[0] & 0xFF) << 16) + + ((params[1] & 0xFF) << 8) + + (params[2] & 0xFF); + if (record.mVendorId != vendorId) { + continue; + } } try { record.mListener.onReceived(srcAddress, destAddress, params, hasVendorId); diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java index 3e52f5e07e62..5b7f5c85c1bb 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -2837,7 +2837,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub return; } final IBinder targetWindow = mImeTargetWindowMap.get(startInputToken); - if (targetWindow != null && mLastImeTargetWindow != targetWindow) { + if (targetWindow != null) { mWindowManagerInternal.updateInputMethodTargetWindow(token, targetWindow); } mLastImeTargetWindow = targetWindow; diff --git a/services/core/java/com/android/server/net/NetworkPolicyLogger.java b/services/core/java/com/android/server/net/NetworkPolicyLogger.java index 81106b1a5ca7..b66c4668f2a0 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyLogger.java +++ b/services/core/java/com/android/server/net/NetworkPolicyLogger.java @@ -15,12 +15,14 @@ */ package com.android.server.net; +import static android.net.ConnectivityManager.BLOCKED_REASON_NONE; import static android.net.INetd.FIREWALL_CHAIN_DOZABLE; import static android.net.INetd.FIREWALL_CHAIN_POWERSAVE; import static android.net.INetd.FIREWALL_CHAIN_RESTRICTED; import static android.net.INetd.FIREWALL_CHAIN_STANDBY; import static android.net.INetd.FIREWALL_RULE_ALLOW; import static android.net.INetd.FIREWALL_RULE_DENY; +import static android.net.NetworkPolicyManager.ALLOWED_REASON_NONE; import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_DOZABLE; import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_POWERSAVE; import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_RESTRICTED; @@ -29,6 +31,7 @@ import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT; import static android.os.PowerExemptionManager.reasonCodeToString; import static android.os.Process.INVALID_UID; +import android.annotation.Nullable; import android.app.ActivityManager; import android.app.ActivityManager.ProcessCapability; import android.net.NetworkPolicyManager; @@ -81,13 +84,18 @@ public class NetworkPolicyLogger { private final Object mLock = new Object(); - void networkBlocked(int uid, UidBlockedState uidBlockedState) { + void networkBlocked(int uid, @Nullable UidBlockedState uidBlockedState) { synchronized (mLock) { if (LOGD || uid == mDebugUid) { Slog.d(TAG, "Blocked state of uid: " + uidBlockedState.toString()); } - mNetworkBlockedBuffer.networkBlocked(uid, uidBlockedState.blockedReasons, - uidBlockedState.allowedReasons, uidBlockedState.effectiveBlockedReasons); + if (uidBlockedState == null) { + mNetworkBlockedBuffer.networkBlocked(uid, BLOCKED_REASON_NONE, ALLOWED_REASON_NONE, + BLOCKED_REASON_NONE); + } else { + mNetworkBlockedBuffer.networkBlocked(uid, uidBlockedState.blockedReasons, + uidBlockedState.allowedReasons, uidBlockedState.effectiveBlockedReasons); + } } } diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index 6a66d5b4d95e..6a00d06440b9 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -24,7 +24,6 @@ import static android.Manifest.permission.MANAGE_SUBSCRIPTION_PLANS; import static android.Manifest.permission.NETWORK_SETTINGS; import static android.Manifest.permission.NETWORK_STACK; import static android.Manifest.permission.OBSERVE_NETWORK_POLICY; -import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY; import static android.Manifest.permission.READ_PHONE_STATE; import static android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE; import static android.app.PendingIntent.FLAG_IMMUTABLE; @@ -99,9 +98,6 @@ import static android.net.NetworkStats.METERED_YES; import static android.net.NetworkTemplate.MATCH_CARRIER; import static android.net.NetworkTemplate.MATCH_MOBILE; import static android.net.NetworkTemplate.MATCH_WIFI; -import static android.net.NetworkTemplate.buildTemplateCarrierMetered; -import static android.net.NetworkTemplate.buildTemplateMobileAll; -import static android.net.TrafficStats.MB_IN_BYTES; import static android.net.netstats.provider.NetworkStatsProvider.QUOTA_UNLIMITED; import static android.os.Trace.TRACE_TAG_NETWORK; import static android.provider.Settings.Global.NETPOLICY_OVERRIDE_ENABLED; @@ -130,7 +126,6 @@ import static com.android.internal.util.XmlUtils.writeIntAttribute; import static com.android.internal.util.XmlUtils.writeLongAttribute; import static com.android.internal.util.XmlUtils.writeStringAttribute; import static com.android.net.module.util.NetworkStatsUtils.LIMIT_GLOBAL_ALERT; -import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_UPDATED; import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT; import static org.xmlpull.v1.XmlPullParser.END_TAG; @@ -171,7 +166,6 @@ import android.net.ConnectivityManager.NetworkCallback; import android.net.INetworkManagementEventObserver; import android.net.INetworkPolicyListener; import android.net.INetworkPolicyManager; -import android.net.INetworkStatsService; import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkIdentity; @@ -184,7 +178,6 @@ import android.net.NetworkStack; import android.net.NetworkStateSnapshot; import android.net.NetworkTemplate; import android.net.TelephonyNetworkSpecifier; -import android.net.TrafficStats; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiManager; import android.os.BestClock; @@ -1012,10 +1005,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { userFilter.addAction(ACTION_USER_REMOVED); mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler); - // listen for stats update events - final IntentFilter statsFilter = new IntentFilter(ACTION_NETWORK_STATS_UPDATED); - mContext.registerReceiver( - mStatsReceiver, statsFilter, READ_NETWORK_USAGE_HISTORY, mHandler); + // listen for stats updated callbacks for interested network types. + mNetworkStats.registerUsageCallback(new NetworkTemplate.Builder(MATCH_MOBILE).build(), + 0 /* thresholdBytes */, new HandlerExecutor(mHandler), mStatsCallback); + mNetworkStats.registerUsageCallback(new NetworkTemplate.Builder(MATCH_WIFI).build(), + 0 /* thresholdBytes */, new HandlerExecutor(mHandler), mStatsCallback); // listen for restrict background changes from notifications final IntentFilter allowFilter = new IntentFilter(ACTION_ALLOW_BACKGROUND); @@ -1220,19 +1214,16 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { }; /** - * Receiver that watches for {@link NetworkStatsManager} updates, which we - * use to check against {@link NetworkPolicy#warningBytes}. + * Listener that watches for {@link NetworkStatsManager} updates, which + * NetworkPolicyManagerService uses to check against {@link NetworkPolicy#warningBytes}. */ - private final NetworkStatsBroadcastReceiver mStatsReceiver = - new NetworkStatsBroadcastReceiver(); - private class NetworkStatsBroadcastReceiver extends BroadcastReceiver { - private boolean mIsAnyIntentReceived = false; - @Override - public void onReceive(Context context, Intent intent) { - // on background handler thread, and verified - // READ_NETWORK_USAGE_HISTORY permission above. + private final StatsCallback mStatsCallback = new StatsCallback(); + private class StatsCallback extends NetworkStatsManager.UsageCallback { + private boolean mIsAnyCallbackReceived = false; - mIsAnyIntentReceived = true; + @Override + public void onThresholdReached(int networkType, String subscriberId) { + mIsAnyCallbackReceived = true; synchronized (mNetworkPoliciesSecondLock) { updateNetworkRulesNL(); @@ -1242,11 +1233,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } /** - * Return whether any {@code ACTION_NETWORK_STATS_UPDATED} intent is received. + * Return whether any callback is received. * Used to determine if NetworkStatsService is ready. */ - public boolean isAnyIntentReceived() { - return mIsAnyIntentReceived; + public boolean isAnyCallbackReceived() { + return mIsAnyCallbackReceived; } }; @@ -1350,7 +1341,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { }; /** - * Check {@link NetworkPolicy} against current {@link INetworkStatsService} + * Check {@link NetworkPolicy} against current {@link NetworkStatsManager} * to show visible notifications as needed. */ @GuardedBy("mNetworkPoliciesSecondLock") @@ -1473,7 +1464,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { // Skip if not ready. NetworkStatsService will block public API calls until it is // ready. To prevent NPMS be blocked on that, skip and fail fast instead. - if (!mStatsReceiver.isAnyIntentReceived()) return null; + if (!mStatsCallback.isAnyCallbackReceived()) return null; final List<NetworkStats.Bucket> stats = mDeps.getNetworkUidBytes(template, start, end); for (final NetworkStats.Bucket entry : stats) { @@ -2323,7 +2314,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { if (dataWarningConfig == WARNING_DISABLED) { return WARNING_DISABLED; } else { - return dataWarningConfig * MB_IN_BYTES; + return DataUnit.MEBIBYTES.toBytes(dataWarningConfig); } } @@ -2348,6 +2339,18 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } /** + * Template to match all metered carrier networks with the given IMSI. + * + * @hide + */ + public static NetworkTemplate buildTemplateCarrierMetered(@NonNull String subscriberId) { + Objects.requireNonNull(subscriberId); + return new NetworkTemplate.Builder(MATCH_CARRIER) + .setSubscriberIds(Set.of(subscriberId)) + .setMeteredness(METERED_YES).build(); + } + + /** * Update the given {@link NetworkPolicy} based on any carrier-provided * defaults via {@link SubscriptionPlan} or {@link CarrierConfigManager}. * Leaves policy untouched if the user has modified it. @@ -2750,7 +2753,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { out.startTag(null, TAG_NETWORK_POLICY); writeIntAttribute(out, ATTR_NETWORK_TEMPLATE, template.getMatchRule()); - final String subscriberId = template.getSubscriberId(); + final String subscriberId = template.getSubscriberIds().isEmpty() ? null + : template.getSubscriberIds().iterator().next(); if (subscriberId != null) { out.attribute(null, ATTR_SUBSCRIBER_ID, subscriberId); } @@ -3127,7 +3131,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } // When two normalized templates conflict, prefer the most // restrictive policy - policy.template = NetworkTemplate.normalize(policy.template, mMergedSubscriberIds); + policy.template = normalizeTemplate(policy.template, mMergedSubscriberIds); final NetworkPolicy existing = mNetworkPolicy.get(policy.template); if (existing == null || existing.compareTo(policy) > 0) { if (existing != null) { @@ -3138,6 +3142,46 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } + /** + * Examine the given template and normalize it. + * We pick the "lowest" merged subscriber as the primary + * for key purposes, and expand the template to match all other merged + * subscribers. + * + * There can be multiple merged subscriberIds for multi-SIM devices. + * + * <p> + * For example, given an incoming template matching B, and the currently + * active merge set [A,B], we'd return a new template that primarily matches + * A, but also matches B. + */ + private static NetworkTemplate normalizeTemplate(@NonNull NetworkTemplate template, + @NonNull List<String[]> mergedList) { + // Now there are several types of network which uses Subscriber Id to store network + // information. For instance: + // 1. A merged carrier wifi network which has TYPE_WIFI with a Subscriber Id. + // 2. A typical cellular network could have TYPE_MOBILE with a Subscriber Id. + + if (template.getSubscriberIds().isEmpty()) return template; + + for (final String[] merged : mergedList) { + // TODO: Handle incompatible subscriberIds if that happens in practice. + for (final String subscriberId : template.getSubscriberIds()) { + if (com.android.net.module.util.CollectionUtils.contains(merged, subscriberId)) { + // Requested template subscriber is part of the merged group; return + // a template that matches all merged subscribers. + return new NetworkTemplate.Builder(template.getMatchRule()) + .setWifiNetworkKeys(template.getWifiNetworkKeys()) + .setSubscriberIds(Set.of(merged)) + .setMeteredness(template.getMeteredness()) + .build(); + } + } + } + + return template; + } + @Override public void snoozeLimit(NetworkTemplate template) { mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); @@ -3492,9 +3536,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { plans.add(SubscriptionPlan.Builder .createRecurringMonthly(ZonedDateTime.parse("2007-03-14T00:00:00.000Z")) .setTitle("G-Mobile") - .setDataLimit(5 * TrafficStats.GB_IN_BYTES, + .setDataLimit(DataUnit.GIBIBYTES.toBytes(5), SubscriptionPlan.LIMIT_BEHAVIOR_BILLED) - .setDataUsage(1 * TrafficStats.GB_IN_BYTES, + .setDataUsage(DataUnit.GIBIBYTES.toBytes(1), ZonedDateTime.now().minusHours(36).toInstant().toEpochMilli()) .build()); plans.add(SubscriptionPlan.Builder @@ -3502,15 +3546,15 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { .setTitle("G-Mobile Happy") .setDataLimit(SubscriptionPlan.BYTES_UNLIMITED, SubscriptionPlan.LIMIT_BEHAVIOR_BILLED) - .setDataUsage(5 * TrafficStats.GB_IN_BYTES, + .setDataUsage(DataUnit.GIBIBYTES.toBytes(5), ZonedDateTime.now().minusHours(36).toInstant().toEpochMilli()) .build()); plans.add(SubscriptionPlan.Builder .createRecurringMonthly(ZonedDateTime.parse("2017-03-14T00:00:00.000Z")) .setTitle("G-Mobile, Charged after limit") - .setDataLimit(5 * TrafficStats.GB_IN_BYTES, + .setDataLimit(DataUnit.GIBIBYTES.toBytes(5), SubscriptionPlan.LIMIT_BEHAVIOR_BILLED) - .setDataUsage(5 * TrafficStats.GB_IN_BYTES, + .setDataUsage(DataUnit.GIBIBYTES.toBytes(5), ZonedDateTime.now().minusHours(36).toInstant().toEpochMilli()) .build()); } else if ("month_soft".equals(fake)) { @@ -3519,25 +3563,25 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { .setTitle("G-Mobile is the carriers name who this plan belongs to") .setSummary("Crazy unlimited bandwidth plan with incredibly long title " + "that should be cut off to prevent UI from looking terrible") - .setDataLimit(5 * TrafficStats.GB_IN_BYTES, + .setDataLimit(DataUnit.GIBIBYTES.toBytes(5), SubscriptionPlan.LIMIT_BEHAVIOR_THROTTLED) - .setDataUsage(1 * TrafficStats.GB_IN_BYTES, + .setDataUsage(DataUnit.GIBIBYTES.toBytes(1), ZonedDateTime.now().minusHours(1).toInstant().toEpochMilli()) .build()); plans.add(SubscriptionPlan.Builder .createRecurringMonthly(ZonedDateTime.parse("2017-03-14T00:00:00.000Z")) .setTitle("G-Mobile, Throttled after limit") - .setDataLimit(5 * TrafficStats.GB_IN_BYTES, + .setDataLimit(DataUnit.GIBIBYTES.toBytes(5), SubscriptionPlan.LIMIT_BEHAVIOR_THROTTLED) - .setDataUsage(5 * TrafficStats.GB_IN_BYTES, + .setDataUsage(DataUnit.GIBIBYTES.toBytes(5), ZonedDateTime.now().minusHours(1).toInstant().toEpochMilli()) .build()); plans.add(SubscriptionPlan.Builder .createRecurringMonthly(ZonedDateTime.parse("2017-03-14T00:00:00.000Z")) .setTitle("G-Mobile, No data connection after limit") - .setDataLimit(5 * TrafficStats.GB_IN_BYTES, + .setDataLimit(DataUnit.GIBIBYTES.toBytes(5), SubscriptionPlan.LIMIT_BEHAVIOR_DISABLED) - .setDataUsage(5 * TrafficStats.GB_IN_BYTES, + .setDataUsage(DataUnit.GIBIBYTES.toBytes(5), ZonedDateTime.now().minusHours(1).toInstant().toEpochMilli()) .build()); @@ -3545,25 +3589,25 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { plans.add(SubscriptionPlan.Builder .createRecurringMonthly(ZonedDateTime.parse("2007-03-14T00:00:00.000Z")) .setTitle("G-Mobile is the carriers name who this plan belongs to") - .setDataLimit(5 * TrafficStats.GB_IN_BYTES, + .setDataLimit(DataUnit.GIBIBYTES.toBytes(5), SubscriptionPlan.LIMIT_BEHAVIOR_THROTTLED) - .setDataUsage(6 * TrafficStats.GB_IN_BYTES, + .setDataUsage(DataUnit.GIBIBYTES.toBytes(6), ZonedDateTime.now().minusHours(1).toInstant().toEpochMilli()) .build()); plans.add(SubscriptionPlan.Builder .createRecurringMonthly(ZonedDateTime.parse("2017-03-14T00:00:00.000Z")) .setTitle("G-Mobile, Throttled after limit") - .setDataLimit(5 * TrafficStats.GB_IN_BYTES, + .setDataLimit(DataUnit.GIBIBYTES.toBytes(5), SubscriptionPlan.LIMIT_BEHAVIOR_THROTTLED) - .setDataUsage(5 * TrafficStats.GB_IN_BYTES, + .setDataUsage(DataUnit.GIBIBYTES.toBytes(5), ZonedDateTime.now().minusHours(1).toInstant().toEpochMilli()) .build()); plans.add(SubscriptionPlan.Builder .createRecurringMonthly(ZonedDateTime.parse("2017-03-14T00:00:00.000Z")) .setTitle("G-Mobile, No data connection after limit") - .setDataLimit(5 * TrafficStats.GB_IN_BYTES, + .setDataLimit(DataUnit.GIBIBYTES.toBytes(5), SubscriptionPlan.LIMIT_BEHAVIOR_DISABLED) - .setDataUsage(5 * TrafficStats.GB_IN_BYTES, + .setDataUsage(DataUnit.GIBIBYTES.toBytes(5), ZonedDateTime.now().minusHours(1).toInstant().toEpochMilli()) .build()); @@ -3577,9 +3621,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { .createNonrecurring(ZonedDateTime.now().minusDays(20), ZonedDateTime.now().plusDays(10)) .setTitle("G-Mobile") - .setDataLimit(512 * TrafficStats.MB_IN_BYTES, + .setDataLimit(DataUnit.MEBIBYTES.toBytes(512), SubscriptionPlan.LIMIT_BEHAVIOR_DISABLED) - .setDataUsage(100 * TrafficStats.MB_IN_BYTES, + .setDataUsage(DataUnit.MEBIBYTES.toBytes(100), ZonedDateTime.now().minusHours(3).toInstant().toEpochMilli()) .build()); } else if ("prepaid_crazy".equals(fake)) { @@ -3587,9 +3631,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { .createNonrecurring(ZonedDateTime.now().minusDays(20), ZonedDateTime.now().plusDays(10)) .setTitle("G-Mobile Anytime") - .setDataLimit(512 * TrafficStats.MB_IN_BYTES, + .setDataLimit(DataUnit.MEBIBYTES.toBytes(512), SubscriptionPlan.LIMIT_BEHAVIOR_DISABLED) - .setDataUsage(100 * TrafficStats.MB_IN_BYTES, + .setDataUsage(DataUnit.MEBIBYTES.toBytes(100), ZonedDateTime.now().minusHours(3).toInstant().toEpochMilli()) .build()); plans.add(SubscriptionPlan.Builder @@ -3597,9 +3641,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { ZonedDateTime.now().plusDays(20)) .setTitle("G-Mobile Nickel Nights") .setSummary("5¢/GB between 1-5AM") - .setDataLimit(5 * TrafficStats.GB_IN_BYTES, + .setDataLimit(DataUnit.GIBIBYTES.toBytes(5), SubscriptionPlan.LIMIT_BEHAVIOR_THROTTLED) - .setDataUsage(15 * TrafficStats.MB_IN_BYTES, + .setDataUsage(DataUnit.MEBIBYTES.toBytes(15), ZonedDateTime.now().minusHours(30).toInstant().toEpochMilli()) .build()); plans.add(SubscriptionPlan.Builder @@ -3607,9 +3651,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { ZonedDateTime.now().plusDays(20)) .setTitle("G-Mobile Bonus 3G") .setSummary("Unlimited 3G data") - .setDataLimit(1 * TrafficStats.GB_IN_BYTES, + .setDataLimit(DataUnit.GIBIBYTES.toBytes(1), SubscriptionPlan.LIMIT_BEHAVIOR_THROTTLED) - .setDataUsage(300 * TrafficStats.MB_IN_BYTES, + .setDataUsage(DataUnit.MEBIBYTES.toBytes(300), ZonedDateTime.now().minusHours(1).toInstant().toEpochMilli()) .build()); } else if ("unlimited".equals(fake)) { @@ -3619,7 +3663,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { .setTitle("G-Mobile Awesome") .setDataLimit(SubscriptionPlan.BYTES_UNLIMITED, SubscriptionPlan.LIMIT_BEHAVIOR_THROTTLED) - .setDataUsage(50 * TrafficStats.MB_IN_BYTES, + .setDataUsage(DataUnit.MEBIBYTES.toBytes(50), ZonedDateTime.now().minusHours(3).toInstant().toEpochMilli()) .build()); } @@ -5470,7 +5514,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { private long getTotalBytes(NetworkTemplate template, long start, long end) { // Skip if not ready. NetworkStatsService will block public API calls until it is // ready. To prevent NPMS be blocked on that, skip and fail fast instead. - if (!mStatsReceiver.isAnyIntentReceived()) return 0; + if (!mStatsCallback.isAnyCallbackReceived()) return 0; return mDeps.getNetworkTotalBytes(template, start, end); } @@ -5589,7 +5633,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { NetworkPolicy[] policies = getNetworkPolicies(mContext.getOpPackageName()); NetworkTemplate templateCarrier = subscriber != null ? buildTemplateCarrierMetered(subscriber) : null; - NetworkTemplate templateMobile = buildTemplateMobileAll(subscriber); + NetworkTemplate templateMobile = subscriber != null + ? new NetworkTemplate.Builder(MATCH_MOBILE) + .setSubscriberIds(Set.of(subscriber)) + .setMeteredness(android.net.NetworkStats.METERED_YES) + .build() : null; for (NetworkPolicy policy : policies) { // All policies loaded from disk will be carrier templates, and setting will also only // set carrier templates, but we clear mobile templates just in case one is set by diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java index 8fd545f271f3..5a5f9ef3b6aa 100644 --- a/services/core/java/com/android/server/pm/Installer.java +++ b/services/core/java/com/android/server/pm/Installer.java @@ -40,7 +40,6 @@ import com.android.server.SystemService; import dalvik.system.BlockGuard; import dalvik.system.VMRuntime; -import java.io.FileDescriptor; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -681,28 +680,6 @@ public class Installer extends SystemService { } } - public void installApkVerity(String filePath, FileDescriptor verityInput, int contentSize) - throws InstallerException { - if (!checkBeforeRemote()) return; - BlockGuard.getVmPolicy().onPathAccess(filePath); - try { - mInstalld.installApkVerity(filePath, verityInput, contentSize); - } catch (Exception e) { - throw InstallerException.from(e); - } - } - - public void assertFsverityRootHashMatches(String filePath, @NonNull byte[] expectedHash) - throws InstallerException { - if (!checkBeforeRemote()) return; - BlockGuard.getVmPolicy().onPathAccess(filePath); - try { - mInstalld.assertFsverityRootHashMatches(filePath, expectedHash); - } catch (Exception e) { - throw InstallerException.from(e); - } - } - public boolean reconcileSecondaryDexFile(String apkPath, String packageName, int uid, String[] isas, @Nullable String volumeUuid, int flags) throws InstallerException { for (int i = 0; i < isas.length; i++) { diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index bc28cffbcbfc..2d3cbfe61b1a 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -12118,14 +12118,14 @@ public class PackageManagerService extends IPackageManager.Stub * Returns if forced apk verification can be skipped for the whole package, including splits. */ private boolean canSkipForcedPackageVerification(AndroidPackage pkg) { - if (!canSkipForcedApkVerification(pkg.getBaseApkPath())) { + if (!VerityUtils.hasFsverity(pkg.getBaseApkPath())) { return false; } // TODO: Allow base and splits to be verified individually. String[] splitCodePaths = pkg.getSplitCodePaths(); if (!ArrayUtils.isEmpty(splitCodePaths)) { for (int i = 0; i < splitCodePaths.length; i++) { - if (!canSkipForcedApkVerification(splitCodePaths[i])) { + if (!VerityUtils.hasFsverity(splitCodePaths[i])) { return false; } } @@ -12134,33 +12134,6 @@ public class PackageManagerService extends IPackageManager.Stub } /** - * Returns if forced apk verification can be skipped, depending on current FSVerity setup and - * whether the apk contains signed root hash. Note that the signer's certificate still needs to - * match one in a trusted source, and should be done separately. - */ - private boolean canSkipForcedApkVerification(String apkPath) { - if (!PackageManagerServiceUtils.isLegacyApkVerityEnabled()) { - return VerityUtils.hasFsverity(apkPath); - } - - try { - final byte[] rootHashObserved = VerityUtils.generateApkVerityRootHash(apkPath); - if (rootHashObserved == null) { - return false; // APK does not contain Merkle tree root hash. - } - synchronized (mInstallLock) { - // Returns whether the observed root hash matches what kernel has. - mInstaller.assertFsverityRootHashMatches(apkPath, rootHashObserved); - return true; - } - } catch (InstallerException | IOException | DigestException | - NoSuchAlgorithmException e) { - Slog.w(TAG, "Error in fsverity check. Fallback to full apk verification.", e); - } - return false; - } - - /** * Adds a new package to the internal data structures during platform initialization. * <p>After adding, the package is known to the system and available for querying. * <p>For packages located on the device ROM [eg. packages located in /system, /vendor, @@ -21192,9 +21165,7 @@ public class PackageManagerService extends IPackageManager.Stub */ private void setUpFsVerityIfPossible(AndroidPackage pkg) throws InstallerException, PrepareFailure, IOException, DigestException, NoSuchAlgorithmException { - final boolean standardMode = PackageManagerServiceUtils.isApkVerityEnabled(); - final boolean legacyMode = PackageManagerServiceUtils.isLegacyApkVerityEnabled(); - if (!standardMode && !legacyMode) { + if (!PackageManagerServiceUtils.isApkVerityEnabled()) { return; } @@ -21205,39 +21176,25 @@ public class PackageManagerService extends IPackageManager.Stub // Collect files we care for fs-verity setup. ArrayMap<String, String> fsverityCandidates = new ArrayMap<>(); - if (legacyMode) { - synchronized (mLock) { - final PackageSetting ps = mSettings.getPackageLPr(pkg.getPackageName()); - if (ps != null && ps.isPrivileged()) { - fsverityCandidates.put(pkg.getBaseApkPath(), null); - if (pkg.getSplitCodePaths() != null) { - for (String splitPath : pkg.getSplitCodePaths()) { - fsverityCandidates.put(splitPath, null); - } - } - } - } - } else { - // NB: These files will become only accessible if the signing key is loaded in kernel's - // .fs-verity keyring. - fsverityCandidates.put(pkg.getBaseApkPath(), - VerityUtils.getFsveritySignatureFilePath(pkg.getBaseApkPath())); + // NB: These files will become only accessible if the signing key is loaded in kernel's + // .fs-verity keyring. + fsverityCandidates.put(pkg.getBaseApkPath(), + VerityUtils.getFsveritySignatureFilePath(pkg.getBaseApkPath())); - final String dmPath = DexMetadataHelper.buildDexMetadataPathForApk( - pkg.getBaseApkPath()); - if (new File(dmPath).exists()) { - fsverityCandidates.put(dmPath, VerityUtils.getFsveritySignatureFilePath(dmPath)); - } + final String dmPath = DexMetadataHelper.buildDexMetadataPathForApk( + pkg.getBaseApkPath()); + if (new File(dmPath).exists()) { + fsverityCandidates.put(dmPath, VerityUtils.getFsveritySignatureFilePath(dmPath)); + } - if (pkg.getSplitCodePaths() != null) { - for (String path : pkg.getSplitCodePaths()) { - fsverityCandidates.put(path, VerityUtils.getFsveritySignatureFilePath(path)); + if (pkg.getSplitCodePaths() != null) { + for (String path : pkg.getSplitCodePaths()) { + fsverityCandidates.put(path, VerityUtils.getFsveritySignatureFilePath(path)); - final String splitDmPath = DexMetadataHelper.buildDexMetadataPathForApk(path); - if (new File(splitDmPath).exists()) { - fsverityCandidates.put(splitDmPath, - VerityUtils.getFsveritySignatureFilePath(splitDmPath)); - } + final String splitDmPath = DexMetadataHelper.buildDexMetadataPathForApk(path); + if (new File(splitDmPath).exists()) { + fsverityCandidates.put(splitDmPath, + VerityUtils.getFsveritySignatureFilePath(splitDmPath)); } } } @@ -21246,40 +21203,14 @@ public class PackageManagerService extends IPackageManager.Stub final String filePath = entry.getKey(); final String signaturePath = entry.getValue(); - if (!legacyMode) { - // fs-verity is optional for now. Only set up if signature is provided. - if (new File(signaturePath).exists() && !VerityUtils.hasFsverity(filePath)) { - try { - VerityUtils.setUpFsverity(filePath, signaturePath); - } catch (IOException e) { - throw new PrepareFailure(PackageManager.INSTALL_FAILED_BAD_SIGNATURE, - "Failed to enable fs-verity: " + e); - } - } - continue; - } - - // In legacy mode, fs-verity can only be enabled by process with CAP_SYS_ADMIN. - final VerityUtils.SetupResult result = VerityUtils.generateApkVeritySetupData(filePath); - if (result.isOk()) { - if (Build.IS_DEBUGGABLE) Slog.i(TAG, "Enabling verity to " + filePath); - final FileDescriptor fd = result.getUnownedFileDescriptor(); + // fs-verity is optional for now. Only set up if signature is provided. + if (new File(signaturePath).exists() && !VerityUtils.hasFsverity(filePath)) { try { - final byte[] rootHash = VerityUtils.generateApkVerityRootHash(filePath); - try { - // A file may already have fs-verity, e.g. when reused during a split - // install. If the measurement succeeds, no need to attempt to set up. - mInstaller.assertFsverityRootHashMatches(filePath, rootHash); - } catch (InstallerException e) { - mInstaller.installApkVerity(filePath, fd, result.getContentSize()); - mInstaller.assertFsverityRootHashMatches(filePath, rootHash); - } - } finally { - IoUtils.closeQuietly(fd); + VerityUtils.setUpFsverity(filePath, signaturePath); + } catch (IOException e) { + throw new PrepareFailure(PackageManager.INSTALL_FAILED_BAD_SIGNATURE, + "Failed to enable fs-verity: " + e); } - } else if (result.isFailed()) { - throw new PrepareFailure(PackageManager.INSTALL_FAILED_BAD_SIGNATURE, - "Failed to generate verity"); } } } diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java index 8b5abf3afe51..8970049d85cc 100644 --- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java +++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java @@ -591,12 +591,6 @@ public class PackageManagerServiceUtils { /** Default is to not use fs-verity since it depends on kernel support. */ private static final int FSVERITY_DISABLED = 0; - /** - * Experimental implementation targeting priv apps, with Android specific kernel patches to - * extend fs-verity. - */ - private static final int FSVERITY_LEGACY = 1; - /** Standard fs-verity. */ private static final int FSVERITY_ENABLED = 2; @@ -607,10 +601,6 @@ public class PackageManagerServiceUtils { == FSVERITY_ENABLED; } - static boolean isLegacyApkVerityEnabled() { - return SystemProperties.getInt("ro.apk_verity.mode", FSVERITY_DISABLED) == FSVERITY_LEGACY; - } - /** Returns true to force apk verification if the package is considered privileged. */ static boolean isApkVerificationForced(@Nullable PackageSetting ps) { // TODO(b/154310064): re-enable. diff --git a/services/core/java/com/android/server/pm/UserDataPreparer.java b/services/core/java/com/android/server/pm/UserDataPreparer.java index 045a295da965..504769064808 100644 --- a/services/core/java/com/android/server/pm/UserDataPreparer.java +++ b/services/core/java/com/android/server/pm/UserDataPreparer.java @@ -22,6 +22,7 @@ import android.content.Context; import android.content.pm.UserInfo; import android.os.Environment; import android.os.FileUtils; +import android.os.RecoverySystem; import android.os.storage.StorageManager; import android.os.storage.VolumeInfo; import android.os.SystemProperties; @@ -115,6 +116,13 @@ class UserDataPreparer { // Try one last time; if we fail again we're really in trouble prepareUserDataLI(volumeUuid, userId, userSerial, flags | StorageManager.FLAG_STORAGE_DE, false); + } else { + try { + Log.e(TAG, "prepareUserData failed", e); + RecoverySystem.rebootPromptAndWipeUserData(mContext, "prepareUserData failed"); + } catch (IOException e2) { + throw new RuntimeException("error rebooting into recovery", e2); + } } } } diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java index d4e7573bf216..1fa948cef216 100644 --- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java +++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java @@ -22,14 +22,13 @@ import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED; import static android.content.pm.PermissionInfo.PROTECTION_DANGEROUS; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_WIFI; -import static android.net.NetworkIdentity.OEM_PAID; -import static android.net.NetworkIdentity.OEM_PRIVATE; import static android.net.NetworkStats.METERED_YES; import static android.net.NetworkTemplate.MATCH_ETHERNET; import static android.net.NetworkTemplate.MATCH_MOBILE; import static android.net.NetworkTemplate.MATCH_WIFI; import static android.net.NetworkTemplate.OEM_MANAGED_ALL; -import static android.net.NetworkTemplate.getAllCollapsedRatTypes; +import static android.net.NetworkTemplate.OEM_MANAGED_PAID; +import static android.net.NetworkTemplate.OEM_MANAGED_PRIVATE; import static android.os.Debug.getIonHeapsSizeKb; import static android.os.Process.LAST_SHARED_APPLICATION_GID; import static android.os.Process.getUidForPid; @@ -1168,13 +1167,14 @@ public class StatsPullAtomService extends SystemService { Slog.e(TAG, "baseline is null for " + atomTag + ", return."); return StatsManager.PULL_SKIP; } + final NetworkStatsExt diff = new NetworkStatsExt( - item.stats.subtract(baseline.stats).removeEmptyEntries(), item.transports, + removeEmptyEntries(item.stats.subtract(baseline.stats)), item.transports, item.slicedByFgbg, item.slicedByTag, item.slicedByMetered, item.ratType, item.subInfo, item.oemManaged); // If no diff, skip. - if (diff.stats.size() == 0) continue; + if (!diff.stats.iterator().hasNext()) continue; switch (atomTag) { case FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED: @@ -1193,6 +1193,17 @@ public class StatsPullAtomService extends SystemService { return StatsManager.PULL_SUCCESS; } + @NonNull private static NetworkStats removeEmptyEntries(NetworkStats stats) { + NetworkStats ret = new NetworkStats(0, 1); + for (NetworkStats.Entry e : stats) { + if (e.getRxBytes() != 0 || e.getRxPackets() != 0 || e.getTxBytes() != 0 + || e.getTxPackets() != 0 || e.getOperations() != 0) { + ret = ret.addEntry(e); + } + } + return ret; + } + private void addNetworkStats(int atomTag, @NonNull List<StatsEvent> ret, @NonNull NetworkStatsExt statsExt) { for (NetworkStats.Entry entry : statsExt.stats) { @@ -1227,11 +1238,11 @@ public class StatsPullAtomService extends SystemService { private void addDataUsageBytesTransferAtoms(@NonNull NetworkStatsExt statsExt, @NonNull List<StatsEvent> pulledData) { - // Workaround for 5G NSA mode, see {@link NetworkTemplate#NETWORK_TYPE_5G_NSA}. + // Workaround for 5G NSA mode, see {@link NetworkStatsManager#NETWORK_TYPE_5G_NSA}. // 5G NSA mode means the primary cell is LTE with a secondary connection to an // NR cell. To mitigate risk, NetworkStats is currently storing this state as // a fake RAT type rather than storing the boolean separately. - final boolean is5GNsa = statsExt.ratType == NetworkTemplate.NETWORK_TYPE_5G_NSA; + final boolean is5GNsa = statsExt.ratType == NetworkStatsManager.NETWORK_TYPE_5G_NSA; // Report NR connected in 5G non-standalone mode, or if the RAT type is NR to begin with. final boolean isNR = is5GNsa || statsExt.ratType == TelephonyManager.NETWORK_TYPE_NR; @@ -1266,7 +1277,8 @@ public class StatsPullAtomService extends SystemService { @NonNull private List<NetworkStatsExt> getDataUsageBytesTransferSnapshotForOemManaged() { final int[] matchRules = new int[] {MATCH_ETHERNET, MATCH_MOBILE, MATCH_WIFI}; - final int[] oemManagedTypes = new int[] {OEM_PAID | OEM_PRIVATE, OEM_PAID, OEM_PRIVATE}; + final int[] oemManagedTypes = new int[] {OEM_MANAGED_PAID | OEM_MANAGED_PRIVATE, + OEM_MANAGED_PAID, OEM_MANAGED_PRIVATE}; final List<NetworkStatsExt> ret = new ArrayList<>(); @@ -1340,12 +1352,12 @@ public class StatsPullAtomService extends SystemService { NetworkStatsUtils.fromPublicNetworkStats(queryNonTaggedStats); if (!includeTags) return nonTaggedStats; - final android.app.usage.NetworkStats quaryTaggedStats = + final android.app.usage.NetworkStats queryTaggedStats = mNetworkStatsManager.queryTaggedSummary(template, currentTimeInMillis - elapsedMillisSinceBoot - bucketDuration, currentTimeInMillis); final NetworkStats taggedStats = - NetworkStatsUtils.fromPublicNetworkStats(quaryTaggedStats); + NetworkStatsUtils.fromPublicNetworkStats(queryTaggedStats); return nonTaggedStats.add(taggedStats); } @@ -1370,6 +1382,27 @@ public class StatsPullAtomService extends SystemService { return ret; } + /** + * Return all supported collapsed RAT types that could be returned by + * {@link android.app.usage.NetworkStatsManager#getCollapsedRatType(int)}. + */ + @NonNull + private static int[] getAllCollapsedRatTypes() { + final int[] ratTypes = TelephonyManager.getAllNetworkTypes(); + final HashSet<Integer> collapsedRatTypes = new HashSet<>(); + for (final int ratType : ratTypes) { + collapsedRatTypes.add(NetworkStatsManager.getCollapsedRatType(ratType)); + } + // Add NETWORK_TYPE_5G_NSA to the returned list since 5G NSA is a virtual RAT type and + // it is not in TelephonyManager#NETWORK_TYPE_* constants. + // See {@link NetworkStatsManager#NETWORK_TYPE_5G_NSA}. + collapsedRatTypes.add( + NetworkStatsManager.getCollapsedRatType(NetworkStatsManager.NETWORK_TYPE_5G_NSA)); + // Ensure that unknown type is returned. + collapsedRatTypes.add(TelephonyManager.NETWORK_TYPE_UNKNOWN); + return com.android.net.module.util.CollectionUtils.toIntArray(collapsedRatTypes); + } + @NonNull private NetworkStats sliceNetworkStatsByUid(@NonNull NetworkStats stats) { return sliceNetworkStats(stats, (entry) -> { @@ -1442,13 +1475,9 @@ public class StatsPullAtomService extends SystemService { */ @NonNull private NetworkStats sliceNetworkStats(@NonNull NetworkStats stats, @NonNull Function<NetworkStats.Entry, NetworkStats.Entry> slicer) { - NetworkStats ret = new NetworkStats(stats.getElapsedRealtime(), 1); - NetworkStats.Entry entry = new NetworkStats.Entry(); + NetworkStats ret = new NetworkStats(0, 1); for (NetworkStats.Entry e : stats) { - if (slicer != null) { - entry = slicer.apply(e); - } - ret = ret.addEntry(entry); + ret = ret.addEntry(slicer.apply(e)); } return ret; } diff --git a/services/core/java/com/android/server/tracing/TracingServiceProxy.java b/services/core/java/com/android/server/tracing/TracingServiceProxy.java index ff2f08bc4a50..27c0beee9c27 100644 --- a/services/core/java/com/android/server/tracing/TracingServiceProxy.java +++ b/services/core/java/com/android/server/tracing/TracingServiceProxy.java @@ -15,34 +15,56 @@ */ package com.android.server.tracing; +import android.Manifest; +import android.annotation.NonNull; +import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; +import android.content.pm.ServiceInfo; import android.os.Binder; +import android.os.IMessenger; +import android.os.Message; +import android.os.ParcelFileDescriptor; +import android.os.ParcelFileDescriptor.AutoCloseInputStream; +import android.os.ParcelFileDescriptor.AutoCloseOutputStream; import android.os.UserHandle; +import android.service.tracing.TraceReportService; import android.tracing.ITracingServiceProxy; +import android.tracing.TraceReportParams; import android.util.Log; +import android.util.LruCache; +import android.util.Slog; +import com.android.internal.infra.ServiceConnector; import com.android.server.SystemService; +import java.io.IOException; + /** * TracingServiceProxy is the system_server intermediary between the Perfetto tracing daemon and the - * system tracing app Traceur. + * other components (e.g. system tracing app Traceur, trace reporting apps). * * Access to this service is restricted via SELinux. Normal apps do not have access. * * @hide */ public class TracingServiceProxy extends SystemService { - private static final String TAG = "TracingServiceProxy"; - public static final String TRACING_SERVICE_PROXY_BINDER_NAME = "tracing.proxy"; - + private static final String TAG = "TracingServiceProxy"; private static final String TRACING_APP_PACKAGE_NAME = "com.android.traceur"; private static final String TRACING_APP_ACTIVITY = "com.android.traceur.StopTraceService"; + private static final int MAX_CACHED_REPORTER_SERVICES = 8; + + // The maximum size of the trace allowed if the option |usePipeForTesting| is set. + // Note: this size MUST be smaller than the buffer size of the pipe (i.e. what you can + // write to the pipe without blocking) to avoid system_server blocking on this. + // (on Linux, the minimum value is 4K i.e. 1 minimally sized page). + private static final int MAX_FILE_SIZE_BYTES_TO_PIPE = 1024; + // Keep this in sync with the definitions in TraceService private static final String INTENT_ACTION_NOTIFY_SESSION_STOPPED = "com.android.traceur.NOTIFY_SESSION_STOPPED"; @@ -51,16 +73,22 @@ public class TracingServiceProxy extends SystemService { private final Context mContext; private final PackageManager mPackageManager; + private final LruCache<ComponentName, ServiceConnector<IMessenger>> mCachedReporterServices; private final ITracingServiceProxy.Stub mTracingServiceProxy = new ITracingServiceProxy.Stub() { /** - * Notifies system tracing app that a tracing session has ended. If a session is repurposed - * for use in a bugreport, sessionStolen can be set to indicate that tracing has ended but - * there is no buffer available to dump. - */ + * Notifies system tracing app that a tracing session has ended. If a session is repurposed + * for use in a bugreport, sessionStolen can be set to indicate that tracing has ended but + * there is no buffer available to dump. + */ @Override public void notifyTraceSessionEnded(boolean sessionStolen) { - notifyTraceur(sessionStolen); + TracingServiceProxy.this.notifyTraceur(sessionStolen); + } + + @Override + public void reportTrace(@NonNull TraceReportParams params) { + TracingServiceProxy.this.reportTrace(params); } }; @@ -68,6 +96,7 @@ public class TracingServiceProxy extends SystemService { super(context); mContext = context; mPackageManager = context.getPackageManager(); + mCachedReporterServices = new LruCache<>(MAX_CACHED_REPORTER_SERVICES); } @Override @@ -103,4 +132,119 @@ public class TracingServiceProxy extends SystemService { Log.e(TAG, "Failed to locate Traceur", e); } } + + private void reportTrace(@NonNull TraceReportParams params) { + // We don't need to do any permission checks on the caller because access + // to this service is guarded by SELinux. + ComponentName component = new ComponentName(params.reporterPackageName, + params.reporterClassName); + if (!hasBindServicePermission(component)) { + return; + } + boolean hasDumpPermission = hasPermission(component, Manifest.permission.DUMP); + boolean hasUsageStatsPermission = hasPermission(component, + Manifest.permission.PACKAGE_USAGE_STATS); + if (!hasDumpPermission || !hasUsageStatsPermission) { + return; + } + final long ident = Binder.clearCallingIdentity(); + try { + reportTrace(getOrCreateReporterService(component), params); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + private void reportTrace( + @NonNull ServiceConnector<IMessenger> reporterService, + @NonNull TraceReportParams params) { + reporterService.post(messenger -> { + if (params.usePipeForTesting) { + ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe(); + try (AutoCloseInputStream i = new AutoCloseInputStream(params.fd)) { + try (AutoCloseOutputStream o = new AutoCloseOutputStream(pipe[1])) { + byte[] array = i.readNBytes(MAX_FILE_SIZE_BYTES_TO_PIPE); + if (array.length == MAX_FILE_SIZE_BYTES_TO_PIPE) { + throw new IllegalArgumentException( + "Trace file too large when |usePipeForTesting| is set."); + } + o.write(array); + } + } + params.fd = pipe[0]; + } + + Message message = Message.obtain(); + message.what = TraceReportService.MSG_REPORT_TRACE; + message.obj = params; + messenger.send(message); + }).whenComplete((res, err) -> { + if (err != null) { + Slog.e(TAG, "Failed to report trace", err); + } + try { + params.fd.close(); + } catch (IOException ignored) { + } + }); + } + + private ServiceConnector<IMessenger> getOrCreateReporterService( + @NonNull ComponentName component) { + ServiceConnector<IMessenger> connector = mCachedReporterServices.get(component); + if (connector == null) { + Intent intent = new Intent(); + intent.setComponent(component); + connector = new ServiceConnector.Impl<IMessenger>( + mContext, intent, + Context.BIND_AUTO_CREATE | Context.BIND_WAIVE_PRIORITY, + mContext.getUser().getIdentifier(), IMessenger.Stub::asInterface) { + private static final long DISCONNECT_TIMEOUT_MS = 15_000; + private static final long REQUEST_TIMEOUT_MS = 10_000; + + @Override + protected long getAutoDisconnectTimeoutMs() { + return DISCONNECT_TIMEOUT_MS; + } + + @Override + protected long getRequestTimeoutMs() { + return REQUEST_TIMEOUT_MS; + } + }; + mCachedReporterServices.put(intent.getComponent(), connector); + } + return connector; + } + + private boolean hasPermission(@NonNull ComponentName componentName, + @NonNull String permission) throws SecurityException { + if (mPackageManager.checkPermission(permission, componentName.getPackageName()) + != PackageManager.PERMISSION_GRANTED) { + Slog.e(TAG, + "Trace reporting service " + componentName.toShortString() + " does not have " + + permission + " permission"); + return false; + } + return true; + } + + private boolean hasBindServicePermission(@NonNull ComponentName componentName) { + ServiceInfo info; + try { + info = mPackageManager.getServiceInfo(componentName, 0); + } catch (NameNotFoundException ex) { + Slog.e(TAG, + "Trace reporting service " + componentName.toShortString() + " does not exist"); + return false; + } + if (!Manifest.permission.BIND_TRACE_REPORT_SERVICE.equals(info.permission)) { + Slog.e(TAG, + "Trace reporting service " + componentName.toShortString() + + " does not request " + Manifest.permission.BIND_TRACE_REPORT_SERVICE + + " permission; instead requests " + info.permission); + return false; + } + return true; + } } diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index b52e527b0556..b685d484db79 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -1038,6 +1038,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A pw.print(" forceNewConfig="); pw.println(forceNewConfig); pw.print(prefix); pw.print("mActivityType="); pw.println(activityTypeToString(getActivityType())); + pw.print(prefix); pw.print("mImeInsetsFrozenUntilStartInput="); + pw.println(mImeInsetsFrozenUntilStartInput); if (requestedVrComponent != null) { pw.print(prefix); pw.print("requestedVrComponent="); @@ -4932,6 +4934,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_STOPPED); break; case DESTROYED: + if (app != null && (mVisible || mVisibleRequested)) { + // The app may be died while visible (no PAUSED state). + mAtmService.updateBatteryStats(this, false); + } mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_DESTROYED); // Fall through. case DESTROYING: diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 9335846e7805..bb8d6ef8fb12 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -3969,11 +3969,11 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp * which controls the visibility and animation of the input method window. */ void updateImeInputAndControlTarget(WindowState target) { + if (target != null && target.mActivityRecord != null) { + target.mActivityRecord.mImeInsetsFrozenUntilStartInput = false; + } if (mImeInputTarget != target) { ProtoLog.i(WM_DEBUG_IME, "setInputMethodInputTarget %s", target); - if (target != null && target.mActivityRecord != null) { - target.mActivityRecord.mImeInsetsFrozenUntilStartInput = false; - } setImeInputTarget(target); updateImeControlTarget(); } diff --git a/services/core/java/com/android/server/wm/SurfaceAnimator.java b/services/core/java/com/android/server/wm/SurfaceAnimator.java index c7bf8ecfe949..94f0e24f88c9 100644 --- a/services/core/java/com/android/server/wm/SurfaceAnimator.java +++ b/services/core/java/com/android/server/wm/SurfaceAnimator.java @@ -85,6 +85,8 @@ class SurfaceAnimator { private boolean mAnimationStartDelayed; + private boolean mAnimationFinished; + /** * @param animatable The object to animate. * @param staticAnimationFinishedCallback Callback to invoke when an animation has finished @@ -134,6 +136,7 @@ class SurfaceAnimator { || anim.shouldDeferAnimationFinish(resetAndInvokeFinish))) { resetAndInvokeFinish.run(); } + mAnimationFinished = true; } }; } @@ -289,6 +292,9 @@ class SurfaceAnimator { Slog.w(TAG, "Unable to transfer animation, surface or parent is null"); cancelAnimation(); return; + } else if (from.mAnimationFinished) { + Slog.w(TAG, "Unable to transfer animation, because " + from + " animation is finished"); + return; } endDelayingAnimationStart(); final Transaction t = mAnimatable.getPendingTransaction(); @@ -367,6 +373,7 @@ class SurfaceAnimator { SurfaceControl leash = mLeash; mLeash = null; final boolean scheduleAnim = removeLeash(t, mAnimatable, leash, destroyLeash); + mAnimationFinished = false; if (scheduleAnim) { mService.scheduleAnimationLocked(); } diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp index e7005daf5626..e48b5e17739b 100644 --- a/services/core/jni/Android.bp +++ b/services/core/jni/Android.bp @@ -141,8 +141,8 @@ cc_defaults { "libutils", "libhwui", "libbpf_android", - "libnetdbpf", "libnetdutils", + "libnetworkstats", "libpsi", "libdataloader", "libincfs", diff --git a/services/core/jni/com_android_server_UsbAlsaJackDetector.cpp b/services/core/jni/com_android_server_UsbAlsaJackDetector.cpp index ccb4f5995330..cba54b39fe9a 100644 --- a/services/core/jni/com_android_server_UsbAlsaJackDetector.cpp +++ b/services/core/jni/com_android_server_UsbAlsaJackDetector.cpp @@ -25,7 +25,6 @@ #include <stdio.h> #include <string.h> -#include <asm/byteorder.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> diff --git a/services/core/jni/com_android_server_UsbDescriptorParser.cpp b/services/core/jni/com_android_server_UsbDescriptorParser.cpp index d29d3fcb51d5..9917bcb45c0a 100644 --- a/services/core/jni/com_android_server_UsbDescriptorParser.cpp +++ b/services/core/jni/com_android_server_UsbDescriptorParser.cpp @@ -15,16 +15,14 @@ */ #define LOG_TAG "UsbHostManagerJNI" -#include "utils/Log.h" - +#include <nativehelper/JNIHelp.h> #include <stdlib.h> +#include <usbhost/usbhost.h> +#include <usbhost/usbhost_jni.h> #include "jni.h" -#include <nativehelper/JNIHelp.h> - -#include <usbhost/usbhost.h> +#include "utils/Log.h" -#define MAX_DESCRIPTORS_LENGTH 4096 static const int USB_CONTROL_TRANSFER_TIMEOUT_MS = 200; // com.android.server.usb.descriptors @@ -41,26 +39,9 @@ jbyteArray JNICALL Java_com_android_server_usb_descriptors_UsbDescriptorParser_g } int fd = usb_device_get_fd(device); - if (fd < 0) { - usb_device_close(device); - return NULL; - } - - // from android_hardware_UsbDeviceConnection_get_desc() - jbyte buffer[MAX_DESCRIPTORS_LENGTH]; - lseek(fd, 0, SEEK_SET); - int numBytes = read(fd, buffer, sizeof(buffer)); - jbyteArray ret = NULL; + jbyteArray descriptors = usb_jni_read_descriptors(env, fd); usb_device_close(device); - - if (numBytes > 0) { - ret = env->NewByteArray(numBytes); - env->SetByteArrayRegion(ret, 0, numBytes, buffer); - } else { - ALOGE("error reading descriptors\n"); - } - - return ret; + return descriptors; } jstring JNICALL Java_com_android_server_usb_descriptors_UsbDescriptorParser_getDescriptorString_1native( diff --git a/services/core/jni/com_android_server_UsbDeviceManager.cpp b/services/core/jni/com_android_server_UsbDeviceManager.cpp index 3ab5920d8b59..0a9ce2fed7fc 100644 --- a/services/core/jni/com_android_server_UsbDeviceManager.cpp +++ b/services/core/jni/com_android_server_UsbDeviceManager.cpp @@ -25,7 +25,6 @@ #include "MtpDescriptors.h" #include <stdio.h> -#include <asm/byteorder.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> diff --git a/services/core/jni/com_android_server_UsbHostManager.cpp b/services/core/jni/com_android_server_UsbHostManager.cpp index a629b69c1c27..e29d2ca663f7 100644 --- a/services/core/jni/com_android_server_UsbHostManager.cpp +++ b/services/core/jni/com_android_server_UsbHostManager.cpp @@ -23,7 +23,6 @@ #include "android_runtime/Log.h" #include <stdio.h> -#include <asm/byteorder.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> @@ -31,8 +30,6 @@ #include <usbhost/usbhost.h> -#define MAX_DESCRIPTORS_LENGTH 4096 - namespace android { diff --git a/services/core/jni/com_android_server_net_NetworkStatsService.cpp b/services/core/jni/com_android_server_net_NetworkStatsService.cpp index 5178132e4a2e..f8a81682bdcf 100644 --- a/services/core/jni/com_android_server_net_NetworkStatsService.cpp +++ b/services/core/jni/com_android_server_net_NetworkStatsService.cpp @@ -16,20 +16,18 @@ #define LOG_TAG "NetworkStatsNative" +#include <cutils/qtaguid.h> #include <dirent.h> #include <errno.h> #include <fcntl.h> #include <inttypes.h> -#include <sys/stat.h> -#include <sys/types.h> - -#include "core_jni_helpers.h" #include <jni.h> #include <nativehelper/ScopedUtfChars.h> -#include <utils/misc.h> +#include <sys/stat.h> +#include <sys/types.h> #include <utils/Log.h> +#include <utils/misc.h> -#include "android-base/unique_fd.h" #include "bpf/BpfUtils.h" #include "netdbpf/BpfNetworkStats.h" @@ -104,10 +102,15 @@ static jlong getUidStat(JNIEnv* env, jclass clazz, jint uid, jint type) { } } +static int deleteTagData(JNIEnv* /* env */, jclass /* clazz */, jint uid) { + return qtaguid_deleteTagData(0, uid); +} + static const JNINativeMethod gMethods[] = { {"nativeGetTotalStat", "(I)J", (void*)getTotalStat}, {"nativeGetIfaceStat", "(Ljava/lang/String;I)J", (void*)getIfaceStat}, {"nativeGetUidStat", "(II)J", (void*)getUidStat}, + {"nativeDeleteTagData", "(I)I", (void*)deleteTagData}, }; int register_android_server_net_NetworkStatsService(JNIEnv* env) { diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java b/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java index 37a84f3698c1..1c9d58458629 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java @@ -32,6 +32,7 @@ import android.app.admin.DeviceAdminInfo; import android.app.admin.DevicePolicyManager; import android.app.admin.FactoryResetProtectionPolicy; import android.app.admin.PasswordPolicy; +import android.app.admin.PreferentialNetworkServiceConfig; import android.graphics.Color; import android.os.Bundle; import android.os.PersistableBundle; @@ -294,6 +295,8 @@ class ActiveAdmin { public boolean mAdminCanGrantSensorsPermissions; public boolean mPreferentialNetworkServiceEnabled = DevicePolicyManager.PREFERENTIAL_NETWORK_SERVICE_ENABLED_DEFAULT; + public PreferentialNetworkServiceConfig mPreferentialNetworkServiceConfig = + PreferentialNetworkServiceConfig.DEFAULT; private static final boolean USB_DATA_SIGNALING_ENABLED_DEFAULT = true; boolean mUsbDataSignalingEnabled = USB_DATA_SIGNALING_ENABLED_DEFAULT; diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index a4162ba0e080..564b60825ab0 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -109,6 +109,7 @@ import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE; import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES; import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_DEFAULT; import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE; +import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK; import static android.net.NetworkCapabilities.NET_ENTERPRISE_ID_1; import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK; import static android.provider.Settings.Global.PRIVATE_DNS_SPECIFIER; @@ -180,6 +181,7 @@ import android.app.admin.NetworkEvent; import android.app.admin.ParcelableGranteeMap; import android.app.admin.PasswordMetrics; import android.app.admin.PasswordPolicy; +import android.app.admin.PreferentialNetworkServiceConfig; import android.app.admin.SecurityLog; import android.app.admin.SecurityLog.SecurityEvent; import android.app.admin.StartInstallingUpdateCallback; @@ -3278,14 +3280,14 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { updatePermissionPolicyCache(userId); updateAdminCanGrantSensorsPermissionCache(userId); - final boolean preferentialNetworkServiceEnabled; + final PreferentialNetworkServiceConfig preferentialNetworkServiceConfig; synchronized (getLockObject()) { ActiveAdmin owner = getDeviceOrProfileOwnerAdminLocked(userId); - preferentialNetworkServiceEnabled = owner != null - ? owner.mPreferentialNetworkServiceEnabled - : DevicePolicyManager.PREFERENTIAL_NETWORK_SERVICE_ENABLED_DEFAULT; + preferentialNetworkServiceConfig = owner != null + ? owner.mPreferentialNetworkServiceConfig + : PreferentialNetworkServiceConfig.DEFAULT; } - updateNetworkPreferenceForUser(userId, preferentialNetworkServiceEnabled); + updateNetworkPreferenceForUser(userId, preferentialNetworkServiceConfig); startOwnerService(userId, "start-user"); } @@ -3302,7 +3304,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override void handleStopUser(int userId) { - updateNetworkPreferenceForUser(userId, false); + updateNetworkPreferenceForUser(userId, PreferentialNetworkServiceConfig.DEFAULT); stopOwnerService(userId, "stop-user"); } @@ -11846,7 +11848,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { final CallerIdentity caller = getCallerIdentity(); Preconditions.checkCallAuthorization(isProfileOwner(caller), "Caller is not profile owner;" - + " only profile owner may control the preferntial network service"); + + " only profile owner may control the preferential network service"); synchronized (getLockObject()) { final ActiveAdmin requiredAdmin = getProfileOwnerAdminLocked( caller.getUserId()); @@ -11883,6 +11885,47 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } @Override + public void setPreferentialNetworkServiceConfig( + PreferentialNetworkServiceConfig preferentialNetworkServiceConfig) { + if (!mHasFeature) { + return; + } + final CallerIdentity caller = getCallerIdentity(); + Preconditions.checkCallAuthorization(isProfileOwner(caller), + "Caller is not profile owner;" + + " only profile owner may control the preferential network service"); + synchronized (getLockObject()) { + final ActiveAdmin requiredAdmin = getProfileOwnerAdminLocked( + caller.getUserId()); + if (!requiredAdmin.mPreferentialNetworkServiceConfig.equals( + preferentialNetworkServiceConfig)) { + requiredAdmin.mPreferentialNetworkServiceConfig = preferentialNetworkServiceConfig; + saveSettingsLocked(caller.getUserId()); + } + } + updateNetworkPreferenceForUser(caller.getUserId(), preferentialNetworkServiceConfig); + DevicePolicyEventLogger + .createEvent(DevicePolicyEnums.SET_PREFERENTIAL_NETWORK_SERVICE_ENABLED) + .setBoolean(preferentialNetworkServiceConfig.isEnabled()) + .write(); + } + + @Override + public PreferentialNetworkServiceConfig getPreferentialNetworkServiceConfig() { + if (!mHasFeature) { + return PreferentialNetworkServiceConfig.DEFAULT; + } + + final CallerIdentity caller = getCallerIdentity(); + Preconditions.checkCallAuthorization(isProfileOwner(caller), + "Caller is not profile owner"); + synchronized (getLockObject()) { + final ActiveAdmin requiredAdmin = getProfileOwnerAdminLocked(caller.getUserId()); + return requiredAdmin.mPreferentialNetworkServiceConfig; + } + } + + @Override public void setLockTaskPackages(ComponentName who, String[] packages) throws SecurityException { Objects.requireNonNull(who, "ComponentName is null"); @@ -17538,8 +17581,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!isManagedProfile(userId)) { return; } - int networkPreference = preferentialNetworkServiceEnabled - ? PROFILE_NETWORK_PREFERENCE_ENTERPRISE : PROFILE_NETWORK_PREFERENCE_DEFAULT; ProfileNetworkPreference.Builder preferenceBuilder = new ProfileNetworkPreference.Builder(); if (preferentialNetworkServiceEnabled) { @@ -17556,6 +17597,40 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { null /* executor */, null /* listener */)); } + private void updateNetworkPreferenceForUser(int userId, + PreferentialNetworkServiceConfig preferentialNetworkServiceConfig) { + if (!isManagedProfile(userId)) { + return; + } + ProfileNetworkPreference.Builder preferenceBuilder = + new ProfileNetworkPreference.Builder(); + if (preferentialNetworkServiceConfig.isEnabled()) { + if (preferentialNetworkServiceConfig.isFallbackToDefaultConnectionAllowed()) { + preferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE); + } else { + preferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK); + } + } else { + preferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_DEFAULT); + } + List<Integer> allowedUids = Arrays.stream( + preferentialNetworkServiceConfig.getIncludedUids()).boxed().collect( + Collectors.toList()); + List<Integer> excludedUids = Arrays.stream( + preferentialNetworkServiceConfig.getExcludedUids()).boxed().collect( + Collectors.toList()); + preferenceBuilder.setIncludedUids(allowedUids); + preferenceBuilder.setExcludedUids(excludedUids); + preferenceBuilder.setPreferenceEnterpriseId( + preferentialNetworkServiceConfig.getNetworkId()); + List<ProfileNetworkPreference> preferences = new ArrayList<>(); + preferences.add(preferenceBuilder.build()); + mInjector.binderWithCleanCallingIdentity(() -> + mInjector.getConnectivityManager().setProfileNetworkPreferences( + UserHandle.of(userId), preferences, + null /* executor */, null /* listener */)); + } + @Override public boolean canAdminGrantSensorsPermissionsForUser(int userId) { if (!mHasFeature) { diff --git a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java index 62a16f7f24fd..c5f990d52b82 100644 --- a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java +++ b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java @@ -60,6 +60,12 @@ public final class ProfcollectForwardingService extends SystemService { private static ProfcollectForwardingService sSelfService; private final Handler mHandler = new ProfcollectdHandler(IoThread.getHandler().getLooper()); + private IProviderStatusCallback mProviderStatusCallback = new IProviderStatusCallback.Stub() { + public void onProviderReady() { + mHandler.sendEmptyMessage(ProfcollectdHandler.MESSAGE_REGISTER_SCHEDULERS); + } + }; + public ProfcollectForwardingService(Context context) { super(context); @@ -93,13 +99,23 @@ public final class ProfcollectForwardingService extends SystemService { } BackgroundThread.get().getThreadHandler().post(() -> { if (serviceHasSupportedTraceProvider()) { - registerObservers(); - ProfcollectBGJobService.schedule(getContext()); + registerProviderStatusCallback(); } }); } } + private void registerProviderStatusCallback() { + if (mIProfcollect == null) { + return; + } + try { + mIProfcollect.registerProviderStatusCallback(mProviderStatusCallback); + } catch (RemoteException e) { + Log.e(LOG_TAG, e.getMessage()); + } + } + private boolean serviceHasSupportedTraceProvider() { if (mIProfcollect == null) { return false; @@ -141,6 +157,7 @@ public final class ProfcollectForwardingService extends SystemService { } public static final int MESSAGE_BINDER_CONNECT = 0; + public static final int MESSAGE_REGISTER_SCHEDULERS = 1; @Override public void handleMessage(android.os.Message message) { @@ -148,6 +165,10 @@ public final class ProfcollectForwardingService extends SystemService { case MESSAGE_BINDER_CONNECT: connectNativeService(); break; + case MESSAGE_REGISTER_SCHEDULERS: + registerObservers(); + ProfcollectBGJobService.schedule(getContext()); + break; default: throw new AssertionError("Unknown message: " + message); } diff --git a/services/tests/servicestests/src/com/android/server/audio/AudioDeviceBrokerTest.java b/services/tests/servicestests/src/com/android/server/audio/AudioDeviceBrokerTest.java index 9e1445cf589d..bdea679a3311 100644 --- a/services/tests/servicestests/src/com/android/server/audio/AudioDeviceBrokerTest.java +++ b/services/tests/servicestests/src/com/android/server/audio/AudioDeviceBrokerTest.java @@ -30,7 +30,7 @@ import android.content.Context; import android.content.Intent; import android.media.AudioManager; import android.media.AudioSystem; -import android.media.BtProfileConnectionInfo; +import android.media.BluetoothProfileConnectionInfo; import android.util.Log; import androidx.test.InstrumentationRegistry; @@ -100,7 +100,7 @@ public class AudioDeviceBrokerTest { mAudioDeviceBroker.queueOnBluetoothActiveDeviceChanged( new AudioDeviceBroker.BtDeviceChangedData(mFakeBtDevice, null, - BtProfileConnectionInfo.a2dpInfo(true, 1), "testSource")); + BluetoothProfileConnectionInfo.createA2dpInfo(true, 1), "testSource")); Thread.sleep(2 * MAX_MESSAGE_HANDLING_DELAY_MS); verify(mSpyDevInventory, times(1)).setBluetoothActiveDevice( any(AudioDeviceBroker.BtDeviceInfo.class) @@ -208,13 +208,13 @@ public class AudioDeviceBrokerTest { // first connection: ensure the device is connected as a starting condition for the test mAudioDeviceBroker.queueOnBluetoothActiveDeviceChanged( new AudioDeviceBroker.BtDeviceChangedData(mFakeBtDevice, null, - BtProfileConnectionInfo.a2dpInfo(true, 1), "testSource")); + BluetoothProfileConnectionInfo.createA2dpInfo(true, 1), "testSource")); Thread.sleep(MAX_MESSAGE_HANDLING_DELAY_MS); // disconnection mAudioDeviceBroker.queueOnBluetoothActiveDeviceChanged( new AudioDeviceBroker.BtDeviceChangedData(null, mFakeBtDevice, - BtProfileConnectionInfo.a2dpInfo(false, -1), "testSource")); + BluetoothProfileConnectionInfo.createA2dpInfo(false, -1), "testSource")); if (delayAfterDisconnection > 0) { Thread.sleep(delayAfterDisconnection); } @@ -222,7 +222,7 @@ public class AudioDeviceBrokerTest { // reconnection mAudioDeviceBroker.queueOnBluetoothActiveDeviceChanged( new AudioDeviceBroker.BtDeviceChangedData(mFakeBtDevice, null, - BtProfileConnectionInfo.a2dpInfo(true, 2), "testSource")); + BluetoothProfileConnectionInfo.createA2dpInfo(true, 2), "testSource")); Thread.sleep(AudioService.BECOMING_NOISY_DELAY_MS + MAX_MESSAGE_HANDLING_DELAY_MS); // Verify disconnection has been cancelled and we're seeing two connections attempts, diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java index 6c1d16402cab..3511fc1c36d5 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java @@ -39,6 +39,7 @@ import static android.app.admin.PasswordMetrics.computeForPasswordOrPin; import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE; import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_DEFAULT; import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE; +import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK; import static android.net.InetAddresses.parseNumericAddress; import static android.net.NetworkCapabilities.NET_ENTERPRISE_ID_1; @@ -90,6 +91,7 @@ import android.app.admin.DevicePolicyManagerInternal; import android.app.admin.DevicePolicyManagerLiteInternal; import android.app.admin.FactoryResetProtectionPolicy; import android.app.admin.PasswordMetrics; +import android.app.admin.PreferentialNetworkServiceConfig; import android.app.admin.SystemUpdatePolicy; import android.content.BroadcastReceiver; import android.content.ComponentName; @@ -4120,6 +4122,164 @@ public class DevicePolicyManagerTest extends DpmTestBase { } @Test + public void testSetPreferentialNetworkServiceConfig_noProfileOwner() throws Exception { + assertExpectException(SecurityException.class, null, + () -> dpm.setPreferentialNetworkServiceConfig( + PreferentialNetworkServiceConfig.DEFAULT)); + } + + @Test + public void testIsPreferentialNetworkServiceEnabled_noProfileOwner() throws Exception { + assertExpectException(SecurityException.class, null, + () -> dpm.isPreferentialNetworkServiceEnabled()); + } + + @Test + public void testSetPreferentialNetworkServiceConfig_invalidConfig() throws Exception { + final int managedProfileUserId = 15; + final int managedProfileAdminUid = UserHandle.getUid(managedProfileUserId, 19436); + addManagedProfile(admin1, managedProfileAdminUid, admin1); + mContext.binder.callingUid = managedProfileAdminUid; + + PreferentialNetworkServiceConfig.Builder preferentialNetworkServiceConfigBuilder = + new PreferentialNetworkServiceConfig.Builder(); + assertExpectException(NullPointerException.class, null, + () -> preferentialNetworkServiceConfigBuilder.setIncludedUids(null)); + assertExpectException(NullPointerException.class, null, + () -> preferentialNetworkServiceConfigBuilder.setExcludedUids(null)); + assertExpectException(IllegalArgumentException.class, null, + () -> preferentialNetworkServiceConfigBuilder.setNetworkId(6)); + int[] includedUids = new int[]{1, 2}; + int[] excludedUids = new int[]{3, 4}; + preferentialNetworkServiceConfigBuilder.setIncludedUids(includedUids); + preferentialNetworkServiceConfigBuilder.setExcludedUids(excludedUids); + + assertExpectException(IllegalStateException.class, null, + () -> preferentialNetworkServiceConfigBuilder.build()); + } + + @Test + public void testSetPreferentialNetworkServiceConfig_defaultPreference() throws Exception { + final int managedProfileUserId = 15; + final int managedProfileAdminUid = UserHandle.getUid(managedProfileUserId, 19436); + addManagedProfile(admin1, managedProfileAdminUid, admin1); + mContext.binder.callingUid = managedProfileAdminUid; + + dpm.setPreferentialNetworkServiceConfig(PreferentialNetworkServiceConfig.DEFAULT); + assertThat(dpm.isPreferentialNetworkServiceEnabled()).isFalse(); + assertThat(dpm.getPreferentialNetworkServiceConfig() + .isEnabled()).isFalse(); + + ProfileNetworkPreference preferenceDetails = + new ProfileNetworkPreference.Builder() + .setPreference(PROFILE_NETWORK_PREFERENCE_DEFAULT) + .build(); + List<ProfileNetworkPreference> preferences = new ArrayList<>(); + preferences.add(preferenceDetails); + verify(getServices().connectivityManager, times(1)) + .setProfileNetworkPreferences(UserHandle.of(managedProfileUserId), preferences, + null, null); + } + + @Test + public void testSetPreferentialNetworkServiceConfig_enterprisePreference() throws Exception { + PreferentialNetworkServiceConfig preferentialNetworkServiceConfigEnabled = + (new PreferentialNetworkServiceConfig.Builder()) + .setEnabled(true) + .setNetworkId(NET_ENTERPRISE_ID_1) + .build(); + + final int managedProfileUserId = 15; + final int managedProfileAdminUid = UserHandle.getUid(managedProfileUserId, 19436); + addManagedProfile(admin1, managedProfileAdminUid, admin1); + mContext.binder.callingUid = managedProfileAdminUid; + + dpm.setPreferentialNetworkServiceConfig(preferentialNetworkServiceConfigEnabled); + assertThat(dpm.getPreferentialNetworkServiceConfig() + .isEnabled()).isTrue(); + ProfileNetworkPreference preferenceDetails = + new ProfileNetworkPreference.Builder() + .setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE) + .setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1) + .build(); + List<ProfileNetworkPreference> preferences = new ArrayList<>(); + preferences.add(preferenceDetails); + verify(getServices().connectivityManager, times(1)) + .setProfileNetworkPreferences(UserHandle.of(managedProfileUserId), preferences, + null, null); + } + + @Test + public void testSetPreferentialNetworkServiceConfig_enterprisePreferenceIncludedUids() + throws Exception { + final int managedProfileUserId = 15; + final int managedProfileAdminUid = UserHandle.getUid(managedProfileUserId, 19436); + addManagedProfile(admin1, managedProfileAdminUid, admin1); + mContext.binder.callingUid = managedProfileAdminUid; + + PreferentialNetworkServiceConfig preferentialNetworkServiceConfigEnabled = + (new PreferentialNetworkServiceConfig.Builder()) + .setEnabled(true) + .setNetworkId(NET_ENTERPRISE_ID_1) + .setFallbackToDefaultConnectionAllowed(false) + .setIncludedUids(new int[]{1, 2}) + .build(); + dpm.setPreferentialNetworkServiceConfig(preferentialNetworkServiceConfigEnabled); + assertThat(dpm.getPreferentialNetworkServiceConfig() + .isEnabled()).isTrue(); + List<Integer> includedList = new ArrayList<>(); + includedList.add(1); + includedList.add(2); + ProfileNetworkPreference preferenceDetails = + new ProfileNetworkPreference.Builder() + .setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK) + .setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1) + .setIncludedUids(includedList) + .build(); + List<ProfileNetworkPreference> preferences = new ArrayList<>(); + preferences.add(preferenceDetails); + verify(getServices().connectivityManager, times(1)) + .setProfileNetworkPreferences(UserHandle.of(managedProfileUserId), preferences, + null, null); + } + + @Test + public void testSetPreferentialNetworkServiceConfig_enterprisePreferenceExcludedUids() + throws Exception { + final int managedProfileUserId = 15; + final int managedProfileAdminUid = UserHandle.getUid(managedProfileUserId, 19436); + addManagedProfile(admin1, managedProfileAdminUid, admin1); + mContext.binder.callingUid = managedProfileAdminUid; + + PreferentialNetworkServiceConfig preferentialNetworkServiceConfigEnabled = + (new PreferentialNetworkServiceConfig.Builder()) + .setEnabled(true) + .setNetworkId(NET_ENTERPRISE_ID_1) + .setFallbackToDefaultConnectionAllowed(false) + .setExcludedUids(new int[]{1, 2}) + .build(); + + dpm.setPreferentialNetworkServiceConfig(preferentialNetworkServiceConfigEnabled); + assertThat(dpm.getPreferentialNetworkServiceConfig() + .isEnabled()).isTrue(); + List<Integer> excludedUids = new ArrayList<>(); + excludedUids.add(1); + excludedUids.add(2); + ProfileNetworkPreference preferenceDetails = + new ProfileNetworkPreference.Builder() + .setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK) + .setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1) + .setExcludedUids(excludedUids) + .build(); + List<ProfileNetworkPreference> preferences = new ArrayList<>(); + preferences.clear(); + preferences.add(preferenceDetails); + verify(getServices().connectivityManager, times(1)) + .setProfileNetworkPreferences(UserHandle.of(managedProfileUserId), preferences, + null, null); + } + + @Test public void testSetSystemSettingFailWithNonWhitelistedSettings() throws Exception { mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID; setupDeviceOwner(); diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java index 01bd04c6f06b..77e49addf79f 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java @@ -43,6 +43,7 @@ import android.hardware.hdmi.HdmiControlManager; import android.hardware.hdmi.HdmiPortInfo; import android.hardware.hdmi.IHdmiCecVolumeControlFeatureListener; import android.hardware.hdmi.IHdmiControlStatusChangeListener; +import android.hardware.hdmi.IHdmiVendorCommandListener; import android.os.Binder; import android.os.IPowerManager; import android.os.IThermalService; @@ -886,6 +887,117 @@ public class HdmiControlServiceTest { } @Test + public void addVendorCommandListener_receiveCallback_VendorCmdNoIdTest() { + int destAddress = mHdmiControlServiceSpy.playback().getDeviceInfo().getLogicalAddress(); + int sourceAddress = Constants.ADDR_TV; + byte[] params = {0x00, 0x01, 0x02, 0x03}; + int vendorId = 0x123456; + mHdmiControlServiceSpy.setPowerStatus(HdmiControlManager.POWER_STATUS_ON); + + VendorCommandListener vendorCmdListener = + new VendorCommandListener(sourceAddress, destAddress, params, vendorId); + mHdmiControlServiceSpy.addVendorCommandListener(vendorCmdListener, vendorId); + mTestLooper.dispatchAll(); + + HdmiCecMessage vendorCommandNoId = + HdmiCecMessageBuilder.buildVendorCommand(sourceAddress, destAddress, params); + mNativeWrapper.onCecMessage(vendorCommandNoId); + mTestLooper.dispatchAll(); + assertThat(vendorCmdListener.mVendorCommandCallbackReceived).isTrue(); + assertThat(vendorCmdListener.mParamsCorrect).isTrue(); + assertThat(vendorCmdListener.mHasVendorId).isFalse(); + } + + @Test + public void addVendorCommandListener_receiveCallback_VendorCmdWithIdTest() { + int destAddress = mHdmiControlServiceSpy.playback().getDeviceInfo().getLogicalAddress(); + int sourceAddress = Constants.ADDR_TV; + byte[] params = {0x00, 0x01, 0x02, 0x03}; + int vendorId = 0x123456; + mHdmiControlServiceSpy.setPowerStatus(HdmiControlManager.POWER_STATUS_ON); + + VendorCommandListener vendorCmdListener = + new VendorCommandListener(sourceAddress, destAddress, params, vendorId); + mHdmiControlServiceSpy.addVendorCommandListener(vendorCmdListener, vendorId); + mTestLooper.dispatchAll(); + + HdmiCecMessage vendorCommandWithId = + HdmiCecMessageBuilder.buildVendorCommandWithId( + sourceAddress, destAddress, vendorId, params); + mNativeWrapper.onCecMessage(vendorCommandWithId); + mTestLooper.dispatchAll(); + assertThat(vendorCmdListener.mVendorCommandCallbackReceived).isTrue(); + assertThat(vendorCmdListener.mParamsCorrect).isTrue(); + assertThat(vendorCmdListener.mHasVendorId).isTrue(); + } + + @Test + public void addVendorCommandListener_noCallback_VendorCmdDiffIdTest() { + int destAddress = mHdmiControlServiceSpy.playback().getDeviceInfo().getLogicalAddress(); + int sourceAddress = Constants.ADDR_TV; + byte[] params = {0x00, 0x01, 0x02, 0x03}; + int vendorId = 0x123456; + int diffVendorId = 0x345678; + mHdmiControlServiceSpy.setPowerStatus(HdmiControlManager.POWER_STATUS_ON); + + VendorCommandListener vendorCmdListener = + new VendorCommandListener(sourceAddress, destAddress, params, vendorId); + mHdmiControlServiceSpy.addVendorCommandListener(vendorCmdListener, vendorId); + mTestLooper.dispatchAll(); + + HdmiCecMessage vendorCommandWithDiffId = + HdmiCecMessageBuilder.buildVendorCommandWithId( + sourceAddress, destAddress, diffVendorId, params); + mNativeWrapper.onCecMessage(vendorCommandWithDiffId); + mTestLooper.dispatchAll(); + assertThat(vendorCmdListener.mVendorCommandCallbackReceived).isFalse(); + } + + private static class VendorCommandListener extends IHdmiVendorCommandListener.Stub { + boolean mVendorCommandCallbackReceived = false; + boolean mParamsCorrect = false; + boolean mHasVendorId = false; + + int mSourceAddress; + int mDestAddress; + byte[] mParams; + int mVendorId; + + VendorCommandListener(int sourceAddress, int destAddress, byte[] params, int vendorId) { + this.mSourceAddress = sourceAddress; + this.mDestAddress = destAddress; + this.mParams = params.clone(); + this.mVendorId = vendorId; + } + + @Override + public void onReceived( + int sourceAddress, int destAddress, byte[] params, boolean hasVendorId) { + mVendorCommandCallbackReceived = true; + if (mSourceAddress == sourceAddress && mDestAddress == destAddress) { + byte[] expectedParams; + if (hasVendorId) { + // If the command has vendor ID, we have to add it to mParams. + expectedParams = new byte[params.length]; + expectedParams[0] = (byte) ((mVendorId >> 16) & 0xFF); + expectedParams[1] = (byte) ((mVendorId >> 8) & 0xFF); + expectedParams[2] = (byte) (mVendorId & 0xFF); + System.arraycopy(mParams, 0, expectedParams, 3, mParams.length); + } else { + expectedParams = params.clone(); + } + if (Arrays.equals(expectedParams, params)) { + mParamsCorrect = true; + } + } + mHasVendorId = hasVendorId; + } + + @Override + public void onControlStateChanged(boolean enabled, int reason) {} + } + + @Test public void dispatchMessageToLocalDevice_broadcastMessage_returnsHandled() { HdmiCecMessage message = HdmiCecMessageBuilder.buildStandby( Constants.ADDR_TV, 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 81c98717d2e7..94cf20f9c15b 100644 --- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java @@ -51,9 +51,9 @@ import static android.net.NetworkPolicyManager.uidRulesToString; import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK; import static android.net.NetworkStats.METERED_NO; import static android.net.NetworkStats.METERED_YES; -import static android.net.NetworkTemplate.buildTemplateCarrierMetered; -import static android.net.NetworkTemplate.buildTemplateWifi; -import static android.net.TrafficStats.MB_IN_BYTES; +import static android.net.NetworkTemplate.MATCH_CARRIER; +import static android.net.NetworkTemplate.MATCH_MOBILE; +import static android.net.NetworkTemplate.MATCH_WIFI; import static android.telephony.CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED; import static android.telephony.CarrierConfigManager.DATA_CYCLE_THRESHOLD_DISABLED; import static android.telephony.CarrierConfigManager.DATA_CYCLE_USE_PLATFORM_DEFAULT; @@ -71,7 +71,6 @@ import static com.android.server.net.NetworkPolicyManagerService.TYPE_LIMIT_SNOO 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.UidBlockedState.getEffectiveBlockedReasons; -import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_UPDATED; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -95,6 +94,7 @@ import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -204,6 +204,7 @@ import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.TimeZone; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; @@ -228,10 +229,12 @@ public class NetworkPolicyManagerServiceTest { private static final int TEST_SUB_ID = 42; private static final Network TEST_NETWORK = mock(Network.class, CALLS_REAL_METHODS); - - private static NetworkTemplate sTemplateWifi = buildTemplateWifi(TEST_WIFI_NETWORK_KEY); + private static NetworkTemplate sTemplateWifi = new NetworkTemplate.Builder(MATCH_WIFI) + .setWifiNetworkKeys(Set.of(TEST_WIFI_NETWORK_KEY)).build(); private static NetworkTemplate sTemplateCarrierMetered = - buildTemplateCarrierMetered(TEST_IMSI); + new NetworkTemplate.Builder(MATCH_CARRIER) + .setSubscriberIds(Set.of(TEST_IMSI)) + .setMeteredness(METERED_YES).build(); /** * Path on assets where files used by {@link NetPolicyXml} are located. @@ -495,8 +498,14 @@ public class NetworkPolicyManagerServiceTest { verify(mNetworkManager).registerObserver(networkObserver.capture()); mNetworkObserver = networkObserver.getValue(); - // Simulate NetworkStatsService broadcast stats updated to signal its readiness. - mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_UPDATED)); + // Catch UsageCallback during systemReady(). Simulate NetworkStatsService triggered + // stats updated callback to signal its readiness. + final ArgumentCaptor<NetworkStatsManager.UsageCallback> usageObserver = + ArgumentCaptor.forClass(NetworkStatsManager.UsageCallback.class); + verify(mStatsManager, times(2)) + .registerUsageCallback(any(), anyLong(), any(), usageObserver.capture()); + usageObserver.getValue().onThresholdReached( + new NetworkTemplate.Builder(MATCH_MOBILE).build()); NetworkPolicy defaultPolicy = mService.buildDefaultCarrierPolicy(0, ""); mDefaultWarningBytes = defaultPolicy.warningBytes; @@ -1153,11 +1162,12 @@ public class NetworkPolicyManagerServiceTest { mPolicyListener.expect().onMeteredIfacesChanged(any()); setNetworkPolicies(new NetworkPolicy( - sTemplateWifi, CYCLE_DAY, TIMEZONE_UTC, 1 * MB_IN_BYTES, 2 * MB_IN_BYTES, false)); + sTemplateWifi, CYCLE_DAY, TIMEZONE_UTC, DataUnit.MEBIBYTES.toBytes(1), + DataUnit.MEBIBYTES.toBytes(2), false)); mPolicyListener.waitAndVerify().onMeteredIfacesChanged(eq(new String[]{TEST_IFACE})); verify(mNetworkManager, atLeastOnce()).setInterfaceQuota(TEST_IFACE, - (2 * MB_IN_BYTES) - 512); + DataUnit.MEBIBYTES.toBytes(2) - 512); } @Test @@ -1245,7 +1255,7 @@ public class NetworkPolicyManagerServiceTest { reset(mTelephonyManager, mNetworkManager, mNotifManager); TelephonyManager tmSub = expectMobileDefaults(); - mService.snoozeLimit(NetworkTemplate.buildTemplateCarrierMetered(TEST_IMSI)); + mService.snoozeLimit(sTemplateCarrierMetered); mService.updateNetworks(); verify(tmSub, atLeastOnce()).setPolicyDataEnabled(true); @@ -1948,7 +1958,7 @@ public class NetworkPolicyManagerServiceTest { assertEquals("Unexpected number of network policies", 1, policies.length); NetworkPolicy actualPolicy = policies[0]; assertEquals("Unexpected template match rule in network policies", - NetworkTemplate.MATCH_WIFI, + MATCH_WIFI, actualPolicy.template.getMatchRule()); assertEquals("Unexpected subscriberIds size in network policies", actualPolicy.template.getSubscriberIds().size(), 0); @@ -2019,7 +2029,10 @@ public class NetworkPolicyManagerServiceTest { private static NetworkPolicy buildFakeCarrierPolicy(int cycleDay, long warningBytes, long limitBytes, boolean inferred) { - final NetworkTemplate template = buildTemplateCarrierMetered(FAKE_SUBSCRIBER_ID); + // TODO: Refactor this to use sTemplateCarrierMetered. + final NetworkTemplate template = new NetworkTemplate.Builder(MATCH_CARRIER) + .setSubscriberIds(Set.of(FAKE_SUBSCRIBER_ID)) + .setMeteredness(METERED_YES).build(); return new NetworkPolicy(template, cycleDay, TimeZone.getDefault().getID(), warningBytes, limitBytes, SNOOZE_NEVER, SNOOZE_NEVER, true, inferred); } diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java index 6f04f176afd8..29fa2d379379 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java @@ -37,6 +37,7 @@ import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; import static android.content.res.Configuration.ORIENTATION_PORTRAIT; import static android.os.Process.NOBODY_UID; import static android.view.Display.DEFAULT_DISPLAY; +import static android.view.InsetsState.ITYPE_IME; import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW; import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW; import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; @@ -127,6 +128,8 @@ import android.view.IRemoteAnimationFinishedCallback; import android.view.IRemoteAnimationRunner.Stub; import android.view.IWindowManager; import android.view.IWindowSession; +import android.view.InsetsSource; +import android.view.InsetsState; import android.view.RemoteAnimationAdapter; import android.view.RemoteAnimationTarget; import android.view.Surface; @@ -2884,6 +2887,41 @@ public class ActivityRecordTests extends WindowTestsBase { assertFalse(app.mActivityRecord.mImeInsetsFrozenUntilStartInput); } + @UseTestDisplay(addWindows = W_INPUT_METHOD) + @Test + public void testImeInsetsFrozenFlag_resetWhenReportedToBeImeInputTarget() { + final WindowState app = createWindow(null, TYPE_APPLICATION, "app"); + + InsetsSource imeSource = new InsetsSource(ITYPE_IME); + app.getInsetsState().addSource(imeSource); + mDisplayContent.setImeLayeringTarget(app); + mDisplayContent.updateImeInputAndControlTarget(app); + + InsetsState state = mDisplayContent.getInsetsPolicy().getInsetsForWindow(app); + assertFalse(state.getSource(ITYPE_IME).isVisible()); + assertTrue(state.getSource(ITYPE_IME).getFrame().isEmpty()); + + // Simulate app is closing and expect IME insets is frozen. + mDisplayContent.mOpeningApps.clear(); + app.mActivityRecord.commitVisibility(false, false); + app.mActivityRecord.onWindowsGone(); + assertTrue(app.mActivityRecord.mImeInsetsFrozenUntilStartInput); + + // Simulate app re-start input or turning screen off/on then unlocked by un-secure + // keyguard to back to the app, expect IME insets is not frozen + imeSource.setFrame(new Rect(100, 400, 500, 500)); + app.getInsetsState().addSource(imeSource); + app.getInsetsState().setSourceVisible(ITYPE_IME, true); + mDisplayContent.updateImeInputAndControlTarget(app); + assertFalse(app.mActivityRecord.mImeInsetsFrozenUntilStartInput); + + // Verify when IME is visible and the app can receive the right IME insets from policy. + makeWindowVisibleAndDrawn(app, mImeWindow); + state = mDisplayContent.getInsetsPolicy().getInsetsForWindow(app); + assertTrue(state.getSource(ITYPE_IME).isVisible()); + assertEquals(state.getSource(ITYPE_IME).getFrame(), imeSource.getFrame()); + } + private void assertHasStartingWindow(ActivityRecord atoken) { assertNotNull(atoken.mStartingSurface); assertNotNull(atoken.mStartingData); diff --git a/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java b/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java index 125296540688..9a991a1b4a9a 100644 --- a/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java +++ b/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java @@ -107,6 +107,25 @@ public final class TelephonyUtils { } } + /** + * Convenience method for running the provided action in the provided + * executor enclosed in + * {@link Binder#clearCallingIdentity}/{@link Binder#restoreCallingIdentity} + * + * Any exception thrown by the given action will need to be handled by caller. + * + */ + public static void runWithCleanCallingIdentity( + @NonNull Runnable action, @NonNull Executor executor) { + if (action != null) { + if (executor != null) { + executor.execute(() -> runWithCleanCallingIdentity(action)); + } else { + runWithCleanCallingIdentity(action); + } + } + } + /** * Convenience method for running the provided action enclosed in diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index 9a764a0a0a3a..d7135a57aafd 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -168,7 +168,10 @@ public class CarrierConfigManager { /** * This flag specifies whether VoLTE availability is based on provisioning. By default this is * false. + * Used for UCE to determine if EAB provisioning checks should be based on provisioning. + * @deprecated Use {@link Ims#KEY_MMTEL_REQUIRES_PROVISIONING_BUNDLE} instead. */ + @Deprecated public static final String KEY_CARRIER_VOLTE_PROVISIONED_BOOL = "carrier_volte_provisioned_bool"; @@ -349,6 +352,12 @@ public class CarrierConfigManager { KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL = "require_entitlement_checks_bool"; /** + * Flag indicating if the carrier supports tethering of mobile data. + */ + public static final String KEY_CARRIER_SUPPORTS_TETHERING_BOOL = + "carrier_supports_tethering_bool"; + + /** * Flag indicating whether radio is to be restarted on error PDP_FAIL_REGULAR_DEACTIVATION * This is false by default. * @@ -858,7 +867,12 @@ public class CarrierConfigManager { /** * Flag specifying whether provisioning is required for VoLTE, Video Telephony, and WiFi * Calling. + + * Combines VoLTE, VT, VoWiFI calling provisioning into one parameter. + * @deprecated Use {@link Ims#KEY_MMTEL_REQUIRES_PROVISIONING_BUNDLE} instead for + * finer-grained control. */ + @Deprecated public static final String KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL = "carrier_volte_provisioning_required_bool"; @@ -872,7 +886,11 @@ public class CarrierConfigManager { * and enable the UT over IMS capability for the subscription when the subscription is loaded. * * The default value for this key is {@code false}. + * + * @deprecated Use {@link Ims#KEY_MMTEL_REQUIRES_PROVISIONING_BUNDLE} instead for + * determining if UT requires provisioning. */ + @Deprecated public static final String KEY_CARRIER_UT_PROVISIONING_REQUIRED_BOOL = "carrier_ut_provisioning_required_bool"; @@ -4402,12 +4420,10 @@ public class CarrierConfigManager { "carrier_auto_cancel_cs_notification"; /** - * Passing this value as {@link KEY_SUBSCRIPTION_GROUP_UUID_STRING} will remove the + * Passing this value as {@link #KEY_SUBSCRIPTION_GROUP_UUID_STRING} will remove the * subscription from a group instead of adding it to a group. * - * TODO: Expose in a future release. - * - * @hide + * <p>This value will work all the way back to {@link android.os.Build.VERSION_CODES#Q}. */ public static final String REMOVE_GROUP_UUID_STRING = "00000000-0000-0000-0000-000000000000"; @@ -4420,9 +4436,7 @@ public class CarrierConfigManager { * <p>If set to {@link #REMOVE_GROUP_UUID_STRING}, then the subscription will be removed from * its current group. * - * TODO: unhide this key. - * - * @hide + * <p>This key will work all the way back to {@link android.os.Build.VERSION_CODES#Q}. */ public static final String KEY_SUBSCRIPTION_GROUP_UUID_STRING = "subscription_group_uuid_string"; @@ -4447,17 +4461,15 @@ public class CarrierConfigManager { "data_switch_validation_min_gap_long"; /** - * A boolean property indicating whether this subscription should be managed as an opportunistic - * subscription. - * - * If true, then this subscription will be selected based on available coverage and will not be - * available for a user in settings menus for selecting macro network providers. If unset, - * defaults to “false”. - * - * TODO: unhide this key. - * - * @hide - */ + * A boolean property indicating whether this subscription should be managed as an opportunistic + * subscription. + * + * If true, then this subscription will be selected based on available coverage and will not be + * available for a user in settings menus for selecting macro network providers. If unset, + * defaults to “false”. + * + * <p>This key will work all the way back to {@link android.os.Build.VERSION_CODES#Q}. + */ public static final String KEY_IS_OPPORTUNISTIC_SUBSCRIPTION_BOOL = "is_opportunistic_subscription_bool"; @@ -4637,6 +4649,95 @@ public class CarrierConfigManager { public static final String KEY_RCS_REQUEST_RETRY_INTERVAL_MILLIS_LONG = KEY_PREFIX + "rcs_request_retry_interval_millis_long"; + /** + * A bundle which specifies the MMTEL capability and registration technology + * that requires provisioning. If a tuple is not present, the + * framework will not require that the tuple requires provisioning before + * enabling the capability. + * <p> Possible keys in this bundle are + * <ul> + * <li>{@link #KEY_CAPABILITY_TYPE_VOICE_INT_ARRAY}</li> + * <li>{@link #KEY_CAPABILITY_TYPE_VIDEO_INT_ARRAY}</li> + * <li>{@link #KEY_CAPABILITY_TYPE_UT_INT_ARRAY}</li> + * <li>{@link #KEY_CAPABILITY_TYPE_SMS_INT_ARRAY}</li> + * <li>{@link #KEY_CAPABILITY_CALL_COMPOSER_INT_ARRAY}</li> + * </ul> + * <p> The values are defined in + * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationTech} + */ + public static final String KEY_MMTEL_REQUIRES_PROVISIONING_BUNDLE = + KEY_PREFIX + "mmtel_requires_provisioning_bundle"; + + /** + * This MmTelFeature supports Voice calling (IR.92) + * @see MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VOICE + */ + public static final String KEY_CAPABILITY_TYPE_VOICE_INT_ARRAY = + KEY_PREFIX + "key_capability_type_voice_int_array"; + + /** + * This MmTelFeature supports Video (IR.94) + * @see MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VIDEO + */ + public static final String KEY_CAPABILITY_TYPE_VIDEO_INT_ARRAY = + KEY_PREFIX + "key_capability_type_video_int_array"; + + /** + * This MmTelFeature supports XCAP over Ut for supplementary services. (IR.92) + * @see MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_UT + */ + public static final String KEY_CAPABILITY_TYPE_UT_INT_ARRAY = + KEY_PREFIX + "key_capability_type_ut_int_array"; + + /** + * This MmTelFeature supports SMS (IR.92) + * @see MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_SMS + */ + public static final String KEY_CAPABILITY_TYPE_SMS_INT_ARRAY = + KEY_PREFIX + "key_capability_type_sms_int_array"; + + /** + * This MmTelFeature supports Call Composer (section 2.4 of RCC.20) + * @see MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_CALL_COMPOSER + */ + public static final String KEY_CAPABILITY_CALL_COMPOSER_INT_ARRAY = + KEY_PREFIX + "key_capability_type_call_composer_int_array"; + + /** + * A bundle which specifies the RCS capability and registration technology + * that requires provisioning. If a tuple is not present, the + * framework will not require that the tuple requires provisioning before + * enabling the capability. + * <p> Possible keys in this bundle are + * <ul> + * <li>{@link #KEY_CAPABILITY_TYPE_OPTIONS_UCE_INT_ARRAY}</li> + * <li>{@link #KEY_CAPABILITY_TYPE_PRESENCE_UCE_INT_ARRAY}</li> + * </ul> + * <p> The values are defined in + * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationTech} + */ + public static final String KEY_RCS_REQUIRES_PROVISIONING_BUNDLE = + KEY_PREFIX + "rcs_requires_provisioning_bundle"; + + /** + * This carrier supports User Capability Exchange using SIP OPTIONS as defined by the + * framework. If set, the RcsFeature should support capability exchange using SIP OPTIONS. + * If not set, this RcsFeature should not service capability requests. + * @see RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_OPTIONS_UCE + */ + public static final String KEY_CAPABILITY_TYPE_OPTIONS_UCE_INT_ARRAY = + KEY_PREFIX + "key_capability_type_options_uce_int_array"; + + /** + * This carrier supports User Capability Exchange using a presence server as defined by the + * framework. If set, the RcsFeature should support capability exchange using a presence + * server. If not set, this RcsFeature should not publish capabilities or service capability + * requests using presence. + * @see RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_PRESENCE_UCE + */ + public static final String KEY_CAPABILITY_TYPE_PRESENCE_UCE_INT_ARRAY = + KEY_PREFIX + "key_capability_type_presence_uce_int_array"; + private Ims() {} private static PersistableBundle getDefaults() { @@ -4673,6 +4774,20 @@ public class CarrierConfigManager { "+g.gsma.rcs.botversion=\"#=1,#=2\"", "+g.gsma.rcs.cpimext"}); + /** + * @see #KEY_MMTEL_REQUIRES_PROVISIONING_BUNDLE + */ + PersistableBundle mmtel_requires_provisioning_int_array = new PersistableBundle(); + defaults.putPersistableBundle( + KEY_MMTEL_REQUIRES_PROVISIONING_BUNDLE, mmtel_requires_provisioning_int_array); + + /** + * @see #KEY_RCS_REQUIRES_PROVISIONING_BUNDLE + */ + PersistableBundle rcs_requires_provisioning_int_array = new PersistableBundle(); + defaults.putPersistableBundle( + KEY_RCS_REQUIRES_PROVISIONING_BUNDLE, rcs_requires_provisioning_int_array); + return defaults; } } @@ -5421,6 +5536,7 @@ public class CarrierConfigManager { sDefaults.putBoolean(KEY_VOICE_PRIVACY_DISABLE_UI_BOOL, false); sDefaults.putBoolean(KEY_WORLD_PHONE_BOOL, false); sDefaults.putBoolean(KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL, true); + sDefaults.putBoolean(KEY_CARRIER_SUPPORTS_TETHERING_BOOL, true); sDefaults.putBoolean(KEY_RESTART_RADIO_ON_PDP_FAIL_REGULAR_DEACTIVATION_BOOL, false); sDefaults.putIntArray(KEY_RADIO_RESTART_FAILURE_CAUSES_INT_ARRAY, new int[]{}); sDefaults.putInt(KEY_VOLTE_REPLACEMENT_RAT_INT, 0); diff --git a/telephony/java/android/telephony/ImsManager.java b/telephony/java/android/telephony/ImsManager.java index fc76f99cf074..6b9871c3f5d7 100644 --- a/telephony/java/android/telephony/ImsManager.java +++ b/telephony/java/android/telephony/ImsManager.java @@ -160,6 +160,26 @@ public class ImsManager { return new SipDelegateManager(mContext, subscriptionId, sRcsCache, sTelephonyCache); } + + /** + * Create an instance of {@link ProvisioningManager} for the subscription id specified. + * <p> + * Provides a ProvisioningManager instance to carrier apps to update carrier provisioning + * information, as well as provides a callback so that apps can listen for changes + * in MMTEL/RCS provisioning + * @param subscriptionId The ID of the subscription that this ProvisioningManager will use. + * @throws IllegalArgumentException if the subscription is invalid. + * @return a ProvisioningManager instance with the specific subscription ID. + */ + @NonNull + public ProvisioningManager getProvisioningManager(int subscriptionId) { + if (!SubscriptionManager.isValidSubscriptionId(subscriptionId)) { + throw new IllegalArgumentException("Invalid subscription ID: " + subscriptionId); + } + + return new ProvisioningManager(subscriptionId); + } + private static IImsRcsController getIImsRcsControllerInterface() { return IImsRcsController.Stub.asInterface( TelephonyFrameworkInitializer diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 9ac9d66b3965..4934f11f4097 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -8765,7 +8765,8 @@ public class TelephonyManager { * @param allowedNetworkTypes The bitmask of allowed network types. * @return true on success; false on any failure. * @hide - * @deprecated Use {@link #setAllowedNetworkTypesForReason} instead. + * @deprecated Use {@link #setAllowedNetworkTypesForReason} instead with reason + * {@link #ALLOWED_NETWORK_TYPES_REASON_CARRIER}. */ @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @@ -8799,10 +8800,7 @@ public class TelephonyManager { /** * To indicate allowed network type change is requested by user. - * - * @hide */ - @SystemApi public static final int ALLOWED_NETWORK_TYPES_REASON_USER = 0; /** @@ -8821,10 +8819,7 @@ public class TelephonyManager { * Carrier configuration won't affect the settings configured through * other reasons and will result in allowing network types that are in both * configurations (i.e intersection of both sets). - * - * @hide */ - @SystemApi public static final int ALLOWED_NETWORK_TYPES_REASON_CARRIER = 2; /** @@ -8838,35 +8833,23 @@ public class TelephonyManager { /** * Set the allowed network types of the device and provide the reason triggering the allowed * network change. + * <p>Requires permission: android.Manifest.MODIFY_PHONE_STATE or + * that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}). + * * This can be called for following reasons * <ol> * <li>Allowed network types control by USER {@link #ALLOWED_NETWORK_TYPES_REASON_USER} - * <li>Allowed network types control by power manager - * {@link #ALLOWED_NETWORK_TYPES_REASON_POWER} * <li>Allowed network types control by carrier {@link #ALLOWED_NETWORK_TYPES_REASON_CARRIER} - * <li>Allowed network types control by the user-controlled "Allow 2G" toggle - * {@link #ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G} * </ol> * This API will result in allowing an intersection of allowed network types for all reasons, * including the configuration done through other reasons. * - * The functionality of this API with the parameter - * {@link #ALLOWED_NETWORK_TYPES_REASON_CARRIER} is the same as the API - * {@link TelephonyManager#setAllowedNetworkTypes}. Use this API instead of - * {@link TelephonyManager#setAllowedNetworkTypes}. - * <p> - * If {@link android.telephony.TelephonyManager#isRadioInterfaceCapabilitySupported} - * ({@link TelephonyManager#CAPABILITY_USES_ALLOWED_NETWORK_TYPES_BITMASK}) returns true, then - * setAllowedNetworkTypesBitmap is used on the radio interface. Otherwise, - * setPreferredNetworkTypesBitmap is used instead. - * * @param reason the reason the allowed network type change is taking place - * @param allowedNetworkTypes The bitmask of allowed network types. + * @param allowedNetworkTypes The bitmask of allowed network type * @throws IllegalStateException if the Telephony process is not currently available. * @throws IllegalArgumentException if invalid AllowedNetworkTypesReason is passed. - * @hide + * @throws SecurityException if the caller does not have the required privileges */ - @SystemApi @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @RequiresFeature( enforcement = "android.telephony.TelephonyManager#isRadioInterfaceCapabilitySupported", @@ -8896,18 +8879,19 @@ public class TelephonyManager { * * {@link #getAllowedNetworkTypesForReason} returns allowed network type for a * specific reason. + * <p>Requires permission: android.Manifest.READ_PRIVILEGED_PHONE_STATE or + * that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}). * * @param reason the reason the allowed network type change is taking place * @return the allowed network type bitmask * @throws IllegalStateException if the Telephony process is not currently available. * @throws IllegalArgumentException if invalid AllowedNetworkTypesReason is passed. - * @hide + * @throws SecurityException if the caller does not have the required permission/privileges */ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @RequiresFeature( enforcement = "android.telephony.TelephonyManager#isRadioInterfaceCapabilitySupported", value = TelephonyManager.CAPABILITY_USES_ALLOWED_NETWORK_TYPES_BITMASK) - @SystemApi public @NetworkTypeBitMask long getAllowedNetworkTypesForReason( @AllowedNetworkTypesReason int reason) { if (!isValidAllowedNetworkTypesReason(reason)) { @@ -11487,7 +11471,11 @@ public class TelephonyManager { private final int mErrorCode; - /** @hide */ + /** + * An exception with ModemActivityInfo specific error codes. + * + * @param errorCode a ModemActivityInfoError code. + */ public ModemActivityInfoException(@ModemActivityInfoError int errorCode) { mErrorCode = errorCode; } @@ -13022,127 +13010,88 @@ public class TelephonyManager { // 2G /** * network type bitmask unknown. - * @hide */ - @SystemApi public static final long NETWORK_TYPE_BITMASK_UNKNOWN = 0L; /** * network type bitmask indicating the support of radio tech GSM. - * @hide */ - @SystemApi public static final long NETWORK_TYPE_BITMASK_GSM = (1 << (NETWORK_TYPE_GSM -1)); /** * network type bitmask indicating the support of radio tech GPRS. - * @hide */ - @SystemApi public static final long NETWORK_TYPE_BITMASK_GPRS = (1 << (NETWORK_TYPE_GPRS -1)); /** * network type bitmask indicating the support of radio tech EDGE. - * @hide */ - @SystemApi public static final long NETWORK_TYPE_BITMASK_EDGE = (1 << (NETWORK_TYPE_EDGE -1)); /** * network type bitmask indicating the support of radio tech CDMA(IS95A/IS95B). - * @hide */ - @SystemApi public static final long NETWORK_TYPE_BITMASK_CDMA = (1 << (NETWORK_TYPE_CDMA -1)); /** * network type bitmask indicating the support of radio tech 1xRTT. - * @hide */ - @SystemApi + @SuppressLint("AllUpper") public static final long NETWORK_TYPE_BITMASK_1xRTT = (1 << (NETWORK_TYPE_1xRTT - 1)); // 3G /** * network type bitmask indicating the support of radio tech EVDO 0. - * @hide */ - @SystemApi public static final long NETWORK_TYPE_BITMASK_EVDO_0 = (1 << (NETWORK_TYPE_EVDO_0 -1)); /** * network type bitmask indicating the support of radio tech EVDO A. - * @hide */ - @SystemApi public static final long NETWORK_TYPE_BITMASK_EVDO_A = (1 << (NETWORK_TYPE_EVDO_A - 1)); /** * network type bitmask indicating the support of radio tech EVDO B. - * @hide */ - @SystemApi public static final long NETWORK_TYPE_BITMASK_EVDO_B = (1 << (NETWORK_TYPE_EVDO_B -1)); /** * network type bitmask indicating the support of radio tech EHRPD. - * @hide */ - @SystemApi public static final long NETWORK_TYPE_BITMASK_EHRPD = (1 << (NETWORK_TYPE_EHRPD -1)); /** * network type bitmask indicating the support of radio tech HSUPA. - * @hide */ - @SystemApi public static final long NETWORK_TYPE_BITMASK_HSUPA = (1 << (NETWORK_TYPE_HSUPA -1)); /** * network type bitmask indicating the support of radio tech HSDPA. - * @hide */ - @SystemApi public static final long NETWORK_TYPE_BITMASK_HSDPA = (1 << (NETWORK_TYPE_HSDPA -1)); /** * network type bitmask indicating the support of radio tech HSPA. - * @hide */ - @SystemApi public static final long NETWORK_TYPE_BITMASK_HSPA = (1 << (NETWORK_TYPE_HSPA -1)); /** * network type bitmask indicating the support of radio tech HSPAP. - * @hide */ - @SystemApi public static final long NETWORK_TYPE_BITMASK_HSPAP = (1 << (NETWORK_TYPE_HSPAP -1)); /** * network type bitmask indicating the support of radio tech UMTS. - * @hide */ - @SystemApi public static final long NETWORK_TYPE_BITMASK_UMTS = (1 << (NETWORK_TYPE_UMTS -1)); /** * network type bitmask indicating the support of radio tech TD_SCDMA. - * @hide */ - @SystemApi public static final long NETWORK_TYPE_BITMASK_TD_SCDMA = (1 << (NETWORK_TYPE_TD_SCDMA -1)); // 4G /** * network type bitmask indicating the support of radio tech LTE. - * @hide */ - @SystemApi public static final long NETWORK_TYPE_BITMASK_LTE = (1 << (NETWORK_TYPE_LTE -1)); /** * network type bitmask indicating the support of radio tech LTE CA (carrier aggregation). - * @hide */ - @SystemApi public static final long NETWORK_TYPE_BITMASK_LTE_CA = (1 << (NETWORK_TYPE_LTE_CA -1)); /** * network type bitmask indicating the support of radio tech NR(New Radio) 5G. - * @hide */ - @SystemApi public static final long NETWORK_TYPE_BITMASK_NR = (1 << (NETWORK_TYPE_NR -1)); /** * network type bitmask indicating the support of radio tech IWLAN. - * @hide */ - @SystemApi public static final long NETWORK_TYPE_BITMASK_IWLAN = (1 << (NETWORK_TYPE_IWLAN -1)); /** @hide */ @@ -13197,12 +13146,11 @@ public class TelephonyManager { /** * @return Modem supported radio access family bitmask * - * <p>Requires permission: {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE} or + * <p>Requires permission: android.Manifest.READ_PRIVILEGED_PHONE_STATE or * that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}). - * @hide + * + * @throws SecurityException if the caller does not have the required permission */ - @SystemApi - @TestApi @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public @NetworkTypeBitMask long getSupportedRadioAccessFamily() { try { diff --git a/telephony/java/android/telephony/data/DataServiceCallback.java b/telephony/java/android/telephony/data/DataServiceCallback.java index 051d6c5d5ec0..13d8c7b9c915 100644 --- a/telephony/java/android/telephony/data/DataServiceCallback.java +++ b/telephony/java/android/telephony/data/DataServiceCallback.java @@ -259,9 +259,10 @@ public class DataServiceCallback { } /** - * Unthrottles the APN on the current transport. There is no matching "APN throttle" method. - * Instead, the APN is throttled when {@link IDataService#setupDataCall} fails within - * the time specified by {@link DataCallResponse#getRetryDurationMillis}. + * Unthrottles the APN on the current transport. + * The APN is throttled when {@link IDataService#setupDataCall} fails within + * the time specified by {@link DataCallResponse#getRetryDurationMillis} and will remain + * throttled until this method is called. * <p/> * see: {@link DataCallResponse#getRetryDurationMillis} * @@ -282,9 +283,9 @@ public class DataServiceCallback { /** * Unthrottles the DataProfile on the current transport. - * There is no matching "DataProfile throttle" method. - * Instead, the DataProfile is throttled when {@link IDataService#setupDataCall} fails within - * the time specified by {@link DataCallResponse#getRetryDurationMillis}. + * The DataProfile is throttled when {@link IDataService#setupDataCall} fails within + * the time specified by {@link DataCallResponse#getRetryDurationMillis} and will remain + * throttled until this method is called. * <p/> * see: {@link DataCallResponse#getRetryDurationMillis} * diff --git a/telephony/java/android/telephony/ims/ImsCallSession.java b/telephony/java/android/telephony/ims/ImsCallSession.java index dfe5e6c93f53..d65286f26447 100755 --- a/telephony/java/android/telephony/ims/ImsCallSession.java +++ b/telephony/java/android/telephony/ims/ImsCallSession.java @@ -27,10 +27,12 @@ import android.util.Log; import com.android.ims.internal.IImsCallSession; import com.android.ims.internal.IImsVideoCallProvider; +import com.android.internal.telephony.util.TelephonyUtils; import java.util.ArrayList; import java.util.List; import java.util.Set; +import java.util.concurrent.Executor; /** * Provides the call initiation/termination, and media exchange between two IMS endpoints. @@ -522,6 +524,7 @@ public class ImsCallSession { private final IImsCallSession miSession; private boolean mClosed = false; private Listener mListener; + private Executor mListenerExecutor = Runnable::run; /** @hide */ public ImsCallSession(IImsCallSession iSession) { @@ -538,9 +541,9 @@ public class ImsCallSession { } /** @hide */ - public ImsCallSession(IImsCallSession iSession, Listener listener) { + public ImsCallSession(IImsCallSession iSession, Listener listener, Executor executor) { this(iSession); - setListener(listener); + setListener(listener, executor); } /** @@ -738,10 +741,14 @@ public class ImsCallSession { * override the previous listener. * * @param listener to listen to the session events of this object + * @param executor an Executor that will execute callbacks * @hide */ - public void setListener(Listener listener) { + public void setListener(Listener listener, Executor executor) { mListener = listener; + if (executor != null) { + mListenerExecutor = executor; + } } /** @@ -1205,44 +1212,56 @@ public class ImsCallSession { */ @Override public void callSessionInitiating(ImsCallProfile profile) { - if (mListener != null) { - mListener.callSessionInitiating(ImsCallSession.this, profile); - } + TelephonyUtils.runWithCleanCallingIdentity(()-> { + if (mListener != null) { + mListener.callSessionInitiating(ImsCallSession.this, profile); + } + }, mListenerExecutor); } @Override public void callSessionProgressing(ImsStreamMediaProfile profile) { - if (mListener != null) { - mListener.callSessionProgressing(ImsCallSession.this, profile); - } + TelephonyUtils.runWithCleanCallingIdentity(()-> { + if (mListener != null) { + mListener.callSessionProgressing(ImsCallSession.this, profile); + } + }, mListenerExecutor); } @Override public void callSessionInitiated(ImsCallProfile profile) { - if (mListener != null) { - mListener.callSessionStarted(ImsCallSession.this, profile); - } + TelephonyUtils.runWithCleanCallingIdentity(()-> { + if (mListener != null) { + mListener.callSessionStarted(ImsCallSession.this, profile); + } + }, mListenerExecutor); } @Override public void callSessionInitiatingFailed(ImsReasonInfo reasonInfo) { - if (mListener != null) { - mListener.callSessionStartFailed(ImsCallSession.this, reasonInfo); - } + TelephonyUtils.runWithCleanCallingIdentity(()-> { + if (mListener != null) { + mListener.callSessionStartFailed(ImsCallSession.this, reasonInfo); + } + }, mListenerExecutor); } @Override public void callSessionInitiatedFailed(ImsReasonInfo reasonInfo) { - if (mListener != null) { - mListener.callSessionStartFailed(ImsCallSession.this, reasonInfo); - } + TelephonyUtils.runWithCleanCallingIdentity(()-> { + if (mListener != null) { + mListener.callSessionStartFailed(ImsCallSession.this, reasonInfo); + } + }, mListenerExecutor); } @Override public void callSessionTerminated(ImsReasonInfo reasonInfo) { - if (mListener != null) { - mListener.callSessionTerminated(ImsCallSession.this, reasonInfo); - } + TelephonyUtils.runWithCleanCallingIdentity(()-> { + if (mListener != null) { + mListener.callSessionTerminated(ImsCallSession.this, reasonInfo); + } + }, mListenerExecutor); } /** @@ -1250,44 +1269,56 @@ public class ImsCallSession { */ @Override public void callSessionHeld(ImsCallProfile profile) { - if (mListener != null) { - mListener.callSessionHeld(ImsCallSession.this, profile); - } + TelephonyUtils.runWithCleanCallingIdentity(()-> { + if (mListener != null) { + mListener.callSessionHeld(ImsCallSession.this, profile); + } + }, mListenerExecutor); } @Override public void callSessionHoldFailed(ImsReasonInfo reasonInfo) { - if (mListener != null) { - mListener.callSessionHoldFailed(ImsCallSession.this, reasonInfo); - } + TelephonyUtils.runWithCleanCallingIdentity(()-> { + if (mListener != null) { + mListener.callSessionHoldFailed(ImsCallSession.this, reasonInfo); + } + }, mListenerExecutor); } @Override public void callSessionHoldReceived(ImsCallProfile profile) { - if (mListener != null) { - mListener.callSessionHoldReceived(ImsCallSession.this, profile); - } + TelephonyUtils.runWithCleanCallingIdentity(()-> { + if (mListener != null) { + mListener.callSessionHoldReceived(ImsCallSession.this, profile); + } + }, mListenerExecutor); } @Override public void callSessionResumed(ImsCallProfile profile) { - if (mListener != null) { - mListener.callSessionResumed(ImsCallSession.this, profile); - } + TelephonyUtils.runWithCleanCallingIdentity(()-> { + if (mListener != null) { + mListener.callSessionResumed(ImsCallSession.this, profile); + } + }, mListenerExecutor); } @Override public void callSessionResumeFailed(ImsReasonInfo reasonInfo) { - if (mListener != null) { - mListener.callSessionResumeFailed(ImsCallSession.this, reasonInfo); - } + TelephonyUtils.runWithCleanCallingIdentity(()-> { + if (mListener != null) { + mListener.callSessionResumeFailed(ImsCallSession.this, reasonInfo); + } + }, mListenerExecutor); } @Override public void callSessionResumeReceived(ImsCallProfile profile) { - if (mListener != null) { - mListener.callSessionResumeReceived(ImsCallSession.this, profile); - } + TelephonyUtils.runWithCleanCallingIdentity(()-> { + if (mListener != null) { + mListener.callSessionResumeReceived(ImsCallSession.this, profile); + } + }, mListenerExecutor); } /** @@ -1310,15 +1341,17 @@ public class ImsCallSession { */ @Override public void callSessionMergeComplete(IImsCallSession newSession) { - if (mListener != null) { - if (newSession != null) { - // New session created after conference - mListener.callSessionMergeComplete(new ImsCallSession(newSession)); - } else { - // Session already exists. Hence no need to pass - mListener.callSessionMergeComplete(null); - } - } + TelephonyUtils.runWithCleanCallingIdentity(()-> { + if (mListener != null) { + if (newSession != null) { + // New session created after conference + mListener.callSessionMergeComplete(new ImsCallSession(newSession)); + } else { + // Session already exists. Hence no need to pass + mListener.callSessionMergeComplete(null); + } + } + }, mListenerExecutor); } /** @@ -1328,9 +1361,11 @@ public class ImsCallSession { */ @Override public void callSessionMergeFailed(ImsReasonInfo reasonInfo) { - if (mListener != null) { - mListener.callSessionMergeFailed(ImsCallSession.this, reasonInfo); - } + TelephonyUtils.runWithCleanCallingIdentity(()-> { + if (mListener != null) { + mListener.callSessionMergeFailed(ImsCallSession.this, reasonInfo); + } + }, mListenerExecutor); } /** @@ -1338,23 +1373,29 @@ public class ImsCallSession { */ @Override public void callSessionUpdated(ImsCallProfile profile) { - if (mListener != null) { - mListener.callSessionUpdated(ImsCallSession.this, profile); - } + TelephonyUtils.runWithCleanCallingIdentity(()-> { + if (mListener != null) { + mListener.callSessionUpdated(ImsCallSession.this, profile); + } + }, mListenerExecutor); } @Override public void callSessionUpdateFailed(ImsReasonInfo reasonInfo) { - if (mListener != null) { - mListener.callSessionUpdateFailed(ImsCallSession.this, reasonInfo); - } + TelephonyUtils.runWithCleanCallingIdentity(()-> { + if (mListener != null) { + mListener.callSessionUpdateFailed(ImsCallSession.this, reasonInfo); + } + }, mListenerExecutor); } @Override public void callSessionUpdateReceived(ImsCallProfile profile) { - if (mListener != null) { - mListener.callSessionUpdateReceived(ImsCallSession.this, profile); - } + TelephonyUtils.runWithCleanCallingIdentity(()-> { + if (mListener != null) { + mListener.callSessionUpdateReceived(ImsCallSession.this, profile); + } + }, mListenerExecutor); } /** @@ -1363,26 +1404,33 @@ public class ImsCallSession { @Override public void callSessionConferenceExtended(IImsCallSession newSession, ImsCallProfile profile) { - if (mListener != null) { - mListener.callSessionConferenceExtended(ImsCallSession.this, - new ImsCallSession(newSession), profile); - } + TelephonyUtils.runWithCleanCallingIdentity(()-> { + if (mListener != null) { + mListener.callSessionConferenceExtended(ImsCallSession.this, + new ImsCallSession(newSession), profile); + } + }, mListenerExecutor); } @Override public void callSessionConferenceExtendFailed(ImsReasonInfo reasonInfo) { - if (mListener != null) { - mListener.callSessionConferenceExtendFailed(ImsCallSession.this, reasonInfo); - } + TelephonyUtils.runWithCleanCallingIdentity(()-> { + if (mListener != null) { + mListener.callSessionConferenceExtendFailed( + ImsCallSession.this, reasonInfo); + } + }, mListenerExecutor); } @Override public void callSessionConferenceExtendReceived(IImsCallSession newSession, ImsCallProfile profile) { - if (mListener != null) { - mListener.callSessionConferenceExtendReceived(ImsCallSession.this, - new ImsCallSession(newSession), profile); - } + TelephonyUtils.runWithCleanCallingIdentity(()-> { + if (mListener != null) { + mListener.callSessionConferenceExtendReceived(ImsCallSession.this, + new ImsCallSession(newSession), profile); + } + }, mListenerExecutor); } /** @@ -1391,32 +1439,41 @@ public class ImsCallSession { */ @Override public void callSessionInviteParticipantsRequestDelivered() { - if (mListener != null) { - mListener.callSessionInviteParticipantsRequestDelivered(ImsCallSession.this); - } + TelephonyUtils.runWithCleanCallingIdentity(()-> { + if (mListener != null) { + mListener.callSessionInviteParticipantsRequestDelivered( + ImsCallSession.this); + } + }, mListenerExecutor); } @Override public void callSessionInviteParticipantsRequestFailed(ImsReasonInfo reasonInfo) { - if (mListener != null) { - mListener.callSessionInviteParticipantsRequestFailed(ImsCallSession.this, - reasonInfo); - } + TelephonyUtils.runWithCleanCallingIdentity(()-> { + if (mListener != null) { + mListener.callSessionInviteParticipantsRequestFailed(ImsCallSession.this, + reasonInfo); + } + }, mListenerExecutor); } @Override public void callSessionRemoveParticipantsRequestDelivered() { - if (mListener != null) { - mListener.callSessionRemoveParticipantsRequestDelivered(ImsCallSession.this); - } + TelephonyUtils.runWithCleanCallingIdentity(()-> { + if (mListener != null) { + mListener.callSessionRemoveParticipantsRequestDelivered(ImsCallSession.this); + } + }, mListenerExecutor); } @Override public void callSessionRemoveParticipantsRequestFailed(ImsReasonInfo reasonInfo) { - if (mListener != null) { - mListener.callSessionRemoveParticipantsRequestFailed(ImsCallSession.this, - reasonInfo); - } + TelephonyUtils.runWithCleanCallingIdentity(()-> { + if (mListener != null) { + mListener.callSessionRemoveParticipantsRequestFailed(ImsCallSession.this, + reasonInfo); + } + }, mListenerExecutor); } /** @@ -1424,9 +1481,11 @@ public class ImsCallSession { */ @Override public void callSessionConferenceStateUpdated(ImsConferenceState state) { - if (mListener != null) { - mListener.callSessionConferenceStateUpdated(ImsCallSession.this, state); - } + TelephonyUtils.runWithCleanCallingIdentity(()-> { + if (mListener != null) { + mListener.callSessionConferenceStateUpdated(ImsCallSession.this, state); + } + }, mListenerExecutor); } /** @@ -1434,9 +1493,12 @@ public class ImsCallSession { */ @Override public void callSessionUssdMessageReceived(int mode, String ussdMessage) { - if (mListener != null) { - mListener.callSessionUssdMessageReceived(ImsCallSession.this, mode, ussdMessage); - } + TelephonyUtils.runWithCleanCallingIdentity(()-> { + if (mListener != null) { + mListener.callSessionUssdMessageReceived(ImsCallSession.this, mode, + ussdMessage); + } + }, mListenerExecutor); } /** @@ -1452,10 +1514,12 @@ public class ImsCallSession { */ @Override public void callSessionMayHandover(int srcNetworkType, int targetNetworkType) { - if (mListener != null) { - mListener.callSessionMayHandover(ImsCallSession.this, srcNetworkType, - targetNetworkType); - } + TelephonyUtils.runWithCleanCallingIdentity(()-> { + if (mListener != null) { + mListener.callSessionMayHandover(ImsCallSession.this, srcNetworkType, + targetNetworkType); + } + }, mListenerExecutor); } /** @@ -1464,10 +1528,12 @@ public class ImsCallSession { @Override public void callSessionHandover(int srcNetworkType, int targetNetworkType, ImsReasonInfo reasonInfo) { - if (mListener != null) { - mListener.callSessionHandover(ImsCallSession.this, srcNetworkType, - targetNetworkType, reasonInfo); - } + TelephonyUtils.runWithCleanCallingIdentity(()-> { + if (mListener != null) { + mListener.callSessionHandover(ImsCallSession.this, srcNetworkType, + targetNetworkType, reasonInfo); + } + }, mListenerExecutor); } /** @@ -1476,10 +1542,12 @@ public class ImsCallSession { @Override public void callSessionHandoverFailed(int srcNetworkType, int targetNetworkType, ImsReasonInfo reasonInfo) { - if (mListener != null) { - mListener.callSessionHandoverFailed(ImsCallSession.this, srcNetworkType, - targetNetworkType, reasonInfo); - } + TelephonyUtils.runWithCleanCallingIdentity(()-> { + if (mListener != null) { + mListener.callSessionHandoverFailed(ImsCallSession.this, srcNetworkType, + targetNetworkType, reasonInfo); + } + }, mListenerExecutor); } /** @@ -1487,9 +1555,11 @@ public class ImsCallSession { */ @Override public void callSessionTtyModeReceived(int mode) { - if (mListener != null) { - mListener.callSessionTtyModeReceived(ImsCallSession.this, mode); - } + TelephonyUtils.runWithCleanCallingIdentity(()-> { + if (mListener != null) { + mListener.callSessionTtyModeReceived(ImsCallSession.this, mode); + } + }, mListenerExecutor); } /** @@ -1499,16 +1569,22 @@ public class ImsCallSession { * otherwise. */ public void callSessionMultipartyStateChanged(boolean isMultiParty) { - if (mListener != null) { - mListener.callSessionMultipartyStateChanged(ImsCallSession.this, isMultiParty); - } + TelephonyUtils.runWithCleanCallingIdentity(()-> { + if (mListener != null) { + mListener.callSessionMultipartyStateChanged(ImsCallSession.this, + isMultiParty); + } + }, mListenerExecutor); } @Override public void callSessionSuppServiceReceived(ImsSuppServiceNotification suppServiceInfo ) { - if (mListener != null) { - mListener.callSessionSuppServiceReceived(ImsCallSession.this, suppServiceInfo); - } + TelephonyUtils.runWithCleanCallingIdentity(()-> { + if (mListener != null) { + mListener.callSessionSuppServiceReceived(ImsCallSession.this, + suppServiceInfo); + } + }, mListenerExecutor); } /** @@ -1516,9 +1592,12 @@ public class ImsCallSession { */ @Override public void callSessionRttModifyRequestReceived(ImsCallProfile callProfile) { - if (mListener != null) { - mListener.callSessionRttModifyRequestReceived(ImsCallSession.this, callProfile); - } + TelephonyUtils.runWithCleanCallingIdentity(()-> { + if (mListener != null) { + mListener.callSessionRttModifyRequestReceived(ImsCallSession.this, + callProfile); + } + }, mListenerExecutor); } /** @@ -1526,9 +1605,11 @@ public class ImsCallSession { */ @Override public void callSessionRttModifyResponseReceived(int status) { - if (mListener != null) { - mListener.callSessionRttModifyResponseReceived(status); - } + TelephonyUtils.runWithCleanCallingIdentity(()-> { + if (mListener != null) { + mListener.callSessionRttModifyResponseReceived(status); + } + }, mListenerExecutor); } /** @@ -1536,9 +1617,11 @@ public class ImsCallSession { */ @Override public void callSessionRttMessageReceived(String rttMessage) { - if (mListener != null) { - mListener.callSessionRttMessageReceived(rttMessage); - } + TelephonyUtils.runWithCleanCallingIdentity(()-> { + if (mListener != null) { + mListener.callSessionRttMessageReceived(rttMessage); + } + }, mListenerExecutor); } /** @@ -1546,23 +1629,29 @@ public class ImsCallSession { */ @Override public void callSessionRttAudioIndicatorChanged(ImsStreamMediaProfile profile) { - if (mListener != null) { - mListener.callSessionRttAudioIndicatorChanged(profile); - } + TelephonyUtils.runWithCleanCallingIdentity(()-> { + if (mListener != null) { + mListener.callSessionRttAudioIndicatorChanged(profile); + } + }, mListenerExecutor); } @Override public void callSessionTransferred() { - if (mListener != null) { - mListener.callSessionTransferred(ImsCallSession.this); - } + TelephonyUtils.runWithCleanCallingIdentity(()-> { + if (mListener != null) { + mListener.callSessionTransferred(ImsCallSession.this); + } + }, mListenerExecutor); } @Override public void callSessionTransferFailed(@Nullable ImsReasonInfo reasonInfo) { - if (mListener != null) { - mListener.callSessionTransferFailed(ImsCallSession.this, reasonInfo); - } + TelephonyUtils.runWithCleanCallingIdentity(()-> { + if (mListener != null) { + mListener.callSessionTransferFailed(ImsCallSession.this, reasonInfo); + } + }, mListenerExecutor); } /** @@ -1571,9 +1660,11 @@ public class ImsCallSession { */ @Override public void callSessionDtmfReceived(char dtmf) { - if (mListener != null) { - mListener.callSessionDtmfReceived(dtmf); - } + TelephonyUtils.runWithCleanCallingIdentity(()-> { + if (mListener != null) { + mListener.callSessionDtmfReceived(dtmf); + } + }, mListenerExecutor); } /** @@ -1581,9 +1672,11 @@ public class ImsCallSession { */ @Override public void callQualityChanged(CallQuality callQuality) { - if (mListener != null) { - mListener.callQualityChanged(callQuality); - } + TelephonyUtils.runWithCleanCallingIdentity(()-> { + if (mListener != null) { + mListener.callQualityChanged(callQuality); + } + }, mListenerExecutor); } /** @@ -1593,10 +1686,12 @@ public class ImsCallSession { @Override public void callSessionRtpHeaderExtensionsReceived( @NonNull List<RtpHeaderExtension> extensions) { - if (mListener != null) { - mListener.callSessionRtpHeaderExtensionsReceived( - new ArraySet<RtpHeaderExtension>(extensions)); - } + TelephonyUtils.runWithCleanCallingIdentity(()-> { + if (mListener != null) { + mListener.callSessionRtpHeaderExtensionsReceived( + new ArraySet<RtpHeaderExtension>(extensions)); + } + }, mListenerExecutor); } } diff --git a/telephony/java/android/telephony/ims/ImsService.java b/telephony/java/android/telephony/ims/ImsService.java index 9ab5aeb9c34c..be233b82c426 100644 --- a/telephony/java/android/telephony/ims/ImsService.java +++ b/telephony/java/android/telephony/ims/ImsService.java @@ -17,6 +17,7 @@ package android.telephony.ims; import android.annotation.LongDef; +import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SuppressLint; import android.annotation.SystemApi; @@ -41,14 +42,22 @@ import android.telephony.ims.stub.ImsRegistrationImplBase; import android.telephony.ims.stub.SipTransportImplBase; import android.util.Log; import android.util.SparseArray; +import android.util.SparseBooleanArray; import com.android.ims.internal.IImsFeatureStatusCallback; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.telephony.util.TelephonyUtils; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.CancellationException; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executor; +import java.util.function.Supplier; /** * Main ImsService implementation, which binds via the Telephony ImsResolver. Services that extend @@ -172,8 +181,28 @@ public class ImsService extends Service { // call ImsFeature#onFeatureRemoved. private final SparseArray<SparseArray<ImsFeature>> mFeaturesBySlot = new SparseArray<>(); + // A map of slot id -> boolean array, where each entry in the boolean array corresponds to an + // ImsFeature that was created for a slot id and not a sub id for backwards compatibility + // purposes. + private final SparseArray<SparseBooleanArray> mCreateImsFeatureWithSlotIdFlagMap = + new SparseArray<>(); + private IImsServiceControllerListener mListener; + private Executor mExecutor; + /** + * Create a new ImsService. + * <p> + * Method stubs called from the framework will be called asynchronously. Vendor specifies the + * {@link Executor} that the methods stubs will be called. If mExecutor is set to null by + * vendor use Runnable::run. + */ + public ImsService() { + mExecutor = ImsService.this.getExecutor(); + if (mExecutor == null) { + mExecutor = Runnable::run; + } + } /** * Listener that notifies the framework of ImsService changes. @@ -200,79 +229,163 @@ public class ImsService extends Service { } @Override - public IImsMmTelFeature createMmTelFeature(int slotId) { - return createMmTelFeatureInternal(slotId); + public IImsMmTelFeature createMmTelFeature(int slotId, int subId) { + MmTelFeature f = (MmTelFeature) getImsFeature(slotId, ImsFeature.FEATURE_MMTEL); + if (f == null) { + return executeMethodAsyncForResult(() -> createMmTelFeatureInternal(slotId, subId), + "createMmTelFeature"); + } else { + return f.getBinder(); + } + } + + @Override + public IImsMmTelFeature createEmergencyOnlyMmTelFeature(int slotId) { + MmTelFeature f = (MmTelFeature) getImsFeature(slotId, ImsFeature.FEATURE_MMTEL); + if (f == null) { + return executeMethodAsyncForResult(() -> createEmergencyOnlyMmTelFeatureInternal( + slotId), "createEmergencyOnlyMmTelFeature"); + } else { + return f.getBinder(); + } } @Override - public IImsRcsFeature createRcsFeature(int slotId) { - return createRcsFeatureInternal(slotId); + public IImsRcsFeature createRcsFeature(int slotId, int subId) { + RcsFeature f = (RcsFeature) getImsFeature(slotId, ImsFeature.FEATURE_RCS); + if (f == null) { + return executeMethodAsyncForResult(() -> + createRcsFeatureInternal(slotId, subId), "createRcsFeature"); + } else { + return f.getBinder(); + } } @Override public void addFeatureStatusCallback(int slotId, int featureType, IImsFeatureStatusCallback c) { - ImsService.this.addImsFeatureStatusCallback(slotId, featureType, c); + executeMethodAsync(() -> ImsService.this.addImsFeatureStatusCallback( + slotId, featureType, c), "addFeatureStatusCallback"); } @Override public void removeFeatureStatusCallback(int slotId, int featureType, IImsFeatureStatusCallback c) { - ImsService.this.removeImsFeatureStatusCallback(slotId, featureType, c); + executeMethodAsync(() -> ImsService.this.removeImsFeatureStatusCallback( + slotId, featureType, c), "removeFeatureStatusCallback"); } @Override - public void removeImsFeature(int slotId, int featureType) { - ImsService.this.removeImsFeature(slotId, featureType); + public void removeImsFeature(int slotId, int featureType, boolean changeSubId) { + if (changeSubId && isImsFeatureCreatedForSlot(slotId, featureType)) { + Log.w(LOG_TAG, "Do not remove Ims feature for compatibility"); + return; + } + executeMethodAsync(() -> ImsService.this.removeImsFeature(slotId, featureType), + "removeImsFeature"); + setImsFeatureCreatedForSlot(slotId, featureType, false); } @Override public ImsFeatureConfiguration querySupportedImsFeatures() { - return ImsService.this.querySupportedImsFeatures(); + return executeMethodAsyncForResult(() -> ImsService.this.querySupportedImsFeatures(), + "ImsFeatureConfiguration"); } @Override public long getImsServiceCapabilities() { - long caps = ImsService.this.getImsServiceCapabilities(); - long sanitizedCaps = sanitizeCapabilities(caps); - if (caps != sanitizedCaps) { - Log.w(LOG_TAG, "removing invalid bits from field: 0x" - + Long.toHexString(caps ^ sanitizedCaps)); - } - return sanitizedCaps; + return executeMethodAsyncForResult(() -> { + long caps = ImsService.this.getImsServiceCapabilities(); + long sanitizedCaps = sanitizeCapabilities(caps); + if (caps != sanitizedCaps) { + Log.w(LOG_TAG, "removing invalid bits from field: 0x" + + Long.toHexString(caps ^ sanitizedCaps)); + } + return sanitizedCaps; + }, "getImsServiceCapabilities"); } @Override public void notifyImsServiceReadyForFeatureCreation() { - ImsService.this.readyForFeatureCreation(); + executeMethodAsync(() -> ImsService.this.readyForFeatureCreation(), + "notifyImsServiceReadyForFeatureCreation"); } @Override - public IImsConfig getConfig(int slotId) { - ImsConfigImplBase c = ImsService.this.getConfig(slotId); - return c != null ? c.getIImsConfig() : null; + public IImsConfig getConfig(int slotId, int subId) { + return executeMethodAsyncForResult(() -> { + ImsConfigImplBase c = + ImsService.this.getConfigForSubscription(slotId, subId); + if (c != null) { + c.setDefaultExecutor(mExecutor); + return c.getIImsConfig(); + } else { + return null; + } + }, "getConfig"); } @Override - public IImsRegistration getRegistration(int slotId) { - ImsRegistrationImplBase r = ImsService.this.getRegistration(slotId); - return r != null ? r.getBinder() : null; + public IImsRegistration getRegistration(int slotId, int subId) { + return executeMethodAsyncForResult(() -> { + ImsRegistrationImplBase r = + ImsService.this.getRegistrationForSubscription(slotId, subId); + if (r != null) { + r.setDefaultExecutor(mExecutor); + return r.getBinder(); + } else { + return null; + } + }, "getRegistration"); } @Override public ISipTransport getSipTransport(int slotId) { - SipTransportImplBase s = ImsService.this.getSipTransport(slotId); - return s != null ? s.getBinder() : null; + return executeMethodAsyncForResult(() -> { + SipTransportImplBase s = ImsService.this.getSipTransport(slotId); + if (s != null) { + s.setDefaultExecutor(mExecutor); + return s.getBinder(); + } else { + return null; + } + }, "getSipTransport"); } @Override - public void enableIms(int slotId) { - ImsService.this.enableIms(slotId); + public void enableIms(int slotId, int subId) { + executeMethodAsync(() -> + ImsService.this.enableImsForSubscription(slotId, subId), "enableIms"); } @Override - public void disableIms(int slotId) { - ImsService.this.disableIms(slotId); + public void disableIms(int slotId, int subId) { + executeMethodAsync(() -> + ImsService.this.disableImsForSubscription(slotId, subId), "disableIms"); + } + + // Call the methods with a clean calling identity on the executor and wait indefinitely for + // the future to return. + private void executeMethodAsync(Runnable r, String errorLogName) { + try { + CompletableFuture.runAsync( + () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join(); + } catch (CancellationException | CompletionException e) { + Log.w(LOG_TAG, "ImsService Binder - " + errorLogName + " exception: " + + e.getMessage()); + } + } + + private <T> T executeMethodAsyncForResult(Supplier<T> r, String errorLogName) { + CompletableFuture<T> future = CompletableFuture.supplyAsync( + () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor); + try { + return future.get(); + } catch (ExecutionException | InterruptedException e) { + Log.w(LOG_TAG, "ImsService Binder - " + errorLogName + " exception: " + + e.getMessage()); + return null; + } } }; @@ -288,28 +401,34 @@ public class ImsService extends Service { return null; } - /** - * @hide - */ - @VisibleForTesting - public SparseArray<ImsFeature> getFeatures(int slotId) { - return mFeaturesBySlot.get(slotId); + private IImsMmTelFeature createMmTelFeatureInternal(int slotId, int subscriptionId) { + MmTelFeature f = createMmTelFeatureForSubscription(slotId, subscriptionId); + if (f != null) { + setupFeature(f, slotId, ImsFeature.FEATURE_MMTEL); + f.setDefaultExecutor(mExecutor); + return f.getBinder(); + } else { + Log.e(LOG_TAG, "createMmTelFeatureInternal: null feature returned."); + return null; + } } - private IImsMmTelFeature createMmTelFeatureInternal(int slotId) { - MmTelFeature f = createMmTelFeature(slotId); + private IImsMmTelFeature createEmergencyOnlyMmTelFeatureInternal(int slotId) { + MmTelFeature f = createEmergencyOnlyMmTelFeature(slotId); if (f != null) { setupFeature(f, slotId, ImsFeature.FEATURE_MMTEL); + f.setDefaultExecutor(mExecutor); return f.getBinder(); } else { - Log.e(LOG_TAG, "createMmTelFeatureInternal: null feature returned."); + Log.e(LOG_TAG, "createEmergencyOnlyMmTelFeatureInternal: null feature returned."); return null; } } - private IImsRcsFeature createRcsFeatureInternal(int slotId) { - RcsFeature f = createRcsFeature(slotId); + private IImsRcsFeature createRcsFeatureInternal(int slotId, int subI) { + RcsFeature f = createRcsFeatureForSubscription(slotId, subI); if (f != null) { + f.setDefaultExecutor(mExecutor); setupFeature(f, slotId, ImsFeature.FEATURE_RCS); return f.getBinder(); } else { @@ -388,6 +507,49 @@ public class ImsService extends Service { f.onFeatureRemoved(); features.remove(featureType); } + + } + + /** + * @hide + */ + @VisibleForTesting + public ImsFeature getImsFeature(int slotId, int featureType) { + synchronized (mFeaturesBySlot) { + // Get SparseArray for Features, by querying slot Id + SparseArray<ImsFeature> features = mFeaturesBySlot.get(slotId); + if (features == null) { + return null; + } + return features.get(featureType); + } + } + + private void setImsFeatureCreatedForSlot(int slotId, + @ImsFeature.FeatureType int featureType, boolean createdForSlot) { + synchronized (mCreateImsFeatureWithSlotIdFlagMap) { + getImsFeatureCreatedForSlot(slotId).put(featureType, createdForSlot); + } + } + + /** + * @hide + */ + @VisibleForTesting + public boolean isImsFeatureCreatedForSlot(int slotId, + @ImsFeature.FeatureType int featureType) { + synchronized (mCreateImsFeatureWithSlotIdFlagMap) { + return getImsFeatureCreatedForSlot(slotId).get(featureType); + } + } + + private SparseBooleanArray getImsFeatureCreatedForSlot(int slotId) { + SparseBooleanArray createFlag = mCreateImsFeatureWithSlotIdFlagMap.get(slotId); + if (createFlag == null) { + createFlag = new SparseBooleanArray(); + mCreateImsFeatureWithSlotIdFlagMap.put(slotId, createFlag); + } + return createFlag; } /** @@ -446,27 +608,95 @@ public class ImsService extends Service { } /** + * The framework has enabled IMS for the subscription specified, the ImsService should register + * for IMS and perform all appropriate initialization to bring up all ImsFeatures. + * + * @param slotId The slot ID that IMS will be enabled for. + * @param subscriptionId The subscription ID that IMS will be enabled for. + */ + public void enableImsForSubscription(int slotId, int subscriptionId) { + enableIms(slotId); + } + + /** + * The framework has disabled IMS for the subscription specified. The ImsService must deregister + * for IMS and set capability status to false for all ImsFeatures. + * @param slotId The slot ID that IMS will be disabled for. + * @param subscriptionId The subscription ID that IMS will be disabled for. + */ + public void disableImsForSubscription(int slotId, int subscriptionId) { + disableIms(slotId); + } + + /** * The framework has enabled IMS for the slot specified, the ImsService should register for IMS * and perform all appropriate initialization to bring up all ImsFeatures. + * @deprecated Use {@link #enableImsForSubscription} instead. */ + @Deprecated public void enableIms(int slotId) { } /** * The framework has disabled IMS for the slot specified. The ImsService must deregister for IMS * and set capability status to false for all ImsFeatures. + * @deprecated Use {@link #disableImsForSubscription} instead. */ + @Deprecated public void disableIms(int slotId) { } /** * When called, the framework is requesting that a new {@link MmTelFeature} is created for the + * specified subscription. + * + * @param subscriptionId The subscription ID that the MMTEL Feature is being created for. + * @return The newly created {@link MmTelFeature} associated with the subscription or null if + * the feature is not supported. + */ + public @Nullable MmTelFeature createMmTelFeatureForSubscription(int slotId, + int subscriptionId) { + setImsFeatureCreatedForSlot(slotId, ImsFeature.FEATURE_MMTEL, true); + return createMmTelFeature(slotId); + } + + /** + * When called, the framework is requesting that a new {@link RcsFeature} is created for the + * specified subscription. + * + * @param subscriptionId The subscription ID that the RCS Feature is being created for. + * @return The newly created {@link RcsFeature} associated with the subscription or null if the + * feature is not supported. + */ + public @Nullable RcsFeature createRcsFeatureForSubscription(int slotId, int subscriptionId) { + setImsFeatureCreatedForSlot(slotId, ImsFeature.FEATURE_RCS, true); + return createRcsFeature(slotId); + } + + /** + * When called, the framework is requesting that a new emergency-only {@link MmTelFeature} is + * created for the specified slot. For emergency calls, there is no known Subscription Id. + * + * @param slotId The slot ID that the MMTEL Feature is being created for. + * @return An MmTelFeature instance to be used for the slot ID when there is not + * subscription inserted. Only requested when there is no subscription active on + * the specified slot. + */ + public @Nullable MmTelFeature createEmergencyOnlyMmTelFeature(int slotId) { + setImsFeatureCreatedForSlot(slotId, ImsFeature.FEATURE_MMTEL, true); + return createMmTelFeature(slotId); + } + + /** + * When called, the framework is requesting that a new {@link MmTelFeature} is created for the * specified slot. + * @deprecated Use {@link #createMmTelFeatureForSubscription} instead * * @param slotId The slot ID that the MMTEL Feature is being created for. * @return The newly created {@link MmTelFeature} associated with the slot or null if the * feature is not supported. */ + @Deprecated public MmTelFeature createMmTelFeature(int slotId) { return null; } @@ -474,32 +704,62 @@ public class ImsService extends Service { /** * When called, the framework is requesting that a new {@link RcsFeature} is created for the * specified slot. + * @deprecated Use {@link #createRcsFeatureForSubscription} instead * * @param slotId The slot ID that the RCS Feature is being created for. * @return The newly created {@link RcsFeature} associated with the slot or null if the feature * is not supported. */ + @Deprecated public RcsFeature createRcsFeature(int slotId) { return null; } /** + * Return the {@link ImsConfigImplBase} implementation associated with the provided + * subscription. This will be used by the platform to get/set specific IMS related + * configurations. + * + * @param subscriptionId The subscription ID that the IMS configuration is associated with. + * @return ImsConfig implementation that is associated with the specified subscription. + */ + public @NonNull ImsConfigImplBase getConfigForSubscription(int slotId, int subscriptionId) { + return getConfig(slotId); + } + + /** + * Return the {@link ImsRegistrationImplBase} implementation associated with the provided + * subscription. + * + * @param subscriptionId The subscription ID that is associated with the IMS Registration. + * @return the ImsRegistration implementation associated with the subscription. + */ + public @NonNull ImsRegistrationImplBase getRegistrationForSubscription(int slotId, + int subscriptionId) { + return getRegistration(slotId); + } + + /** * Return the {@link ImsConfigImplBase} implementation associated with the provided slot. This * will be used by the platform to get/set specific IMS related configurations. + * @deprecated use {@link #getConfigForSubscription} instead. * * @param slotId The slot that the IMS configuration is associated with. * @return ImsConfig implementation that is associated with the specified slot. */ + @Deprecated public ImsConfigImplBase getConfig(int slotId) { return new ImsConfigImplBase(); } /** * Return the {@link ImsRegistrationImplBase} implementation associated with the provided slot. + * @deprecated use {@link #getRegistrationForSubscription} instead. * * @param slotId The slot that is associated with the IMS Registration. * @return the ImsRegistration implementation associated with the slot. */ + @Deprecated public ImsRegistrationImplBase getRegistration(int slotId) { return new ImsRegistrationImplBase(); } @@ -562,4 +822,15 @@ public class ImsService extends Service { result.append("}"); return result.toString(); } + + /** + * The ImsService will now be able to define an Executor that the ImsService can be used to + * execute the methods. By default all ImsService level method calls will use this Executor. + * The ImsService has set the default executor as Runnable::run, + * Should be override or default executor will be used. + * @return an Executor used to execute methods called remotely by the framework. + */ + public @NonNull Executor getExecutor() { + return Runnable::run; + } } diff --git a/telephony/java/android/telephony/ims/ProvisioningManager.java b/telephony/java/android/telephony/ims/ProvisioningManager.java index abc5606e6743..5aef8a6638ac 100644 --- a/telephony/java/android/telephony/ims/ProvisioningManager.java +++ b/telephony/java/android/telephony/ims/ProvisioningManager.java @@ -33,6 +33,7 @@ import android.telephony.CarrierConfigManager; import android.telephony.SubscriptionManager; import android.telephony.TelephonyFrameworkInitializer; import android.telephony.TelephonyManager; +import android.telephony.ims.aidl.IFeatureProvisioningCallback; import android.telephony.ims.aidl.IImsConfigCallback; import android.telephony.ims.aidl.IRcsConfigCallback; import android.telephony.ims.feature.MmTelFeature; @@ -53,17 +54,11 @@ import java.util.concurrent.Executor; * IMS provisioning keys are defined per carrier or OEM using OMA-DM or other provisioning * applications and may vary. It is up to the carrier and OEM applications to ensure that the * correct provisioning keys are being used when integrating with a vendor's ImsService. - * - * Note: For compatibility purposes, the integer values [0 - 99] used in - * {@link #setProvisioningIntValue(int, int)} have been reserved for existing provisioning keys - * previously defined in the Android framework. Please do not redefine new provisioning keys in this - * range or it may generate collisions with existing keys. Some common constants have also been - * defined in this class to make integrating with other system apps easier. - * @hide */ -@SystemApi public class ProvisioningManager { + private static final String TAG = "ProvisioningManager"; + /**@hide*/ @StringDef(prefix = "STRING_QUERY_RESULT_ERROR_", value = { STRING_QUERY_RESULT_ERROR_GENERIC, @@ -74,14 +69,18 @@ public class ProvisioningManager { /** * The query from {@link #getProvisioningStringValue(int)} has resulted in an unspecified error. + * @hide */ + @SystemApi public static final String STRING_QUERY_RESULT_ERROR_GENERIC = "STRING_QUERY_RESULT_ERROR_GENERIC"; /** * The query from {@link #getProvisioningStringValue(int)} has resulted in an error because the * ImsService implementation was not ready for provisioning queries. + * @hide */ + @SystemApi public static final String STRING_QUERY_RESULT_ERROR_NOT_READY = "STRING_QUERY_RESULT_ERROR_NOT_READY"; @@ -93,12 +92,16 @@ public class ProvisioningManager { /** * The integer result of provisioning for the queried key is disabled. + * @hide */ + @SystemApi public static final int PROVISIONING_VALUE_DISABLED = 0; /** * The integer result of provisioning for the queried key is enabled. + * @hide */ + @SystemApi public static final int PROVISIONING_VALUE_ENABLED = 1; @@ -443,27 +446,31 @@ public class ProvisioningManager { /** * Override the user-defined WiFi Roaming enabled setting for this subscription, defined in - * {@link SubscriptionManager#WFC_ROAMING_ENABLED_CONTENT_URI}, for the purposes of provisioning - * the subscription for WiFi Calling. + * {@link android.telephony.SubscriptionManager#WFC_ROAMING_ENABLED_CONTENT_URI}, + * for the purposes of provisioning the subscription for WiFi Calling. * - * @see #getProvisioningIntValue(int) * @see #setProvisioningIntValue(int, int) + * @see #getProvisioningIntValue(int) + * @hide */ + @SystemApi public static final int KEY_VOICE_OVER_WIFI_ROAMING_ENABLED_OVERRIDE = 26; /** * Override the user-defined WiFi mode for this subscription, defined in - * {@link SubscriptionManager#WFC_MODE_CONTENT_URI}, for the purposes of provisioning - * this subscription for WiFi Calling. + * {@link android.telephony.SubscriptionManager#WFC_MODE_CONTENT_URI}, + * for the purposes of provisioning this subscription for WiFi Calling. * * Valid values for this key are: * {@link ImsMmTelManager#WIFI_MODE_WIFI_ONLY}, * {@link ImsMmTelManager#WIFI_MODE_CELLULAR_PREFERRED}, or * {@link ImsMmTelManager#WIFI_MODE_WIFI_PREFERRED}. * - * @see #getProvisioningIntValue(int) * @see #setProvisioningIntValue(int, int) + * @see #getProvisioningIntValue(int) + * @hide */ + @SystemApi public static final int KEY_VOICE_OVER_WIFI_MODE_OVERRIDE = 27; /** @@ -862,7 +869,9 @@ public class ProvisioningManager { * <p>Value is in String format. * @see #setProvisioningStringValue(int, String) * @see #getProvisioningStringValue(int) + * @hide */ + @SystemApi public static final int KEY_VOICE_OVER_WIFI_ENTITLEMENT_ID = 67; /** @@ -884,7 +893,9 @@ public class ProvisioningManager { /** * Callback for IMS provisioning changes. + * @hide */ + @SystemApi public static class Callback { private static class CallbackBinder extends IImsConfigCallback.Stub { @@ -954,11 +965,105 @@ public class ProvisioningManager { } } + /** + * Callback for IMS provisioning feature changes. + */ + public static class FeatureProvisioningCallback { + + private static class CallbackBinder extends IFeatureProvisioningCallback.Stub { + + private final FeatureProvisioningCallback mFeatureProvisioningCallback; + private Executor mExecutor; + + private CallbackBinder(FeatureProvisioningCallback featureProvisioningCallback) { + mFeatureProvisioningCallback = featureProvisioningCallback; + } + + @Override + public final void onFeatureProvisioningChanged( + int capability, int tech, boolean isProvisioned) { + final long callingIdentity = Binder.clearCallingIdentity(); + try { + mExecutor.execute(() -> + mFeatureProvisioningCallback.onFeatureProvisioningChanged( + capability, tech, isProvisioned)); + } finally { + restoreCallingIdentity(callingIdentity); + } + } + + @Override + public final void onRcsFeatureProvisioningChanged( + int capability, int tech, boolean isProvisioned) { + final long callingIdentity = Binder.clearCallingIdentity(); + try { + mExecutor.execute(() -> + mFeatureProvisioningCallback.onRcsFeatureProvisioningChanged( + capability, tech, isProvisioned)); + } finally { + restoreCallingIdentity(callingIdentity); + } + } + + private void setExecutor(Executor executor) { + mExecutor = executor; + } + } + + private final CallbackBinder mBinder = new CallbackBinder(this); + + /** + * The IMS MMTEL provisioning has changed for a specific capability and IMS + * registration technology. + * @param capability The MMTEL capability that provisioning has changed for. + * @param tech The IMS registration technology associated with the MMTEL capability that + * provisioning has changed for. + * @param isProvisioned {@code true} if the capability is provisioned for the technology + * specified, or {@code false} if the capability is not provisioned for the technology + * specified. + */ + public void onFeatureProvisioningChanged( + @MmTelFeature.MmTelCapabilities.MmTelCapability int capability, + @ImsRegistrationImplBase.ImsRegistrationTech int tech, + boolean isProvisioned) { + // Base Implementation + } + + /** + * The IMS RCS provisioning has changed for a specific capability and IMS + * registration technology. + * @param capability The RCS capability that provisioning has changed for. + * @param tech The IMS registration technology associated with the RCS capability that + * provisioning has changed for. + * @param isProvisioned {@code true} if the capability is provisioned for the technology + * specified, or {@code false} if the capability is not provisioned for the technology + * specified. + */ + public void onRcsFeatureProvisioningChanged( + @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability, + @ImsRegistrationImplBase.ImsRegistrationTech int tech, + boolean isProvisioned) { + // Base Implementation + } + + /**@hide*/ + public final IFeatureProvisioningCallback getBinder() { + return mBinder; + } + + /**@hide*/ + public void setExecutor(Executor executor) { + mBinder.setExecutor(executor); + } + } + private int mSubId; /** * The callback for RCS provisioning changes. + * @hide */ + @SystemApi public static class RcsProvisioningCallback { private static class CallbackBinder extends IRcsConfigCallback.Stub { @@ -1096,7 +1201,9 @@ public class ProvisioningManager { * @param subId The ID of the subscription that this ProvisioningManager will use. * @see android.telephony.SubscriptionManager#getActiveSubscriptionInfoList() * @throws IllegalArgumentException if the subscription is invalid. + * @hide */ + @SystemApi public static @NonNull ProvisioningManager createForSubscriptionId(int subId) { if (!SubscriptionManager.isValidSubscriptionId(subId)) { throw new IllegalArgumentException("Invalid subscription ID"); @@ -1105,7 +1212,9 @@ public class ProvisioningManager { return new ProvisioningManager(subId); } - private ProvisioningManager(int subId) { + /**@hide*/ + //@SystemApi + public ProvisioningManager(int subId) { mSubId = subId; } @@ -1114,6 +1223,12 @@ public class ProvisioningManager { * * When the subscription associated with this callback is removed (SIM removed, ESIM swap, * etc...), this callback will automatically be removed. + * + * <p> Requires Permission: + * <ul> + * <li>{@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE},</li> + * </ul> + * * @param executor The {@link Executor} to call the callback methods on * @param callback The provisioning callbackto be registered. * @see #unregisterProvisioningChangedCallback(Callback) @@ -1124,7 +1239,9 @@ public class ProvisioningManager { * the {@link ImsService} associated with the subscription is not available. This can happen if * the service crashed, for example. See {@link ImsException#getCode()} for a more detailed * reason. + * @hide */ + @SystemApi @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerProvisioningChangedCallback(@NonNull @CallbackExecutor Executor executor, @NonNull Callback callback) throws ImsException { @@ -1142,12 +1259,20 @@ public class ProvisioningManager { * Unregister an existing {@link Callback}. When the subscription associated with this * callback is removed (SIM removed, ESIM swap, etc...), this callback will automatically be * removed. If this method is called for an inactive subscription, it will result in a no-op. + * + * <p> Requires Permission: + * <ul> + * <li>{@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE},</li> + * </ul> + * * @param callback The existing {@link Callback} to be removed. * @see #registerProvisioningChangedCallback(Executor, Callback) * * @throws IllegalArgumentException if the subscription associated with this callback is * invalid. + * @hide */ + @SystemApi @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterProvisioningChangedCallback(@NonNull Callback callback) { try { @@ -1158,6 +1283,62 @@ public class ProvisioningManager { } /** + * Register a new {@link FeatureProvisioningCallback}, which is used to listen for + * IMS feature provisioning updates. + * <p> + * When the subscription associated with this callback is removed (SIM removed, + * ESIM swap,etc...), this callback will automatically be removed. + * + * <p> Requires Permission: + * <ul> + * <li> android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE,</li> + * <li>{@link android.Manifest.permission#READ_PRECISE_PHONE_STATE},</li> + * <li>or that the caller has carrier privileges (see + * {@link TelephonyManager#hasCarrierPrivileges()}).</li> + * </ul> + * + * @param executor The executor that the callback methods will be called on. + * @param callback The callback instance being registered. + * @throws ImsException if the subscription associated with this callback is + * valid, but the {@link ImsService the service crashed, for example. See + * {@link ImsException#getCode()} for a more detailed reason. + */ + @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE) + public void registerFeatureProvisioningChangedCallback( + @NonNull @CallbackExecutor Executor executor, + @NonNull FeatureProvisioningCallback callback) throws ImsException { + callback.setExecutor(executor); + try { + getITelephony().registerFeatureProvisioningChangedCallback(mSubId, + callback.getBinder()); + } catch (ServiceSpecificException e) { + throw new ImsException(e.getMessage(), e.errorCode); + } catch (RemoteException | IllegalStateException e) { + throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); + } + } + + /** + * Unregisters a previously registered {@link FeatureProvisioningCallback} + * instance. When the subscription associated with this + * callback is removed (SIM removed, ESIM swap, etc...), this callback will + * automatically be removed. If this method is called for an inactive + * subscription, it will result in a no-op. + * + * @param callback The existing {@link FeatureProvisioningCallback} to be removed. + * @see #registerFeatureProvisioningChangedCallback(Executor, FeatureProvisioningCallback) + */ + public void unregisterFeatureProvisioningChangedCallback( + @NonNull FeatureProvisioningCallback callback) { + try { + getITelephony().unregisterFeatureProvisioningChangedCallback(mSubId, + callback.getBinder()); + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } + } + + /** * Query for the integer value associated with the provided key. * * This operation is blocking and should not be performed on the UI thread. @@ -1166,7 +1347,9 @@ public class ProvisioningManager { * @return an integer value for the provided key, or * {@link ImsConfigImplBase#CONFIG_RESULT_UNKNOWN} if the key doesn't exist. * @throws IllegalArgumentException if the key provided was invalid. + * @hide */ + @SystemApi @WorkerThread @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getProvisioningIntValue(int key) { @@ -1186,7 +1369,9 @@ public class ProvisioningManager { * @return a String value for the provided key, {@code null} if the key doesn't exist, or * {@link StringResultError} if there was an error getting the value for the provided key. * @throws IllegalArgumentException if the key provided was invalid. + * @hide */ + @SystemApi @WorkerThread @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public @Nullable @StringResultError String getProvisioningStringValue(int key) { @@ -1207,7 +1392,15 @@ public class ProvisioningManager { * @param key An integer that represents the provisioning key, which is defined by the OEM. * @param value a integer value for the provided key. * @return the result of setting the configuration value. + * @hide + * + * Note: For compatibility purposes, the integer values [0 - 99] used in + * {@link #setProvisioningIntValue(int, int)} have been reserved for existing provisioning keys + * previously defined in the Android framework. Please do not redefine new provisioning keys + * in this range or it may generate collisions with existing keys. Some common constants have + * also been defined in this class to make integrating with other system apps easier. */ + @SystemApi @WorkerThread @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) public @ImsConfigImplBase.SetConfigResult int setProvisioningIntValue(int key, int value) { @@ -1227,7 +1420,9 @@ public class ProvisioningManager { * should be appropriately namespaced to avoid collision. * @param value a String value for the provided key. * @return the result of setting the configuration value. + * @hide */ + @SystemApi @WorkerThread @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) public @ImsConfigImplBase.SetConfigResult int setProvisioningStringValue(int key, @@ -1247,8 +1442,14 @@ public class ProvisioningManager { * does not support the capability/technology combination specified, this operation will be a * no-op. * - * @see CarrierConfigManager#KEY_CARRIER_UT_PROVISIONING_REQUIRED_BOOL - * @see CarrierConfigManager#KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL + * <p>Requires Permission: + * <ul> + * <li>{@link android.Manifest.permission#MODIFY_PHONE_STATE},</li> + * <li>or that the calling app has carrier privileges (see</li> + * <li>{@link TelephonyManager#hasCarrierPrivileges}).</li> + * </ul> + * + * @see CarrierConfigManager.Ims#KEY_MMTEL_REQUIRES_PROVISIONING_BUNDLE * @param isProvisioned true if the device is provisioned for UT over IMS, false otherwise. */ @WorkerThread @@ -1256,9 +1457,10 @@ public class ProvisioningManager { public void setProvisioningStatusForCapability( @MmTelFeature.MmTelCapabilities.MmTelCapability int capability, @ImsRegistrationImplBase.ImsRegistrationTech int tech, boolean isProvisioned) { + try { getITelephony().setImsProvisioningStatusForCapability(mSubId, capability, tech, - isProvisioned); + isProvisioned); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } @@ -1272,14 +1474,21 @@ public class ProvisioningManager { * {@link ImsRegistrationImplBase.ImsRegistrationTech} combination specified, this method will * always return {@code true}. * - * @see CarrierConfigManager#KEY_CARRIER_UT_PROVISIONING_REQUIRED_BOOL - * @see CarrierConfigManager#KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL + * <p> Requires Permission: + * <ul> + * <li>android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE,</li> + * <li>{@link android.Manifest.permission#READ_PRECISE_PHONE_STATE},</li> + * <li>or that the caller has carrier privileges (see + * {@link TelephonyManager#hasCarrierPrivileges()}).</li> + * </ul> + * + * @see CarrierConfigManager.Ims#KEY_MMTEL_REQUIRES_PROVISIONING_BUNDLE * @return true if the device is provisioned for the capability or does not require * provisioning, false if the capability does require provisioning and has not been * provisioned yet. */ @WorkerThread - @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE) public boolean getProvisioningStatusForCapability( @MmTelFeature.MmTelCapabilities.MmTelCapability int capability, @ImsRegistrationImplBase.ImsRegistrationTech int tech) { @@ -1297,17 +1506,55 @@ public class ProvisioningManager { * {@link RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag} this method will always return * {@code true}. * - * @see CarrierConfigManager#KEY_CARRIER_RCS_PROVISIONING_REQUIRED_BOOL + * @see CarrierConfigManager.Ims#KEY_CARRIER_RCS_PROVISIONING_REQUIRED_BOOL * @return true if the device is provisioned for the capability or does not require * provisioning, false if the capability does require provisioning and has not been * provisioned yet. + * @deprecated Use {@link #getRcsProvisioningStatusForCapability(int, int)} instead, + * as this only retrieves provisioning information for + * {@link ImsRegistrationImplBase#REGISTRATION_TECH_LTE} + * @hide */ + @Deprecated + @SystemApi @WorkerThread @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean getRcsProvisioningStatusForCapability( @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability) { try { - return getITelephony().getRcsProvisioningStatusForCapability(mSubId, capability); + return getITelephony().getRcsProvisioningStatusForCapability(mSubId, capability, + ImsRegistrationImplBase.REGISTRATION_TECH_LTE); + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } + } + + /** + * Get the provisioning status for the IMS RCS capability specified. + * + * If provisioning is not required for the queried + * {@link RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag} this method + * will always return {@code true}. + * + * <p> Requires Permission: + * <ul> + * <li>{@link android.Manifest.permission#READ_PRECISE_PHONE_STATE},</li> + * <li>or that the caller has carrier privileges (see + * {@link TelephonyManager#hasCarrierPrivileges()}).</li> + * </ul> + * + * @see CarrierConfigManager.Ims#KEY_RCS_REQUIRES_PROVISIONING_BUNDLE + * @return true if the device is provisioned for the capability or does not require + * provisioning, false if the capability does require provisioning and has not been + * provisioned yet. + */ + @WorkerThread + @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE) + public boolean getRcsProvisioningStatusForCapability( + @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability, + @ImsRegistrationImplBase.ImsRegistrationTech int tech) { + try { + return getITelephony().getRcsProvisioningStatusForCapability(mSubId, capability, tech); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } @@ -1316,6 +1563,13 @@ public class ProvisioningManager { /** * Set the provisioning status for the IMS RCS capability using the specified subscription. * + * <p> Requires Permission: + * <ul> + * <li>{@link android.Manifest.permission#MODIFY_PHONE_STATE}</li> + * <li>or that the caller has carrier privileges (see + * {@link TelephonyManager#hasCarrierPrivileges()}).</li> + * </ul> + * Provisioning may or may not be required, depending on the carrier configuration. If * provisioning is not required for the carrier associated with this subscription or the device * does not support the capability/technology combination specified, this operation will be a @@ -1324,7 +1578,13 @@ public class ProvisioningManager { * @see CarrierConfigManager#KEY_CARRIER_RCS_PROVISIONING_REQUIRED_BOOL * @param isProvisioned true if the device is provisioned for the RCS capability specified, * false otherwise. + * @deprecated Use {@link #setRcsProvisioningStatusForCapability(int, int, boolean)} instead, + * as this method only sets provisioning information for + * {@link ImsRegistrationImplBase#REGISTRATION_TECH_LTE} + * @hide */ + @Deprecated + @SystemApi @WorkerThread @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) public void setRcsProvisioningStatusForCapability( @@ -1332,28 +1592,121 @@ public class ProvisioningManager { boolean isProvisioned) { try { getITelephony().setRcsProvisioningStatusForCapability(mSubId, capability, - isProvisioned); + ImsRegistrationImplBase.REGISTRATION_TECH_LTE, isProvisioned); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } } /** + * Set the provisioning status for the IMS RCS capability using the specified subscription. + * + * Provisioning may or may not be required, depending on the carrier configuration. If + * provisioning is not required for the carrier associated with this subscription or the device + * does not support the capability/technology combination specified, this operation will be a + * no-op. + * + * <p> Requires Permission: + * <ul> + * <li>{@link android.Manifest.permission#MODIFY_PHONE_STATE},</li> + * <li>or that the caller has carrier privileges (see + * {@link TelephonyManager#hasCarrierPrivileges()}).</li> + * </ul> + * + * @see CarrierConfigManager.Ims#KEY_RCS_REQUIRES_PROVISIONING_BUNDLE + * @param isProvisioned true if the device is provisioned for the RCS capability specified, + * false otherwise. + */ + @WorkerThread + @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) + public void setRcsProvisioningStatusForCapability( + @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability, + @ImsRegistrationImplBase.ImsRegistrationTech int tech, boolean isProvisioned) { + try { + getITelephony().setRcsProvisioningStatusForCapability(mSubId, capability, + tech, isProvisioned); + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } + } + + /** + * Indicates whether provisioning for the MMTEL capability and IMS registration technology + * specified is required or not + * + * <p> Requires Permission: + * <ul> + * <li> android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE,</li> + * <li>{@link android.Manifest.permission#READ_PRECISE_PHONE_STATE},</li> + * <li> or that the caller has carrier privileges (see + * {@link TelephonyManager#hasCarrierPrivileges()}).</li> + * </ul> + * + * @return true if provisioning is required for the MMTEL capability and IMS + * registration technology specified, false if it is not required. + */ + @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE) + public boolean isProvisioningRequiredForCapability( + @MmTelFeature.MmTelCapabilities.MmTelCapability int capability, + @ImsRegistrationImplBase.ImsRegistrationTech int tech) { + try { + return getITelephony().isProvisioningRequiredForCapability(mSubId, capability, tech); + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } + } + + + /** + * Indicates whether provisioning for the RCS capability and IMS registration technology + * specified is required or not + * + * <p> Requires Permission: + * <ul> + * <li> android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE,</li> + * <li>{@link android.Manifest.permission#READ_PRECISE_PHONE_STATE},</li> + * <li> or that the caller has carrier privileges (see + * {@link TelephonyManager#hasCarrierPrivileges()}).</li> + * </ul> + * + * @return true if provisioning is required for the RCS capability and IMS + * registration technology specified, false if it is not required. + */ + @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE) + public boolean isRcsProvisioningRequiredForCapability( + @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability, + @ImsRegistrationImplBase.ImsRegistrationTech int tech) { + try { + return getITelephony().isRcsProvisioningRequiredForCapability(mSubId, capability, tech); + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } + } + + + /** * Notify the framework that an RCS autoconfiguration XML file has been received for * provisioning. - * <p> - * Requires Permission: Manifest.permission.MODIFY_PHONE_STATE or that the calling app has - * carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges}). + * + * <p>Requires Permission: + * <ul> + * <li>{@link Manifest.permission#MODIFY_PHONE_STATE},</li> + * <li>or that the calling app has carrier privileges (see + * {@link TelephonyManager#hasCarrierPrivileges()}).</li> + * </ul> + * * @param config The XML file to be read. ASCII/UTF8 encoded text if not compressed. * @param isCompressed The XML file is compressed in gzip format and must be decompressed * before being read. - * + * @hide */ + @SystemApi @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) public void notifyRcsAutoConfigurationReceived(@NonNull byte[] config, boolean isCompressed) { if (config == null) { throw new IllegalArgumentException("Must include a non-null config XML file."); } + try { getITelephony().notifyRcsAutoConfigurationReceived(mSubId, config, isCompressed); } catch (RemoteException e) { @@ -1372,7 +1725,9 @@ public class ProvisioningManager { * <p>Contains {@link #EXTRA_SUBSCRIPTION_ID} to specify the subscription index for which * the intent is valid. and {@link #EXTRA_STATUS} to specify RCS VoLTE single registration * status. + * @hide */ + @SystemApi @RequiresPermission(Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION) @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_RCS_SINGLE_REGISTRATION_CAPABILITY_UPDATE = @@ -1380,7 +1735,9 @@ public class ProvisioningManager { /** * Integer extra to specify subscription index. + * @hide */ + @SystemApi public static final String EXTRA_SUBSCRIPTION_ID = "android.telephony.ims.extra.SUBSCRIPTION_ID"; @@ -1390,22 +1747,30 @@ public class ProvisioningManager { * <p>The value can be {@link #STATUS_CAPABLE}, {@link #STATUS_DEVICE_NOT_CAPABLE}, * {@link #STATUS_CARRIER_NOT_CAPABLE}, or bitwise OR of * {@link #STATUS_DEVICE_NOT_CAPABLE} and {@link #STATUS_CARRIER_NOT_CAPABLE}. + * @hide */ + @SystemApi public static final String EXTRA_STATUS = "android.telephony.ims.extra.STATUS"; /** * RCS VoLTE single registration is supported by the device and carrier. + * @hide */ + @SystemApi public static final int STATUS_CAPABLE = 0; /** * RCS VoLTE single registration is not supported by the device. + * @hide */ + @SystemApi public static final int STATUS_DEVICE_NOT_CAPABLE = 0x01; /** * RCS VoLTE single registration is not supported by the carrier + * @hide */ + @SystemApi public static final int STATUS_CARRIER_NOT_CAPABLE = 0x01 << 1; /** @@ -1415,11 +1780,14 @@ public class ProvisioningManager { * provisioning is done using autoconfiguration, then these parameters shall be * sent in the HTTP get request to fetch the RCS provisioning. RCS client * configuration must be provided by the application before registering for the - * provisioning status events {@link #registerRcsProvisioningCallback()} + * provisioning status events + * {@link #registerRcsProvisioningCallback(Executor, RcsProvisioningCallback)} * When the IMS/RCS service receives the RCS client configuration, it will detect * the change in the configuration, and trigger the auto-configuration as needed. * @param rcc RCS client configuration {@link RcsClientConfiguration} + * @hide */ + @SystemApi @RequiresPermission(Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION) public void setRcsClientConfiguration( @NonNull RcsClientConfiguration rcc) throws ImsException { @@ -1440,18 +1808,21 @@ public class ProvisioningManager { * <ul> * <li>{@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE},</li> * <li>{@link android.Manifest.permission#PERFORM_IMS_SINGLE_REGISTRATION},</li> - * <li>or that the caller has carrier privileges (see + * <li>or that the calling app has carrier privileges (see * {@link TelephonyManager#hasCarrierPrivileges()}).</li> * </ul> + * * @return true if IMS single registration is capable at this time, or false otherwise - * @throws ImsException If the remote ImsService is not available for - * any reason or the subscription associated with this instance is no - * longer active. See {@link ImsException#getCode()} for more - * information. + * @throws ImsException If the remote ImsService is not available for any reason or + * the subscription associated with this instance is no longer active. + * See {@link ImsException#getCode()} for more information. * @see PackageManager#FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION for whether or not this * device supports IMS single registration. + * @hide */ - @RequiresPermission(anyOf = {Manifest.permission.READ_PRIVILEGED_PHONE_STATE, + @SystemApi + @RequiresPermission(anyOf = { + Manifest.permission.READ_PRIVILEGED_PHONE_STATE, Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION}) public boolean isRcsVolteSingleRegistrationCapable() throws ImsException { try { @@ -1478,8 +1849,6 @@ public class ProvisioningManager { * <ul> * <li>{@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE},</li> * <li>{@link android.Manifest.permission#PERFORM_IMS_SINGLE_REGISTRATION},</li> - * <li>or that the caller has carrier privileges (see - * {@link TelephonyManager#hasCarrierPrivileges()}).</li> * </ul> * * @param executor The {@link Executor} to call the callback methods on @@ -1497,8 +1866,11 @@ public class ProvisioningManager { * params (See {@link #setRcsClientConfiguration}) and re register the * callback. * See {@link ImsException#getCode()} for a more detailed reason. + * @hide */ - @RequiresPermission(anyOf = {Manifest.permission.READ_PRIVILEGED_PHONE_STATE, + @SystemApi + @RequiresPermission(anyOf = { + Manifest.permission.READ_PRIVILEGED_PHONE_STATE, Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION}) public void registerRcsProvisioningCallback( @NonNull @CallbackExecutor Executor executor, @@ -1525,8 +1897,6 @@ public class ProvisioningManager { * <ul> * <li>{@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE},</li> * <li>{@link android.Manifest.permission#PERFORM_IMS_SINGLE_REGISTRATION},</li> - * <li>or that the caller has carrier privileges (see - * {@link TelephonyManager#hasCarrierPrivileges()}).</li> * </ul> * * @param callback The existing {@link RcsProvisioningCallback} to be @@ -1534,8 +1904,11 @@ public class ProvisioningManager { * @see #registerRcsProvisioningCallback(Executor, RcsProvisioningCallback) * @throws IllegalArgumentException if the subscription associated with * this callback is invalid. + * @hide */ - @RequiresPermission(anyOf = {Manifest.permission.READ_PRIVILEGED_PHONE_STATE, + @SystemApi + @RequiresPermission(anyOf = { + Manifest.permission.READ_PRIVILEGED_PHONE_STATE, Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION}) public void unregisterRcsProvisioningCallback( @NonNull RcsProvisioningCallback callback) { @@ -1556,9 +1929,10 @@ public class ProvisioningManager { * {@link RcsProvisioningCallback} may expect to receive * {@link RcsProvisioningCallback#onConfigurationReset}, then * {@link RcsProvisioningCallback#onConfigurationChanged} when the new - * RCS configuration is received and notified by - * {@link #notifyRcsAutoConfigurationReceived} + * RCS configuration is received and notified by {@link #notifyRcsAutoConfigurationReceived} + * @hide */ + @SystemApi @RequiresPermission(Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION) public void triggerRcsReconfiguration() { try { diff --git a/telephony/java/android/telephony/ims/RcsClientConfiguration.java b/telephony/java/android/telephony/ims/RcsClientConfiguration.java index c25ace0c6a62..f367e404a35b 100644 --- a/telephony/java/android/telephony/ims/RcsClientConfiguration.java +++ b/telephony/java/android/telephony/ims/RcsClientConfiguration.java @@ -34,7 +34,7 @@ public final class RcsClientConfiguration implements Parcelable { /**@hide*/ @StringDef(prefix = "RCS_PROFILE_", - value = {RCS_PROFILE_1_0, RCS_PROFILE_2_3}) + value = {RCS_PROFILE_1_0, RCS_PROFILE_2_3, RCS_PROFILE_2_4}) public @interface StringRcsProfile {} /** @@ -45,6 +45,10 @@ public final class RcsClientConfiguration implements Parcelable { * RCS profile UP 2.3 */ public static final String RCS_PROFILE_2_3 = "UP_2.3"; + /** + * RCS profile UP 2.4 + */ + public static final String RCS_PROFILE_2_4 = "UP_2.4"; private String mRcsVersion; private String mRcsProfile; @@ -58,8 +62,8 @@ public final class RcsClientConfiguration implements Parcelable { * @param rcsVersion The parameter identifies the RCS version supported * by the client. Refer to GSMA RCC.07 "rcs_version" parameter. * @param rcsProfile Identifies a fixed set of RCS services that are - * supported by the client. See {@link #RCS_PROFILE_1_0 } or - * {@link #RCS_PROFILE_2_3 } + * supported by the client. See {@link #RCS_PROFILE_1_0 }, + * {@link #RCS_PROFILE_2_3 } or {@link #RCS_PROFILE_2_4 } * @param clientVendor Identifies the vendor providing the RCS client. * @param clientVersion Identifies the RCS client version. Refer to GSMA * RCC.07 "client_version" parameter. @@ -80,8 +84,8 @@ public final class RcsClientConfiguration implements Parcelable { * @param rcsVersion The parameter identifies the RCS version supported * by the client. Refer to GSMA RCC.07 "rcs_version" parameter. * @param rcsProfile Identifies a fixed set of RCS services that are - * supported by the client. See {@link #RCS_PROFILE_1_0 } or - * {@link #RCS_PROFILE_2_3 } + * supported by the client. See {@link #RCS_PROFILE_1_0 }, + * {@link #RCS_PROFILE_2_3 } or {@link #RCS_PROFILE_2_4 } * @param clientVendor Identifies the vendor providing the RCS client. * @param clientVersion Identifies the RCS client version. Refer to GSMA * RCC.07 "client_version" parameter. diff --git a/telephony/java/android/telephony/ims/RcsUceAdapter.java b/telephony/java/android/telephony/ims/RcsUceAdapter.java index 61de3ac2b25e..154bb11db5e3 100644 --- a/telephony/java/android/telephony/ims/RcsUceAdapter.java +++ b/telephony/java/android/telephony/ims/RcsUceAdapter.java @@ -268,6 +268,13 @@ public class RcsUceAdapter { @SystemApi public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_ENABLED = 11; + /** + * A capability update has been requested due to IMS being registered over INTERNET PDN. + * @hide + */ + @SystemApi + public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_INTERNET_PDN = 12; + /**@hide*/ @Retention(RetentionPolicy.SOURCE) @IntDef(prefix = "ERROR_", value = { @@ -282,7 +289,8 @@ public class RcsUceAdapter { CAPABILITY_UPDATE_TRIGGER_MOVE_TO_WLAN, CAPABILITY_UPDATE_TRIGGER_MOVE_TO_IWLAN, CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_DISABLED, - CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_ENABLED + CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_ENABLED, + CAPABILITY_UPDATE_TRIGGER_MOVE_TO_INTERNET_PDN }) public @interface StackPublishTriggerType {} diff --git a/telephony/java/android/telephony/ims/aidl/IFeatureProvisioningCallback.aidl b/telephony/java/android/telephony/ims/aidl/IFeatureProvisioningCallback.aidl new file mode 100644 index 000000000000..63ec4aaf1f48 --- /dev/null +++ b/telephony/java/android/telephony/ims/aidl/IFeatureProvisioningCallback.aidl @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package android.telephony.ims.aidl; + +/** + * Provides callback interface for FeatureProvisioning when a value has changed. + * + * {@hide} + */ +oneway interface IFeatureProvisioningCallback { + void onFeatureProvisioningChanged(int capability, int tech, boolean isProvisioned); + void onRcsFeatureProvisioningChanged(int capability, int tech, boolean isProvisioned); +} diff --git a/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl b/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl index c6966b3cf53e..ae6166fea02a 100644 --- a/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl +++ b/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl @@ -32,18 +32,19 @@ import com.android.ims.internal.IImsFeatureStatusCallback; */ interface IImsServiceController { void setListener(IImsServiceControllerListener l); - IImsMmTelFeature createMmTelFeature(int slotId); - IImsRcsFeature createRcsFeature(int slotId); + IImsMmTelFeature createMmTelFeature(int slotId, int subId); + IImsMmTelFeature createEmergencyOnlyMmTelFeature(int slotId); + IImsRcsFeature createRcsFeature(int slotId, int subId); ImsFeatureConfiguration querySupportedImsFeatures(); long getImsServiceCapabilities(); void addFeatureStatusCallback(int slotId, int featureType, in IImsFeatureStatusCallback c); void removeFeatureStatusCallback(int slotId, int featureType, in IImsFeatureStatusCallback c); // Synchronous call to ensure the ImsService is ready before continuing with feature creation. void notifyImsServiceReadyForFeatureCreation(); - void removeImsFeature(int slotId, int featureType); - IImsConfig getConfig(int slotId); - IImsRegistration getRegistration(int slotId); + void removeImsFeature(int slotId, int featureType, boolean changeSubId); + IImsConfig getConfig(int slotId, int subId); + IImsRegistration getRegistration(int slotId, int subId); ISipTransport getSipTransport(int slotId); - oneway void enableIms(int slotId); - oneway void disableIms(int slotId); + oneway void enableIms(int slotId, int subId); + oneway void disableIms(int slotId, int subId); } diff --git a/telephony/java/android/telephony/ims/feature/MmTelFeature.java b/telephony/java/android/telephony/ims/feature/MmTelFeature.java index 9a3f592480d1..ad2e9e133a11 100644 --- a/telephony/java/android/telephony/ims/feature/MmTelFeature.java +++ b/telephony/java/android/telephony/ims/feature/MmTelFeature.java @@ -40,16 +40,25 @@ import android.telephony.ims.stub.ImsRegistrationImplBase; import android.telephony.ims.stub.ImsSmsImplBase; import android.telephony.ims.stub.ImsUtImplBase; import android.util.ArraySet; +import android.util.Log; import com.android.ims.internal.IImsCallSession; import com.android.ims.internal.IImsEcbm; import com.android.ims.internal.IImsMultiEndpoint; import com.android.ims.internal.IImsUt; +import com.android.internal.telephony.util.TelephonyUtils; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.List; import java.util.Set; +import java.util.concurrent.CancellationException; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executor; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Supplier; /** * Base implementation for Voice and SMS (IR-92) and Video (IR-94) IMS support. @@ -60,6 +69,7 @@ import java.util.Set; public class MmTelFeature extends ImsFeature { private static final String LOG_TAG = "MmTelFeature"; + private Executor mExecutor; /** * @hide @@ -68,160 +78,261 @@ public class MmTelFeature extends ImsFeature { public MmTelFeature() { } + /** + * Create a new MmTelFeature using the Executor specified for methods being called by the + * framework. + * @param executor The executor for the framework to use when executing the methods overridden + * by the implementation of MmTelFeature. + * @hide + */ + @SystemApi + public MmTelFeature(@NonNull Executor executor) { + super(); + mExecutor = executor; + } + private final IImsMmTelFeature mImsMMTelBinder = new IImsMmTelFeature.Stub() { @Override public void setListener(IImsMmTelListener l) { - MmTelFeature.this.setListener(l); + executeMethodAsyncNoException(() -> MmTelFeature.this.setListener(l), "setListener"); } @Override public int getFeatureState() throws RemoteException { - try { - return MmTelFeature.this.getFeatureState(); - } catch (Exception e) { - throw new RemoteException(e.getMessage()); - } + return executeMethodAsyncForResult(() -> MmTelFeature.this.getFeatureState(), + "getFeatureState"); } - @Override public ImsCallProfile createCallProfile(int callSessionType, int callType) throws RemoteException { - synchronized (mLock) { - try { - return MmTelFeature.this.createCallProfile(callSessionType, callType); - } catch (Exception e) { - throw new RemoteException(e.getMessage()); - } - } + return executeMethodAsyncForResult(() -> MmTelFeature.this.createCallProfile( + callSessionType, callType), "createCallProfile"); } @Override public void changeOfferedRtpHeaderExtensionTypes(List<RtpHeaderExtensionType> types) throws RemoteException { - synchronized (mLock) { - try { - MmTelFeature.this.changeOfferedRtpHeaderExtensionTypes(new ArraySet<>(types)); - } catch (Exception e) { - throw new RemoteException(e.getMessage()); - } - } + executeMethodAsync(() -> MmTelFeature.this.changeOfferedRtpHeaderExtensionTypes( + new ArraySet<>(types)), "changeOfferedRtpHeaderExtensionTypes"); } @Override public IImsCallSession createCallSession(ImsCallProfile profile) throws RemoteException { - synchronized (mLock) { - return createCallSessionInterface(profile); + AtomicReference<RemoteException> exceptionRef = new AtomicReference<>(); + IImsCallSession result = executeMethodAsyncForResult(() -> { + try { + return createCallSessionInterface(profile); + } catch (RemoteException e) { + exceptionRef.set(e); + return null; + } + }, "createCallSession"); + + if (exceptionRef.get() != null) { + throw exceptionRef.get(); } + + return result; } @Override public int shouldProcessCall(String[] numbers) { - synchronized (mLock) { - return MmTelFeature.this.shouldProcessCall(numbers); + Integer result = executeMethodAsyncForResultNoException(() -> + MmTelFeature.this.shouldProcessCall(numbers), "shouldProcessCall"); + if (result != null) { + return result.intValue(); + } else { + return PROCESS_CALL_CSFB; } } @Override public IImsUt getUtInterface() throws RemoteException { - synchronized (mLock) { - return MmTelFeature.this.getUtInterface(); + AtomicReference<RemoteException> exceptionRef = new AtomicReference<>(); + IImsUt result = executeMethodAsyncForResult(() -> { + try { + return MmTelFeature.this.getUtInterface(); + } catch (RemoteException e) { + exceptionRef.set(e); + return null; + } + }, "getUtInterface"); + + if (exceptionRef.get() != null) { + throw exceptionRef.get(); } + + return result; } @Override public IImsEcbm getEcbmInterface() throws RemoteException { - synchronized (mLock) { - return MmTelFeature.this.getEcbmInterface(); + AtomicReference<RemoteException> exceptionRef = new AtomicReference<>(); + IImsEcbm result = executeMethodAsyncForResult(() -> { + try { + return MmTelFeature.this.getEcbmInterface(); + } catch (RemoteException e) { + exceptionRef.set(e); + return null; + } + }, "getEcbmInterface"); + + if (exceptionRef.get() != null) { + throw exceptionRef.get(); } + + return result; } @Override public void setUiTtyMode(int uiTtyMode, Message onCompleteMessage) throws RemoteException { - synchronized (mLock) { - try { - MmTelFeature.this.setUiTtyMode(uiTtyMode, onCompleteMessage); - } catch (Exception e) { - throw new RemoteException(e.getMessage()); - } - } + executeMethodAsync(() -> MmTelFeature.this.setUiTtyMode(uiTtyMode, onCompleteMessage), + "setUiTtyMode"); } @Override public IImsMultiEndpoint getMultiEndpointInterface() throws RemoteException { - synchronized (mLock) { - return MmTelFeature.this.getMultiEndpointInterface(); + AtomicReference<RemoteException> exceptionRef = new AtomicReference<>(); + IImsMultiEndpoint result = executeMethodAsyncForResult(() -> { + try { + return MmTelFeature.this.getMultiEndpointInterface(); + } catch (RemoteException e) { + exceptionRef.set(e); + return null; + } + }, "getMultiEndpointInterface"); + + if (exceptionRef.get() != null) { + throw exceptionRef.get(); } + + return result; } @Override public int queryCapabilityStatus() { - return MmTelFeature.this.queryCapabilityStatus().mCapabilities; + Integer result = executeMethodAsyncForResultNoException(() -> MmTelFeature.this + .queryCapabilityStatus().mCapabilities, "queryCapabilityStatus"); + + if (result != null) { + return result.intValue(); + } else { + return 0; + } } @Override public void addCapabilityCallback(IImsCapabilityCallback c) { - // no need to lock, structure already handles multithreading. - MmTelFeature.this.addCapabilityCallback(c); + executeMethodAsyncNoException(() -> MmTelFeature.this + .addCapabilityCallback(c), "addCapabilityCallback"); } @Override public void removeCapabilityCallback(IImsCapabilityCallback c) { - // no need to lock, structure already handles multithreading. - MmTelFeature.this.removeCapabilityCallback(c); + executeMethodAsyncNoException(() -> MmTelFeature.this + .removeCapabilityCallback(c), "removeCapabilityCallback"); } @Override public void changeCapabilitiesConfiguration(CapabilityChangeRequest request, IImsCapabilityCallback c) { - MmTelFeature.this.requestChangeEnabledCapabilities(request, c); + executeMethodAsyncNoException(() -> MmTelFeature.this + .requestChangeEnabledCapabilities(request, c), + "changeCapabilitiesConfiguration"); } @Override public void queryCapabilityConfiguration(int capability, int radioTech, IImsCapabilityCallback c) { - queryCapabilityConfigurationInternal(capability, radioTech, c); + executeMethodAsyncNoException(() -> queryCapabilityConfigurationInternal( + capability, radioTech, c), "queryCapabilityConfiguration"); } @Override public void setSmsListener(IImsSmsListener l) { - MmTelFeature.this.setSmsListener(l); + executeMethodAsyncNoException(() -> MmTelFeature.this.setSmsListener(l), + "setSmsListener"); } @Override public void sendSms(int token, int messageRef, String format, String smsc, boolean retry, byte[] pdu) { - synchronized (mLock) { - MmTelFeature.this.sendSms(token, messageRef, format, smsc, retry, pdu); - } + executeMethodAsyncNoException(() -> MmTelFeature.this + .sendSms(token, messageRef, format, smsc, retry, pdu), "sendSms"); } @Override public void acknowledgeSms(int token, int messageRef, int result) { - synchronized (mLock) { - MmTelFeature.this.acknowledgeSms(token, messageRef, result); - } + executeMethodAsyncNoException(() -> MmTelFeature.this + .acknowledgeSms(token, messageRef, result), "acknowledgeSms"); } @Override public void acknowledgeSmsReport(int token, int messageRef, int result) { - synchronized (mLock) { - MmTelFeature.this.acknowledgeSmsReport(token, messageRef, result); - } + executeMethodAsyncNoException(() -> MmTelFeature.this + .acknowledgeSmsReport(token, messageRef, result), "acknowledgeSmsReport"); } @Override public String getSmsFormat() { - synchronized (mLock) { - return MmTelFeature.this.getSmsFormat(); - } + return executeMethodAsyncForResultNoException(() -> MmTelFeature.this + .getSmsFormat(), "getSmsFormat"); } @Override public void onSmsReady() { - synchronized (mLock) { - MmTelFeature.this.onSmsReady(); + executeMethodAsyncNoException(() -> MmTelFeature.this.onSmsReady(), + "onSmsReady"); + } + + // Call the methods with a clean calling identity on the executor and wait indefinitely for + // the future to return. + private void executeMethodAsync(Runnable r, String errorLogName) throws RemoteException { + try { + CompletableFuture.runAsync( + () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join(); + } catch (CancellationException | CompletionException e) { + Log.w(LOG_TAG, "MmTelFeature Binder - " + errorLogName + " exception: " + + e.getMessage()); + throw new RemoteException(e.getMessage()); + } + } + + private void executeMethodAsyncNoException(Runnable r, String errorLogName) { + try { + CompletableFuture.runAsync( + () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join(); + } catch (CancellationException | CompletionException e) { + Log.w(LOG_TAG, "MmTelFeature Binder - " + errorLogName + " exception: " + + e.getMessage()); + } + } + + private <T> T executeMethodAsyncForResult(Supplier<T> r, + String errorLogName) throws RemoteException { + CompletableFuture<T> future = CompletableFuture.supplyAsync( + () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor); + try { + return future.get(); + } catch (ExecutionException | InterruptedException e) { + Log.w(LOG_TAG, "MmTelFeature Binder - " + errorLogName + " exception: " + + e.getMessage()); + throw new RemoteException(e.getMessage()); + } + } + + private <T> T executeMethodAsyncForResultNoException(Supplier<T> r, + String errorLogName) { + CompletableFuture<T> future = CompletableFuture.supplyAsync( + () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor); + try { + return future.get(); + } catch (ExecutionException | InterruptedException e) { + Log.w(LOG_TAG, "MmTelFeature Binder - " + errorLogName + " exception: " + + e.getMessage()); + return null; } } }; @@ -283,6 +394,13 @@ public class MmTelFeature extends ImsFeature { public @interface MmTelCapability {} /** + * Undefined capability type for initialization + * This is used to check the upper range of MmTel capability + * {@hide} + */ + public static final int CAPABILITY_TYPE_NONE = 0; + + /** * This MmTelFeature supports Voice calling (IR.92) */ public static final int CAPABILITY_TYPE_VOICE = 1 << 0; @@ -308,6 +426,12 @@ public class MmTelFeature extends ImsFeature { public static final int CAPABILITY_TYPE_CALL_COMPOSER = 1 << 4; /** + * This is used to check the upper range of MmTel capability + * {@hide} + */ + public static final int CAPABILITY_TYPE_MAX = CAPABILITY_TYPE_CALL_COMPOSER + 1; + + /** * @hide */ @Override @@ -672,7 +796,12 @@ public class MmTelFeature extends ImsFeature { public IImsCallSession createCallSessionInterface(ImsCallProfile profile) throws RemoteException { ImsCallSessionImplBase s = MmTelFeature.this.createCallSession(profile); - return s != null ? s.getServiceImpl() : null; + if (s != null) { + s.setDefaultExecutor(mExecutor); + return s.getServiceImpl(); + } else { + return null; + } } /** @@ -713,7 +842,12 @@ public class MmTelFeature extends ImsFeature { */ protected IImsUt getUtInterface() throws RemoteException { ImsUtImplBase utImpl = getUt(); - return utImpl != null ? utImpl.getInterface() : null; + if (utImpl != null) { + utImpl.setDefaultExecutor(mExecutor); + return utImpl.getInterface(); + } else { + return null; + } } /** @@ -721,7 +855,12 @@ public class MmTelFeature extends ImsFeature { */ protected IImsEcbm getEcbmInterface() throws RemoteException { ImsEcbmImplBase ecbmImpl = getEcbm(); - return ecbmImpl != null ? ecbmImpl.getImsEcbm() : null; + if (ecbmImpl != null) { + ecbmImpl.setDefaultExecutor(mExecutor); + return ecbmImpl.getImsEcbm(); + } else { + return null; + } } /** @@ -729,7 +868,12 @@ public class MmTelFeature extends ImsFeature { */ public IImsMultiEndpoint getMultiEndpointInterface() throws RemoteException { ImsMultiEndpointImplBase multiendpointImpl = getMultiEndpoint(); - return multiendpointImpl != null ? multiendpointImpl.getIImsMultiEndpoint() : null; + if (multiendpointImpl != null) { + multiendpointImpl.setDefaultExecutor(mExecutor); + return multiendpointImpl.getIImsMultiEndpoint(); + } else { + return null; + } } /** @@ -859,4 +1003,16 @@ public class MmTelFeature extends ImsFeature { public final IImsMmTelFeature getBinder() { return mImsMMTelBinder; } + + /** + * Set default Executor from ImsService. + * @param executor The default executor for the framework to use when executing the methods + * overridden by the implementation of MmTelFeature. + * @hide + */ + public final void setDefaultExecutor(@NonNull Executor executor) { + if (mExecutor == null) { + mExecutor = executor; + } + } } diff --git a/telephony/java/android/telephony/ims/feature/RcsFeature.java b/telephony/java/android/telephony/ims/feature/RcsFeature.java index 18cc37d7fbda..70e4ef1f1a3a 100644 --- a/telephony/java/android/telephony/ims/feature/RcsFeature.java +++ b/telephony/java/android/telephony/ims/feature/RcsFeature.java @@ -59,9 +59,7 @@ import java.util.function.Supplier; /** * Base implementation of the RcsFeature APIs. Any ImsService wishing to support RCS should extend * this class and provide implementations of the RcsFeature methods that they support. - * @hide */ -@SystemApi public class RcsFeature extends ImsFeature { private static final String LOG_TAG = "RcsFeature"; @@ -70,7 +68,7 @@ public class RcsFeature extends ImsFeature { // Reference the outer class in order to have better test coverage metrics instead of // creating a inner class referencing the outer class directly. private final RcsFeature mReference; - private final Executor mExecutor; + private Executor mExecutor; RcsFeatureBinder(RcsFeature classRef, @CallbackExecutor Executor executor) { mReference = classRef; @@ -186,14 +184,14 @@ public class RcsFeature extends ImsFeature { * Contains the capabilities defined and supported by a {@link RcsFeature} in the * form of a bitmask. The capabilities that are used in the RcsFeature are * defined as: - * {@link RcsUceAdatper.RcsImsCapabilityFlag#CAPABILITY_TYPE_OPTIONS_UCE} - * {@link RceUceAdapter.RcsImsCapabilityFlag#CAPABILITY_TYPE_PRESENCE_UCE} + * {RcsUceAdapter.RcsImsCapabilityFlag#CAPABILITY_TYPE_OPTIONS_UCE} + * {RcsUceAdapter.RcsImsCapabilityFlag#CAPABILITY_TYPE_PRESENCE_UCE} * * The enabled capabilities of this RcsFeature will be set by the framework - * using {@link #changeEnabledCapabilities(CapabilityChangeRequest, CapabilityCallbackProxy)}. + * using {#changeEnabledCapabilities(CapabilityChangeRequest, CapabilityCallbackProxy)}. * After the capabilities have been set, the RcsFeature may then perform the necessary bring up * of the capability and notify the capability status as true using - * {@link #notifyCapabilitiesStatusChanged(RcsImsCapabilities)}. This will signal to the + * {#notifyCapabilitiesStatusChanged(RcsImsCapabilities)}. This will signal to the * framework that the capability is available for usage. */ public static class RcsImsCapabilities extends Capabilities { @@ -227,10 +225,18 @@ public class RcsFeature extends ImsFeature { public static final int CAPABILITY_TYPE_PRESENCE_UCE = 1 << 1; /** + * This is used to check the upper range of RCS capability + * {@hide} + */ + public static final int CAPABILITY_TYPE_MAX = CAPABILITY_TYPE_PRESENCE_UCE + 1; + + /** * Create a new {@link RcsImsCapabilities} instance with the provided capabilities. * @param capabilities The capabilities that are supported for RCS in the form of a * bitfield. + * @hide */ + @SystemApi public RcsImsCapabilities(@RcsUceAdapter.RcsImsCapabilityFlag int capabilities) { super(capabilities); } @@ -243,23 +249,35 @@ public class RcsFeature extends ImsFeature { super(capabilities.getMask()); } + /** + * @hide + */ @Override + @SystemApi public void addCapabilities(@RcsUceAdapter.RcsImsCapabilityFlag int capabilities) { super.addCapabilities(capabilities); } + /** + * @hide + */ @Override + @SystemApi public void removeCapabilities(@RcsUceAdapter.RcsImsCapabilityFlag int capabilities) { super.removeCapabilities(capabilities); } + /** + * @hide + */ @Override + @SystemApi public boolean isCapable(@RcsUceAdapter.RcsImsCapabilityFlag int capabilities) { return super.isCapable(capabilities); } } - private final Executor mExecutor; + private Executor mExecutor; private final RcsFeatureBinder mImsRcsBinder; private RcsCapabilityExchangeImplBase mCapabilityExchangeImpl; private CapabilityExchangeEventListener mCapExchangeEventListener; @@ -270,13 +288,11 @@ public class RcsFeature extends ImsFeature { * Method stubs called from the framework will be called asynchronously. To specify the * {@link Executor} that the methods stubs will be called, use * {@link RcsFeature#RcsFeature(Executor)} instead. - * - * @deprecated Use {@link #RcsFeature(Executor)} to create the RcsFeature. + * @hide */ - @Deprecated + @SystemApi public RcsFeature() { super(); - mExecutor = Runnable::run; // Run on the Binder threads that call them. mImsRcsBinder = new RcsFeatureBinder(this, mExecutor); } @@ -286,7 +302,9 @@ public class RcsFeature extends ImsFeature { * framework. * @param executor The executor for the framework to use when executing the methods overridden * by the implementation of RcsFeature. + * @hide */ + @SystemApi public RcsFeature(@NonNull Executor executor) { super(); if (executor == null) { @@ -305,7 +323,7 @@ public class RcsFeature extends ImsFeature { * @hide */ @Override - public void initialize(Context context, int slotId) { + public void initialize(@NonNull Context context, @NonNull int slotId) { super.initialize(context, slotId); // Notify that the RcsFeature is ready. mExecutor.execute(() -> onFeatureReady()); @@ -317,8 +335,10 @@ public class RcsFeature extends ImsFeature { * requests. To change the status of the capabilities * {@link #notifyCapabilitiesStatusChanged(RcsImsCapabilities)} should be called. * @return A copy of the current RcsFeature capability status. + * @hide */ @Override + @SystemApi public @NonNull final RcsImsCapabilities queryCapabilityStatus() { return new RcsImsCapabilities(super.queryCapabilityStatus()); } @@ -328,7 +348,9 @@ public class RcsFeature extends ImsFeature { * this signals to the framework that the capability has been initialized and is ready. * Call {@link #queryCapabilityStatus()} to return the current capability status. * @param capabilities The current capability status of the RcsFeature. + * @hide */ + @SystemApi public final void notifyCapabilitiesStatusChanged(@NonNull RcsImsCapabilities capabilities) { if (capabilities == null) { throw new IllegalArgumentException("RcsImsCapabilities must be non-null!"); @@ -345,7 +367,9 @@ public class RcsFeature extends ImsFeature { * @param capability The capability that we are querying the configuration for. * @param radioTech The radio technology type that we are querying. * @return true if the capability is enabled, false otherwise. + * @hide */ + @SystemApi public boolean queryCapabilityConfiguration( @RcsUceAdapter.RcsImsCapabilityFlag int capability, @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) { @@ -368,8 +392,10 @@ public class RcsFeature extends ImsFeature { * be called for each capability change that resulted in an error. * @param request The request to change the capability. * @param callback To notify the framework that the result of the capability changes. + * @hide */ @Override + @SystemApi public void changeEnabledCapabilities(@NonNull CapabilityChangeRequest request, @NonNull CapabilityCallbackProxy callback) { // Base Implementation - Override to provide functionality @@ -389,7 +415,9 @@ public class RcsFeature extends ImsFeature { * event to the framework. * @return An instance of {@link RcsCapabilityExchangeImplBase} that implements capability * exchange if it is supported by the device. + * @hide */ + @SystemApi public @NonNull RcsCapabilityExchangeImplBase createCapabilityExchangeImpl( @NonNull CapabilityExchangeEventListener listener) { // Base Implementation, override to implement functionality @@ -399,20 +427,28 @@ public class RcsFeature extends ImsFeature { /** * Remove the given CapabilityExchangeImplBase instance. * @param capExchangeImpl The {@link RcsCapabilityExchangeImplBase} instance to be destroyed. + * @hide */ + @SystemApi public void destroyCapabilityExchangeImpl( @NonNull RcsCapabilityExchangeImplBase capExchangeImpl) { // Override to implement the process of destroying RcsCapabilityExchangeImplBase instance. } - /**{@inheritDoc}*/ + /**{@inheritDoc} + * @hide + */ @Override + @SystemApi public void onFeatureRemoved() { } - /**{@inheritDoc}*/ + /**{@inheritDoc} + * @hide + */ @Override + @SystemApi public void onFeatureReady() { } @@ -477,4 +513,17 @@ public class RcsFeature extends ImsFeature { return mCapabilityExchangeImpl; } } + + /** + * Set default Executor from ImsService. + * @param executor The default executor for the framework to use when executing the methods + * overridden by the implementation of RcsFeature. + * @hide + */ + public final void setDefaultExecutor(@NonNull Executor executor) { + if (mImsRcsBinder.mExecutor == null) { + mExecutor = executor; + mImsRcsBinder.mExecutor = executor; + } + } } diff --git a/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java b/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java index a3a6cb864fa5..e8100957517f 100644 --- a/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java +++ b/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java @@ -30,12 +30,20 @@ import android.telephony.ims.RtpHeaderExtension; import android.telephony.ims.RtpHeaderExtensionType; import android.telephony.ims.aidl.IImsCallSessionListener; import android.util.ArraySet; +import android.util.Log; import com.android.ims.internal.IImsCallSession; import com.android.ims.internal.IImsVideoCallProvider; +import com.android.internal.telephony.util.TelephonyUtils; import java.util.List; import java.util.Set; +import java.util.concurrent.CancellationException; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executor; +import java.util.function.Supplier; /** * Base implementation of IImsCallSession, which implements stub versions of the methods available. @@ -48,6 +56,8 @@ import java.util.Set; // DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you // will break other implementations of ImsCallSession maintained by other ImsServices. public class ImsCallSessionImplBase implements AutoCloseable { + + private static final String LOG_TAG = "ImsCallSessionImplBase"; /** * Notify USSD Mode. */ @@ -110,185 +120,235 @@ public class ImsCallSessionImplBase implements AutoCloseable { } } + private Executor mExecutor = Runnable::run; + // Non-final for injection by tests private IImsCallSession mServiceImpl = new IImsCallSession.Stub() { @Override public void close() { - ImsCallSessionImplBase.this.close(); + executeMethodAsync(() -> ImsCallSessionImplBase.this.close(), "close"); } @Override public String getCallId() { - return ImsCallSessionImplBase.this.getCallId(); + return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this.getCallId(), + "getCallId"); } @Override public ImsCallProfile getCallProfile() { - return ImsCallSessionImplBase.this.getCallProfile(); + return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this.getCallProfile(), + "getCallProfile"); } @Override public ImsCallProfile getLocalCallProfile() { - return ImsCallSessionImplBase.this.getLocalCallProfile(); + return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this + .getLocalCallProfile(), "getLocalCallProfile"); } @Override public ImsCallProfile getRemoteCallProfile() { - return ImsCallSessionImplBase.this.getRemoteCallProfile(); + return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this + .getRemoteCallProfile(), "getRemoteCallProfile"); } @Override public String getProperty(String name) { - return ImsCallSessionImplBase.this.getProperty(name); + return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this.getProperty(name), + "getProperty"); } @Override public int getState() { - return ImsCallSessionImplBase.this.getState(); + return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this.getState(), + "getState"); } @Override public boolean isInCall() { - return ImsCallSessionImplBase.this.isInCall(); + return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this.isInCall(), + "isInCall"); } @Override public void setListener(IImsCallSessionListener listener) { - ImsCallSessionImplBase.this.setListener(new ImsCallSessionListener(listener)); + executeMethodAsync(() -> ImsCallSessionImplBase.this.setListener( + new ImsCallSessionListener(listener)), "setListener"); } @Override public void setMute(boolean muted) { - ImsCallSessionImplBase.this.setMute(muted); + executeMethodAsync(() -> ImsCallSessionImplBase.this.setMute(muted), "setMute"); } @Override public void start(String callee, ImsCallProfile profile) { - ImsCallSessionImplBase.this.start(callee, profile); + executeMethodAsync(() -> ImsCallSessionImplBase.this.start(callee, profile), "start"); } @Override public void startConference(String[] participants, ImsCallProfile profile) throws RemoteException { - ImsCallSessionImplBase.this.startConference(participants, profile); + executeMethodAsync(() -> ImsCallSessionImplBase.this.startConference(participants, + profile), "startConference"); } @Override public void accept(int callType, ImsStreamMediaProfile profile) { - ImsCallSessionImplBase.this.accept(callType, profile); + executeMethodAsync(() -> ImsCallSessionImplBase.this.accept(callType, profile), + "accept"); } @Override public void deflect(String deflectNumber) { - ImsCallSessionImplBase.this.deflect(deflectNumber); + executeMethodAsync(() -> ImsCallSessionImplBase.this.deflect(deflectNumber), + "deflect"); } @Override public void reject(int reason) { - ImsCallSessionImplBase.this.reject(reason); + executeMethodAsync(() -> ImsCallSessionImplBase.this.reject(reason), "reject"); } @Override public void transfer(@NonNull String number, boolean isConfirmationRequired) { - ImsCallSessionImplBase.this.transfer(number, isConfirmationRequired); + executeMethodAsync(() -> ImsCallSessionImplBase.this.transfer(number, + isConfirmationRequired), "transfer"); } @Override public void consultativeTransfer(@NonNull IImsCallSession transferToSession) { - ImsCallSessionImplBase otherSession = new ImsCallSessionImplBase(); - otherSession.setServiceImpl(transferToSession); - ImsCallSessionImplBase.this.transfer(otherSession); + executeMethodAsync(() -> { + ImsCallSessionImplBase otherSession = new ImsCallSessionImplBase(); + otherSession.setServiceImpl(transferToSession); + ImsCallSessionImplBase.this.transfer(otherSession); + }, "consultativeTransfer"); } @Override public void terminate(int reason) { - ImsCallSessionImplBase.this.terminate(reason); + executeMethodAsync(() -> ImsCallSessionImplBase.this.terminate(reason), "terminate"); } @Override public void hold(ImsStreamMediaProfile profile) { - ImsCallSessionImplBase.this.hold(profile); + executeMethodAsync(() -> ImsCallSessionImplBase.this.hold(profile), "hold"); } @Override public void resume(ImsStreamMediaProfile profile) { - ImsCallSessionImplBase.this.resume(profile); + executeMethodAsync(() -> ImsCallSessionImplBase.this.resume(profile), "resume"); } @Override public void merge() { - ImsCallSessionImplBase.this.merge(); + executeMethodAsync(() -> ImsCallSessionImplBase.this.merge(), "merge"); } @Override public void update(int callType, ImsStreamMediaProfile profile) { - ImsCallSessionImplBase.this.update(callType, profile); + executeMethodAsync(() -> ImsCallSessionImplBase.this.update(callType, profile), + "update"); } @Override public void extendToConference(String[] participants) { - ImsCallSessionImplBase.this.extendToConference(participants); + executeMethodAsync(() -> ImsCallSessionImplBase.this.extendToConference(participants), + "extendToConference"); } @Override public void inviteParticipants(String[] participants) { - ImsCallSessionImplBase.this.inviteParticipants(participants); + executeMethodAsync(() -> ImsCallSessionImplBase.this.inviteParticipants(participants), + "inviteParticipants"); } @Override public void removeParticipants(String[] participants) { - ImsCallSessionImplBase.this.removeParticipants(participants); + executeMethodAsync(() -> ImsCallSessionImplBase.this.removeParticipants(participants), + "removeParticipants"); } @Override public void sendDtmf(char c, Message result) { - ImsCallSessionImplBase.this.sendDtmf(c, result); + executeMethodAsync(() -> ImsCallSessionImplBase.this.sendDtmf(c, result), "sendDtmf"); } @Override public void startDtmf(char c) { - ImsCallSessionImplBase.this.startDtmf(c); + executeMethodAsync(() -> ImsCallSessionImplBase.this.startDtmf(c), "startDtmf"); } @Override public void stopDtmf() { - ImsCallSessionImplBase.this.stopDtmf(); + executeMethodAsync(() -> ImsCallSessionImplBase.this.stopDtmf(), "stopDtmf"); } @Override public void sendUssd(String ussdMessage) { - ImsCallSessionImplBase.this.sendUssd(ussdMessage); + executeMethodAsync(() -> ImsCallSessionImplBase.this.sendUssd(ussdMessage), "sendUssd"); } @Override public IImsVideoCallProvider getVideoCallProvider() { - return ImsCallSessionImplBase.this.getVideoCallProvider(); + return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this + .getVideoCallProvider(), "getVideoCallProvider"); } @Override public boolean isMultiparty() { - return ImsCallSessionImplBase.this.isMultiparty(); + return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this.isMultiparty(), + "isMultiparty"); } @Override public void sendRttModifyRequest(ImsCallProfile toProfile) { - ImsCallSessionImplBase.this.sendRttModifyRequest(toProfile); + executeMethodAsync(() -> ImsCallSessionImplBase.this.sendRttModifyRequest(toProfile), + "sendRttModifyRequest"); } @Override public void sendRttModifyResponse(boolean status) { - ImsCallSessionImplBase.this.sendRttModifyResponse(status); + executeMethodAsync(() -> ImsCallSessionImplBase.this.sendRttModifyResponse(status), + "sendRttModifyResponse"); } @Override public void sendRttMessage(String rttMessage) { - ImsCallSessionImplBase.this.sendRttMessage(rttMessage); + executeMethodAsync(() -> ImsCallSessionImplBase.this.sendRttMessage(rttMessage), + "sendRttMessage"); } @Override public void sendRtpHeaderExtensions(@NonNull List<RtpHeaderExtension> extensions) { - ImsCallSessionImplBase.this.sendRtpHeaderExtensions( - new ArraySet<RtpHeaderExtension>(extensions)); + executeMethodAsync(() -> ImsCallSessionImplBase.this.sendRtpHeaderExtensions( + new ArraySet<RtpHeaderExtension>(extensions)), "sendRtpHeaderExtensions"); + } + + // Call the methods with a clean calling identity on the executor and wait indefinitely for + // the future to return. + private void executeMethodAsync(Runnable r, String errorLogName) { + try { + CompletableFuture.runAsync( + () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join(); + } catch (CancellationException | CompletionException e) { + Log.w(LOG_TAG, "ImsCallSessionImplBase Binder - " + errorLogName + " exception: " + + e.getMessage()); + } + } + + private <T> T executeMethodAsyncForResult(Supplier<T> r, + String errorLogName) { + CompletableFuture<T> future = CompletableFuture.supplyAsync( + () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor); + try { + return future.get(); + } catch (ExecutionException | InterruptedException e) { + Log.w(LOG_TAG, "ImsCallSessionImplBase Binder - " + errorLogName + " exception: " + + e.getMessage()); + return null; + } } }; @@ -674,4 +734,14 @@ public class ImsCallSessionImplBase implements AutoCloseable { public void setServiceImpl(IImsCallSession serviceImpl) { mServiceImpl = serviceImpl; } + + /** + * Set default Executor from MmTelFeature. + * @param executor The default executor for the framework to use when executing the methods + * overridden by the implementation of ImsCallSession. + * @hide + */ + public final void setDefaultExecutor(@NonNull Executor executor) { + mExecutor = executor; + } } diff --git a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java index d75da9035124..11fc328a42c7 100644 --- a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java +++ b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java @@ -33,12 +33,21 @@ import android.util.Log; import com.android.ims.ImsConfig; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telephony.util.RemoteCallbackListExt; +import com.android.internal.telephony.util.TelephonyUtils; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.ref.WeakReference; import java.util.Arrays; import java.util.HashMap; +import java.util.concurrent.CancellationException; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executor; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Supplier; + /** * Controls the modification of IMS specific configurations. For more information on the supported @@ -81,21 +90,48 @@ public class ImsConfigImplBase { WeakReference<ImsConfigImplBase> mImsConfigImplBaseWeakReference; private HashMap<Integer, Integer> mProvisionedIntValue = new HashMap<>(); private HashMap<Integer, String> mProvisionedStringValue = new HashMap<>(); + private final Object mLock = new Object(); + private Executor mExecutor; @VisibleForTesting - public ImsConfigStub(ImsConfigImplBase imsConfigImplBase) { + public ImsConfigStub(ImsConfigImplBase imsConfigImplBase, Executor executor) { + mExecutor = executor; mImsConfigImplBaseWeakReference = new WeakReference<ImsConfigImplBase>(imsConfigImplBase); } @Override public void addImsConfigCallback(IImsConfigCallback c) throws RemoteException { - getImsConfigImpl().addImsConfigCallback(c); + AtomicReference<RemoteException> exceptionRef = new AtomicReference<>(); + executeMethodAsync(()-> { + try { + getImsConfigImpl().addImsConfigCallback(c); + } catch (RemoteException e) { + exceptionRef.set(e); + } + }, "addImsConfigCallback"); + + if (exceptionRef.get() != null) { + Log.d(TAG, "ImsConfigImplBase Exception addImsConfigCallback"); + throw exceptionRef.get(); + } } @Override public void removeImsConfigCallback(IImsConfigCallback c) throws RemoteException { - getImsConfigImpl().removeImsConfigCallback(c); + AtomicReference<RemoteException> exceptionRef = new AtomicReference<>(); + executeMethodAsync(()-> { + try { + getImsConfigImpl().removeImsConfigCallback(c); + } catch (RemoteException e) { + exceptionRef.set(e); + } + }, "removeImsConfigCallback"); + + if (exceptionRef.get() != null) { + Log.d(TAG, "ImsConfigImplBase Exception removeImsConfigCallback"); + throw exceptionRef.get(); + } } /** @@ -108,16 +144,34 @@ public class ImsConfigImplBase { * unavailable. */ @Override - public synchronized int getConfigInt(int item) throws RemoteException { - if (mProvisionedIntValue.containsKey(item)) { - return mProvisionedIntValue.get(item); - } else { - int retVal = getImsConfigImpl().getConfigInt(item); - if (retVal != ImsConfig.OperationStatusConstants.UNKNOWN) { - updateCachedValue(item, retVal, false); + public int getConfigInt(int item) throws RemoteException { + AtomicReference<RemoteException> exceptionRef = new AtomicReference<>(); + int retVal = executeMethodAsyncForResult(()-> { + int returnVal = ImsConfig.OperationStatusConstants.UNKNOWN; + synchronized (mLock) { + if (mProvisionedIntValue.containsKey(item)) { + return mProvisionedIntValue.get(item); + } else { + try { + returnVal = getImsConfigImpl().getConfigInt(item); + if (returnVal != ImsConfig.OperationStatusConstants.UNKNOWN) { + mProvisionedIntValue.put(item, returnVal); + } + } catch (RemoteException e) { + exceptionRef.set(e); + return returnVal; + } + } } - return retVal; + return returnVal; + }, "getConfigInt"); + + if (exceptionRef.get() != null) { + Log.d(TAG, "ImsConfigImplBase Exception getConfigString"); + throw exceptionRef.get(); } + + return retVal; } /** @@ -129,16 +183,34 @@ public class ImsConfigImplBase { * @return value in String format. */ @Override - public synchronized String getConfigString(int item) throws RemoteException { - if (mProvisionedStringValue.containsKey(item)) { - return mProvisionedStringValue.get(item); - } else { - String retVal = getImsConfigImpl().getConfigString(item); - if (retVal != null) { - updateCachedValue(item, retVal, false); + public String getConfigString(int item) throws RemoteException { + AtomicReference<RemoteException> exceptionRef = new AtomicReference<>(); + String retVal = executeMethodAsyncForResult(()-> { + String returnVal = null; + synchronized (mLock) { + if (mProvisionedStringValue.containsKey(item)) { + returnVal = mProvisionedStringValue.get(item); + } else { + try { + returnVal = getImsConfigImpl().getConfigString(item); + if (returnVal != null) { + mProvisionedStringValue.put(item, returnVal); + } + } catch (RemoteException e) { + exceptionRef.set(e); + return returnVal; + } + } } - return retVal; + return returnVal; + }, "getConfigString"); + + if (exceptionRef.get() != null) { + Log.d(TAG, "ImsConfigImplBase Exception getConfigString"); + throw exceptionRef.get(); } + + return retVal; } /** @@ -153,14 +225,32 @@ public class ImsConfigImplBase { * {@link #CONFIG_RESULT_FAILED} or {@link #CONFIG_RESULT_SUCCESS}. */ @Override - public synchronized int setConfigInt(int item, int value) throws RemoteException { - mProvisionedIntValue.remove(item); - int retVal = getImsConfigImpl().setConfig(item, value); - if (retVal == ImsConfig.OperationStatusConstants.SUCCESS) { - updateCachedValue(item, value, true); - } else { - Log.d(TAG, "Set provision value of " + item + - " to " + value + " failed with error code " + retVal); + public int setConfigInt(int item, int value) throws RemoteException { + AtomicReference<RemoteException> exceptionRef = new AtomicReference<>(); + int retVal = executeMethodAsyncForResult(()-> { + int returnVal = ImsConfig.OperationStatusConstants.UNKNOWN; + try { + synchronized (mLock) { + mProvisionedIntValue.remove(item); + returnVal = getImsConfigImpl().setConfig(item, value); + if (returnVal == ImsConfig.OperationStatusConstants.SUCCESS) { + mProvisionedIntValue.put(item, value); + } else { + Log.d(TAG, "Set provision value of " + item + + " to " + value + " failed with error code " + returnVal); + } + } + notifyImsConfigChanged(item, value); + return returnVal; + } catch (RemoteException e) { + exceptionRef.set(e); + return returnVal; + } + }, "setConfigInt"); + + if (exceptionRef.get() != null) { + Log.d(TAG, "ImsConfigImplBase Exception setConfigInt"); + throw exceptionRef.get(); } return retVal; @@ -178,12 +268,30 @@ public class ImsConfigImplBase { * {@link #CONFIG_RESULT_FAILED} or {@link #CONFIG_RESULT_SUCCESS}. */ @Override - public synchronized int setConfigString(int item, String value) + public int setConfigString(int item, String value) throws RemoteException { - mProvisionedStringValue.remove(item); - int retVal = getImsConfigImpl().setConfig(item, value); - if (retVal == ImsConfig.OperationStatusConstants.SUCCESS) { - updateCachedValue(item, value, true); + AtomicReference<RemoteException> exceptionRef = new AtomicReference<>(); + int retVal = executeMethodAsyncForResult(()-> { + int returnVal = ImsConfig.OperationStatusConstants.UNKNOWN; + try { + synchronized (mLock) { + mProvisionedStringValue.remove(item); + returnVal = getImsConfigImpl().setConfig(item, value); + if (returnVal == ImsConfig.OperationStatusConstants.SUCCESS) { + mProvisionedStringValue.put(item, value); + } + } + notifyImsConfigChanged(item, value); + return returnVal; + } catch (RemoteException e) { + exceptionRef.set(e); + return returnVal; + } + }, "setConfigString"); + + if (exceptionRef.get() != null) { + Log.d(TAG, "ImsConfigImplBase Exception setConfigInt"); + throw exceptionRef.get(); } return retVal; @@ -191,7 +299,19 @@ public class ImsConfigImplBase { @Override public void updateImsCarrierConfigs(PersistableBundle bundle) throws RemoteException { - getImsConfigImpl().updateImsCarrierConfigs(bundle); + AtomicReference<RemoteException> exceptionRef = new AtomicReference<>(); + executeMethodAsync(()-> { + try { + getImsConfigImpl().updateImsCarrierConfigs(bundle); + } catch (RemoteException e) { + exceptionRef.set(e); + } + }, "updateImsCarrierConfigs"); + + if (exceptionRef.get() != null) { + Log.d(TAG, "ImsConfigImplBase Exception updateImsCarrierConfigs"); + throw exceptionRef.get(); + } } private ImsConfigImplBase getImsConfigImpl() throws RemoteException { @@ -206,13 +326,37 @@ public class ImsConfigImplBase { @Override public void notifyRcsAutoConfigurationReceived(byte[] config, boolean isCompressed) throws RemoteException { - getImsConfigImpl().onNotifyRcsAutoConfigurationReceived(config, isCompressed); + AtomicReference<RemoteException> exceptionRef = new AtomicReference<>(); + executeMethodAsync(()-> { + try { + getImsConfigImpl().onNotifyRcsAutoConfigurationReceived(config, isCompressed); + } catch (RemoteException e) { + exceptionRef.set(e); + } + }, "notifyRcsAutoConfigurationReceived"); + + if (exceptionRef.get() != null) { + Log.d(TAG, "ImsConfigImplBase Exception notifyRcsAutoConfigurationReceived"); + throw exceptionRef.get(); + } } @Override public void notifyRcsAutoConfigurationRemoved() throws RemoteException { - getImsConfigImpl().onNotifyRcsAutoConfigurationRemoved(); + AtomicReference<RemoteException> exceptionRef = new AtomicReference<>(); + executeMethodAsync(()-> { + try { + getImsConfigImpl().onNotifyRcsAutoConfigurationRemoved(); + } catch (RemoteException e) { + exceptionRef.set(e); + } + }, "notifyRcsAutoConfigurationRemoved"); + + if (exceptionRef.get() != null) { + Log.d(TAG, "ImsConfigImplBase Exception notifyRcsAutoConfigurationRemoved"); + throw exceptionRef.get(); + } } private void notifyImsConfigChanged(int item, int value) throws RemoteException { @@ -223,50 +367,144 @@ public class ImsConfigImplBase { getImsConfigImpl().notifyConfigChanged(item, value); } - protected synchronized void updateCachedValue(int item, int value, boolean notifyChange) - throws RemoteException { - mProvisionedIntValue.put(item, value); - if (notifyChange) { - notifyImsConfigChanged(item, value); + protected void updateCachedValue(int item, int value) { + synchronized (mLock) { + mProvisionedIntValue.put(item, value); } } - protected synchronized void updateCachedValue(int item, String value, - boolean notifyChange) throws RemoteException { - mProvisionedStringValue.put(item, value); - if (notifyChange) { - notifyImsConfigChanged(item, value); + protected void updateCachedValue(int item, String value) { + synchronized (mLock) { + mProvisionedStringValue.put(item, value); } } @Override public void addRcsConfigCallback(IRcsConfigCallback c) throws RemoteException { - getImsConfigImpl().addRcsConfigCallback(c); + AtomicReference<RemoteException> exceptionRef = new AtomicReference<>(); + executeMethodAsync(()-> { + try { + getImsConfigImpl().addRcsConfigCallback(c); + } catch (RemoteException e) { + exceptionRef.set(e); + } + }, "addRcsConfigCallback"); + + if (exceptionRef.get() != null) { + Log.d(TAG, "ImsConfigImplBase Exception addRcsConfigCallback"); + throw exceptionRef.get(); + } } @Override public void removeRcsConfigCallback(IRcsConfigCallback c) throws RemoteException { - getImsConfigImpl().removeRcsConfigCallback(c); + AtomicReference<RemoteException> exceptionRef = new AtomicReference<>(); + executeMethodAsync(()-> { + try { + getImsConfigImpl().removeRcsConfigCallback(c); + } catch (RemoteException e) { + exceptionRef.set(e); + } + }, "removeRcsConfigCallback"); + + if (exceptionRef.get() != null) { + Log.d(TAG, "ImsConfigImplBase Exception removeRcsConfigCallback"); + throw exceptionRef.get(); + } } @Override public void triggerRcsReconfiguration() throws RemoteException { - getImsConfigImpl().triggerAutoConfiguration(); + AtomicReference<RemoteException> exceptionRef = new AtomicReference<>(); + executeMethodAsync(()-> { + try { + getImsConfigImpl().triggerAutoConfiguration(); + } catch (RemoteException e) { + exceptionRef.set(e); + } + }, "triggerRcsReconfiguration"); + + if (exceptionRef.get() != null) { + Log.d(TAG, "ImsConfigImplBase Exception triggerRcsReconfiguration"); + throw exceptionRef.get(); + } } @Override public void setRcsClientConfiguration(RcsClientConfiguration rcc) throws RemoteException { - getImsConfigImpl().setRcsClientConfiguration(rcc); + AtomicReference<RemoteException> exceptionRef = new AtomicReference<>(); + executeMethodAsync(()-> { + try { + getImsConfigImpl().setRcsClientConfiguration(rcc); + } catch (RemoteException e) { + exceptionRef.set(e); + } + }, "setRcsClientConfiguration"); + + if (exceptionRef.get() != null) { + Log.d(TAG, "ImsConfigImplBase Exception setRcsClientConfiguration"); + throw exceptionRef.get(); + } } @Override public void notifyIntImsConfigChanged(int item, int value) throws RemoteException { - notifyImsConfigChanged(item, value); + AtomicReference<RemoteException> exceptionRef = new AtomicReference<>(); + executeMethodAsync(()-> { + try { + notifyImsConfigChanged(item, value); + } catch (RemoteException e) { + exceptionRef.set(e); + } + }, "notifyIntImsConfigChanged"); + + if (exceptionRef.get() != null) { + Log.d(TAG, "ImsConfigImplBase Exception notifyIntImsConfigChanged"); + throw exceptionRef.get(); + } } @Override public void notifyStringImsConfigChanged(int item, String value) throws RemoteException { - notifyImsConfigChanged(item, value); + AtomicReference<RemoteException> exceptionRef = new AtomicReference<>(); + executeMethodAsync(()-> { + try { + notifyImsConfigChanged(item, value); + } catch (RemoteException e) { + exceptionRef.set(e); + } + }, "notifyStringImsConfigChanged"); + + if (exceptionRef.get() != null) { + Log.d(TAG, "ImsConfigImplBase Exception notifyStringImsConfigChanged"); + throw exceptionRef.get(); + } + } + + // Call the methods with a clean calling identity on the executor and wait indefinitely for + // the future to return. + private void executeMethodAsync(Runnable r, String errorLogName) throws RemoteException { + try { + CompletableFuture.runAsync( + () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join(); + } catch (CancellationException | CompletionException e) { + Log.w(TAG, "ImsConfigImplBase Binder - " + errorLogName + " exception: " + + e.getMessage()); + throw new RemoteException(e.getMessage()); + } + } + + private <T> T executeMethodAsyncForResult(Supplier<T> r, + String errorLogName) throws RemoteException { + CompletableFuture<T> future = CompletableFuture.supplyAsync( + () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor); + try { + return future.get(); + } catch (ExecutionException | InterruptedException e) { + Log.w(TAG, "ImsConfigImplBase Binder - " + errorLogName + " exception: " + + e.getMessage()); + throw new RemoteException(e.getMessage()); + } } } @@ -303,15 +541,24 @@ public class ImsConfigImplBase { ImsConfigStub mImsConfigStub; /** - * Used for compatibility between older versions of the ImsService. + * Create a ImsConfig using the Executor specified for methods being called by the + * framework. + * @param executor The executor for the framework to use when executing the methods overridden + * by the implementation of ImsConfig. + */ + public ImsConfigImplBase(@NonNull Executor executor) { + mImsConfigStub = new ImsConfigStub(this, executor); + } + + /** * @hide */ - public ImsConfigImplBase(Context context) { - mImsConfigStub = new ImsConfigStub(this); + public ImsConfigImplBase(@NonNull Context context) { + mImsConfigStub = new ImsConfigStub(this, null); } public ImsConfigImplBase() { - mImsConfigStub = new ImsConfigStub(this); + mImsConfigStub = new ImsConfigStub(this, null); } /** @@ -427,8 +674,10 @@ public class ImsConfigImplBase { * @param value in Integer format. */ public final void notifyProvisionedValueChanged(int item, int value) { + mImsConfigStub.updateCachedValue(item, value); + try { - mImsConfigStub.updateCachedValue(item, value, true); + mImsConfigStub.notifyImsConfigChanged(item, value); } catch (RemoteException e) { Log.w(TAG, "notifyProvisionedValueChanged(int): Framework connection is dead."); } @@ -443,8 +692,10 @@ public class ImsConfigImplBase { * @param value in String format. */ public final void notifyProvisionedValueChanged(int item, String value) { + mImsConfigStub.updateCachedValue(item, value); + try { - mImsConfigStub.updateCachedValue(item, value, true); + mImsConfigStub.notifyImsConfigChanged(item, value); } catch (RemoteException e) { Log.w(TAG, "notifyProvisionedValueChanged(string): Framework connection is dead."); } @@ -582,4 +833,16 @@ public class ImsConfigImplBase { } }); } + + /** + * Set default Executor from ImsService. + * @param executor The default executor for the framework to use when executing the methods + * overridden by the implementation of ImsConfig. + * @hide + */ + public final void setDefaultExecutor(@NonNull Executor executor) { + if (mImsConfigStub.mExecutor == null) { + mImsConfigStub.mExecutor = executor; + } + } } diff --git a/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java b/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java index 8ad40ed1032c..84b2253e1b27 100644 --- a/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java +++ b/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java @@ -16,14 +16,21 @@ package android.telephony.ims.stub; +import android.annotation.NonNull; import android.annotation.SystemApi; import android.os.RemoteException; import android.util.Log; import com.android.ims.internal.IImsEcbm; import com.android.ims.internal.IImsEcbmListener; +import com.android.internal.telephony.util.TelephonyUtils; import java.util.Objects; +import java.util.concurrent.CancellationException; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; +import java.util.concurrent.Executor; + /** * Base implementation of ImsEcbm, which implements stub versions of the methods @@ -40,10 +47,12 @@ public class ImsEcbmImplBase { private final Object mLock = new Object(); private IImsEcbmListener mListener; + private Executor mExecutor = Runnable::run; + private final IImsEcbm mImsEcbm = new IImsEcbm.Stub() { @Override public void setListener(IImsEcbmListener listener) { - synchronized (mLock) { + executeMethodAsync(() -> { if (mListener != null && !mListener.asBinder().isBinderAlive()) { Log.w(TAG, "setListener: discarding dead Binder"); mListener = null; @@ -62,12 +71,25 @@ public class ImsEcbmImplBase { + "listener"); mListener = listener; } - } + }, "setListener"); } @Override public void exitEmergencyCallbackMode() { - ImsEcbmImplBase.this.exitEmergencyCallbackMode(); + executeMethodAsync(() -> ImsEcbmImplBase.this.exitEmergencyCallbackMode(), + "exitEmergencyCallbackMode"); + } + + // Call the methods with a clean calling identity on the executor and wait indefinitely for + // the future to return. + private void executeMethodAsync(Runnable r, String errorLogName) { + try { + CompletableFuture.runAsync( + () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join(); + } catch (CancellationException | CompletionException e) { + Log.w(TAG, "ImsEcbmImplBase Binder - " + errorLogName + " exception: " + + e.getMessage()); + } } }; @@ -123,4 +145,14 @@ public class ImsEcbmImplBase { } } } + + /** + * Set default Executor from MmTelFeature. + * @param executor The default executor for the framework to use when executing the methods + * overridden by the implementation of ImsEcbm. + * @hide + */ + public final void setDefaultExecutor(@NonNull Executor executor) { + mExecutor = executor; + } } diff --git a/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java b/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java index ec1c7b3a92a8..a723cd8b118c 100644 --- a/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java +++ b/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java @@ -16,6 +16,7 @@ package android.telephony.ims.stub; +import android.annotation.NonNull; import android.annotation.SystemApi; import android.os.RemoteException; import android.telephony.ims.ImsExternalCallState; @@ -23,9 +24,14 @@ import android.util.Log; import com.android.ims.internal.IImsExternalCallStateListener; import com.android.ims.internal.IImsMultiEndpoint; +import com.android.internal.telephony.util.TelephonyUtils; import java.util.List; import java.util.Objects; +import java.util.concurrent.CancellationException; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; +import java.util.concurrent.Executor; /** * Base implementation of ImsMultiEndpoint, which implements stub versions of the methods @@ -43,11 +49,13 @@ public class ImsMultiEndpointImplBase { private IImsExternalCallStateListener mListener; private final Object mLock = new Object(); + private Executor mExecutor = Runnable::run; + private final IImsMultiEndpoint mImsMultiEndpoint = new IImsMultiEndpoint.Stub() { @Override public void setListener(IImsExternalCallStateListener listener) throws RemoteException { - synchronized (mLock) { + executeMethodAsync(() -> { if (mListener != null && !mListener.asBinder().isBinderAlive()) { Log.w(TAG, "setListener: discarding dead Binder"); mListener = null; @@ -67,12 +75,25 @@ public class ImsMultiEndpointImplBase { + "listener"); mListener = listener; } - } + }, "setListener"); } @Override public void requestImsExternalCallStateInfo() throws RemoteException { - ImsMultiEndpointImplBase.this.requestImsExternalCallStateInfo(); + executeMethodAsync(() -> ImsMultiEndpointImplBase.this + .requestImsExternalCallStateInfo(), "requestImsExternalCallStateInfo"); + } + + // Call the methods with a clean calling identity on the executor and wait indefinitely for + // the future to return. + private void executeMethodAsync(Runnable r, String errorLogName) { + try { + CompletableFuture.runAsync( + () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join(); + } catch (CancellationException | CompletionException e) { + Log.w(TAG, "ImsMultiEndpointImplBase Binder - " + errorLogName + " exception: " + + e.getMessage()); + } } }; @@ -108,4 +129,14 @@ public class ImsMultiEndpointImplBase { public void requestImsExternalCallStateInfo() { Log.d(TAG, "requestImsExternalCallStateInfo() not implemented"); } + + /** + * Set default Executor from MmTelFeature. + * @param executor The default executor for the framework to use when executing the methods + * overridden by the implementation of ImsMultiEndpoint. + * @hide + */ + public final void setDefaultExecutor(@NonNull Executor executor) { + mExecutor = executor; + } } diff --git a/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java index 02bcdec621c1..ac5565bea810 100644 --- a/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java +++ b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java @@ -31,10 +31,18 @@ import android.telephony.ims.aidl.IImsRegistrationCallback; import android.util.Log; import com.android.internal.telephony.util.RemoteCallbackListExt; +import com.android.internal.telephony.util.TelephonyUtils; import com.android.internal.util.ArrayUtils; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.concurrent.CancellationException; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executor; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Supplier; /** * Controls IMS registration for this ImsService and notifies the framework when the IMS @@ -42,9 +50,7 @@ import java.lang.annotation.RetentionPolicy; * <p> * Note: There is no guarantee on the thread that the calls from the framework will be called on. It * is the implementors responsibility to handle moving the calls to a working thread if required. - * @hide */ -@SystemApi public class ImsRegistrationImplBase { private static final String LOG_TAG = "ImsRegistrationImplBase"; @@ -85,6 +91,12 @@ public class ImsRegistrationImplBase { */ public static final int REGISTRATION_TECH_NR = 3; + /** + * This is used to check the upper range of registration tech + * {@hide} + */ + public static final int REGISTRATION_TECH_MAX = REGISTRATION_TECH_NR + 1; + // Registration states, used to notify new ImsRegistrationImplBase#Callbacks of the current // state. // The unknown state is set as the initialization state. This is so that we do not call back @@ -92,39 +104,118 @@ public class ImsRegistrationImplBase { // yet. private static final int REGISTRATION_STATE_UNKNOWN = -1; + private Executor mExecutor; + + /** + * Create a new ImsRegistration. + * <p> + * Method stubs called from the framework will be called asynchronously. To specify the + * {@link Executor} that the methods stubs will be called, use + * {@link ImsRegistrationImplBase#ImsRegistrationImplBase(Executor)} instead. + * @hide This API is not part of the Android public SDK API + */ + @SystemApi + public ImsRegistrationImplBase() { + super(); + } + + /** + * Create a ImsRegistration using the Executor specified for methods being called by the + * framework. + * @param executor The executor for the framework to use when executing the methods overridden + * by the implementation of ImsRegistration. + * @hide This API is not part of the Android public SDK API + */ + @SystemApi + public ImsRegistrationImplBase(@NonNull Executor executor) { + super(); + mExecutor = executor; + } + private final IImsRegistration mBinder = new IImsRegistration.Stub() { @Override public @ImsRegistrationTech int getRegistrationTechnology() throws RemoteException { - synchronized (mLock) { - return (mRegistrationAttributes == null) ? REGISTRATION_TECH_NONE - : mRegistrationAttributes.getRegistrationTechnology(); - } + return executeMethodAsyncForResult(() -> (mRegistrationAttributes == null) + ? REGISTRATION_TECH_NONE : mRegistrationAttributes.getRegistrationTechnology(), + "getRegistrationTechnology"); } @Override public void addRegistrationCallback(IImsRegistrationCallback c) throws RemoteException { - ImsRegistrationImplBase.this.addRegistrationCallback(c); + AtomicReference<RemoteException> exceptionRef = new AtomicReference<>(); + executeMethodAsync(() -> { + try { + ImsRegistrationImplBase.this.addRegistrationCallback(c); + } catch (RemoteException e) { + exceptionRef.set(e); + } + }, "addRegistrationCallback"); + + if (exceptionRef.get() != null) { + throw exceptionRef.get(); + } } @Override public void removeRegistrationCallback(IImsRegistrationCallback c) throws RemoteException { - ImsRegistrationImplBase.this.removeRegistrationCallback(c); + executeMethodAsync(() -> ImsRegistrationImplBase.this.removeRegistrationCallback(c), + "removeRegistrationCallback"); } @Override public void triggerFullNetworkRegistration(int sipCode, String sipReason) { - ImsRegistrationImplBase.this.triggerFullNetworkRegistration(sipCode, sipReason); + executeMethodAsyncNoException(() -> ImsRegistrationImplBase.this + .triggerFullNetworkRegistration(sipCode, sipReason), + "triggerFullNetworkRegistration"); } @Override public void triggerUpdateSipDelegateRegistration() { - ImsRegistrationImplBase.this.updateSipDelegateRegistration(); + executeMethodAsyncNoException(() -> ImsRegistrationImplBase.this + .updateSipDelegateRegistration(), "triggerUpdateSipDelegateRegistration"); } @Override public void triggerSipDelegateDeregistration() { - ImsRegistrationImplBase.this.triggerSipDelegateDeregistration(); + executeMethodAsyncNoException(() -> ImsRegistrationImplBase.this + .triggerSipDelegateDeregistration(), "triggerSipDelegateDeregistration"); + } + + // Call the methods with a clean calling identity on the executor and wait indefinitely for + // the future to return. + private void executeMethodAsync(Runnable r, String errorLogName) throws RemoteException { + try { + CompletableFuture.runAsync( + () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join(); + } catch (CancellationException | CompletionException e) { + Log.w(LOG_TAG, "ImsRegistrationImplBase Binder - " + errorLogName + " exception: " + + e.getMessage()); + throw new RemoteException(e.getMessage()); + } + } + + private void executeMethodAsyncNoException(Runnable r, String errorLogName) { + try { + CompletableFuture.runAsync( + () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join(); + } catch (CancellationException | CompletionException e) { + Log.w(LOG_TAG, "ImsRegistrationImplBase Binder - " + errorLogName + " exception: " + + e.getMessage()); + } + } + + private <T> T executeMethodAsyncForResult(Supplier<T> r, + String errorLogName) throws RemoteException { + CompletableFuture<T> future = CompletableFuture.supplyAsync( + () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor); + try { + return future.get(); + } catch (ExecutionException | InterruptedException e) { + Log.w(LOG_TAG, "ImsRegistrationImplBase Binder - " + errorLogName + " exception: " + + e.getMessage()); + throw new RemoteException(e.getMessage()); + } } }; @@ -166,7 +257,9 @@ public class ImsRegistrationImplBase { * If the SIP delegate feature tag configuration has changed, then this method will be * called in order to let the ImsService know that it can pick up these changes in the IMS * registration. + * @hide This API is not part of the Android public SDK API */ + @SystemApi public void updateSipDelegateRegistration() { // Stub implementation, ImsService should implement this } @@ -182,7 +275,9 @@ public class ImsRegistrationImplBase { * <p> * This should not affect the registration of features managed by the ImsService itself, such as * feature tags related to MMTEL registration. + * @hide This API is not part of the Android public SDK API */ + @SystemApi public void triggerSipDelegateDeregistration() { // Stub implementation, ImsService should implement this } @@ -200,7 +295,9 @@ public class ImsRegistrationImplBase { * be carrier specific. * @param sipReason The reason associated with the SIP error code. {@code null} if there was no * reason associated with the error. + * @hide This API is not part of the Android public SDK API */ + @SystemApi public void triggerFullNetworkRegistration(@IntRange(from = 100, to = 699) int sipCode, @Nullable String sipReason) { // Stub implementation, ImsService should implement this @@ -211,7 +308,9 @@ public class ImsRegistrationImplBase { * Notify the framework that the device is connected to the IMS network. * * @param imsRadioTech the radio access technology. + * @hide This API is not part of the Android public SDK API */ + @SystemApi public final void onRegistered(@ImsRegistrationTech int imsRadioTech) { onRegistered(new ImsRegistrationAttributes.Builder(imsRadioTech).build()); } @@ -220,7 +319,9 @@ public class ImsRegistrationImplBase { * Notify the framework that the device is connected to the IMS network. * * @param attributes The attributes associated with the IMS registration. + * @hide This API is not part of the Android public SDK API */ + @SystemApi public final void onRegistered(@NonNull ImsRegistrationAttributes attributes) { updateToState(attributes, RegistrationManager.REGISTRATION_STATE_REGISTERED); mCallbacks.broadcastAction((c) -> { @@ -236,7 +337,9 @@ public class ImsRegistrationImplBase { * Notify the framework that the device is trying to connect the IMS network. * * @param imsRadioTech the radio access technology. + * @hide This API is not part of the Android public SDK API */ + @SystemApi public final void onRegistering(@ImsRegistrationTech int imsRadioTech) { onRegistering(new ImsRegistrationAttributes.Builder(imsRadioTech).build()); } @@ -245,7 +348,9 @@ public class ImsRegistrationImplBase { * Notify the framework that the device is trying to connect the IMS network. * * @param attributes The attributes associated with the IMS registration. + * @hide This API is not part of the Android public SDK API */ + @SystemApi public final void onRegistering(@NonNull ImsRegistrationAttributes attributes) { updateToState(attributes, RegistrationManager.REGISTRATION_STATE_REGISTERING); mCallbacks.broadcastAction((c) -> { @@ -272,7 +377,9 @@ public class ImsRegistrationImplBase { * result. * * @param info the {@link ImsReasonInfo} associated with why registration was disconnected. + * @hide This API is not part of the Android public SDK API */ + @SystemApi public final void onDeregistered(ImsReasonInfo info) { updateToDisconnectedState(info); // ImsReasonInfo should never be null. @@ -293,7 +400,9 @@ public class ImsRegistrationImplBase { * {@link #REGISTRATION_TECH_LTE}, {@link #REGISTRATION_TECH_IWLAN} and * {@link #REGISTRATION_TECH_CROSS_SIM}. * @param info The {@link ImsReasonInfo} for the failure to change technology. + * @hide This API is not part of the Android public SDK API */ + @SystemApi public final void onTechnologyChangeFailed(@ImsRegistrationTech int imsRadioTech, ImsReasonInfo info) { final ImsReasonInfo reasonInfo = (info != null) ? info : new ImsReasonInfo(); @@ -312,7 +421,9 @@ public class ImsRegistrationImplBase { * * The {@link Uri}s are not guaranteed to be different between subsequent calls. * @param uris changed uris + * @hide This API is not part of the Android public SDK API */ + @SystemApi public final void onSubscriberAssociatedUriChanged(Uri[] uris) { synchronized (mLock) { mUris = ArrayUtils.cloneOrNull(uris); @@ -394,4 +505,16 @@ public class ImsRegistrationImplBase { onSubscriberAssociatedUriChanged(c, uris); } } + + /** + * Set default Executor from ImsService. + * @param executor The default executor for the framework to use when executing the methods + * overridden by the implementation of Registration. + * @hide + */ + public final void setDefaultExecutor(@NonNull Executor executor) { + if (mExecutor == null) { + mExecutor = executor; + } + } } diff --git a/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java b/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java index eb3e8ed5a8e4..11cdeed10c5a 100644 --- a/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java +++ b/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java @@ -27,10 +27,17 @@ import android.util.Log; import com.android.ims.internal.IImsUt; import com.android.ims.internal.IImsUtListener; +import com.android.internal.telephony.util.TelephonyUtils; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Objects; +import java.util.concurrent.CancellationException; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executor; +import java.util.function.Supplier; /** * Base implementation of IMS UT interface, which implements stubs. Override these methods to @@ -119,96 +126,108 @@ public class ImsUtImplBase { */ public static final int INVALID_RESULT = -1; + private Executor mExecutor = Runnable::run; + private final IImsUt.Stub mServiceImpl = new IImsUt.Stub() { private final Object mLock = new Object(); private ImsUtListener mUtListener; @Override public void close() throws RemoteException { - ImsUtImplBase.this.close(); + executeMethodAsync(() ->ImsUtImplBase.this.close(), "close"); } @Override public int queryCallBarring(int cbType) throws RemoteException { - return ImsUtImplBase.this.queryCallBarring(cbType); + return executeMethodAsyncForResult(() -> ImsUtImplBase.this.queryCallBarring(cbType), + "queryCallBarring"); } @Override public int queryCallForward(int condition, String number) throws RemoteException { - return ImsUtImplBase.this.queryCallForward(condition, number); + return executeMethodAsyncForResult(() -> ImsUtImplBase.this.queryCallForward( + condition, number), "queryCallForward"); } @Override public int queryCallWaiting() throws RemoteException { - return ImsUtImplBase.this.queryCallWaiting(); + return executeMethodAsyncForResult(() -> ImsUtImplBase.this.queryCallWaiting(), + "queryCallWaiting"); } @Override public int queryCLIR() throws RemoteException { - return ImsUtImplBase.this.queryCLIR(); + return executeMethodAsyncForResult(() -> ImsUtImplBase.this.queryCLIR(), "queryCLIR"); } @Override public int queryCLIP() throws RemoteException { - return ImsUtImplBase.this.queryCLIP(); + return executeMethodAsyncForResult(() -> ImsUtImplBase.this.queryCLIP(), "queryCLIP"); } @Override public int queryCOLR() throws RemoteException { - return ImsUtImplBase.this.queryCOLR(); + return executeMethodAsyncForResult(() -> ImsUtImplBase.this.queryCOLR(), "queryCOLR"); } @Override public int queryCOLP() throws RemoteException { - return ImsUtImplBase.this.queryCOLP(); + return executeMethodAsyncForResult(() -> ImsUtImplBase.this.queryCOLP(), "queryCOLP"); } @Override public int transact(Bundle ssInfo) throws RemoteException { - return ImsUtImplBase.this.transact(ssInfo); + return executeMethodAsyncForResult(() -> ImsUtImplBase.this.transact(ssInfo), + "transact"); } @Override public int updateCallBarring(int cbType, int action, String[] barrList) throws RemoteException { - return ImsUtImplBase.this.updateCallBarring(cbType, action, barrList); + return executeMethodAsyncForResult(() -> ImsUtImplBase.this.updateCallBarring( + cbType, action, barrList), "updateCallBarring"); } @Override public int updateCallForward(int action, int condition, String number, int serviceClass, int timeSeconds) throws RemoteException { - return ImsUtImplBase.this.updateCallForward(action, condition, number, serviceClass, - timeSeconds); + return executeMethodAsyncForResult(() -> ImsUtImplBase.this.updateCallForward( + action, condition, number, serviceClass, timeSeconds), "updateCallForward"); } @Override public int updateCallWaiting(boolean enable, int serviceClass) throws RemoteException { - return ImsUtImplBase.this.updateCallWaiting(enable, serviceClass); + return executeMethodAsyncForResult(() -> ImsUtImplBase.this.updateCallWaiting( + enable, serviceClass), "updateCallWaiting"); } @Override public int updateCLIR(int clirMode) throws RemoteException { - return ImsUtImplBase.this.updateCLIR(clirMode); + return executeMethodAsyncForResult(() -> ImsUtImplBase.this.updateCLIR(clirMode), + "updateCLIR"); } @Override public int updateCLIP(boolean enable) throws RemoteException { - return ImsUtImplBase.this.updateCLIP(enable); + return executeMethodAsyncForResult(() -> ImsUtImplBase.this.updateCLIP(enable), + "updateCLIP"); } @Override public int updateCOLR(int presentation) throws RemoteException { - return ImsUtImplBase.this.updateCOLR(presentation); + return executeMethodAsyncForResult(() -> ImsUtImplBase.this.updateCOLR(presentation), + "updateCOLR"); } @Override public int updateCOLP(boolean enable) throws RemoteException { - return ImsUtImplBase.this.updateCOLP(enable); + return executeMethodAsyncForResult(() -> ImsUtImplBase.this.updateCOLP(enable), + "updateCOLP"); } @Override public void setListener(IImsUtListener listener) throws RemoteException { - synchronized (mLock) { + executeMethodAsync(() -> { if (mUtListener != null && !mUtListener.getListenerInterface().asBinder().isBinderAlive()) { Log.w(TAG, "setListener: discarding dead Binder"); @@ -229,29 +248,59 @@ public class ImsUtImplBase { + "listener"); mUtListener = new ImsUtListener(listener); } - } - ImsUtImplBase.this.setListener(mUtListener); + ImsUtImplBase.this.setListener(mUtListener); + }, "setListener"); } @Override public int queryCallBarringForServiceClass(int cbType, int serviceClass) throws RemoteException { - return ImsUtImplBase.this.queryCallBarringForServiceClass(cbType, serviceClass); + return executeMethodAsyncForResult(() -> ImsUtImplBase.this + .queryCallBarringForServiceClass(cbType, serviceClass), + "queryCallBarringForServiceClass"); } @Override public int updateCallBarringForServiceClass(int cbType, int action, String[] barrList, int serviceClass) throws RemoteException { - return ImsUtImplBase.this.updateCallBarringForServiceClass( - cbType, action, barrList, serviceClass); + return executeMethodAsyncForResult(() -> ImsUtImplBase.this + .updateCallBarringForServiceClass(cbType, action, barrList, serviceClass), + "updateCallBarringForServiceClass"); } @Override public int updateCallBarringWithPassword(int cbType, int action, String[] barrList, int serviceClass, String password) throws RemoteException { - return ImsUtImplBase.this.updateCallBarringWithPassword( - cbType, action, barrList, serviceClass, password); + return executeMethodAsyncForResult(() -> ImsUtImplBase.this + .updateCallBarringWithPassword(cbType, action, barrList, serviceClass, + password), "updateCallBarringWithPassword"); + } + + // Call the methods with a clean calling identity on the executor and wait indefinitely for + // the future to return. + private void executeMethodAsync(Runnable r, String errorLogName) throws RemoteException { + try { + CompletableFuture.runAsync( + () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join(); + } catch (CancellationException | CompletionException e) { + Log.w(TAG, "ImsUtImplBase Binder - " + errorLogName + " exception: " + + e.getMessage()); + throw new RemoteException(e.getMessage()); + } + } + + private <T> T executeMethodAsyncForResult(Supplier<T> r, + String errorLogName) throws RemoteException { + CompletableFuture<T> future = CompletableFuture.supplyAsync( + () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor); + try { + return future.get(); + } catch (ExecutionException | InterruptedException e) { + Log.w(TAG, "ImsUtImplBase Binder - " + errorLogName + " exception: " + + e.getMessage()); + throw new RemoteException(e.getMessage()); + } } }; @@ -470,4 +519,14 @@ public class ImsUtImplBase { public IImsUt getInterface() { return mServiceImpl; } + + /** + * Set default Executor from MmTelFeature. + * @param executor The default executor for the framework to use when executing the methods + * overridden by the implementation of ImsUT. + * @hide + */ + public final void setDefaultExecutor(@NonNull Executor executor) { + mExecutor = executor; + } } diff --git a/telephony/java/android/telephony/ims/stub/SipTransportImplBase.java b/telephony/java/android/telephony/ims/stub/SipTransportImplBase.java index 13ea99735ab4..52538cb4e2df 100644 --- a/telephony/java/android/telephony/ims/stub/SipTransportImplBase.java +++ b/telephony/java/android/telephony/ims/stub/SipTransportImplBase.java @@ -86,10 +86,21 @@ public class SipTransportImplBase { } }; - private final Executor mBinderExecutor; + private Executor mBinderExecutor; private final ArrayList<SipDelegateAidlWrapper> mDelegates = new ArrayList<>(); /** + * Create a new SipTransport. + * <p> + * Method stubs called from the framework will be called asynchronously. To specify the + * {@link Executor} that the methods stubs will be called, use + * {@link SipTransportImplBase#SipTransportImplBase(Executor)} instead. + */ + public SipTransportImplBase() { + super(); + } + + /** * Create an implementation of SipTransportImplBase. * * @param executor The executor that remote calls from the framework will be called on. This @@ -212,4 +223,16 @@ public class SipTransportImplBase { public ISipTransport getBinder() { return mSipTransportImpl; } + + /** + * Set default Executor from ImsService. + * @param executor The default executor for the framework to use when executing the methods + * overridden by the implementation of SipTransport. + * @hide + */ + public final void setDefaultExecutor(@NonNull Executor executor) { + if (mBinderExecutor == null) { + mBinderExecutor = executor; + } + } } diff --git a/telephony/java/com/android/ims/internal/IImsServiceFeatureCallback.aidl b/telephony/java/com/android/ims/internal/IImsServiceFeatureCallback.aidl index f5f67bd36ec3..416096b1f6ec 100644 --- a/telephony/java/com/android/ims/internal/IImsServiceFeatureCallback.aidl +++ b/telephony/java/com/android/ims/internal/IImsServiceFeatureCallback.aidl @@ -23,11 +23,11 @@ import com.android.ims.ImsFeatureContainer; * {@hide} */ oneway interface IImsServiceFeatureCallback { - void imsFeatureCreated(in ImsFeatureContainer feature); + void imsFeatureCreated(in ImsFeatureContainer feature, int subId); // Reason defined in FeatureConnector.UnavailableReason void imsFeatureRemoved(int reason); // Status defined in ImsFeature.ImsState. - void imsStatusChanged(int status); + void imsStatusChanged(int status, int subId); //Capabilities defined in ImsService.ImsServiceCapability void updateCapabilities(long capabilities); }
\ No newline at end of file diff --git a/telephony/java/com/android/internal/telephony/DctConstants.java b/telephony/java/com/android/internal/telephony/DctConstants.java index 409c838cb3e3..24708873986c 100644 --- a/telephony/java/com/android/internal/telephony/DctConstants.java +++ b/telephony/java/com/android/internal/telephony/DctConstants.java @@ -114,6 +114,7 @@ public class DctConstants { public static final int EVENT_CARRIER_CONFIG_CHANGED = BASE + 54; public static final int EVENT_SIM_STATE_UPDATED = BASE + 55; public static final int EVENT_APN_UNTHROTTLED = BASE + 56; + public static final int EVENT_TRAFFIC_DESCRIPTORS_UPDATED = BASE + 57; /***** Constants *****/ diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index 167aa07f3ac2..0ac7cf957ecf 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -55,6 +55,7 @@ import android.telephony.VisualVoicemailSmsFilterSettings; import android.telephony.emergency.EmergencyNumber; import android.telephony.ims.RcsClientConfiguration; import android.telephony.ims.RcsContactUceCapability; +import android.telephony.ims.aidl.IFeatureProvisioningCallback; import android.telephony.ims.aidl.IImsCapabilityCallback; import android.telephony.ims.aidl.IImsConfig; import android.telephony.ims.aidl.IImsConfigCallback; @@ -2027,6 +2028,18 @@ interface ITelephony { void unregisterImsProvisioningChangedCallback(int subId, IImsConfigCallback callback); /** + * Register an IMS provisioning change callback with Telephony. + */ + void registerFeatureProvisioningChangedCallback(int subId, + IFeatureProvisioningCallback callback); + + /** + * unregister an existing IMS provisioning change callback. + */ + void unregisterFeatureProvisioningChangedCallback(int subId, + IFeatureProvisioningCallback callback); + + /** * Set the provisioning status for the IMS MmTel capability using the specified subscription. */ void setImsProvisioningStatusForCapability(int subId, int capability, int tech, @@ -2040,19 +2053,12 @@ interface ITelephony { /** * Get the provisioning status for the IMS Rcs capability specified. */ - boolean getRcsProvisioningStatusForCapability(int subId, int capability); + boolean getRcsProvisioningStatusForCapability(int subId, int capability, int tech); /** * Set the provisioning status for the IMS Rcs capability using the specified subscription. */ - void setRcsProvisioningStatusForCapability(int subId, int capability, - boolean isProvisioned); - - /** Is the capability and tech flagged as provisioned in the cache */ - boolean isMmTelCapabilityProvisionedInCache(int subId, int capability, int tech); - - /** Set the provisioning for the capability and tech in the cache */ - void cacheMmTelCapabilityProvisioning(int subId, int capability, int tech, + void setRcsProvisioningStatusForCapability(int subId, int capability, int tech, boolean isProvisioned); /** @@ -2555,4 +2561,18 @@ interface ITelephony { * @return the service name of the modem service which bind to. */ String getModemService(); + + /** + * Is Provisioning required for capability + * @return true if provisioning is required for the MMTEL capability and IMS + * registration technology specified, false if it is not required. + */ + boolean isProvisioningRequiredForCapability(int subId, int capability, int tech); + + /** + * Is RCS Provisioning required for capability + * @return true if provisioning is required for the RCS capability and IMS + * registration technology specified, false if it is not required. + */ + boolean isRcsProvisioningRequiredForCapability(int subId, int capability, int tech); } diff --git a/tests/SilkFX/AndroidManifest.xml b/tests/SilkFX/AndroidManifest.xml index c30d76137f76..21256d8c9d0b 100644 --- a/tests/SilkFX/AndroidManifest.xml +++ b/tests/SilkFX/AndroidManifest.xml @@ -20,17 +20,20 @@ <uses-sdk android:minSdkVersion="30"/> <uses-permission android:name="android.permission.CONTROL_DISPLAY_BRIGHTNESS" /> + <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" /> <application android:label="SilkFX" android:theme="@android:style/Theme.Material"> <activity android:name=".Main" android:label="SilkFX Demos" + android:banner="@drawable/background1" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.DEFAULT"/> <category android:name="android.intent.category.LAUNCHER"/> + <category android:name="android.intent.category.LEANBACK_LAUNCHER"/> </intent-filter> </activity> @@ -41,13 +44,16 @@ <activity android:name=".materials.GlassActivity" android:label="Glass Examples" - android:banner="@drawable/background1" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN"/> - <category android:name="android.intent.category.LEANBACK_LAUNCHER" /> </intent-filter> </activity> + <activity android:name=".materials.BackgroundBlurActivity" + android:theme="@style/Theme.BackgroundBlurTheme" + android:exported="true"> + </activity> + </application> </manifest> diff --git a/tests/SilkFX/res/drawable/background_blur_drawable.xml b/tests/SilkFX/res/drawable/background_blur_drawable.xml new file mode 100644 index 000000000000..173ca99bdfdf --- /dev/null +++ b/tests/SilkFX/res/drawable/background_blur_drawable.xml @@ -0,0 +1,20 @@ +<!-- + ~ Copyright (C) 2022 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. + --> +<shape xmlns:android="http://schemas.android.com/apk/res/android" + android:shape="rectangle"> + <solid android:color="#20FFFFFF"/> + <corners android:radius="10dp"/> +</shape> diff --git a/tests/SilkFX/res/drawable/blur_activity_background_drawable_white.xml b/tests/SilkFX/res/drawable/blur_activity_background_drawable_white.xml new file mode 100644 index 000000000000..bd8942d46383 --- /dev/null +++ b/tests/SilkFX/res/drawable/blur_activity_background_drawable_white.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2022 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. + --> +<shape xmlns:android="http://schemas.android.com/apk/res/android" + android:shape="rectangle"> + <corners android:radius="10dp"/> +</shape> diff --git a/tests/SilkFX/res/layout/activity_background_blur.xml b/tests/SilkFX/res/layout/activity_background_blur.xml new file mode 100644 index 000000000000..f13c0883cb01 --- /dev/null +++ b/tests/SilkFX/res/layout/activity_background_blur.xml @@ -0,0 +1,173 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2022 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. + --> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/background" + android:layout_width="390dp" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:padding="15dp" + android:orientation="vertical" + tools:context=".materials.BackgroundBlurActivity"> + + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:gravity="center_horizontal" + android:padding="10dp" + android:textColor="#ffffffff" + android:text="Hello blurry world!"/> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal"> + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_weight="1" + android:textColor="#ffffffff" + android:text="Background blur"/> + + <SeekBar + android:id="@+id/set_background_blur" + android:min="0" + android:max="300" + android:layout_width="160dp" + android:layout_height="wrap_content"/> + <TextView + android:id="@+id/background_blur_radius" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textColor="#ffffffff" + android:ems="3" + android:gravity="center" + android:paddingLeft="10dp" + android:paddingRight="10dp" + android:text="TODO"/> + </LinearLayout> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal"> + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_weight="1" + android:textColor="#ffffffff" + android:text="Background alpha"/> + + <SeekBar + android:id="@+id/set_background_alpha" + android:min="0" + android:max="100" + android:layout_width="160dp" + android:layout_height="wrap_content" /> + <TextView + android:id="@+id/background_alpha" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textColor="#ffffffff" + android:ems="3" + android:gravity="center" + android:paddingLeft="10dp" + android:paddingRight="10dp" + android:text="TODO"/> + </LinearLayout> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal"> + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_weight="1" + android:textColor="#ffffffff" + android:text="Blur behind"/> + + <SeekBar + android:id="@+id/set_blur_behind" + android:min="0" + android:max="300" + android:layout_width="160dp" + android:layout_height="wrap_content" /> + <TextView + android:id="@+id/blur_behind_radius" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:gravity="center" + android:textColor="#ffffffff" + android:paddingLeft="10dp" + android:paddingRight="10dp" + android:ems="3" + android:text="TODO"/> + </LinearLayout> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal"> + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_weight="1" + android:textColor="#ffffffff" + android:text="Dim amount"/> + + <SeekBar + android:id="@+id/set_dim_amount" + android:min="0" + android:max="100" + android:layout_width="160dp" + android:layout_height="wrap_content" /> + <TextView + android:id="@+id/dim_amount" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:gravity="center" + android:textColor="#ffffffff" + android:paddingLeft="10dp" + android:paddingRight="10dp" + android:ems="3" + android:text="TODO"/> + </LinearLayout> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:layout_marginTop="5dp" + android:orientation="vertical" + android:gravity="center"> + + <Button + android:id="@+id/toggle_blur_enabled" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="Disable blur" + android:onClick="toggleForceBlurDisabled"/> + + <Button + android:id="@+id/toggle_battery_saving_mode" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="TODO" + android:onClick="toggleBatterySavingMode"/> + </LinearLayout> + <requestFocus/> + +</LinearLayout> diff --git a/tests/SilkFX/res/values/style.xml b/tests/SilkFX/res/values/style.xml new file mode 100644 index 000000000000..66edbb5c9382 --- /dev/null +++ b/tests/SilkFX/res/values/style.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2022 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. + --> +<!-- Styles for immersive actions UI. --> +<resources xmlns:android="http://schemas.android.com/apk/res/android"> + <style name="Theme.BackgroundBlurTheme" parent= "Theme.AppCompat.Dialog"> + <item name="android:windowIsTranslucent">true</item> + <item name="android:windowBlurBehindEnabled">true</item> + <item name="android:backgroundDimEnabled">false</item> + <item name="android:windowElevation">0dp</item> + <item name="buttonStyle">@style/AppTheme.Button</item> + <item name="colorAccent">#bbffffff</item> + </style> + <style name="AppTheme.Button" parent="Widget.AppCompat.Button"> + <item name="android:textColor">#ffffffff</item> + </style> + +</resources> diff --git a/tests/SilkFX/src/com/android/test/silkfx/Main.kt b/tests/SilkFX/src/com/android/test/silkfx/Main.kt index 9ed8d2f5edf7..7132ae8772ea 100644 --- a/tests/SilkFX/src/com/android/test/silkfx/Main.kt +++ b/tests/SilkFX/src/com/android/test/silkfx/Main.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 The Android Open Source Project + * Copyright (C) 2022 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. @@ -30,6 +30,7 @@ import com.android.test.silkfx.app.EXTRA_LAYOUT import com.android.test.silkfx.app.EXTRA_TITLE import com.android.test.silkfx.hdr.GlowActivity import com.android.test.silkfx.materials.GlassActivity +import com.android.test.silkfx.materials.BackgroundBlurActivity import kotlin.reflect.KClass class Demo(val name: String, val makeIntent: (Context) -> Intent) { @@ -51,7 +52,8 @@ private val AllDemos = listOf( Demo("Blingy Notifications", R.layout.bling_notifications) )), DemoGroup("Materials", listOf( - Demo("Glass", GlassActivity::class) + Demo("Glass", GlassActivity::class), + Demo("Background Blur", BackgroundBlurActivity::class) )) ) @@ -126,4 +128,4 @@ class Main : Activity() { AllDemos.forEachIndexed { index, _ -> list.expandGroup(index) } } -}
\ No newline at end of file +} diff --git a/tests/SilkFX/src/com/android/test/silkfx/materials/BackgroundBlurActivity.kt b/tests/SilkFX/src/com/android/test/silkfx/materials/BackgroundBlurActivity.kt new file mode 100644 index 000000000000..9d17d38d4298 --- /dev/null +++ b/tests/SilkFX/src/com/android/test/silkfx/materials/BackgroundBlurActivity.kt @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.test.silkfx.materials + +import android.app.Activity +import android.content.Intent +import android.content.Context +import android.graphics.Bitmap +import android.graphics.BitmapFactory +import android.graphics.Color +import android.graphics.drawable.ColorDrawable +import android.graphics.drawable.PaintDrawable +import android.graphics.drawable.Drawable +import android.os.Bundle +import android.provider.Settings +import android.util.TypedValue +import android.view.View +import android.view.WindowManager +import android.widget.ImageView +import android.widget.SeekBar +import android.widget.Switch +import android.widget.TextView +import com.android.test.silkfx.R +import com.android.internal.graphics.drawable.BackgroundBlurDrawable +import android.widget.LinearLayout +import android.widget.Button + +import android.view.ViewRootImpl + +class BackgroundBlurActivity : Activity(), SeekBar.OnSeekBarChangeListener { + var mBackgroundDrawable = PaintDrawable(Color.WHITE) + var mBackgroundBlurRadius = 50 + var mAlphaWithBlur = 0.2f + var mAlphaNoBlur = 0.5f + + var mBlurBehindRadius = 10 + var mDimAmountWithBlur = 0.2f + var mDimAmountNoBlur = 0.2f + + var mBlurForceDisabled = false + var mBatterySavingModeOn = false + + lateinit var blurBackgroundSeekBar: SeekBar + lateinit var backgroundAlphaSeekBar : SeekBar + lateinit var blurBehindSeekBar : SeekBar + lateinit var dimAmountSeekBar : SeekBar + + val blurEnabledListener = { enabled : Boolean -> + blurBackgroundSeekBar.setProgress(mBackgroundBlurRadius) + blurBehindSeekBar.setProgress(mBlurBehindRadius) + + if (enabled) { + setBackgroundBlur(mBackgroundBlurRadius) + setBackgroundColorAlpha(mAlphaWithBlur) + + setBlurBehind(mBlurBehindRadius) + setDimAmount(mDimAmountWithBlur) + + backgroundAlphaSeekBar.setProgress((mAlphaWithBlur * 100).toInt()) + dimAmountSeekBar.setProgress((mDimAmountWithBlur * 100).toInt()) + } else { + setBackgroundColorAlpha(mAlphaNoBlur) + setDimAmount(mDimAmountNoBlur) + + backgroundAlphaSeekBar.setProgress((mAlphaNoBlur * 100).toInt()) + dimAmountSeekBar.setProgress((mDimAmountNoBlur * 100).toInt()) + } + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_background_blur) + + window.addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND) + window.addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND) + + mBackgroundDrawable.setCornerRadius(30f) + window.setBackgroundDrawable(mBackgroundDrawable) + + mBatterySavingModeOn = + Settings.Global.getInt(getContentResolver(), Settings.Global.LOW_POWER_MODE, 0) == 1 + setBatterySavingModeOn(mBatterySavingModeOn) + + blurBackgroundSeekBar = requireViewById(R.id.set_background_blur) + backgroundAlphaSeekBar = requireViewById(R.id.set_background_alpha) + blurBehindSeekBar = requireViewById(R.id.set_blur_behind) + dimAmountSeekBar = requireViewById(R.id.set_dim_amount) + + arrayOf(blurBackgroundSeekBar, backgroundAlphaSeekBar, blurBehindSeekBar, dimAmountSeekBar) + .forEach { + it.setOnSeekBarChangeListener(this) + } + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + getWindowManager().addCrossWindowBlurEnabledListener(blurEnabledListener) + } + + override fun onDetachedFromWindow() { + super.onDetachedFromWindow() + getWindowManager().removeCrossWindowBlurEnabledListener(blurEnabledListener) + } + + override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) { + when (seekBar) { + blurBackgroundSeekBar -> setBackgroundBlur(progress) + backgroundAlphaSeekBar -> setBackgroundColorAlpha(progress / 100.0f) + blurBehindSeekBar -> setBlurBehind(progress) + dimAmountSeekBar -> setDimAmount(progress / 100.0f) + else -> throw IllegalArgumentException("Unknown seek bar") + } + } + + override fun onStartTrackingTouch(seekBar: SeekBar?) {} + override fun onStopTrackingTouch(seekBar: SeekBar?) {} + + fun setBlurDisabled(disabled: Boolean) { + mBlurForceDisabled = disabled + Settings.Global.putInt(getContentResolver(), Settings.Global.DISABLE_WINDOW_BLURS, + if (mBlurForceDisabled) 1 else 0) + (findViewById(R.id.toggle_blur_enabled) as Button) + .setText(if (mBlurForceDisabled) "Enable blurs" else "Disable blurs") + } + + fun toggleForceBlurDisabled(v: View) { + setBlurDisabled(!mBlurForceDisabled) + } + + fun setBackgroundBlur(radius: Int) { + mBackgroundBlurRadius = radius + (findViewById(R.id.background_blur_radius) as TextView).setText(radius.toString()) + window.setBackgroundBlurRadius(mBackgroundBlurRadius) + } + + fun setBlurBehind(radius: Int) { + mBlurBehindRadius = radius + (findViewById(R.id.blur_behind_radius) as TextView).setText(radius.toString()) + window.getAttributes().setBlurBehindRadius(mBlurBehindRadius) + window.setAttributes(window.getAttributes()) + } + + fun setDimAmount(amount: Float) { + if (getWindowManager().isCrossWindowBlurEnabled()) { + mDimAmountWithBlur = amount + } else { + mDimAmountNoBlur = amount + } + (findViewById(R.id.dim_amount) as TextView).setText("%.2f".format(amount)) + window.getAttributes().dimAmount = amount + window.setAttributes(window.getAttributes()) + } + + fun setBatterySavingModeOn(on: Boolean) { + mBatterySavingModeOn = on + Settings.Global.putInt(getContentResolver(), + Settings.Global.LOW_POWER_MODE, if (on) 1 else 0) + (findViewById(R.id.toggle_battery_saving_mode) as Button).setText( + if (on) "Exit low power mode" else "Enter low power mode") + } + + fun toggleBatterySavingMode(v: View) { + setBatterySavingModeOn(!mBatterySavingModeOn) + } + + fun setBackgroundColorAlpha(alpha: Float) { + if (getWindowManager().isCrossWindowBlurEnabled()) { + mAlphaWithBlur = alpha + } else { + mAlphaNoBlur = alpha + } + (findViewById(R.id.background_alpha) as TextView).setText("%.2f".format(alpha)) + mBackgroundDrawable.setAlpha((alpha * 255f).toInt()) + getWindowManager().updateViewLayout(window.getDecorView(), window.getAttributes()) + } +} diff --git a/tests/benchmarks/Android.bp b/tests/benchmarks/Android.bp deleted file mode 100644 index f87ca2ef928b..000000000000 --- a/tests/benchmarks/Android.bp +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (C) 2015 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. - -// build framework base core benchmarks -// ============================================================ - -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "frameworks_base_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - default_applicable_licenses: ["frameworks_base_license"], -} - -java_library { - name: "networkStatsFactory-benchmarks", - installable: true, - - srcs: ["src/**/*.java"], - - libs: [ - "caliper-api-target", - "services.core", - ], - -} diff --git a/tests/benchmarks/src/com/android/server/net/NetworkStatsFactoryBenchmark.java b/tests/benchmarks/src/com/android/server/net/NetworkStatsFactoryBenchmark.java deleted file mode 100644 index ef014f0d4e53..000000000000 --- a/tests/benchmarks/src/com/android/server/net/NetworkStatsFactoryBenchmark.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.net; - -import android.net.NetworkStats; -import android.os.SystemClock; -import com.android.server.net.NetworkStatsFactory; -import com.google.caliper.AfterExperiment; -import com.google.caliper.BeforeExperiment; -import java.io.File; - -public class NetworkStatsFactoryBenchmark { - private File mStats; - - // TODO: consider staging stats file with different number of rows - - @BeforeExperiment - protected void setUp() { - mStats = new File("/proc/net/xt_qtaguid/stats"); - } - - @AfterExperiment - protected void tearDown() { - mStats = null; - } - - public void timeReadNetworkStatsDetailJava(int reps) throws Exception { - for (int i = 0; i < reps; i++) { - NetworkStatsFactory.javaReadNetworkStatsDetail(mStats, NetworkStats.UID_ALL, - // Looks like this was broken by change d0c5b9abed60b7bc056d026bf0f2b2235410fb70 - // Fixed compilation problem but needs addressing properly. - new String[0], 999); - } - } - - public void timeReadNetworkStatsDetailNative(int reps) { - for (int i = 0; i < reps; i++) { - final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 0); - NetworkStatsFactory.nativeReadNetworkStatsDetail( - stats, mStats.getAbsolutePath(), NetworkStats.UID_ALL, - // Looks like this was broken by change d0c5b9abed60b7bc056d026bf0f2b2235410fb70 - // Fixed compilation problem but needs addressing properly. - new String[0], 999, false); - } - } -} diff --git a/tests/benchmarks/src/com/android/server/net/OWNERS b/tests/benchmarks/src/com/android/server/net/OWNERS deleted file mode 100644 index aa87958f1d53..000000000000 --- a/tests/benchmarks/src/com/android/server/net/OWNERS +++ /dev/null @@ -1 +0,0 @@ -include /services/core/java/com/android/server/net/OWNERS diff --git a/tests/vcn/Android.bp b/tests/vcn/Android.bp index 41f73cd9c706..228520e8545b 100644 --- a/tests/vcn/Android.bp +++ b/tests/vcn/Android.bp @@ -18,6 +18,7 @@ android_test { "java/**/*.kt", ], platform_apis: true, + defaults: ["framework-connectivity-test-defaults"], test_suites: ["device-tests"], certificate: "platform", static_libs: [ @@ -28,6 +29,7 @@ android_test { "net-tests-utils", "platform-test-annotations", "services.core", + "service-connectivity-tiramisu-pre-jarjar", ], libs: [ "android.test.runner", diff --git a/tests/vcn/AndroidManifest.xml b/tests/vcn/AndroidManifest.xml index 2ad9aac67029..a8f657c89f76 100644 --- a/tests/vcn/AndroidManifest.xml +++ b/tests/vcn/AndroidManifest.xml @@ -16,7 +16,8 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.frameworks.tests.vcn"> - + <uses-sdk android:minSdkVersion="33" + android:targetSdkVersion="33"/> <application> <uses-library android:name="android.test.runner" /> </application> |